feat: v0.4.0 — 安全修复×6 + 增量性能×3 + Playwright E2E + 实例级 i18n
CI / test-parser (push) Successful in 9m27s
CI / test-core (push) Successful in 9m34s
CI / test-rest (push) Successful in 9m27s
CI / e2e (push) Failing after 5m15s
CI / verify (20.x) (push) Successful in 9m54s
CI / verify (18.x) (push) Successful in 9m56s
CI / verify (24.x) (push) Successful in 9m48s

0.3.0 修复版:
- 脚注 id 属性注入 XSS 防护(行内引用 + 脚注区)
- 全局插件注入移至 afterCreate(searchReplace 等依赖 textarea 的插件真正生效)+ use() 同名防重
- 行内渲染缓存附加 refs 指纹,防跨文档引用链接串数据
- 白名单裸标签 <u>/</u> 透传,underline(Ctrl+U)预览可见
- getStatus()/渲染 env 使用实例 locale;replaceAll 替换文本按字面处理
- replaceAllRegex 保留 $1 捕获组语义

0.3.1 性能版:
- 高亮规则按语言缓存(registerLanguage 覆盖失效),bench +33%
- 统计增量计算:字数/词数/行数差异区间,击键零全量扫描
- outline 树构建 O(n²) → 迭代栈 O(n)
- 拖放图片 >500KB 拦截、scrollToLine 真实行高、undo/redo 光标恢复
- selectionChange/cursorMove 与浮动工具栏解耦、unregisterShortcut 大小写归一
- toast 接入 7 种 ANIMATIONS、实例主题订阅随 destroy 断开(dispose)

0.4.0 工程版:
- Playwright 真实浏览器冒烟测试(e2e/,22 项断言)+ CI e2e job
- sideEffects: false 便于 tree-shaking
- MeEditor.destroy() 全面复位(全局钩子清理 + 内部注入钩子重建)
- 实例 locale 统一作用于全部 UI 文案(状态栏/工具栏/右键菜单/大纲)

测试 782 → 826,全绿;typecheck/lint/build 通过
This commit is contained in:
2026-08-09 12:31:14 +08:00
parent 64aedb9546
commit cb0caff4cf
24 changed files with 1122 additions and 129 deletions
+12 -4
View File
@@ -1,7 +1,7 @@
/**
* MetonaEditor — Type-safe, lightweight Markdown Editor
* @module metona-editor
* @version 0.2.5
* @version 0.4.0
*/
import { MarkdownEditor } from './core';
@@ -14,14 +14,18 @@ import { highlight, normalizeLanguage, registerLanguage, getSupportedLanguages }
import { DEFAULTS, ICONS, THEMES, EDIT_MODES, DEFAULT_TOOLBAR, TOOLBAR_ACTIONS } from './constants';
import type { EditMode, ThemeName, ToolbarItem, EditorOptions } from './constants';
const VERSION = '0.2.5';
const VERSION = '0.4.0';
const globalPlugins: any[] = [];
MarkdownEditor.on('beforeCreate', (editor) => {
// 全局插件在 afterCreate 安装:此时 DOM 已构建完成,依赖 textarea/el 的插件
// searchReplace / shortcutHelp / imagePaste)才能正常生效。
const injectGlobalPlugins = (editor: MarkdownEditor): void => {
if (!editor || editor.isDestroyed()) return;
globalPlugins.forEach((p) => { try { editor.use(p); } catch (e) { console.error('MeEditor global plugin install error:', e); } });
});
};
MarkdownEditor.on('afterCreate', injectGlobalPlugins);
function create(container: string | HTMLElement, options: EditorOptions = {}): MarkdownEditor {
return new MarkdownEditor(container, options);
@@ -46,6 +50,10 @@ function destroy(): void {
if (i18nUtils) { try { i18nUtils.clearLocaleListeners(); } catch (_) {} }
if (animationUtils) { try { animationUtils.cancelAll(); } catch (_) {} }
globalPlugins.length = 0;
// 清理全局静态钩子(beforeCreate/afterCreate/beforeChange 等),整体复位;
// 随后重建内部 afterCreate 插件注入钩子,保证 destroy 后 MeEditor.use() 仍可用。
try { MarkdownEditor._hooks.clear(); } catch (_) {}
MarkdownEditor.on('afterCreate', injectGlobalPlugins);
}
function getStatus() {