fix(submit): keep the editor iframe tall enough for restored drafts and media
The iframe height is synced explicitly, and two paths were missing it, so long content ended up clipped inside the editor's own scroll area. - restoring a local draft calls setContent with a whole article at once; the iframe stayed at 520px while the body grew to 1410px, so only the first few paragraphs appeared to survive the restore - media inserts called insertContent directly without resyncing, and images load asynchronously: the height was measured while the image was still 0px tall, leaving the paragraphs below it cut off (measured: iframe 946 vs body 1006 with a single image after long text) Fixes - resync the height right after the restore's setContent, and add SetContent to the events that already sync height and content - resync after both media callbacks (picker and embed) - add installHeightWatchers(): capture-phase load listener inside the iframe for img / iframe / video / audio, plus a ResizeObserver on the body, so the height follows assets that finish loading later Tests cover the restore path and both media paths, including async loading.
This commit is contained in:
1 parent
a5386f72c6
commit
49f1212e33
3 files changed
+83
-3
No files matched your search
@@ -137,7 +137,7 @@ test('studio app uses TinyMCE while preserving autosave, recovery, and publishin
|
||||
assert.match(appSource, /PublishDrawer/);
|
||||
assert.match(appSource, /wpEditor\.initialize\(EDITOR_ID/);
|
||||
assert.match(appSource, /editor\.getContent\(\)/);
|
||||
assert.match(appSource, /editorRef\.current\?\.setContent/);
|
||||
assert.match(appSource, /editor\?\.setContent\(content\)/);
|
||||
assert.doesNotMatch(appSource, /BlockEditorProvider|registerCoreBlocks|BlockList|registerCoreBlocks/);
|
||||
assert.doesNotMatch(creatorRest, /block_content\(/);
|
||||
assert.match(creatorRest, /'post_content'\s*=>\s*\$payload\['content'\]/);
|
||||
@@ -774,3 +774,38 @@ test('draft saves never demote a submitted post or consume the publish quota', (
|
||||
// REST 侧要把 autosave 传给 persist()。
|
||||
assert.match(read('src/Core/CreatorRest.php'), /'autosave'\s*=>\s*\$is_auto/);
|
||||
});
|
||||
|
||||
// 恢复本地草稿会一次性把正文换成很长的一篇:iframe 必须跟着变高,
|
||||
// 否则超出的段落留在 iframe 内部滚动区,看起来像「只剩第一段」。
|
||||
test('restoring a draft resyncs the editor height', () => {
|
||||
const app = read('assets/creator-studio/src/index.tsx');
|
||||
const restoreAt = app.indexOf('const restore = useCallback');
|
||||
const restoreBody = app.slice(restoreAt, app.indexOf('const rememberSelection'));
|
||||
|
||||
// setContent 之后必须重新同步高度。
|
||||
assert.match(restoreBody, /editor\?\.setContent\(content\)/);
|
||||
assert.match(restoreBody, /syncEditorHeight\(editor\)/);
|
||||
// SetContent 事件本身也要参与高度同步与内容同步。
|
||||
assert.match(app, /editor\.on\('input change Undo Redo AddUndo SetContent'/);
|
||||
});
|
||||
|
||||
// 图片/视频插入后正文会变高,且资源是异步加载的:高度必须跟着重算,
|
||||
// 否则图片下方的段落会被 iframe 的固定高度裁掉。
|
||||
test('media inserts resync the editor height, including after async loading', () => {
|
||||
const app = read('assets/creator-studio/src/index.tsx');
|
||||
const runtime = read('assets/creator-studio/src/editor-runtime.ts');
|
||||
|
||||
// 两个媒体回调(选择器与嵌入)插入后都要同步高度。
|
||||
const mediaAt = app.indexOf('const openMedia = useCallback');
|
||||
const mediaBody = app.slice(mediaAt, app.indexOf('return (', mediaAt));
|
||||
assert.equal((mediaBody.match(/syncEditorHeight\(target\)/g) || []).length, 2);
|
||||
|
||||
// 图片 / iframe / video 加载完成后补一次同步。
|
||||
assert.match(runtime, /export function installHeightWatchers/);
|
||||
assert.match(runtime, /addEventListener\(\s*'load'/);
|
||||
assert.match(runtime, /tag === 'IMG' \|\| tag === 'IFRAME' \|\| tag === 'VIDEO' \|\| tag === 'AUDIO'/);
|
||||
assert.match(runtime, /ResizeObserver/);
|
||||
// 只在 init 路径挂一次,重复安装要短路。
|
||||
assert.match(runtime, /__jioHeightWatched/);
|
||||
assert.match(app, /installHeightWatchers\(editor\)/);
|
||||
});
|
||||
Reference in new issue
Block a user