diff --git a/README.md b/README.md index 7a7ed5d..5957c4a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![npm version](https://img.shields.io/badge/version-0.1.3-blue.svg)](https://www.npmjs.com/package/@metona-team/metona-editor) [![license](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE) -[![tests](https://img.shields.io/badge/tests-407%20passed-brightgreen.svg)](./tests) +[![tests](https://img.shields.io/badge/tests-425%20passed-brightgreen.svg)](./tests) [![coverage](https://img.shields.io/badge/coverage-97%25-brightgreen.svg)](./tests) --- @@ -14,15 +14,17 @@ - **零依赖** — 单文件打包,无任何运行时依赖,UMD/ESM/CJS 三种格式 - **现代化** — 原生 ES2020+ 实现,CSS 变量主题系统,响应式布局,无障碍支持 - **易扩展** — 完整插件系统(install/destroy 生命周期),自定义工具栏按钮,预设插件开箱即用 -- **易维护** — 模块化源码,JSDoc 注释完整,TypeScript 类型声明,407 个单元测试覆盖 +- **易维护** — 模块化源码,JSDoc 注释完整,TypeScript 类型声明,425 个单元测试覆盖 - **易使用** — 工厂函数 `create()` 一行接入,链式 API,中文优先文档与翻译 - **安全** — 内置 XSS 防护(`javascript:`/`vbscript:`/`file:` 协议过滤),HTML 转义,`safeUrl` 净化 -- **内置解析器** — 自研 CommonMark 子集 + GFM 扩展(表格、任务列表、删除线、自动链接),可整体替换 -- **三模式视图** — edit / split / preview 自由切换,分屏模式支持拖拽调整比例 -- **主题系统** — light / dark / auto / warm 四套预设,CSS 变量定制,跟随系统主题 +- **内置解析器** — 自研 CommonMark 子集 + GFM 扩展(表格含列对齐、任务列表、emoji 短码、上下标),可整体替换 +- **三模式视图** — edit / split / preview 自由切换,分屏拖拽调整比例,滚动同步,模式切换保持滚动位置 +- **主题系统** — light / dark / auto / warm 四套预设,CSS 变量定制,跟随系统主题,@media print 打印样式 - **国际化** — zh-CN / en-US 完整翻译,RTL 支持,`Intl` 数字/货币/日期格式化 -- **历史栈** — 撤销/重做,400ms 防抖合并,可配置上限 -- **预设插件** — autoSave(草稿)、exportTool(导出 .md/.html)、searchReplace(Ctrl+F 查找替换) +- **历史栈** — 撤销/重做,防抖合并(可配置延迟),可配置上限 +- **只读模式** — `readOnly` 配置 / `setReadOnly()` API,适用于预览/展示场景 +- **预设插件** — autoSave(草稿)、exportTool(导出 .md/.html)、searchReplace(Ctrl+F 查找替换)、imagePaste(粘贴图片转 base64) +- **性能优化** — 渲染缓存跳过重复解析,`refresh()` 强制刷新,模式切换无冗余渲染 --- @@ -146,7 +148,9 @@ MeEditor.create(container, { // 行为 autofocus: false, // 自动聚焦 spellcheck: false, // 拼写检查 + readOnly: false, // 只读模式 historyLimit: 100, // 历史栈上限 + historyDebounce: 400, // 历史栈防抖延迟(ms) syncScroll: true, // 分屏模式同步滚动 tabSize: 2, // 制表符空格数(0 表示 \t) @@ -213,6 +217,7 @@ MeEditor.create(container, { editor.getValue(); // 获取 Markdown 文本 editor.setValue(md, { silent }); // 设置内容,silent 不触发 change editor.getHTML(); // 获取渲染后的 HTML +editor.refresh(); // 强制刷新预览(内容未变时使用) editor.insert(text, { replace }); // 在光标处插入文本 editor.wrap(before, after); // 包裹选区 editor.focus(); // 聚焦编辑器 @@ -260,7 +265,7 @@ editor.getStats(); // 返回:{ characters, words, chineseChars, englishWords, lines, readingTime } editor.getStatus(); -// 返回:{ id, mode, theme, locale, fullscreen, disabled, destroyed, plugins } +// 返回:{ id, mode, theme, locale, fullscreen, readOnly, disabled, destroyed, plugins } ``` #### 事件 @@ -279,12 +284,14 @@ editor.getPlugins(); // 获取已安装插件列表 editor.addToolbarButton(config); // 追加工具栏按钮 ``` -#### 启用/禁用 +#### 启用/禁用/只读 ```javascript editor.enable(); // 启用 editor.disable(); // 禁用 editor.isDisabled(); // 是否禁用 +editor.setReadOnly(true); // 设置为只读 +editor.isReadOnly(); // 是否只读 ``` #### 销毁 @@ -373,6 +380,8 @@ editor.on('destroy', () => { | `fullscreen` | 全屏切换 | `(fullscreen, editor)` | | `destroy` | 销毁 | `()` | | `autosave` | autoSave 插件触发 | `({ key, value })` | +| `beforeRender` | 渲染前(实例级) | `(editor)` | +| `afterRender` | 渲染后(实例级) | `(editor)` | ### 静态钩子(全局) @@ -485,6 +494,15 @@ editor.use(presetPlugins.searchReplace); // Escape — 关闭 ``` +#### imagePaste — 粘贴图片转 base64 + +```javascript +editor.use(presetPlugins.imagePaste); + +// 在编辑区 Ctrl+V 粘贴剪贴板中的图片 +// 自动生成 ![](data:image/png;base64,...) 并插入 +``` + ### 自定义工具栏按钮 ```javascript @@ -518,7 +536,7 @@ pm.destroy(); pluginUtils.createPlugin({ name: 'x', install: () => {} }); pluginUtils.validatePlugin(plugin); // => { valid: boolean, errors: string[] } pluginUtils.getPreset('autoSave'); // => 副本 -pluginUtils.getAllPresets(); // => { autoSave, exportTool, searchReplace } +pluginUtils.getAllPresets(); // => { autoSave, exportTool, searchReplace, imagePaste } ``` --- @@ -666,6 +684,9 @@ MetonaEditor 内置自研轻量解析器,支持 CommonMark 子集 + GFM 扩展 | 粗体 | `**bold**` `__bold__` | `` | | 斜体 | `*italic*` `_italic_` | `` | | 删除线 | `~~text~~` | `` | +| 高亮标记 | `==text==` | `` | +| 上标 | `x^2^` | `` | +| 下标 | `H~2~O` | `` | | 行内代码 | `` `code` `` | `` | | 代码块 | ` ```lang ` | `
` |
 | 引用 | `> quote` | `
` | @@ -673,10 +694,11 @@ MetonaEditor 内置自研轻量解析器,支持 CommonMark 子集 + GFM 扩展 | 有序列表 | `1. item` | `
  1. ` | | 任务列表 | `- [x] done` | `
  2. ` | | 水平线 | `---` `***` `___` | `
    ` | -| 表格 | `\| a \| b \|` | `` | +| 表格 | `\| a \| b \|` | `
    `(含 `:---:` 列对齐) | | 链接 | `[text](url)` | `` | | 图片 | `![alt](url)` | `` | | 自动链接 | `` | `` | +| Emoji 短码 | `:smile:` `:rocket:` | 😊 🚀(80+ 常用) | ### XSS 防护 @@ -784,12 +806,12 @@ npm run test:coverage | core.js | 99.5% | 96.6% | 98.2% | | **总体** | **96.9%** | **80.3%** | **94.6%** | -测试文件位于 [tests/](./tests) 目录,共 **407 个测试用例**,覆盖: +测试文件位于 [tests/](./tests) 目录,共 **425 个测试用例**,覆盖: -- `parser.test.js` — Markdown 解析器全部语法 + XSS 防护 +- `parser.test.js` — Markdown 解析器全部语法(含新增上下标/高亮/emoji/表格对齐) + XSS 防护 - `utils.test.js` — 工具函数(generateId / escapeHTML / debounce / throttle / deepMerge 等) -- `core.test.js` — MarkdownEditor 构造、内容 API、exec 命令、历史栈、模式、事件、插件、销毁 -- `plugins.test.js` — 预设插件(autoSave / exportTool / searchReplace)+ PluginManager + pluginUtils +- `core.test.js` — MarkdownEditor 构造、内容 API、exec 命令(含自定义动作)、历史栈、模式、事件、插件、销毁、readOnly +- `plugins.test.js` — 预设插件(autoSave / exportTool / searchReplace / imagePaste)+ PluginManager + pluginUtils - `animations.test.js` — 动画注册与查询 - `themes.test.js` — 主题切换、持久化、监听、自定义注册 - `i18n.test.js` — 翻译、语言切换、格式化、监听