fix: 复查修复 5 处问题 — URL 双重转义/zen 泄漏/高亮环境不一致等
- parser: href/src/alt 改最小属性转义(escapeAttr 会把已实体化的 & 再转义成 &amp;,导致链接 URL 双重转义错误);新增 URL/alt 防回归测试 - core: _pushHistory 增加 maxLength 兜底截断(exec/Tab/Smart Enter/括号 自动闭合等程序化路径此前绕过 maxlength 限制) - core: destroy 时清理 Zen 模式的 document mousemove 监听(此前泄漏) - highlight: 自写环境无关转义(仅 & < >),修复 Node 环境下字符串高亮 失效、浏览器与 SSR 输出不一致的问题 - floating-toolbar/context-menu: toggleFloatingToolbar/registerContextMenu 恢复链式 return this(拆分时丢失) - plugins: 补齐 3 个硬编码文案的 i18n(regex/shortcuts/imageTooLarge), 6 种语言同步 - 测试 768 → 780
This commit is contained in:
@@ -2414,3 +2414,79 @@ describe('MarkdownEditor - v0.2.5 分隔条实例隔离', () => {
|
||||
a.destroy(); b.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
// ============ v0.2.5 复查:maxLength 兜底 + zen destroy 清理 ============
|
||||
|
||||
describe('MarkdownEditor - v0.2.5 maxLength 兜底', () => {
|
||||
test('exec 命令路径不突破 maxLength', () => {
|
||||
document.body.innerHTML = '';
|
||||
const c = document.createElement('div');
|
||||
document.body.appendChild(c);
|
||||
const ed = new MarkdownEditor(c, { maxLength: 20, value: '12345678901234567890' });
|
||||
ed.focus();
|
||||
ed.textarea.setSelectionRange(0, 0);
|
||||
ed.exec('indent');
|
||||
expect(ed.getValue().length).toBeLessThanOrEqual(20);
|
||||
ed.destroy();
|
||||
});
|
||||
|
||||
test('Smart Enter 不突破 maxLength', () => {
|
||||
document.body.innerHTML = '';
|
||||
const c = document.createElement('div');
|
||||
document.body.appendChild(c);
|
||||
const ed = new MarkdownEditor(c, { maxLength: 30, value: '- item 123456789012345678901234' });
|
||||
ed.focus();
|
||||
ed.textarea.setSelectionRange(ed.getValue().length, ed.getValue().length);
|
||||
ed.textarea.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
|
||||
expect(ed.getValue().length).toBeLessThanOrEqual(30);
|
||||
ed.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('MarkdownEditor - v0.2.5 zen destroy 清理', () => {
|
||||
test('destroy 移除 zen mousemove 监听', () => {
|
||||
document.body.innerHTML = '';
|
||||
const c = document.createElement('div');
|
||||
document.body.appendChild(c);
|
||||
const ed = new MarkdownEditor(c, { zenMode: true });
|
||||
expect(ed._zenMouseHandler).not.toBeNull();
|
||||
const spy = jest.spyOn(document, 'removeEventListener');
|
||||
ed.destroy();
|
||||
expect(spy).toHaveBeenCalledWith('mousemove', expect.any(Function));
|
||||
spy.mockRestore();
|
||||
});
|
||||
|
||||
test('destroy 后 mousemove 不再修改 toolbar', () => {
|
||||
document.body.innerHTML = '';
|
||||
const c = document.createElement('div');
|
||||
document.body.appendChild(c);
|
||||
const ed = new MarkdownEditor(c, { zenMode: true });
|
||||
const toolbar = ed.toolbarEl;
|
||||
ed.destroy();
|
||||
toolbar.style.opacity = '1';
|
||||
document.dispatchEvent(new MouseEvent('mousemove', { clientY: 10 }));
|
||||
expect(toolbar.style.opacity).toBe('1');
|
||||
});
|
||||
});
|
||||
|
||||
// ============ v0.2.5 复查:链式 API 契约 ============
|
||||
|
||||
describe('MarkdownEditor - v0.2.5 链式返回', () => {
|
||||
test('toggleFloatingToolbar 返回 this', () => {
|
||||
document.body.innerHTML = '';
|
||||
const c = document.createElement('div');
|
||||
document.body.appendChild(c);
|
||||
const ed = new MarkdownEditor(c, {});
|
||||
expect(ed.toggleFloatingToolbar()).toBe(ed);
|
||||
ed.destroy();
|
||||
});
|
||||
|
||||
test('registerContextMenu 返回 this', () => {
|
||||
document.body.innerHTML = '';
|
||||
const c = document.createElement('div');
|
||||
document.body.appendChild(c);
|
||||
const ed = new MarkdownEditor(c, {});
|
||||
expect(ed.registerContextMenu([{ label: 'x', onClick: () => {} }])).toBe(ed);
|
||||
ed.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user