refactor(submit): drop the hover block-delete overlay

Hovering a quote, hidden block, code block or table showed a ✕ button in the
block's top-right corner. It read as a stray close button and is not wanted.

Removed
- installBlockActions() and the two-step select/delete flow it drove
- the block-actions markup, positioning, selected-state CSS in the iframe
  content style
- BLOCK_SELECTOR, which only the overlay used

Deleting blocks still works: removeAdjacentBlock() keeps Backspace / Delete
next to a structural block (table, pre, hr, quote, hidden block) working, and
that is covered by both code and tests.
This commit is contained in:
kate522 committed 2026-11-10 18:56:30 +08:00
1 parent 49f1212e33
commit a061ec86ce
6 files changed
+25 -288

No files matched your search

@@ -312,38 +312,25 @@ test('top bar is masthead + centered toolbar, with no brand text in the toolbar
assert.doesNotMatch(rest, /'home'\s*=>\s*esc_url_raw\(\$home\)/);
});
test('block delete overlay lives outside the editable body and stays hidden', () => {
// 块右上角的悬停删除浮层已移除:删除统一走键盘(退格 / Delete)与工具栏。
// 浮层留在这里会被误当成「不需要的关闭按钮」,也曾在 body 里破坏 mceInsertContent。
test('hover block-delete overlay is gone', () => {
const runtime = read('assets/creator-studio/src/editor-runtime.ts');
const contentStyle = read('assets/creator-studio/src/editor-content-style.ts');
const pageStyles = read('assets/creator-studio/src/styles/_block-tools.scss');
const app = read('assets/creator-studio/src/index.tsx');
// 浮层挂在 iframe 的 documentElement 上,不能进 body:data-mce-bogus 只跳过
// 序列化,body 里多一个非常规子节点会让 mceInsertContent 把整篇正文清空
// (表现为「第一次点隐藏块没有插进正文」)。
assert.match(runtime, /doc\.documentElement\.appendChild\(bar\)/);
assert.doesNotMatch(runtime, /doc\.body\.appendChild\(bar\)/);
assert.match(runtime, /bar\.id = 'jio-block-actions'/);
// iframe 是独立文档:页面级样式表管不到它,隐藏规则必须写在 content_style。
assert.match(contentStyle, /#jio-block-actions\s*\{[^}]*position:\s*absolute/);
assert.match(contentStyle, /#jio-block-actions\s*\{[^}]*opacity:\s*0/);
assert.match(contentStyle, /#jio-block-actions\.is-visible\s*\{[^}]*opacity:\s*1/);
assert.match(contentStyle, /body\s*\{[^}]*position:\s*relative/);
// 页面级 SCSS 不再重复定义 iframe 内部的选择器(否则只是死样式)。
assert.doesNotMatch(pageStyles, /\.jio-creator__block-actions\s*\{/);
// data-mce-bogus 让 TinyMCE 序列化、字数和选区都跳过这个浮层。
assert.match(runtime, /setAttribute\('data-mce-bogus', 'all'\)/);
assert.doesNotMatch(runtime, /jio-block-actions/);
assert.doesNotMatch(runtime, /jio-creator__block-actions/);
assert.doesNotMatch(runtime, /installBlockActions/);
assert.doesNotMatch(runtime, /BLOCK_SELECTOR/);
assert.doesNotMatch(contentStyle, /jio-block-actions/);
assert.doesNotMatch(contentStyle, /jio-creator__block-selected/);
assert.doesNotMatch(app, /installBlockActions/);
// 两步删除:第一次点击只选中,第二次才真删;不再有关闭 / 叉号语义。
const firstClick = runtime.indexOf('if (selected !== block) {');
const secondClick = runtime.indexOf('// 第二次点击:真正删除。');
assert.ok(firstClick !== -1 && secondClick !== -1, 'two-step delete branches both exist');
assert.ok(firstClick < secondClick, 'first click only selects');
assert.ok(
runtime.indexOf('block.classList.add(SELECTED_CLASS)', firstClick) < secondClick,
'selection class is applied on the first click'
);
assert.match(contentStyle, /\.jio-creator__block-selected\s*\{/);
assert.match(runtime, /再次点击删除此块/);
// 键盘删除仍然保留:空段落旁的结构块要能被退格删掉。
assert.match(runtime, /export function removeAdjacentBlock/);
assert.match(runtime, /STRUCTURAL_SELECTOR/);
assert.match(app, /removeAdjacentBlock\(editor, event\)/);
});
// 工具栏下拉:菜单必须 portal 到 body,否则会被横向滚动的工具条裁剪。
@@ -140,13 +140,13 @@ test('placeholder never becomes a DOM node in the editable body', () => {
});
test('editor chrome injected into the body does not count as content', () => {
// 真实页面上 editor-runtime 会把块删除浮层插进 body,它带 data-mce-bogus
// 但含文字(「✕ 选中此块」)。若按 body.textContent 判断,空正文永远非空,
// 占位符就永远不显示 —— 这正是「首次加载不显示」的真实原因。
// TinyMCE 会往 body 里插带 data-mce-bogus 的工具节点,其中可能含文字。
// 若按 body.textContent 判断,空正文永远非空,占位符就永远不显示 ——
// 这正是「首次加载不显示」的真实原因。
const { doc, editor } = createEditor(
'<p><br data-mce-bogus="1"></p>' +
'<div id="jio-block-actions" data-mce-bogus="all">' +
'<button type="button"><span>✕</span><span>选中此块</span></button></div>',
'<div data-mce-bogus="all">' +
'<button type="button"><span>✕</span><span>工具节点</span></button></div>',
{ placeholder: '请输入正文' }
);
const plugin = loadPlugin()[PLUGIN];