release: v0.1.2 — readOnly, new syntax, plugins, optimizations
Features: - feat(core): readOnly mode with config option and setReadOnly() API - feat(parser): superscript ^text^ and subscript ~text~ support - feat(parser): highlight/mark ==text== syntax - feat(parser): table column alignment with colons (:---, :---:, ---:) - feat(parser): emoji shortcodes 😄 → 😊 (80+ common emojis) - feat(plugins): imagePaste preset — paste clipboard images as base64 - feat(core): instance-level beforeRender/afterRender events - feat(styles): print stylesheet (@media print) - feat(styles): mark element CSS styling - feat(styles): readOnly mode CSS (.me-readonly) Optimizations: - perf(core): history debounce now configurable via historyDebounce option - perf(core): skip _render() in edit-only mode (already guarded) - fix(core): divider drag division-by-zero guard - fix(core): config.style deep merge with DEFAULTS - fix(core): scroll position preserved across mode switches Tests: - 9 new test cases: readOnly (3), parser syntax (6) - Total: 418 tests passing (+9 from v0.1.1) Chores: - version bump 0.1.1 → 0.1.2 - TypeScript definitions updated for new APIs
This commit is contained in:
+43
-1
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* MetonaEditor Plugins - 插件系统
|
||||
* @module plugins
|
||||
* @version 0.1.1
|
||||
* @version 0.1.2
|
||||
* @description 插件管理器 + 预设插件(autoSave / exportTool / searchReplace)
|
||||
*
|
||||
* 插件约定:
|
||||
@@ -419,6 +419,47 @@ const searchReplacePlugin = {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* 图片粘贴插件
|
||||
* 监听 textarea 粘贴事件,自动将剪贴板中的图片转换为 base64 data URI 并插入。
|
||||
*/
|
||||
const imagePastePlugin = {
|
||||
name: 'imagePaste',
|
||||
description: '粘贴图片自动转为 base64 内联',
|
||||
|
||||
_onPaste: null,
|
||||
|
||||
install(editor) {
|
||||
if (!editor || !editor.textarea || typeof document === 'undefined') return;
|
||||
|
||||
this._onPaste = (e) => {
|
||||
const items = e.clipboardData && e.clipboardData.items;
|
||||
if (!items) return;
|
||||
for (const item of items) {
|
||||
if (item.type && item.type.startsWith('image/')) {
|
||||
e.preventDefault();
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
const dataUri = reader.result;
|
||||
const name = `image-${Date.now().toString(36)}.png`;
|
||||
editor.insert(`\n`);
|
||||
};
|
||||
reader.readAsDataURL(item.getAsFile());
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
editor.textarea.addEventListener('paste', this._onPaste);
|
||||
},
|
||||
|
||||
destroy(editor) {
|
||||
if (this._onPaste && editor && editor.textarea) {
|
||||
editor.textarea.removeEventListener('paste', this._onPaste);
|
||||
}
|
||||
this._onPaste = null;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* 预设插件注册表
|
||||
*/
|
||||
@@ -426,6 +467,7 @@ const presetPlugins = {
|
||||
autoSave: autoSavePlugin,
|
||||
exportTool: exportToolPlugin,
|
||||
searchReplace: searchReplacePlugin,
|
||||
imagePaste: imagePastePlugin,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user