[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-10026":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":22,"hasPages":22,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":37,"readmeContent":38,"aiSummary":39,"trendingCount":16,"starSnapshotCount":16,"syncStatus":40,"lastSyncTime":41,"discoverSource":42},10026,"vditor","Vanessa219\u002Fvditor","Vanessa219","♏  一款浏览器端的 Markdown 编辑器，支持所见即所得（富文本）、即时渲染（类似 Typora）和分屏预览模式。An In-browser Markdown editor, support WYSIWYG (Rich Text),  Instant Rendering (Typora-like) and Split View modes.","https:\u002F\u002Fb3log.org\u002Fvditor",null,"TypeScript",11031,1063,74,134,0,16,80,4,44.08,"MIT License",false,"master",[25,26,27,28,29,30,31,32,33,34,35,36],"commonmark","editor","gfm","lute","markdown","md","react","rich-text","typescript","typora","vue","wysiwyg","2026-06-12 02:02:16","\u003Cp align=\"center\">\n\u003Cimg alt=\"Vditor\" src=\"https:\u002F\u002Fb3log.org\u002Fimages\u002Fbrand\u002Fvditor-128.png\" \u002F>\n\n\u003Cbr>\n易于使用的 Markdown 编辑器，为适配不同的应用场景而生\n\u003Cbr>\u003Cbr>\n\u003Ca title=\"MIT\" target=\"_blank\" href=\"https:\u002F\u002Fopensource.org\u002Flicenses\u002FMIT\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-MIT-orange.svg?style=flat-square\">\u003C\u002Fa>\n\u003Ca title=\"npm bundle size\" target=\"_blank\" href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fvditor\">\u003Cimg alt=\"npm bundle size\" src=\"https:\u002F\u002Fimg.shields.io\u002Fbundlephobia\u002Fminzip\u002Fvditor?style=flat-square&color=blueviolet\">\u003C\u002Fa>\n\u003Ca title=\"Version\" target=\"_blank\" href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fvditor\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002Fvditor.svg?style=flat-square\">\u003C\u002Fa>\u003Cbr>\n\u003Ca title=\"Downloads\" target=\"_blank\" href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fvditor\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fdt\u002Fvditor.svg?style=flat-square&color=97ca00\">\u003C\u002Fa>\n\u003Ca title=\"jsdelivr\" target=\"_blank\" href=\"https:\u002F\u002Fwww.jsdelivr.com\u002Fpackage\u002Fnpm\u002Fvditor\">\u003Cimg src=\"https:\u002F\u002Fdata.jsdelivr.com\u002Fv1\u002Fpackage\u002Fnpm\u002Fvditor\u002Fbadge\"\u002F>\u003C\u002Fa>\n\u003Ca title=\"Hits\" target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002F88250\u002Fhits\">\u003Cimg src=\"https:\u002F\u002Fhits.b3log.org\u002FVanessa219\u002Fvditor.svg\">\u003C\u002Fa> \u003Cbr>\u003Cbr>\n\u003Ca title=\"GitHub Watchers\" target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fwatchers\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fwatchers\u002FVanessa219\u002Fvditor.svg?label=Watchers&style=social\">\u003C\u002Fa>\n\u003Ca title=\"GitHub Stars\" target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fstargazers\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fstars\u002FVanessa219\u002Fvditor.svg?label=Stars&style=social\">\u003C\u002Fa>\n\u003Ca title=\"GitHub Forks\" target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fnetwork\u002Fmembers\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fforks\u002FVanessa219\u002Fvditor.svg?label=Forks&style=social\">\u003C\u002Fa>\n\u003Ca title=\"Author GitHub Followers\" target=\"_blank\" href=\"https:\u002F\u002Fgithub.com\u002Fvanessa219\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Ffollowers\u002Fvanessa219.svg?label=Followers&style=social\">\u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n\u003Ca href=\"https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fblob\u002Fmaster\u002FREADME_en_US.md\">English\u003C\u002Fa> &nbsp;|&nbsp; \u003Ca href=\"https:\u002F\u002Fb3log.org\u002Fvditor\u002Fdemo\u002Findex.html\">Demo\u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n🔥 欢迎观摩我们的另一个开源项目 \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fsiyuan-note\u002Fsiyuan\">思源笔记\u003C\u002Fa>\n\u003Cp>\n\n## 💡 简介\n\n[Vditor](https:\u002F\u002Fb3log.org\u002Fvditor) 是一款浏览器端的 Markdown 编辑器，支持所见即所得、即时渲染（类似 Typora）和分屏预览模式。它使用 TypeScript 实现，支持原生 JavaScript 以及 Vue、React、Angular 和 Svelte 等框架。\n\n欢迎到 [Vditor 官方讨论区](https:\u002F\u002Fld246.com\u002Ftag\u002Fvditor)了解更多。同时也欢迎关注 B3log 开源社区微信公众号 `B3log开源`：\n\n![b3logos.jpg](https:\u002F\u002Fb3logfile.com\u002Ffile\u002F2020\u002F08\u002Fb3logos-032af045.jpg)\n\n## 🗺️ 背景\n\n随着 Markdown 排版方式的普及，越来越多的应用开始集成 Markdown 编辑器。目前主流可集成的 Markdown 编辑器现状如下：\n\n* 有的仅支持分屏预览，即编辑区和预览区分离\n* 有的同时支持所见即所得和分屏预览，但所见即所得模式下不能完整支持 Markdown 语法排版\n* 几乎没有类似 Typora 的即时渲染\n\n而这三点恰好对应了三种应用场景：\n\n* 分屏预览：适配传统的 Markdown 使用场景，适合大屏下编辑排版\n* 所见即所得：对不熟悉 Markdown 的用户友好，熟悉 Markdown 的用户也可以无缝使用\n* 即时渲染：理论上这是最为优雅的 Markdown 编辑方式，让熟悉 Markdown 的用户能够更专注于内容创作\n\n所以，一个能够**适配应用场景**的 Markdown 编辑器至关重要，它需要考虑到：\n\n* 传统 Markdown 用户的使用场景，提供分屏预览\n* 富文本编辑用户的使用场景，提供所见即所得\n* 高阶 Markdown 用户的使用场景，提供即时渲染\n\nVditor 在这些方面做了努力，希望能为现代化的通用 Markdown 编辑领域做出一些贡献。\n\n## ✨  特性\n\n* 支持三种编辑模式：所见即所得（wysiwyg）、即时渲染（ir）、分屏预览（sv）\n* 支持大纲、数学公式、脑图、图表、流程图、甘特图、时序图、五线谱、[多媒体](https:\u002F\u002Fld246.com\u002Farticle\u002F1589813914768)、语音阅读、标题锚点、代码高亮及复制、graphviz 渲染、[plantuml](https:\u002F\u002Fplantuml.com)UML图\n* 导出、图片懒加载、任务列表、多平台预览、多主题切换、复制到微信公众号\u002F知乎功能\n* 实现 CommonMark 和 GFM 规范，可对 Markdown 进行格式化和语法树查看，并支持[10+项](https:\u002F\u002Fld246.com\u002Farticle\u002F1549638745630#options-preview-markdown)配置\n* 工具栏包含 36+ 项操作，除支持扩展外还可对每一项中的[快捷键](https:\u002F\u002Fld246.com\u002Farticle\u002F1582778815353)、提示、提示位置、图标、点击事件、类名、子工具栏进行自定义\n* 表情\u002Fat\u002F话题等自动补全扩展\n* 可使用拖拽、剪切板粘贴上传，显示实时上传进度，支持 CORS 跨域上传\n* 实时保存内容，防止意外丢失\n* 录音支持，用户可直接发布语音\n* 粘贴 HTML 自动转换为 Markdown，如粘贴中包含外链图片可通过指定接口上传到服务器\n* 支持主窗口大小拖拽、字符计数\n* 多主题支持，内置黑白绿三套主题\n* 多语言支持，内置中、英、韩文本地化\n* 支持主流浏览器，对移动端友好\n\n![editor.png](https:\u002F\u002Fb3logfile.com\u002Ffile\u002F2020\u002F07\u002Feditor-b304aa97.png)\n\n![preview.png](https:\u002F\u002Fb3logfile.com\u002Ffile\u002F2020\u002F05\u002Fpreview-80846f66.png)\n\n## 🔮 编辑模式\n\n### 所见即所得（WYSIWYG）\n\n*所见即所得*模式对不熟悉 Markdown 的用户较为友好，熟悉 Markdown 的话也可以无缝使用。\n\n![vditor-wysiwyg](https:\u002F\u002Fb3logfile.com\u002Ffile\u002F2020\u002F07\u002Fwysiwyg-4f216b9b.gif)\n\n### 即时渲染（IR）\n\n*即时渲染*模式对熟悉 Typora 的用户应该不会感到陌生，理论上这是最优雅的 Markdown 编辑方式。\n\n![vditor-ir](https:\u002F\u002Fb3logfile.com\u002Ffile\u002F2020\u002F07\u002Fir-67cd956c.gif)\n\n### 分屏预览（SV）\n\n传统的*分屏预览*模式适合大屏下的 Markdown 编辑。\n\n![vditor-sv](https:\u002F\u002Fb3logfile.com\u002Ffile\u002F2020\u002F07\u002Fsv-595dcb28.gif)\n\n## 🍱 语法支持\n\n* 所有 CommonMark 语法：分隔线、ATX 标题、Setext 标题、缩进代码块、围栏代码块、HTML 块、链接引用定义、段落、块引用、列表、反斜杠转义、HTML 实体、行级代码、强调、加粗、链接、图片、行级 HTML、硬换行、软换行和纯文本。\n* 所有 GFM 语法：表格、任务列表项、删除线、自动链接、XSS 过滤\n* 常用 Markdown 扩展语法：脚注、ToC、自定义标题 ID\n* 图表语法\n  * 流程图、时序图、甘特图，通过 Mermaid 支持\n  * Graphviz\n  * 折线图、饼图、脑图等，通过 ECharts 支持\n* 五线谱：通过 abc.js 支持\n* 数学公式：数学公式块、行级数学公式，通过 MathJax 和 KaTeX 支持\n* YAML Front Matter\n* 中文语境优化\n  * 中西文之间插入空格\n  * 术语拼写修正\n  * 中文后跟英文逗号句号等标点替换为中文对应标点\n\n以上大部分特性可以通过开关配置是否启用，开发者可根据自己的应用场景选择搭配。\n\n## 🗃 案例\n\n* [Sym](https:\u002F\u002Fgithub.com\u002F88250\u002Fsymphony) 一款用 Java 实现的现代化社区（论坛\u002FBBS\u002F社交网络\u002F博客）平台\n* [Solo](https:\u002F\u002Fgithub.com\u002F88250\u002Fsolo) & [Pipe](https:\u002F\u002Fgithub.com\u002F88250\u002Fpipe) B3log 分布式社区的博客端节点，欢迎加入下一代社区网络\n* [Tditor](https:\u002F\u002Ftditor.com) 基于React、Vditor、Springboot，一款打造极致文字创作体验的在线Markdown编辑平台\n* [Arya](https:\u002F\u002Fgithub.com\u002Fnicejade\u002Fmarkdown-online-editor) 基于 Vue、Vditor，所构建的在线 Markdown 编辑器\n* [更多案例](https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fnetwork\u002Fdependents?package_id=UGFja2FnZS0zMTY2Mzg4MzE%3D)\n\n## 🛠️ 使用文档\n\n### CommonJS\n\n* 安装依赖\n\n```shell\nnpm install vditor --save\n```\n\n* 在代码中引入并初始化对象，可参考 [index.js](https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fblob\u002Fmaster\u002Fdemo\u002Findex.js)\n\n```ts\nimport Vditor from 'vditor'\nimport \"~vditor\u002Fsrc\u002Fassets\u002Fless\u002Findex\"\n\nconst vditor = new Vditor(id, {options...})\n```\n\n### HTML script\n\n* 在 HTML 中插入 CSS 和 JavaScript，可参考 [demo](https:\u002F\u002Fb3log.org\u002Fvditor\u002Fdemo\u002Findex.html)\n\n```html\n\u003C!-- ⚠️生产环境请指定版本号，如 https:\u002F\u002Funpkg.com\u002Fvditor@x.x.x\u002Fdist... -->\n\u003Clink rel=\"stylesheet\" href=\"https:\u002F\u002Funpkg.com\u002Fvditor\u002Fdist\u002Findex.css\" \u002F>\n\u003Cscript src=\"https:\u002F\u002Funpkg.com\u002Fvditor\u002Fdist\u002Findex.min.js\">\u003C\u002Fscript>\n```\n\n### 示例代码\n\n* [官方示例](https:\u002F\u002Fb3log.org\u002Fvditor\u002Fdemo\u002Findex.html) \u002F [示例源码](https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fb3log-index\u002Ftree\u002Fmaster\u002Fsrc\u002Fvditor)\n* [CommonJS Editor](https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fblob\u002Fmaster\u002Fdemo\u002Findex.js)\n* [CommonJS Render](https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fblob\u002Fmaster\u002Fdemo\u002Frender.js)\n* [在Svelte中使用](https:\u002F\u002Fgithub.com\u002FHerbertHe\u002Fsvelte-vditor-demo)\n\n### 主题\n\n#### 编辑器主题\n\n编辑器所展现的外观。内置classic，dark 2 套主题。\n\n* 编辑器初始化时可通过 `options.theme` 设置内置主题\n* 初始化完成后可通过 `setTheme` 更新编辑器主题\n* 可通过修改 [index.less](https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fblob\u002Fmaster\u002Fsrc\u002Fassets\u002Fless\u002Findex.less) 中的变量对主题颜色进行定制\n* 可参考现有结构和类名在原有基础上进行修改\n\n#### 内容主题\n\nMarkdown 输出的 HTML 所展现的外观。内置 ant-design, light，dark，wechat 4 套主题。支持内容主题扩展接口。\n\n* 需在显示元素上添加 `class=\"vditor-reset\"`\n* 编辑器初始化时可通过 `options.preview.theme` 设置内置或自己开发的主题列表\n* 内容渲染初始化时可通过 `IPreviewOptions.theme` 设置内置或自己开发的主题\n* 初始化完成后可通过 `setTheme` 或 `setContentTheme` 更新内容主题\n\n#### 代码主题\n\n代码块所展现的外观。内置 github 等 36 套主题。\n\n* 编辑器初始化时可通过 `options.preview.hljs` 对代码块样式、行号、是否启用进行设置\n* 内容渲染初始化时可通过 `IPreviewOptions.hljs` 对代码块样式、行号、是否启用进行设置\n* 初始化完成后可通过 `setTheme` 或 `setCodeTheme` 更新代码主题\n\n### API\n\n#### id\n\n可填入元素 `id` 或元素自身 `HTMLElement`\n\n⚠️：当填入元素自身的 `HTMLElement` 时需设置 `options.cache.id` 或将 `options.cache.enable` 设置为 `false`\n\n#### options\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| i18n | 多语言，参见 ITips | - |\n| undoDelay | 历史记录间隔 | - |\n| after | 编辑器异步渲染完成后的回调方法 | - |\n| height | 编辑器总高度 | 'auto' |\n| minHeight | 编辑区域最小高度 | - |\n| width | 编辑器总宽度，支持 % | 'auto' |\n| placeholder | 输入区域为空时的提示 | '' |\n| lang | 语言种类：de_DE, en_US, es_ES, fr_FR, ja_JP, ko_KR, pt_BR, ru_RU, sv_SE, vi_VN, zh_CN, zh_TW | 'zh_CN' |\n| input(value: string) | 输入后触发  | - |\n| focus(value: string) | 聚焦后触发 | - |\n| blur(value: string) | 失焦后触发 | - |\n| keydown(event: KeyboardEvent) | 按下后触发 | - |\n| esc(value: string) | \u003Ckbd>esc\u003C\u002Fkbd> 按下后触发 | - |\n| ctrlEnter(value: string) | \u003Ckbd>⌘\u002Fctrl+enter\u003C\u002Fkbd> 按下后触发 | - |\n| select(value: string) | 编辑器中选中文字后触发 | - |\n| unSelect() | 编辑器中未选中文字后触发 | - |\n| tab | \u003Ckbd>tab\u003C\u002Fkbd> 键操作字符串，支持 `\\t` 及任意字符串 | - |\n| typewriterMode | 是否启用打字机模式 | false |\n| cdn | 配置自建 CDN 地址 | `https:\u002F\u002Funpkg.com\u002Fvditor@${VDITOR_VERSION}` |\n| mode | 可选模式：sv, ir, wysiwyg | 'ir' |\n| debugger | 是否显示日志 | false |\n| value | 编辑器初始化值 | '' |\n| theme | 主题：classic, dark | 'classic' |\n| icon | 图标风格：ant, material | 'ant' |\n| customRenders: {language: string, render: (element: HTMLElement, vditor: IVditor) => void}[] | 自定义渲染器 | [] |\n| customWysiwygToolbar(type: TWYSISYGToolbar, element: HTMLElement): void | 对 wysiwyg 模式下的工具栏进行自定义 | - |\n\n#### options.toolbar\n\n* 工具栏，可使用 name 进行简写： `toolbar: ['emoji', 'br', 'bold', '|', 'line']` 。默认值参见 [src\u002Fts\u002Futil\u002FOptions.ts](https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fblob\u002Fmaster\u002Fsrc\u002Fts\u002Futil\u002FOptions.ts)\n* name 可枚举为： `emoji`，`headings`，`bold`，`italic`，`strike`，`|`，`line`，`quote`，`list`，`ordered-list`，`check` ,`outdent` ,`indent`，`code`，`inline-code`，`insert-after`，`insert-before` ,`undo`，`redo`，`upload`，`link`，`table`，`record`，`edit-mode`，`both`，`preview`，`fullscreen`，`outline`，`code-theme`，`content-theme`，`export`, `devtools`，`info`，`help`，`br`\n* 当 `name` 不在枚举中时，可以添加自定义按钮，格式如下：\n\n```js\nnew Vditor('vditor', {\n  toolbar: [\n    {\n      hotkey: '⇧⌘S',\n      name: 'sponsor',\n      tipPosition: 's',\n      tip: '成为赞助者',\n      className: 'right',\n      icon: '\u003Csvg t=\"1589994565028\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" p-id=\"2808\" width=\"32\" height=\"32\">\u003Cpath d=\"M506.6 423.6m-29.8 0a29.8 29.8 0 1 0 59.6 0 29.8 29.8 0 1 0-59.6 0Z\" fill=\"#0F0F0F\" p-id=\"2809\">\u003C\u002Fpath>\u003Cpath d=\"M717.8 114.5c-83.5 0-158.4 65.4-211.2 122-52.7-56.6-127.7-122-211.2-122-159.5 0-273.9 129.3-273.9 288.9C21.5 562.9 429.3 913 506.6 913s485.1-350.1 485.1-509.7c0.1-159.5-114.4-288.8-273.9-288.8z\" fill=\"#FAFCFB\" p-id=\"2810\">\u003C\u002Fpath>\u003Cpath d=\"M506.6 926c-22 0-61-20.1-116-59.6-51.5-37-109.9-86.4-164.6-139-65.4-63-217.5-220.6-217.5-324 0-81.4 28.6-157.1 80.6-213.1 53.2-57.2 126.4-88.8 206.3-88.8 40 0 81.8 14.1 124.2 41.9 28.1 18.4 56.6 42.8 86.9 74.2 30.3-31.5 58.9-55.8 86.9-74.2 42.5-27.8 84.3-41.9 124.2-41.9 79.9 0 153.2 31.5 206.3 88.8 52 56 80.6 131.7 80.6 213.1 0 103.4-152.1 261-217.5 324-54.6 52.6-113.1 102-164.6 139-54.8 39.5-93.8 59.6-115.8 59.6zM295.4 127.5c-72.6 0-139.1 28.6-187.3 80.4-47.5 51.2-73.7 120.6-73.7 195.4 0 64.8 78.3 178.9 209.6 305.3 53.8 51.8 111.2 100.3 161.7 136.6 56.1 40.4 88.9 54.8 100.9 54.8s44.7-14.4 100.9-54.8c50.5-36.3 108-84.9 161.7-136.6 131.2-126.4 209.6-240.5 209.6-305.3 0-74.9-26.2-144.2-73.7-195.4-48.2-51.9-114.7-80.4-187.3-80.4-61.8 0-127.8 38.5-201.7 117.9-2.5 2.6-5.9 4.1-9.5 4.1s-7.1-1.5-9.5-4.1C423.2 166 357.2 127.5 295.4 127.5z\" fill=\"#141414\" p-id=\"2811\">\u003C\u002Fpath>\u003Cpath d=\"M353.9 415.6m-33.8 0a33.8 33.8 0 1 0 67.6 0 33.8 33.8 0 1 0-67.6 0Z\" fill=\"#0F0F0F\" p-id=\"2812\">\u003C\u002Fpath>\u003Cpath d=\"M659.3 415.6m-33.8 0a33.8 33.8 0 1 0 67.6 0 33.8 33.8 0 1 0-67.6 0Z\" fill=\"#0F0F0F\" p-id=\"2813\">\u003C\u002Fpath>\u003Cpath d=\"M411.6 538.5c0 52.3 42.8 95 95 95 52.3 0 95-42.8 95-95v-31.7h-190v31.7z\" fill=\"#5B5143\" p-id=\"2814\">\u003C\u002Fpath>\u003Cpath d=\"M506.6 646.5c-59.6 0-108-48.5-108-108v-31.7c0-7.2 5.8-13 13-13h190.1c7.2 0 13 5.8 13 13v31.7c0 59.5-48.5 108-108.1 108z m-82-126.7v18.7c0 45.2 36.8 82 82 82s82-36.8 82-82v-18.7h-164z\" fill=\"#141414\" p-id=\"2815\">\u003C\u002Fpath>\u003Cpath d=\"M450.4 578.9a54.7 27.5 0 1 0 109.4 0 54.7 27.5 0 1 0-109.4 0Z\" fill=\"#EA64F9\" p-id=\"2816\">\u003C\u002Fpath>\u003Cpath d=\"M256 502.7a32.1 27.5 0 1 0 64.2 0 32.1 27.5 0 1 0-64.2 0Z\" fill=\"#EFAFF9\" p-id=\"2817\">\u003C\u002Fpath>\u003Cpath d=\"M703.3 502.7a32.1 27.5 0 1 0 64.2 0 32.1 27.5 0 1 0-64.2 0Z\" fill=\"#EFAFF9\" p-id=\"2818\">\u003C\u002Fpath>\u003C\u002Fsvg>',\n      click () {alert('捐赠地址：https:\u002F\u002Fld246.com\u002Fsponsor')},\n    }],\n})\n```\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| name | 唯一标示 | - |\n| icon | svg 图标 | - |\n| tip | 提示 | - |\n| tipPosition | 提示位置：'n', 'ne', 'nw', 's', 'se', 'sw', 'w', 'e' | - |\n| hotkey | 快捷键，格式为\u003Ckbd>⇧⌘\u003C\u002Fkbd>\u002F\u003Ckbd>⌘\u003C\u002Fkbd>\u002F\u003Ckbd>⌥⌘\u003C\u002Fkbd>| - |\n| suffix | 插入编辑器中的后缀 | - |\n| prefix | 插入编辑器中的前缀 | - |\n| click(event: Event, vditor: IVditor) | 自定义按钮点击时触发的事件 | - |\n| className | 样式名 | '' |\n| toolbar?: Array\u003Coptions.toolbar> | 子菜单 | - |\n\n#### options.toolbarConfig\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| hide | 是否隐藏工具栏 | false |\n| pin | 是否固定工具栏 | false |\n\n#### options.counter\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| enable | 是否启用计数器 | false |\n| after(length: number, counter: options.counter): void | 字数统计回调 | - |\n| max | 允许输入的最大值 | - |\n| type | 统计类型：'markdown', 'text' | 'markdown' |\n\n#### options.cache\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| enable | 是否使用 localStorage 进行缓存 | true |\n| id | 缓存 key，第一个参数为元素且启用缓存时**必填** | - |\n| after(html: string): string | 缓存后的回调 | - |\n\n#### options.comment\n\n⚠️：仅支持 wysiwyg 模式\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| enable | 是否启用评论模式 | false |\n| add(id: string, text: string, commentsData: ICommentsData[]) | 添加评论回调 | - |\n| remove(ids: string[]) | 删除评论回调 | - |\n| scroll(top: number) | 滚动回调 | - |\n| adjustTop(commentsData: ICommentsData[]) | 文档修改时，适配评论高度 | - |\n\n#### options.preview\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| delay | 预览 debounce 毫秒间隔 | 1000 |\n| maxWidth | 预览区域最大宽度 | 800 |\n| mode | 显示模式：both, editor | 'both' |\n| url | md 解析请求 | - |\n| parse(element: HTMLElement) | 预览回调 | - |\n| transform(html: string): string | 渲染之前回调 | - |\n\n#### options.preview.hljs\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| defaultLang | 未指定语言时默认使用该语言 | '' |\n| enable | 是否启用代码高亮 | true |\n| style | 可选值参见[Chroma](https:\u002F\u002Fxyproto.github.io\u002Fsplash\u002Fdocs\u002Flonger\u002Fall.html) | `github` |\n| lineNumber | 是否启用行号 | false |\n| langs | 自定义指定语言 | [CODE_LANGUAGES](https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fblob\u002F53ca8f9a0e511b37b5dae7c6b15eb933e9e02ccd\u002Fsrc\u002Fts\u002Fconstants.ts#L20) |\n| renderMenu(code: HTMLElement, copy: HTMLElement) | 渲染菜单按钮 | - |\n\n#### options.preview.markdown\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| autoSpace | 自动空格 | false |\n| gfmAutoLink | 自动链接 | true |\n| fixTermTypo | 自动矫正术语 | false |\n| toc | 插入目录 | false |\n| footnotes | 脚注 | true |\n| codeBlockPreview | wysiwyg 和 ir 模式下是否对代码块进行渲染 | true |\n| mathBlockPreview | wysiwyg 和 ir 模式下是否对数学公式进行渲染 | true |\n| paragraphBeginningSpace | 段落开头空两个 | false |\n| sanitize | 是否启用过滤 XSS | true |\n| listStyle | 为列表添加 data-style 属性 | false |\n| linkBase | 链接相对路径前缀 | '' |\n| linkPrefix | 链接强制前缀 | '' |\n| mark | 启用 mark 标记 | false |\n| sup | 上标 | false |\n| sub | 下标 | false |\n\n#### options.preview.theme\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| current | 当前主题 | \"light\" |\n| list | 可选主题列表 | { \"ant-design\": \"Ant Design\", dark: \"Dark\", light: \"Light\", wechat: \"WeChat\" } |\n| path | 主题样式地址 | `https:\u002F\u002Funpkg.com\u002Fvditor@${VDITOR_VERSION}\u002Fdist\u002Fcss\u002Fcontent-theme` |\n\n#### options.preview.math\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| inlineDigit | 内联数学公式起始 $ 后是否允许数字 | false |\n| macros | 使用 MathJax 渲染时传入的宏定义 | {} |\n| engine | 数学公式渲染引擎：KaTeX, MathJax | 'KaTeX' |\n| mathJaxOptions | 数学公式渲染引擎为 MathJax 时的参数 | - |\n\n#### options.preview.actions?: Array\u003CIPreviewAction | IPreviewActionCustom>\n\n默认值为 [\"desktop\", \"tablet\", \"mobile\", \"mp-wechat\", \"zhihu\"]。\n可从默认值中挑选进行配置，也可使用以下字段进行自定制开发。\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| key | 按钮唯一标识，不能为空 | - |\n| text | 按钮文字 | - |\n| tooltip | 提示 | - |\n| className | 按钮类名 | - |\n| click(key: string) | 按钮点击回调事件 | - |\n\n#### options.preview.render.media\n\n|        | 说明        | 默认值  |\n|--------|-----------|------|\n| enable | 是否启用多媒体渲染 | true |\n\n#### options.image\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| isPreview | 是否预览图片 | true |\n| preview(bom: Element) => void | 图片预览处理 | - |\n\n#### options.link\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| isOpen | 是否打开链接地址 | true |\n| click(bom: Element) => void | 点击链接事件 | - |\n\n#### options.hint\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| parse | 是否进行 md 解析 | true |\n| delay | 提示 debounce 毫秒间隔 | 200 |\n| emoji | 默认表情，可从[lute\u002Femoji_map](https:\u002F\u002Fgithub.com\u002F88250\u002Flute\u002Fblob\u002Fmaster\u002Fparse\u002Femoji_map.go) 中选取，也可自定义 | { '+1': '👍', '-1': '👎', 'heart': '❤️', 'cold_sweat': '😰' } |\n| emojiTail | 常用表情提示 | - |\n| emojiPath | 表情图片地址 | `https:\u002F\u002Funpkg.com\u002Fvditor@${VDITOR_VERSION}\u002Fdist\u002Fimages\u002Femoji` |\n| extend: IHintExtend[] | 对 @\u002F话题等关键字自动补全的扩展 | [] |\n\n```ts\ninterface IHintData {\n  html: string;\n  value: string;\n}\n\ninterface IHintExtend {\n    key: string;\n\n    hint?(value: string): IHintData[] | Promise\u003CIHintData[]>;\n}\n```\n\n#### options.upload\n\n* 文件上传的数据结构如下。后端返回的数据结构不一致时，可使用 `format` 进行转换。\n\n```js\n\u002F\u002F POST data\nxhr.send(formData);  \u002F\u002F formData = FormData.append(\"file[]\", File)\n\u002F\u002F return data\n{\n \"msg\": \"\",\n \"code\": 0,\n \"data\": {\n \"errFiles\": ['filename', 'filename2'],\n \"succMap\": {\n   \"filename3\": \"filepath3\",\n   \"filename3\": \"filepath3\"\n   }\n }\n}\n```\n\n* 为了防止站外图片失效，`linkToImgUrl` 可将剪贴板中的站外图片地址传到服务器端进行保存处理，其数据结构如下：\n\n```js\n\u002F\u002F POST data\nxhr.send(JSON.stringify({url: src})); \u002F\u002F src 为站外图片地址\n\u002F\u002F return data\n{\n msg: '',\n code: 0,\n data : {\n   originalURL: '',\n   url: ''\n }\n}\n```\n\n* `success`，`format`，`error` 不会同时触发，具体调用情况如下：\n\n```js\nif (xhr.status === 200) {\n    if (vditor.options.upload.success) {\n        vditor.options.upload.success(editorElement, xhr.responseText);\n    } else {\n        let responseText = xhr.responseText;\n        if (vditor.options.upload.format) {\n            responseText = vditor.options.upload.format(files as File [], xhr.responseText);\n        }\n        genUploadedLabel(responseText, vditor);\n    }\n} else {\n    if (vditor.options.upload.error) {\n        vditor.options.upload.error(xhr.responseText);\n    } else {\n        vditor.tip.show(xhr.responseText);\n    }\n}\n```\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| xhr | 上传时使用的 XMLHttpRequest | - |\n| url | 上传 url，为空则不会触发上传相关事件 | '' |\n| max | 上传文件最大 Byte | 10 * 1024 * 1024 |\n| linkToImgUrl | 剪切板中包含图片地址时，使用此 url 重新上传 | '' |\n| linkToImgCallback(responseText: string) | 图片地址上传回调 | - |\n| linkToImgFormat(responseText: string): string | 对图片地址上传的返回值进行格式化 | - |\n| success(editor: HTMLPreElement, msg: string) | 上传成功回调 | - |\n| error(msg: string) | 上传失败回调 | - |\n| token | CORS 上传验证，头为 X-Upload-Token | - |\n| withCredentials | 跨站点访问控制 | false |\n| headers | 请求头设置 | - |\n| filename(name: string): string | 文件名安全处理 | name => name.replace(\u002F\\W\u002Fg, '') |\n| accept | 文件上传类型，同[input accept](https:\u002F\u002Fwww.w3schools.com\u002Ftags\u002Fatt_input_accept.asp) | - |\n| validate(files: File[]) => string \\| boolean | 校验，成功时返回 true 否则返回错误信息 | - |\n| handler(files: File[]) => string \\| null \\| Promise\u003Cstring> \\| Promise\u003Cnull> | 自定义上传，当发生错误时返回错误信息 | - |\n| format(files: File[], responseText: string): string | 对服务端返回的数据进行转换，以满足内置的数据结构 | - |\n| file(files: File[]): File[] \\| Promise\u003CFile[]> | 将上传的文件处理后再返回 | - |\n| cancel(files: File[]): void | 取消正在上传的文件 | - |\n| setHeaders(): { [key: string]: string } | 上传前使用返回值设置头 | - |\n| extraData: { [key: string]: string \\| Blob } | 为 FormData 添加额外的参数 | - |\n| multiple | 上传文件是否为多个 | true |\n| fieldName | 上传字段名称 | 'file[]' |\n| renderLinkDest?(vditor: IVditor, node: ILuteNode, entering: boolean): [string, number] | 处理剪贴板中的图片地址 | '' |\n\n#### options.resize\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| enable | 是否支持大小拖拽 | false |\n| position | 拖拽栏位置：'top', 'bottom' | 'bottom' |\n| after(height: number) | 拖拽结束的回调 | - |\n\n#### options.classes\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| preview | 预览元素上的 className | '' |\n\n#### options.fullscreen\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| index | 全屏层级 | 90 |\n\n#### options.outline\n\n|   | 说明 | 默认值 |\n| - | - | - |\n| enable | 初始化是否展现大纲 | false |\n| position | 大纲位置：'left', 'right' | 'left' |\n\n#### methods\n\n|   | 说明 |\n| - | - |\n| exportJSON(markdown: string) | 根据 Markdown 获取对应 JSON |\n| getValue() | 获取 Markdown 内容 |\n| getHTML() | 获取 HTML 内容 |\n| insertValue(value: string, render = true) | 在焦点处插入内容，并默认进行 Markdown 渲染 |\n| focus() | 聚焦到编辑器 |\n| blur() | 让编辑器失焦 |\n| disabled() | 禁用编辑器 |\n| enable() | 解除编辑器禁用 |\n| getSelection(): string | 返回选中的字符串 |\n| setValue(markdown: string, clearStack = false) | 设置编辑器内容且选中清空历史栈 |\n| clearStack() | 清空撤销和重做记录栈|\n| renderPreview(value?: string) | 设置预览区域内容 |\n| getCursorPosition():{top: number, left: number} | 获取焦点位置 |\n| deleteValue() | 删除选中内容 |\n| updateValue(value: string) | 更新选中内容 |\n| isUploading() | 上传是否还在进行中 |\n| clearCache() | 清除缓存 |\n| disabledCache() | 禁用缓存 |\n| enableCache() | 启用缓存 |\n| html2md(value: string) | HTML 转 md |\n| tip(text: string, time: number) | 消息提示。time 为 0 将一直显示 |\n| setPreviewMode(mode: \"both\" \\| \"editor\") | 设置预览模式 |\n| setTheme(theme: \"dark\" \\| \"classic\", contentTheme?: string, codeTheme?: string, contentThemePath?: string) | 设置主题、内容主题及代码块风格 |\n| getCurrentMode(): string | 获取编辑器当前编辑模式 |\n| destroy() | 销毁编辑器 |\n| getCommentIds(): {id: string, top: number}[] | 获取所有评论 |\n| hlCommentIds(ids: string[]) | 高亮评论 |\n| unHlCommentIds(ids: string[]) | 取消评论高亮 |\n| removeCommentIds(removeIds: string[]) | 删除评论 |\n| updateToolbarConfig(config: {hide?: boolean, pin?: boolean}) | 更新工具栏配置 |\n| insertEmptyBlock(position: InsertPosition) | 插入空快 |\n\n#### static methods\n\n* 不需要进行编辑操作时，仅需引入 [`method.min.js`](https:\u002F\u002Funpkg.com\u002Fvditor\u002Fdist\u002F) 后如下直接调用\n\n```js\nVditor.mermaidRender(document)\n```\n\n```js\nimport VditorPreview from 'vditor\u002Fdist\u002Fmethod.min'\nVditorPreview.mermaidRender(document)\n```\n\n* 需要对页面中的 Markdown 进行渲染时可直接调用 `preview` 方法，参数如下：\n\n```ts\npreviewElement: HTMLDivElement,   \u002F\u002F 使用该元素进行渲染\nmarkdown: string,  \u002F\u002F 需要渲染的 markdown 原文\noptions?: IPreviewOptions {\n  mode: \"dark\" | \"light\";\n  anchor?: number;  \u002F\u002F 为标题添加锚点 0：不渲染；1：渲染于标题前；2：渲染于标题后，默认 0\n  customEmoji?: { [key: string]: string };    \u002F\u002F 自定义 emoji，默认为 {}\n  lang?: (keyof II18nLang);    \u002F\u002F 语言，默认为 'zh_CN'\n  emojiPath?: string;    \u002F\u002F 表情图片路径\n  hljs?: IHljs; \u002F\u002F 参见 options.preview.hljs\n  speech?: {  \u002F\u002F 对选中后的内容进行阅读\n    enable?: boolean,\n  };\n  math?: IMath; \u002F\u002F 数学公式渲染配置\n  cdn?: string; \u002F\u002F 自建 CDN 地址\n  transform?(html: string): string; \u002F\u002F 在渲染前进行的回调方法\n  after?(); \u002F\u002F 渲染完成后的回调\n  lazyLoadImage?: string; \u002F\u002F 设置为 Loading 图片地址后将启用图片的懒加载\n  markdown?: options.preview.markdown;\n  theme?: options.preview.theme;\n  render?: options.preview.render;\n  renderers?: ILuteRender; \u002F\u002F 自定义渲染 https:\u002F\u002Fld246.com\u002Farticle\u002F1588412297062\n}\n```\n\n* ⚠️ `method.min.js`  和 `index.min.js` 不可同时引入\n\n|   | 说明 |\n| - | - |\n| previewImage(oldImgElement: HTMLImageElement, lang: keyof II18n = \"zh_CN\", theme = \"classic\") | 点击图片预览 |\n| mermaidRender(element: HTMLElement, cdn = options.cdn, theme = options.theme) | 流程图\u002F时序图\u002F甘特图 |\n| SMILESRender(element: HTMLElement, cdn = options.cdn, theme = options.theme) | 化学物质结构 |\n| markmapRender(element: HTMLElement, cdn = options.cdn) | markdown 思维导图 |\n| flowchartRender(element: HTMLElement, cdn = options.cdn) | flowchart 渲染 |\n| codeRender(element: HTMLElement, option?: IHljs) | 为 element 中的代码块添加复制按钮 |\n| chartRender(element: (HTMLElement \\| Document) = document, cdn = options.cdn, theme = options.theme) | 图表渲染 |\n| mindmapRender(element: (HTMLElement \\| Document) = document, cdn = options.cdn, theme = options.theme) | 脑图渲染 |\n| plantumlRender(element: (HTMLElement \\| Document) = document, cdn = options.cdn) | plantuml 渲染 |\n| abcRender(element: (HTMLElement \\| Document) = document, cdn = options.cdn) | 五线谱渲染 |\n| md2html(mdText: string, options?: IPreviewOptions): Promise\\\u003Cstring> | Markdown 文本转换为 HTML，该方法需使用[异步编程](https:\u002F\u002Fld246.com\u002Farticle\u002F1546828434083?r=Vanessa#toc_h3_1) |\n| preview(previewElement: HTMLDivElement, markdown: string, options?: IPreviewOptions) | 页面 Markdown 文章渲染 |\n| highlightRender(hljsOption?: IHljs, element?: HTMLElement \\| Document, cdn = options.cdn) | 为 element 中的代码块进行高亮渲染 |\n| mediaRender(element: HTMLElement) | 为[特定链接](https:\u002F\u002Fld246.com\u002Farticle\u002F1589813914768)分别渲染为视频、音频、嵌入的 iframe |\n| mathRender(element: HTMLElement, options?: {cdn?: string, math?: IMath}) | 对数学公式进行渲染 |\n| speechRender(element: HTMLElement, lang?: (keyof II18nLang)) | 对选中的文字进行阅读 |\n| graphvizRender(element: HTMLElement, cdn?: string) | 对 graphviz 进行渲染 |\n| outlineRender(contentElement: HTMLElement, targetElement: Element) | 对大纲进行渲染 |\n| lazyLoadImageRender(element: (HTMLElement \\| Document) = document) | 对启用懒加载的图片进行渲染 |\n| setCodeTheme(codeTheme: string, cdn = options.cdn) | 设置代码主题，codeTheme 参见 options.preview.hljs.style |\n| setContentTheme(contentTheme: string, path: string) | 设置内容主题，contentTheme 参见 options.preview.theme.list |\n\n## 🏗 开发文档\n\n### 原理相关\n\n* [关于所见即所得 Markdown 编辑器的讨论](https:\u002F\u002Fld246.com\u002Farticle\u002F1579414663700)\n* [Vditor 实现 Markdown 所见即所得](https:\u002F\u002Fld246.com\u002Farticle\u002F1577370404903)\n* [Lute 一款对中文语境优化的 Markdown 引擎，支持 Go 和 JavaScript](https:\u002F\u002Fld246.com\u002Farticle\u002F1567047822949)\n\n### 环境\n\n1. 安装 [node](https:\u002F\u002Fnodejs.org\u002F) LTS 版本\n2. [下载](https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Farchive\u002Fmaster.zip)最新代码并解压\n3. 根目录运行 `npm install`\n4. `npm run start` 启动本地服务器，打开 http:\u002F\u002Flocalhost:9000\n5. 修改代码\n6. `npm run build` 打包代码到 dist 目录\n\n### CDN 切换\n\n由于使用了按需加载的机制，默认 CDN 为 [https:\u002F\u002Funpkg.com\u002Fvditor](https:\u002F\u002Funpkg.com\u002Fvditor)@版本号\n\n如果代码有修改或需要使用自建 CDN 的话，可按以下步骤进行操作：\n\n* 初始化时，需对 `options` 及 `IPreviewOptions` 中的 `cdn`，`emojiPath`, `themes` 进行配置\n* `highlightRender`，`mathRender`，`abcRender`，`chartRender`，`mermaidRender`，`SMILESRender`，`markmapRender`，`flowchartRender`，`mindmapRender`，`plantumlRender`，`graphvizRender`，`setCodeTheme`，`setContentTheme` 方法中需添加 cdn 参数\n* 将 build 成功的 dist 目录或 [jsDelivr](https:\u002F\u002Fwww.jsdelivr.com\u002Fpackage\u002Fnpm\u002Fvditor?path=dist) 中的 dist 目录拷贝至正确的位置\n\n### 升级\n\n版本升级时请**仔细阅读** [CHANGELOG](https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fblob\u002Fmaster\u002FCHANGELOG.md) 中的**升级**部分\n\n## Ⓜ️ Markdown 使用指南\n\n* [基础语法](https:\u002F\u002Fld246.com\u002Farticle\u002F1583129520165)\n* [扩展语法](https:\u002F\u002Fld246.com\u002Farticle\u002F1583305480675)\n* [速查手册](https:\u002F\u002Fld246.com\u002Farticle\u002F1583308420519)\n\n## 🏘️ 社区\n\n* [官网](https:\u002F\u002Fb3log.org\u002Fvditor)\n* [讨论区](https:\u002F\u002Fld246.com\u002Ftag\u002Fvditor)\n* [报告问题](https:\u002F\u002Fgithub.com\u002FVanessa219\u002Fvditor\u002Fissues\u002Fnew)\n\n## 📄 授权\n\nVditor 使用 [MIT](https:\u002F\u002Fopensource.org\u002Flicenses\u002FMIT) 开源协议。\n\n## 🙏 鸣谢\n\n* [Lute](https:\u002F\u002Fgithub.com\u002F88250\u002Flute)：🎼 一款结构化的 Markdown 引擎，支持 Go 和 JavaScript\n* [highlight.js](https:\u002F\u002Fgithub.com\u002Fhighlightjs\u002Fhighlight.js)：JavaScript syntax highlighter\n* [mermaid](https:\u002F\u002Fgithub.com\u002Fknsv\u002Fmermaid)：Generation of diagram and flowchart from text in a similar manner as Markdown\n* [incubator-echarts](https:\u002F\u002Fgithub.com\u002Fapache\u002Fincubator-echarts)：A powerful, interactive charting and visualization library for browser\n* [abcjs](https:\u002F\u002Fgithub.com\u002Fpaulrosen\u002Fabcjs)：JavaScript library for rendering standard music notation in a browser\n\n## 📽️ 历史\n\n我们在开发 [Sym](https:\u002F\u002Fgithub.com\u002F88250\u002Fsymphony) 的初期是直接使用 WYSIWYG 富文本编辑器的。那时候基于 HTML 的编辑器非常流行，项目中引用起来也很方便，也符合用户当时的使用习惯。\n\n后来，Markdown 的崛起逐步改变了大家的排版方式。再加上我们其他几个项目都是面向程序员用户的，所以迁移到 md 上也是大势所趋。我们选择了 [CodeMirror](https:\u002F\u002Fgithub.com\u002Fcodemirror\u002FCodeMirror)，这是一款优秀的编辑器，它对开发者提供了丰富的编程接口，对各种浏览器的兼容性也比较好。\n\n再后来，随着我们项目业务需求方面的沉淀，使用 CodeMirror 有时候会感到比较“笨重”。比如要实现 @自动完成用户名列表、插入 Emoji、上传文件等就需要比较深入的二次开发，而这些业务需求恰恰是很多项目场景共有且必备的。\n\n终于，我们决定开始在 Sym 中自己实现编辑器。随着几个版本的迭代，Sym 的编辑器也日趋成熟。在我们运营的社区[链滴](https:\u002F\u002Fld246.com)上陆续有人问我们是否能将编辑器单独抽离出来提供给大家使用。与此同时，我们的前端主程 [V](https:\u002F\u002Fld246.com\u002Fmember\u002FVanessa) 同学对于维护分散在各个项目中的编辑器也感到有点力不从心，外加对 TypeScript 的好感，所以就决定使用 ts 来实现一个全新的浏览器端 md 编辑器。\n\n于是，Vditor 就这样诞生了。\n","Vditor 是一款浏览器端的 Markdown 编辑器，支持所见即所得（富文本）、即时渲染（类似 Typora）和分屏预览模式。其核心功能包括实时预览、多种编辑模式切换以及对 CommonMark 和 GFM 标准的支持，使用 TypeScript 开发，确保了代码质量和性能。此外，Vditor 兼容原生 JavaScript 以及 Vue、React 等主流前端框架，便于集成到各种 Web 应用中。适用于需要高效编写和展示 Markdown 文档的各种场景，如博客平台、文档系统或任何希望提供强大 Markdown 编辑体验的应用程序。",2,"2026-06-11 03:26:09","top_topic"]