# MetonaEditor > TypeScript 重构 · 零运行时依赖 · 轻量级桌面端 Markdown Editor 库 [](https://git.metona.cn/MetonaTeam/-/packages/npm/@metona-team%2Fmetona-editor) [](./LICENSE) [](./tests) [](./tests) [](./tsconfig.json) ## 特性 - **TypeScript 源码** — 全模块 TypeScript 严格模式,完整类型导出,IDE 智能提示 - **零运行时依赖** — 打包后单文件,无任何第三方库,UMD / ESM / CJS 三种格式 - **自研解析器** — CommonMark + GFM 扩展,96% 语句覆盖率,parseTokens / renderTokens 分离 API,registerBlockHandler 自定义块语法 - **插件系统 v2** — 拓扑排序依赖管理,6 个预设插件开箱即用,安装 / 卸载生命周期 - **三模式视图** — edit / split / preview,拖拽分隔条调整比例,双向滚动同步 - **主题系统** — light / dark / warm / auto,CSS 变量可定制,实例级隔离,主题继承,外部跟随 - **国际化** — zh-CN / en-US 完整翻译,实例级语言隔离,远程加载翻译包 - **编辑体验** — 行号装订线、智能 Enter、括号自动闭合、拖放文件、大纲面板、Zen 专注模式 - **安全** — HTML 转义,XSS 协议过滤(javascript / vbscript / file / data),sanitize 钩子 - **桌面端优先** — 纯电脑端设计,无移动端冗余代码 --- ## 目录 - [快速开始](#快速开始) - [配置项](#配置项) - [工具栏](#工具栏) - [实例 API](#实例-api) - [静态 API](#静态-api) - [事件系统](#事件系统) - [Markdown 解析器](#markdown-解析器) - [插件系统](#插件系统) - [主题系统](#主题系统) - [国际化](#国际化) - [构建与测试](#构建与测试) - [License](#license) --- ## 快速开始 ### npm 安装 ```bash npm install @metona-team/metona-editor ``` ```typescript import MeEditor from '@metona-team/metona-editor'; const editor = MeEditor.create('#editor', { value: '# Hello World', mode: 'split', plugins: ['autoSave', 'searchReplace'], }); ``` ### CDN 引入 ```html
``` --- ## 配置项 ```typescript MeEditor.create(container, { // 内容 value: '', // 初始 Markdown 文本 placeholder: '', // 占位符 // 视图 mode: 'split', // 'edit' | 'split' | 'preview' height: 400, // 数字为 px,字符串原样使用 toolbar: DEFAULT_TOOLBAR, // 工具栏按钮数组,false 隐藏 wordCount: true, // 状态栏字数统计 lineNumbers: true, // 行号装订线 outline: false, // 大纲面板 // 行为 autofocus: false, // 自动聚焦 spellcheck: false, // 拼写检查 readOnly: false, // 只读模式 tabSize: 2, // Tab 空格数(0 = \t) historyLimit: 100, // 历史栈上限 historyDebounce: 400, // 历史栈防抖(ms) syncScroll: true, // 分屏同步滚动 autoBrackets: true, // 括号自动闭合 zenMode: false, // Zen 专注模式 wordWrap: true, // 自动换行 maxLength: 0, // 最大字符数(0=不限) // 主题与语言 theme: 'auto', // 'light' | 'dark' | 'warm' | 'auto' locale: 'zh-CN', // 'zh-CN' | 'en-US' // 渲染钩子 render: null, // (md: string, env: RenderEnv) => string highlight: null, // (code: string, lang: string) => string sanitize: null, // (html: string) => string // 外观 className: '', // 容器额外 CSS class style: {}, // 容器内联样式 // 插件 plugins: [], // 实例级插件列表 // 回调 onChange: null, // (value: string, editor: MarkdownEditor) => void onInput: null, // (value: string, editor: MarkdownEditor) => void onFocus: null, // (editor: MarkdownEditor) => void onBlur: null, // (editor: MarkdownEditor) => void onSave: null, // (value: string, editor: MarkdownEditor) => void onModeChange: null, // (mode: EditMode, editor: MarkdownEditor) => void onFullscreen: null, // (fullscreen: boolean, editor: MarkdownEditor) => void onCreate: null, // (editor: MarkdownEditor) => void onDestroy: null, // (editor: MarkdownEditor) => void onLinkClick: null, // (href: string, text: string, editor: MarkdownEditor) => void }); ``` --- ## 工具栏 ### 默认工具栏 ```typescript ['bold','italic','strikethrough','code','|', 'h1','h2','h3','|', 'quote','ul','ol','|', 'link','image','table','hr','|', 'undo','redo','|', 'edit','split','preview','fullscreen'] ``` ### 自定义工具栏 ```typescript // 精简版 MeEditor.create('#editor', { toolbar: ['bold', 'italic', '|', 'h1', 'h2', '|', 'undo', 'redo'], }); // 添加自定义按钮 editor.addToolbarButton({ action: 'timestamp', title: '插入时间戳', icon: '', onClick: (editor) => editor.insert(new Date().toISOString()), }); ``` --- ## 实例 API ### 内容操作 ```typescript editor.getValue(): string editor.setValue(md: string, opts?: { silent?: boolean }): this editor.getHTML(): string editor.refresh(): this // 强制重渲染(内容未变时) editor.insert(text: string, opts?: { replace?: boolean }): this editor.wrap(before: string, after?: string): this ``` ### 命令执行 ```typescript editor.exec(action: string): this // 支持 action: // bold italic strikethrough underline code // h1 h2 h3 quote ul ol hr // link image table // indent outdent undo redo // edit split preview fullscreen // zen wordwrap ``` ### 历史栈 ```typescript editor.undo(): this editor.redo(): this editor.canUndo(): boolean editor.canRedo(): boolean ``` ### 模式与全屏 ```typescript editor.setMode(mode: 'edit' | 'split' | 'preview'): this editor.getMode(): EditMode editor.toggleFullscreen(): this editor.isFullscreen(): boolean editor.exitFullscreen(): this ``` ### 主题与语言 ```typescript editor.setTheme(theme: string): this editor.getTheme(): string editor.setLocale(locale: string): this editor.getLocale(): string editor.t(key: string, params?: object): string ``` ### 统计与状态 ```typescript editor.getStats(): { characters, words, chineseChars, englishWords, lines, readingTime } editor.getStatus(): { id, mode, theme, locale, fullscreen, readOnly, disabled, destroyed, plugins } ``` ### 启用 / 禁用 / 只读 ```typescript editor.enable(): this editor.disable(): this editor.isDisabled(): boolean editor.setReadOnly(readOnly: boolean): this editor.isReadOnly(): boolean ``` ### 事件 ```typescript editor.on(name: string, fn: (...args: any[]) => void): () => void editor.off(name: string, fn: (...args: any[]) => void): this ``` ### 插件 ```typescript editor.use(plugin: string | PluginObject, options?: object): this editor.unuse(name: string): this editor.getPlugins(): PluginObject[] editor.addToolbarButton(config: ToolbarButtonConfig): this ``` ### 快捷键 ```typescript editor.registerShortcut(combo: string, handler: Function | string, description?: string): this editor.unregisterShortcut(combo: string): this editor.getShortcuts(): Shortcut[] ``` ### 工具栏管理 ```typescript editor.configureToolbar(tools: string[]): this editor.removeToolbarButton(action: string): this ``` ### Zen / Word Wrap ```typescript editor.toggleZen(): this editor.isZen(): boolean editor.toggleWordWrap(): this editor.setWordWrap(on: boolean): this editor.isWordWrap(): boolean ``` ### Toast ```typescript editor.toast(message: string, opts?: { type?: 'success' | 'error' | 'warning' | 'info'; duration?: number; animation?: 'fade' | 'slide' | 'scale'; }): this ``` ### 销毁 ```typescript editor.destroy(): void editor.isDestroyed(): boolean ``` --- ## 静态 API ```typescript import MeEditor from '@metona-team/metona-editor'; // 工厂函数 MeEditor.create(container, options) // 全局默认插件 MeEditor.use(plugin, options) MeEditor.use('autoSave', { delay: 2000 }) // 全局事件钩子 MeEditor.on('beforeCreate', (editor) => {}) MeEditor.off('beforeCreate', handler) // 全局主题 / 语言 MeEditor.setTheme('dark') MeEditor.setLocale('en-US') // 状态查询 MeEditor.getStatus() // => { version, theme, locale, globalPlugins, presetPlugins } // 销毁全局资源 MeEditor.destroy() // 解析器独立使用 import { parseMarkdown, parseTokens, renderTokens, safeUrl, slugify, registerBlockHandler } from '@metona-team/metona-editor'; ``` --- ## 事件系统 ### 实例事件 | 事件 | 触发时机 | 参数 | |------|---------|------| | `input` | textarea 原生 input | `(value, editor)` | | `change` | 内容变化 | `(value, editor)` | | `focus` | 聚焦 | `(editor)` | | `blur` | 失焦 | `(editor)` | | `save` | Ctrl+S | `(editor)` | | `modeChange` | 模式切换 | `(mode, editor)` | | `fullscreen` | 全屏切换 | `(fullscreen, editor)` | | `themeChange` | 实例主题变更 | `({ theme, resolved, config })` | | `localeChange` | 实例语言变更 | `({ locale, direction })` | | `zenChange` | Zen 模式切换 | `(zen, editor)` | | `destroy` | 销毁 | `()` | | `autosave` | autoSave 触发 | `({ key, value })` | | `beforeRender` | 渲染前 | `(editor)` | | `afterRender` | 渲染后 | `(editor)` | | `linkClick` | 预览区链接点击 | `({ href, text })` | | `fileOpened` | fileSystem 打开文件 | `({ name, handle })` | | `fileSaved` | fileSystem 保存文件 | `({ handle })` | ### 全局钩子 | 钩子 | 触发时机 | |------|---------| | `beforeCreate` | 实例构造初始化前 | | `afterCreate` | 实例构造初始化完成 | | `beforeRender` | 每次渲染前(全局) | | `afterRender` | 每次渲染后(全局) | | `beforeDestroy` | destroy 前 | | `afterDestroy` | destroy 后 | --- ## Markdown 解析器 ### 支持语法 | 语法 | 示例 | 输出 | |------|------|------| | ATX 标题 | `# H1` ~ `###### H6` | `` |
| 代码块 | ` ```lang ` | `` |
| 缩进代码块 | ` code` / `\tcode` | `` |
| 引用 | `> quote` | `` |
| 无序列表 | `- / * / + item` | `- ` |
| 有序列表 | `1. item` | `
- ` |
| 嵌套列表 | 多级缩进 | 多级 `
/` |
| 任务列表 | `- [x] done` | `- ` |
| 水平线 | `---` `***` `___` | `
` |
| 表格 | `\| a \| b \|` | `