跳到正文
QuireKit MSFE
开发者文档
v0.0.0 · 实验版本

MD Editor 产品组件

直接接入使用 QuireKit Prose 样式的 Markdown 文档编辑器。

先体验完整文档

打开 MD Editor 独立示例。同一份文档可以编辑、查看源码、只读浏览, 也可以通过 MdProse 查看静态阅读快照。示例包含嵌套提示块、折叠块、任务、列表、 引用、代码、表格、公式、流程图、思维导图、定义列表和脚注。模式切换保留编辑实例、选区与撤销历史。

@quirekit/md-editor 组合 MSFE 能力与 QuireKit 公共组件。源码、事务与解析仍属于 MSFE;正文外观由 Prose 定义。需要自己组合整个界面时,继续使用 Vue 接入。

先选保存模型,再选编辑器

需求选择与边界
README、技术文章、Git 审阅、跨工具 MarkdownMD Editor 以源码为权威;文档和源码视图共享文本与历史
富文档、可视块、更丰富的表格和格式Block Editor 使用 PM 结构文档与产品界面;按当前已交付能力接入,导出 Markdown 是有损风险的转换
自定义 schema、节点视图、已有 Tiptap 生态原生 Tiptap 提供框架与扩展,宿主组合 UI 和服务;结构能力由 schema 与扩展决定

GFM 表格支持粗体、斜体、删除线、链接和行内代码;不支持嵌套表格、列表、代码块、多个段落、 合并单元格和任意列宽。多种行内样式可以嵌套,但标记前后的标点与文字决定实际解析。 行内代码内容按字面解释。不要把当前尚未实现的局部格式拆分,混同为 Markdown 禁止样式叠加。

可视格式命令共用 语法保真规划:保留既有样式并确认目标样式成立, 否则拒绝并保留原文;不会偷偷添加空格。单元格内允许行内格式,禁用标题、列表和块插入。 源码输入保持自由,不自动修复未完成或自定义语法。未知结构仍走源码回退。 扩展语法需要对应阅读器;仅保存 .md 不会自动包含评论、协作等外部状态。

完整对照与可编辑例子见 固定默认文档。规范依据: GFM 表格、 CommonMark 强调、 Tiptap schema。

四种视图

桌面的代码语言使用紧凑下拉列表,可通过方向键和标签前缀选择;文字样式使用按钮旁的 选择面板。窄屏代码语言保留可搜索的底部面板,文字样式整合到底部文字格式任务。 未知的现有语言仍会列出,选择“纯文本”会清除围栏的语言标记。 代码语言选择立即写回,可一次撤销;取消选择保留原文。文字格式按钮也立即应用, 关闭面板不会撤销已应用的设置。 示例页在窄屏使用同样的面板切换文档视图,回到编辑时保留选区与撤销历史。

窄于 768px 时,正文使用紧凑留白,底部工具栏提供撤销、重做、插入、文字样式、列表和 导入/导出。底栏使用公共 Toolbar 移动模式,不显示 Tooltip;当前表格动作只有放不下时才 收进“更多”,点击打开底部动作面板。插入目录先展示图片、链接、表格等常用内容,再展示 图表、结构和文字格式;搜索和参数表单提供输入提示。文字格式提供“全选、选中当前块”,后者选择光标所在的 最近完整 Markdown 块。空行与不完整围栏不提供块选择,选择动作不写源码或进入历史。 打开设置面板后,已聚焦过的正文保留静止光标或范围选区。 源文档替换、只读/locked 会清理或隐藏静止光标。移动 live 的键盘关闭或窗口失焦保留 被禁用的自绘端点;点击已有选区只切换操作菜单,不重新聚焦或唤起键盘。

选区菜单使用公共 Toolbar,提供复制、剪切、粘贴和全选,执行后自动收起。 粘贴读取系统剪贴板中的纯文本;浏览器不允许读取或使用局域网 HTTP 时,会打开粘贴面板, 可在“粘贴内容”输入框中调用系统粘贴,再点击“粘贴”替换原选区。取消或空内容不改动正文。 粘贴和剪切均可一次撤销;等待读取期间若选区或文档已改变,旧请求会取消。

窄屏触摸设备聚焦可编辑正文后显示公共 SelectionHandles 光标手柄: 拖动圆点移动光标;长按正文或圆点先保留插入点,实际拖动才扩大选区,不预选词语。松手后可拖动任一端点, 跨行或反向调整时保持端点身份。选区移动不增加文本撤销记录。移动 live 模式的正文 退出原生可编辑状态,由独立输入代理和共享 @quirekit/ime 接收键盘与中文组合输入, 光标和选区由产品绘制,避免系统菜单、光标和选区重叠。预编辑文字临时显示在正文中, 确认只提交一笔 CodeMirror 事务并可一次撤销;组合输入时光标继续显示,但手柄暂不可拖动。 源码、桌面、只读和独立嵌入编辑器保留各自的输入方式。文档、选区、命令和历史始终由 MSFE/CM 持有。 隐藏语法和零高度间隙只接受两侧的可见光标位置。点击或拖动到表格分隔线时,光标会 落到相邻单元格的文字插入点,空单元格仍可输入;边界处的中文预编辑保留在对应单元格内。 拖选靠近可用区域边缘时自动滚动, 松手立即停止。键盘缩小可用区域后,光标与圆点一起滚到工具栏上方;已可见的连续输入 不重复滚动,用户手动滚动也不会被拉回原位置。 工具栏消费当前可视视口,键盘遮挡时不重复加入底部安全区;示例编辑器 route 禁用 pinch, 原生输入至少使用 16px 字体以减少聚焦缩放。真实 iOS 的键盘附件条和候选窗仍需设备验证。

MD Editor 有四种视图,编辑和显示的都是同一份 Markdown 原文,中间不经过任何格式转换:

视图设置行为
文档视图(默认)view="document"点击后仍隐藏已识别的标记,直接编辑正文;表格保持单元格,代码保留工具栏,容器保持连续结构
实时预览view="preview"段落或列表项的标记一起显露;活动表格显示结构源码、所选单元格显示行内标记,容器首尾围栏对齐
源码视图view="source"查看和编辑全部原文
阅读视图view="reading"用组件渲染当前文档,不可编辑;编辑器保持挂载,切回后选区和历史不变

只读不是单独的视图,而是叠加在前三种视图上的 readOnly:只停止输入,链接、折叠和复制照常可用,切换视图时保持不变。 四种视图共用一份 Markdown、选区、历史和 Prose 样式。示例页列出全部四种视图和只读开关,宿主也可以只提供其中几种。

vue

无框架实例只包含三种可编辑视图(阅读视图是 Vue 组件里的渲染),通过公开方法切换:

ts

切换不修改源码、不进入撤销栈;拖选或组合输入期间延迟应用,避免改变正在输入的 DOM。 已隐藏的标记参与原生原子导航,列表回车继续列表,行首退格可以移除列表标记。 未知或不完整的语法仍保留可编辑源码;自定义投影应遵循 源码显露合同。 这不意味着任意 Markdown 插件自动拥有可编辑的文档 UI;复杂节点仍需声明投影、命令和回退。

实时预览按语义范围显露:跨行段落一起显示粗体、斜体、链接和行内代码的原始拼写; 任务项的列表前缀与 [x] / [ ] 同步显示,同级其他项保持阅读呈现。嵌套列表分别判断 各层列表项;容器里的段落独立判断,编辑一段不会显露其他段落的行内标记。 表格进入源码呈现时显示所有竖线和分隔行,但只显露所选单元格的行内标记。 输入法预编辑沿用这些范围,前后无关的标题、表格、代码、公式和图表继续保留呈现。

回车与块后输入

光标所在块会显示浅灰圆角背景,帮助识别当前段落、列表或引用的边界。容器内的正文按内部块 显示提示;这个提示不改源码、不增加间距,也不拦截鼠标。源码视图、只读和 阅读视图不显示它。

两种编辑体验都保留新建空段落的高度。被压缩的块间结构分隔行不接受正文光标,导航会落到 相邻真实内容;源码视图可以在这些行输入,切回后按新语法正常显示正文。 正文、ATX 标题及嵌套 容器里的段落按 Enter 会插入 Markdown 段落分隔,中间输入会拆分段落;空文档、连续回车和退出空列表后 都可以直接继续输入。块间纯排版分隔仍由 Prose 控制,编辑动作不重新序列化整篇文档。

位置或按键行为
正文、ATX 标题里的 Enter从光标处分段;末尾开始新段落,标题后恢复正文
列表、引用里的 Enter续写当前标记;空列表项或空引用行直接退出一层,退出到正文时保留段落分隔
代码正文里的 Enter在当前代码块内换行
文档视图的表格单元格里 Enter在当前行后新增一行,保留列数与对齐;Tab / Shift+Tab 继续切换单元格
⌘+Enter / Ctrl+Enter在当前代码块、容器、表格、列表或引用后开始段落;嵌套块保留外层引用和列表缩进
正文里的 Shift+Enter插入两个尾随空格加换行的 Markdown 硬换行;保留外层列表缩进与引用前缀,不插入 <br>

这些换段规则由 document 与 markdown 共用;纯源码视图保持原生源码输入。 引用末尾第一次回车立即显示引用内的可编辑空行,再按一次退出当前引用层级;嵌套引用逐层退出。 代码正文保留字面换行,实时预览中的表格保留源码操作;Setext 标题末尾在下划线之后换段。 换段可以单独撤销,只读与输入法组合状态继续由同一编辑实例管理。

光标与编辑边界

文档模式下,正文光标只能进入可编辑内容。功能插件声明完整结构范围和内部正文范围, 公共运行时据此处理方向键、Home/End、点击、拖选、删除和跨边界替换。所有范围使用 Markdown 源码偏移;隐藏标记和压缩空行不会产生第二套行号或文档。

默认行内代码保留样式外侧与内侧两个插入位置,加粗、斜体、高亮等直接进入内容。 代码围栏和语言信息受保护,代码正文可编辑;部分跨块删除保留外壳,完整选中块可以 整体删除。属性面板、图表等已投影的块组件按整体对象处理,边缘删除先选中整体。 正常回车、显式换行与退出块继续使用 addBlockInput(),见 块级回车 API。

覆盖产品默认规则

editingBoundaries 按解析树节点名称覆盖规则。下面把行内代码改为直接进入内容; 将 navigation 改为 split 可以恢复默认的内外两侧停留。宿主须先准备 #editor 容器。

ts

nodes 是解析树名称,from/to 覆盖反引号及文字,contentFrom/contentTo 只覆盖代码 内容;deletion: 'unwrap' 使边缘删除成对移除标记。规则查询不提交事务,也不改变 光标像素坐标。宿主离开时调用 editor.destroy() 释放实例。

Vue 沿用同一个 inlineCodeRule,通过组件属性传入:

vue

规则在创建/挂载时读取;改变规则集合需要重建实例,并由宿主保留需要的文档。 editingBoundaries: [] 表示没有宿主覆盖,内置规则继续生效。同一节点采用最高优先级 的第一条规则;该规则返回 null 表示退出该节点的语法边界处理,不再回退到默认规则。 已投影组件的整体对象保护独立保留。

在功能插件中声明

属于功能自身的规则放在 addEditingBoundaries()。以已有的行内代码语法为例,沿用 上面的规则声明一个扩展;宿主可以通过 extensions: [InlineCodeBoundaries] 安装它:

ts

插件接入时使用此扩展承担规则,产品的 editingBoundaries 留给业务宿主覆盖。 已有插件可在自身 hook 中返回规则,或通过 .extend() 与父 hook 组合;同一节点的覆盖 规则应排在父规则前。该 hook 只描述边界,新增语法仍需由插件注册解析和投影。

when 默认是 hidden,只在整体隐藏语法的呈现中启用;prose 可在 实时预览 呈现中查询,规则应使用 isSourceRevealed(state, node) 判断具体结构是否已经显露。 源码视图关闭边界约束;在源码分隔行输入文字后,切回文档模式会按新语法把它作为正文。

当前 navigation: 'native' 会退出整条语法边界规则;若希望保留导航约束、将正文修改 交给原生处理,应使用 deletion: 'native'。旧 inlineBoundaries 通过同一个运行时兼容, 只替换原行内规则列表。六类边界、完整字段与高级 CM 接入见 编辑边界 API。

标题折叠

有正文的标题在左侧正文区域外提供折叠箭头,不挤占标题宽度。展开时悬停或键盘聚焦才显示, 收起后一直显示;触摸设备保留入口。点击后保留标题,收起到下一个同级或更高级标题之前的内容; 再次展开会保留子标题各自的折叠选择。支持 ATX 和 Setext 标题,容器、引用及列表项内的标题 以所在容器为边界。

文档视图、实时预览、只读与源码视图共用同一份折叠状态,折叠不改 Markdown,也不占用 文本撤销记录。查找定位到隐藏正文时会自动展开;改变标题层级导致旧范围失效时也会展开。 折叠选择不写入文件,刷新或替换文档后重置;Prose 静态阅读继续展示完整内容。

该能力归 @quirekit/msfe-heading,基础 MSFE 接入可通过 Heading.configure({ folding: false }) 关闭标题控件及章节校验,原有 CodeMirror 源码折叠仍可使用。宿主可用 controls 和 toggleLabel 接入自己的组件与文案;MD Editor 默认使用公共 QuireIconButton 和统一图标。

块手柄与菜单

将鼠标移到块上,左侧会显示灰底描边的块类型与拖柄按钮,位于标题折叠箭头的外侧。点击打开菜单,或在正文中按 ⌘+Alt+B / Ctrl+Alt+B。菜单使用公共 QuireKit 组件,可转换正文、标题和列表, 在上下插入内容,以及复制 Markdown、剪切、创建副本和删除。转换区只展示当前块可以执行的选项: 列表显示列表类型转换,代码、表格和公式等复杂块隐藏转换区,避免丢失结构。 窄屏触摸设备隐藏桌面悬停拖柄,插入入口保留在工具栏中;已经打开的块菜单继续保留锚点。

上下插入菜单按功能分组,在公共 QuireScrollArea 内滚动,包含当前安装的标题、Markdown 块、 公式、流程图、思维导图、白板、文本绘图,以及日期、表情和宿主提供的联系人。 图片、链接、公式和图表等先打开参数编辑器,确认后在原块前后一次插入;取消不会留下空块。 期间原块被改写、文档被替换或权限变为只读时,过时提交会被拒绝。

“流程图”“思维导图”和“白板”分别打开共享 Flow Editor、Mind Editor 和 Whiteboard Editor。 “文本绘图”打开共享源码绘图工作台,可选择 Mermaid、PlantUML 或 Graphviz / DOT。 Mermaid 的流程图、思维导图、时序图等在文本绘图里选择模板编写,保存为 Mermaid 代码块; 可拖拽编辑的流程图和思维导图保留各自的可编辑数据。 工具栏、空行加号和 / 菜单共用这些入口,图表分组放在段落列表之前。

默认示例文档直接包含项目交付流程、项目计划思维导图和灵感白板,保留完整可编辑数据及 从同一数据保存的 PNG 预览;双击即可继续编辑。单击会整体选中图形并浮出操作栏, 可编辑、预览、下载 PNG、复制、剪切或删除,白板还可重命名;选中后按 Delete 删除、Esc 取消。 预览会把文档里的图片和这几类图形按顺序放进同一图集,可左右切换。文本绘图部分还包含 PlantUML 时序图和 Graphviz / DOT 交付图,与公式一样单击整体选中、双击打开编辑;预览与下载 SVG 也在操作栏里。切换到 阅读视图可查看同一份内容。

光标进入或鼠标悬停可编辑空行时,左侧显示灰底描边的“+”,点击直接打开同一插入目录。 选择内容后替换该空行并保留必要的段落分隔,一次撤销恢复原文;取消菜单或参数编辑不改变源码。 代码、公式、列表内部的空白不作为独立插入位置;已声明子流的容器可在其空行内插入。

空段落中输入 / 也可打开同一目录,继续输入中文名称、英文别名或拼音首字母搜索, 例如 /表格、/table、/bg 或 /h2。上下方向键选择、Enter 插入,Esc 关闭并保留输入的文字。 图片、公式等复用同一个参数编辑器,取消保留 /查询,确认后一次撤销可恢复它。 菜单保留正文输入焦点,支持中文输入;普通正文、URL、代码、引用和列表内部不触发。 此入口独立于块拖柄,默认开启,可通过 :slash-menu="false" 动态关闭。

拖动手柄时显示原块摘要与插入线,松手才移动源码;一次撤销恢复整个操作。列表、引用、代码、 表格、公式与容器整体移动,容器内部的直接子块可在同一容器中排序。当前不做跨容器移动或 列表内部逐项拖动;会破坏外层围栏的插入不可用。Escape 或失焦取消拖动,源码更新会关闭旧菜单。 源码视图、只读和 阅读视图不显示操作手柄。行内公式直接点击公式编辑,不再附带铅笔按钮。

Vue 组件默认开启,可在挂载时用 :block-controls="false" 关闭。自建界面可使用 @quirekit/msfe-core 的 createSourceBlockControls,让核心提供当前块、视口几何、拖动状态及 版本化命令目标;宿主负责用自己的组件展示。自定义嵌套语法通过 sourceBlockScopes 声明子流。 空行通过可选的 insertionChange 和 openInsertionMenu 回调提供 SourceInsertionControls; sourceBlankLineAt 查询当前位置,insertAtSourceBlankLine 负责受保护的空行插入,不构造虚假块节点。 rect 是整块边界,firstLine 是首个可见原生文本行的矩形,可用于让控件对齐换行标题的首行; 不含原生文本行的块组件返回 null,宿主可退回块顶部定位。 见 块控制协议 与 源码块命令。

每个 MdEditor 有独立的文档浮层,容纳块控件、块菜单、提及及工具栏插入面板。后代组件可从 @quirekit/md-editor/vue 调用 useMdOverlayTarget(),将返回的只读 ref 传给公共 Menu 的 portalTarget;子菜单自动继承同一目标。Menu 仍负责定位、视口避让与关闭,模态编辑器继续使用 公共 Dialog。该接口只提供挂载容器,不负责块命令或右键菜单的业务行为。

安装与宿主准备

当前包通过工作区或本地打包产物使用,尚未承诺公共 npm 稳定发布。

sh

沿用应用的 QuireKit 主题、图标 Provider 和 UnoCSS / 独立样式入口。产品包没有第二套 颜色或正文 CSS。配置方法见 UI 与主题。SSR 应用应在客户端挂载 MdEditor,例如在 Nuxt 的 ClientOnly 中使用。

产品打包时另有 @quirekit/md-editor/styles.css,只负责工具栏和文档区域的布局,需显式 引入。正文的字体、间距和块外观仍来自公共 Prose 样式。

编辑底层使用源码维护的 @quirekit/cm-* 与 @quirekit/lezer-markdown。相邻块间距的 高度测量、旧视图清理与语法复用观察随包构建交付,无需额外安装 CodeMirror/Lezer 补丁。 每个包的 UPSTREAM.json 记录上游版本、commit 与本地差异,原始 MIT 许可随包保留。 原生 CodeMirror 扩展也必须从同一组 @quirekit/cm-* 导入;依赖官方 @codemirror/* 的第三方扩展需适配后使用,避免在同一编辑器混入两套 State、View 或 Facet。

Mermaid 使用 mermaid@12.1.0 与 patches/mermaid@12.1.0.patch,修复纯 SVG 模式下圆形等思维导图节点文字向右偏移的问题。编辑、阅读和 Word 图片导出共用此修复。 独立打包时仍需保留该 Mermaid 补丁;它针对默认 ESM 入口,不适用于独立浏览器脚本。

挂载、编辑与保存

vue

markdown 只作为挂载时的初始值,不是双向绑定。change 发出原始 MsfeChangeEvent 增量事件,不在每次输入后复制全文。换文档使用公开实例的 replaceDocument(); 版本化外部更新使用 applyChanges()。完整规则见 读取与保存。

错误提示与原文保留

MdEditor 用公共 QuireAlert 显示创建或运行错误,提示文案跟随 locale。 创建失败时不会展示空白编辑器,而是通过 QuireProseSource 展示可复制的初始 Markdown。 已经创建的实例遇到扩展或监听器错误时保留当前文档、选区与撤销历史;关闭提示不会重建实例。 请先保存原文,再由应用决定是否在修正配置后重新挂载。

通过 @error="handleEditorError" 接收原始异常并接入应用自己的诊断服务。这个事件的参数 为 unknown,不把内部错误代码或堆栈当作用户提示。组件处理的是编辑器创建与 MSFE onError 上报的错误,不会屏蔽应用其他位置的 Vue 错误或构建工具诊断。

配置产品能力

属性用途
locale控件语言,zh-CN 或 en;不翻译文档正文
label编辑区的可访问名称
viewdocument(默认)、preview、source 或 reading;四种视图共用一份源码与历史,可响应式更新
readOnly叠加在前三种视图上的只读;只读时仍可展开折叠块和复制
mentions静态联系人数组或可取消的异步搜索函数;提供后启用提及菜单和输入 @ 的候选面板
documentLinks宿主文档链接配置:search 为静态文档数组或可取消的异步搜索(关键词为空时可返回最近文档),提供后输入 [[ 弹出文档搜索并插入标准链接 [标题](地址),“链接”对话框里也能搜索文档;recognize 识别指向宿主文档的地址,这类链接显示为带文档图标的引用;preview 返回文档的 Markdown 摘要,悬停引用时以缩略正文预览;exportUrl 决定导出 Markdown、Word 等文件时文档链接写成的地址,例如补全为完整网址
toolbar内置工具栏:true 或 'fixed'(默认)常驻正文上方;'floating' 在桌面端选中文字时于选区上方浮出样式、行内格式与链接;false 不显示。窄屏在非 false 时都使用底部工具坞
selectionToolbar固定工具栏时,桌面端选中文字也在选区上方浮出样式、行内格式、链接与“添加评论”,默认开启;只读时只保留“添加评论”
blockControls挂载时启用块手柄、菜单与拖动排序,默认开启
slashMenu空段落中输入 / 搜索并插入内容,默认开启,可动态关闭
placeholder可编辑的空文档中显示的提示,默认「输入 / 插入内容,或直接开始写作」;传空字符串隐藏,挂载时读取
docxWord 转换器与转换策略、图片回调,如 { converter: mdDocx() };未提供或 false 时隐藏 Word 导入、导出项
exporters宿主安装的导出格式(MdExporter 列表),如 PDF、OFD;每项在“导出”菜单中增加一个条目,复用所选模板和节点转换策略
layoutembedded 为嵌入式边框;document 为全宽工具栏与居中文档
outline在 document 布局中显示跟随阅读位置的标题大纲,默认关闭;宽度足够时固定在编辑区边缘,可收起成按钮再展开,宽度不足时点按钮弹出;正文独立居中,空间不足时避让大纲和评论
outlinePosition大纲位置:start(默认,正文左侧,右侧留给评论栏)或 end(正文右侧,在评论栏之后)
features按 StarterKit 的同名选项替换或关闭功能
containers容器配置,false 关闭;types 替换完整名称列表
extras按 math、mermaid、textDiagram、footnotes、definitionList、subscript、superscript、insertedText、highlight、frontmatter 替换或关闭默认扩展;false 全部关闭
extensions额外 MSFE 扩展;不要重复安装已由产品提供的同名扩展
codeLanguages默认内置按需语言目录;传入后替换目录,[] 禁用,未注册语言保留纯文本
editingBoundaries挂载时按语法节点覆盖或新增边界规则;[] 保留功能默认策略,详见 光标与编辑边界
inlineBoundaries兼容的行内规则列表;默认代码内外分离,其他格式直接进入正文;[] 移除此列表,链接、块和组件规则仍生效

能力与语言目录在挂载时安装。切换功能集合时显式重新挂载,并由宿主保留需要的文档; view、readOnly 可直接更新。更换整套界面语言建议按 locale 设置组件 key。

行内边界配置接受 InlineBoundaryRule[],每条声明语法 nodes、开闭标记 marker 和 behavior:split 保留内外插入位置,content 跳过重叠的边界停顿,native 使对应行内规则退出公共边界处理。 默认目录 mdInlineBoundaries 可从 @quirekit/md-editor 导入后复制修改;Vue 组件与 createMdEditor 使用同一选项。文档模式隐藏标记时生效,源码揭示、拖选与组合输入保持原有行为。 该选项和底层 inlineBoundaryNavigation(rules) 现在均适配到公共编辑边界运行时;新功能优先使用 addEditingBoundaries()。 空代码块的输入占位和默认语言列表见 代码块定制。

内置工具栏直接使用公共 QuireToolbar,与 Classic 共用分组、提示、选中态、方向键导航和 窄屏滚动。正文/标题使用与 Classic 相同的带边框选择器,文字格式平铺;插入菜单分组展示, 每项复用公共图标。菜单打开时捕获可映射的源码锚点,操作回到同一份 Markdown,参与原有撤销历史。

功能实际写入与交互
正文与标题正文、六级标题,保留原始 Markdown 文本
行内格式粗体、斜体、删除线、行内代码,以及 ++下划线++、==高亮==、H~2~O、x^2^ 扩展
列表对当前段落或选中行切换项目、编号、任务列表;嵌套缩进、回车继续列表、退格退出
链接与图片对话框编辑地址、文字与标题;图片使用 QuireProseImage,不把资源内容写进文档
表格在当前行上方/下方插入、删除当前行;在当前列左侧/右侧插入、删除当前列;按列设置左/中/右/默认对齐
代码与容器代码语言、复制;提示、警告、折叠、高亮块和嵌套容器,内部正文直接编辑
公式行内 $…$ 与块级 $$…$$;复用公共公式编辑器进行结构化输入
文本绘图Mermaid、PlantUML、Graphviz/DOT 共用源码工作区;基础模板、实时预览、SVG/PNG 下载
注释与术语原子插入脚注引用和定义,引用/定义之间跳转;支持定义列表
分隔线、日期与表情--- 块、日历选择的 YYYY-MM-DD 普通日期、原始 Unicode 表情字符
提及联系人由宿主提供;写入可移植的 [@姓名](<地址>) 链接
文件Markdown、Word 共用导入预览,可替换全文或追加末尾;导出 Markdown、Word 或宿主启用的 PDF/OFD

下划线、高亮、公式、脚注和自定义容器属于扩展语法,接收 Markdown 的其他应用也需要 相应插件。GFM 表格没有合并单元格语法;本产品不会把合并、列宽、字体大小或文字颜色 伪装成标准 Markdown。云文档、评论、投票等服务也不属于这些源码命令。

document 布局用 --md-editor-toolbar-top 避开宿主固定页头,默认 0px; 工具栏吸附在宿主自己的滚动区内时,用 --md-editor-panel-top 单独指定右侧面板的顶部位置(默认同前者); --md-editor-document-width 控制正文最大宽度,默认 960px。外部工具栏可设置 :toolbar="false",经 product.editor 调用公开命令;不要直接修改内容 DOM。 宿主自己的菜单可调用实例的 openFile(mode, exporter?),打开与内置“导入 / 导出”相同的窗口: mode 为 markdownImport、wordImport、wordExport 或 formatExport(后者用 exporter 指定已安装的 导出插件,如 pdf、ofd);有其他任务打开或该项未启用时忽略。

header 插槽在正文上方、与正文同宽对齐的位置放置宿主内容,如文档标题输入框或作者信息; footer 插槽对应地放在正文下方,如点赞或评论入口。两者都随正文一起滚动,不属于可编辑文档,也不写入 Markdown。

vue

自定义代码 UI 可通过 features.codeBlock 传入 ProseCodeBlock.extend({ addNodeView() { … } }), 保留产品的 Prose 框架和源语言命令,再替换控制组件。默认公式和文本绘图的替换应放在 extras.math / extras.mermaid / extras.textDiagram,不要在 extensions 重复安装同名功能。新的图表语言 如 ECharts 则经 extensions 加入,详见 代码块、图表 与 Markdown 插件。

高亮块

高亮块是左侧带表情图标、浅色背景的正文块,适合突出一条提醒或结论。可以在空段落输入 /高亮块 (或 /glk、/callout),也可以从工具栏“插入”或块菜单的“上方插入 / 下方插入”创建。块内是普通正文, 可以继续输入、换段、放列表或嵌套其他块。

  • 点击图标打开表情面板,选中后只更换开头一行里的 emoji。
  • 打开高亮块的块菜单,选择“颜色设置”:“高亮块颜色”提供浅橙、浅红、浅绿、浅蓝、浅紫、浅灰 6 种背景, “字体颜色”可选默认或同一组颜色。每次修改是一次可撤销的源码替换。
  • 只读状态下图标仅展示,不能更换;实时预览下光标进入高亮块会显示完整源码。
markdown

属性写在开头一行的 {} 里:emoji 缺省为 📌;color 为背景色名,缺省 orange; text 为字体颜色名,缺省时不写。颜色只保存色名,编辑和阅读时映射到主题的语义颜色,深色主题自动适配; 未知的键或色名按缺省值显示,源码保持原样。不支持 ::: 容器的渲染器会把围栏行显示为普通文字, 正文按普通 Markdown 显示,内容不会丢失。

高亮块属于 containers 的默认名称 highlight。自定义 containers.types 时会替换整个名单, 需要高亮块就把 highlight 一起写上。MdProse 阅读视图、Word、PDF 与 OFD 导出使用同一份源码: 导出时图标作为首行、背景与字体颜色按固定的浅色近似值写入,重新导入 Word 时恢复原始源码。

日期、表情与联系人

“插入 → 日期”直接使用公共 QuireCalendar。浏览月份不会写入,选择一天或“今天”后才 插入 ISO 普通日期,不保存时区或时间戳。“插入 → 表情符号”使用公共 QuireEmojiPicker, 顶部提供常用快捷项,各分类在一个 QuireScrollArea 内连续滚动,使用组件库自定义滚动条。 搜索框和底部分类栏固定;点击分类定位对应区域,滚动同步高亮。支持中英文关键词搜索、 搜索结果去重和本次编辑器会话的最近选择。保存的是 Unicode 字符,组合表情 不会被拆开;所有这些插入都写到菜单打开时捕获的位置,可用一次撤销恢复。

提及必须由宿主提供候选联系人;独立示例中的小林、小陈、小许仅是本地示例数据。静态数组 按姓名、描述或 id 过滤;异步函数负责搜索,可以按业务权限限制候选结果:

vue

提供 mentions 后,可以选择“插入 → 提及”,也可以在正文的空白或开括号后输入 @。 候选面板内输入搜索词;方向键和 Enter 或点击选择联系人。输入 @ 触发时只将该字符替换为 链接;菜单入口替换原选区。取消保留已输入的 @,搜索草稿不写入文档。粘贴、邮箱地址、 代码、公式和链接内部不会触发提及。该能力在挂载时启用,运行中更换 provider 可更新候选来源; 从未配置状态改为启用时需重新挂载。

候选请求通过共享 SuggestionController 取消和关联;旧查询结果不能覆盖新查询,组合输入 期间不发送查询,失败有重试入口。目标被外部修改、换文档或变为只读时拒绝写入。每个联系人 的 id 必须稳定、label 非空、url 是通过安全校验的目的地。当前提及保存为普通 Markdown 链接,不维护隐藏的人员身份数据,不发送通知。通知、权限和人员详情页面由宿主负责。

通用 QuireEmojiPicker 可独立用于任何 QuireKit 界面,经 @quirekit/ui/vue 导入。 items / groups 替换目录,common 自定义常用快捷项顺序([] 隐藏),recent 由宿主 管理并单独显示。默认常用是精选快捷项,不按频次排序。select 发出包含精确 value 的条目。 它不依赖 MD Editor、不创建浮层、不自行存储使用记录。默认目录为常用精选集合,不代表 Unicode 表情全集,也不包含肤色选择器。

把正文文本显示为链接

工单号、需求号这类短标识可以显示为链接而不改动正文:@quirekit/msfe-link 的 textLinks() 按宿主给出的 规则识别可见区域中的文本,经 extensions 安装。保存的 Markdown 仍是原文,例如 CLOUD-15084。

ts

识别出的文本与普通链接外观一致,带 data-msfe-text-link 属性,编辑时 Cmd/Ctrl+点击、只读时单击跳转。 代码、已有链接、图片、HTML 与公式中的文本不识别,前后紧邻字母或数字的匹配也不识别;源码视图保持原样。 校验失败的候选不缓存,之后重新校验;光标仍停在末尾、尚未校验的候选等光标离开后再校验,避免逐字查询。 把同一个 options 对象传给多个编辑器即可共享校验结果。提供 card 后,悬停链接 300ms 显示卡片: 副标题、标题、最多三行说明、状态标签(tone 可选 neutral、info、success、warning、danger)、短字段和 「打开链接」入口;返回 null 不显示。再提供 fromHref(url) 把地址映射回文本,写成普通 Markdown 链接的 同一目标(如 [需求说明](https://issues.example.com/browse/CLOUD-9))也显示这张卡片。 设置 exportLinks: true 后,导出 Markdown、Word、PDF、OFD 时识别出的文本写成标准链接,其他软件中也可点击; 编辑器中的正文不变。宿主自己的导出可调用 linkifyTextLinks(editor.state) 得到同样的结果。卡片结果按文本缓存,失败的请求下次悬停重试。导出时转为真链接由宿主实现。

评论

评论由商业包 @quirekit/md-editor-comments 提供(开发与评估免费,生产使用需要授权码):把 mdComments() 传给 comments 即可打开, 并引入它的 styles.css。选中文字后用工具栏“添加评论”、浮动选区工具栏或 ⌘/Ctrl + Alt + M 留下评论, 可以回复、编辑、删除自己的消息、标记解决。选中的评论卡片上有上一条 / 下一条按钮和当前位置,工具栏“评论”菜单也能跳转或查看全部;解决一条后自动跳到下一条未解决的评论。 评论不写进 Markdown:原文保持干净,评论以标准数据交换格式由应用自己保存。

vue

宽屏的文档布局在右侧页边显示评论,卡片对齐所评论的文字;窄屏、嵌入布局和手机通过“评论” 打开列表。提供 mentions 时,评论输入框中输入 @ 也会列出联系人,保存为与正文相同的 [@名称](<链接>),并在消息的 mentions 中列出,供应用发送通知。评论正文支持粗体、斜体、 行内代码、删除线、链接和提及,其他 Markdown 按原文显示。

canComment: false 只允许查看;canResolve 决定是否显示“解决 / 重开”,未提供时不限制;自己的消息总能删除, canDelete 让管理员等角色也能删除别人的消息(不能编辑)。avatar 按作者返回头像地址,没有时显示姓名缩写。 这些设置只控制界面,权限必须由应用的服务端再次校验。只读文档也可以评论。评论不随 Word、PDF、 OFD 导出,导入 Word 时批注不会转成评论。交换格式、重新定位与协同计划见 @quirekit/msfe-comments 的类型说明。

除了划词评论,也可以对整篇文档发表全文评论:工具栏“评论”菜单或评论列表里的“添加全文评论”。 全文评论没有原文位置,回复、解决、@ 提及与划词评论相同,列在“全部评论”顶部的“全文评论”分组; 设置 documentComments: "end" 时,正文末尾还会显示全文评论区。含全文评论的数据以交换格式 v2 导出, 不含时仍是 v1。

需要和支持 CriticMarkup 的工具交换文件时, 设置 criticMarkup: true:“导出”中多出“导出 Markdown(含评论)”,把评论写成 {==原文==}{>>@作者: 评论<<};导入 Markdown 时识别这些标记并转成评论,正文中不保留标记。 编辑器里的原文和评论数据仍然分开,标记只出现在导出的文件里。也可以分别配置:

ts

suggestions 决定 {++新增++}、{--删除--}、{~~旧~>新~~} 修订标记在导入时原样保留、全部接受 还是全部拒绝。评论落在代码里或跨行时改为写在旁边的单独批注,不会破坏原有语法。不用编辑器时, 也可以直接调用 @quirekit/msfe-comments/critic-markup 的 exportCriticMarkup 与 importCriticMarkup。

AI 助手

@quirekit/md-editor-ai 的 createMdEditorAi() 返回 panel、extensions 与 destroy(): 将前两项交给 MdEditor,在宿主页卸载时调用 destroy()。助手使用内置模型设置、文档工具与改动审批; ownerDocument 提供页面文档,storage 提供浏览器存储,images 可复用宿主图床。

团队统一管理模型时,传入 connection: () => Promise<QuireAiModelConnection>,首次打开面板才加载 授权模型目录。此时隐藏个人连接设置,也不会读取本地保存的 provider 配置;模型选择和审批偏好仍可保存。 管理员页面可复用 createQuireAiProviderSettings({ persistence }) 的表单,由 initialDraft、 异步 save(draft)、clear() 接入宿主服务端。保存失败保留草稿,不会写入浏览器凭据。 服务端使用 @quirekit/ai-assistant/settings 验证配置;模型密钥、成员权限和网关鉴权由宿主负责。

协作记录

协作记录回答“谁、何时、做了什么”。记录写在文档之外,格式遵循公共协议 @quirekit/edit-history, 存储由宿主实现 ActivityStore;编辑器只负责采集和展示。安装两部分并传入同一个存储与文档标识:

ts
vue
  • 同一块里的连续输入在停顿约 3 秒、换块或失焦时合并为一条;粘贴、剪切、撤销、插入块、移动 / 删除块、 转换格式、修改高亮块颜色与图标各记一条。远端和宿主写入的变化不由本端记录。
  • 面板按日期与相近时间分组,可展开明细、查看改动前后的 Markdown 片段、按成员或时间筛选、隐藏系统通知。 点击条目定位到当前原文:位置变了会定位到相同内容并标明“原位置已变化”,原内容已删除或无法确定 (例如同一段文字出现多处)时只提示,不会跳到别处;评论记录定位到评论当前标注的文字。
  • 单人使用时 trust 为 local,local: true 让面板标明“仅保存在本机”。多人可信记录需要服务端确认后写入, 通用协同采集适配器尚未提供。宿主也可在服务端确认正文更新后写入公共协议记录,前端只安装 mdActivityPanel 读取,避免与本地采集重复。@quirekit/edit-history/memory 的内存实现只用于示例和测试,刷新即丢失;自建存储可用 @quirekit/edit-history/conformance 的规则逐条验证。

多人协同时

协同时由服务端确认后写入,客户端不再写存储。服务端安装 Hocuspocus 扩展,作者取自鉴权结果:

ts

客户端只为插入块、粘贴、撤销等带标签的操作发送提示,连续输入由服务端从收到的改动中合并:

ts

提示与实际改动对不上时,服务端把这次改动记为“编辑了正文”。断线后很快重连仍算同一次协作,不重复记“加入协作”。 评论房间传入 commentsRoom: room => room.endsWith(':comments') 后,添加、回复、解决、重新打开与删除评论也会记录, 作者同样取自连接身份;评论房间的记录在保存该房间时用 takeActivity(评论房间名) 取出。

服务端记录要有上限,否则会一直增长。协议的保留策略可以同时限制条数与时间:maxEvents 只保留每篇文档最近的若干条, fullDays 之后删除改动片段只留摘要,summaryDays 之后整条删除。参考内存实现 createMemoryActivityStore({ retention }) 在每次写入后执行;数据库存储可在写入事务后或定时任务里执行同样的清理, 例如按序号删除超出条数的旧记录。历史版本另外按 versionThinning 稀疏化,命名版本不受影响。

历史版本

版本是整篇 Markdown 的快照,存储由宿主实现 VersionStore。把同一个版本存储同时交给 MdActivity 和面板, 面板会多出“版本”页:

ts
  • 可以输入名称保存命名版本,命名版本永久保留;宿主在自己的存档时机调用 getMdVersions(editor).save() 生成自动版本,内容与上一个版本相同时复用它,不会重复存储。
  • 点击版本打开只读预览,可切换到“与当前对比”查看逐行差异,也可以复制全文后手动粘回需要的部分。
  • “恢复此版本”先把当前内容存为一个版本,再只改写不同的行,作为一次可撤销的编辑并记为“恢复了版本”; 没改动的行上的评论和协同锚点不受影响。只读时不能恢复。
  • 协同时,服务端在存档时生成自动版本,命名版本由宿主的版本接口在服务端写入“保存了版本”记录, 作者取自鉴权身份;恢复的记录照常由提示配对确认,客户端不直接写记录。暂不提供撤回某一次编辑。

使用共享公式编辑器

从“插入”选择行内公式或块级公式;双击已有块级公式(或选中后点操作栏“编辑”)、点击行内公式都会打开同一个面板。 面板直接使用 @quirekit/math-ui 的 MathAuthoringPanel,沿用 @quirekit/math 的 公式文档、模板、结构化输入与可选 LaTeX 输入;产品不实现第二套公式 UI。 显示公式的 KaTeX 资源与编辑面板按需加载。

公式草稿独立于正文。取消不会写入;确认只替换该公式的 LaTeX 内容,保留美元围栏和 外围引用/列表前缀,作为一次撤销操作。行内公式要求单行且不含外层 $;多行内容使用 块级公式。原位置在编辑期间被改写、文档被替换或切为只读时,提交被拒绝并保留草稿。

在使用 UnoCSS 的工作区宿主中,除产品和 UI 源码外,也将公共 math-ui 源码纳入扫描。 它使用既有公共组件类名。使用预编译样式的宿主应确保这些公共组件样式已经包含。

需要自建公式宿主时,使用 MSFE 的 Math.configure({ edit }),再将它交给 extras.math。回调给出 editor、range 和 kind;返回 true 表示已接管编辑。 不要在异步面板中长期保存裸 range:先 captureAnchor(range),确认时取得 anchor.target() 并执行 editor.run(replaceMdPreview(latex), target),结束后释放锚点。 这也适用于 Mermaid.configure({ edit })。完整组件生命周期见 呈现 API。

图表、链接与图片的修改

“插入 → 文本绘图”打开 Classic、Block、MSFE 共用的源码工作区,支持 Mermaid、PlantUML、Graphviz/DOT。语言切换保留各自草稿,模板须显式应用;预览成功后可保存或下载 SVG/PNG,失败时保留草稿供修改,取消不改正文。标准 Markdown 围栏不保存独立图题,因此该宿主的工作区不显示标题输入。

保存生成普通的 mermaid、plantuml 或 dot 围栏,也能重开 puml / graphviz 别名。编辑保留原围栏风格及外围块前缀,必要时增长分隔符防止源码关闭外层围栏;切换语言才更新语言名。extras.mermaid: false 关闭 Mermaid;extras.textDiagram: false 同时关闭 PlantUML/DOT。未安装的语言保留为普通代码。引擎本地运行,外部 include、可选 PlantUML 图库与 D2 未启用,详见文本绘图接入。

把光标放在链接中再点工具栏“链接”可编辑该链接。点击图片会整体选中并浮出操作栏,可编辑、预览、复制、剪切或删除;双击图片直接预览。 若未改变显示文字,链接内部的粗体等原始写法会保留。修改引用式链接的单个使用位置 会将该位置改为行内链接,共享引用定义和其他使用位置不变。危险协议被拒绝。

图片地址保存在 Markdown;私有附件、上传接口或对象 URL 的获取应由宿主提供。 可以用 Image.configure({ resolve }) 保留图片来源合同,再覆盖 addNodeView 接入 自己的公共图片组件。解析器返回资源的释放仍由 MSFE 节点生命周期负责,详见 图片与资源生命周期。

提供 images(MdImageStorage)后,宿主的存储负责新图片,正文只写返回的地址:

ts
  • 图片对话框出现「上传本地图片」,上传后填入地址与替代文字,仍由用户确认插入。
  • 粘贴截图或拖入图片文件时直接上传,完成后插入到粘贴或落下的位置;上传期间的编辑不影响落点。 剪贴板同时带文字(如复制网页)时走普通粘贴。上传失败不写入任何内容,失败提示由宿主在 upload 中给出。
  • 流程图、思维导图、白板保存时,预览图以 source: 'diagram' 上传,嵌入块只写地址(preview.url); 上传失败时预览图仍内联保存,不影响这次编辑。导出 Word / PDF / OFD 时经 resolve 取回预览图。
  • docx.storeImage / docx.resolveImage 未设置时,Word 导入与导出使用同一个存储。
  • 只读编辑器不上传;未提供 images 时保持原有行为(只能填写地址,图表预览图内联为 base64)。

调用产品源码命令

工具栏也是公开命令的消费者。需要自定义入口时,使用同一个编辑实例与事务:

ts

replaceMdPreview(body, language?) 要求目标是已识别的公式或文本绘图节点;可选语言用于切换现有绘图围栏的语法,它不负责创建新块。 表格命令要求光标或选区属于同一个表格,列对齐只修改分隔行中对应的一个字段,保留 其他单元格原文。检查 result.ok;只读、过期目标、不适用的结构都会拒绝修改。

不要直接调用命令规划器后写 DOM,也不要绕过 editor.run() 的目标、权限、历史检查。 外部弹层应捕获目标并按生命周期释放,示例与 API 见 命令与事务。

导入与导出

工具栏的上下双箭头图标打开 导入 / 导出 菜单,悬停可查看名称。 菜单按方向分组:导入 Markdown、Word,导出 Markdown、Word。 宿主通过 exporters 安装的格式(如 PDF、OFD)各增加一项导出;未安装的格式不显示。 各导入、导出项使用带 MD、W、PDF、OFD 标记的文件类型图标,禁用项的图标同步弱化。

“导入 Markdown”接受文本或最大 2 MB 的本地 .md/.markdown/.txt 文件。文件通过 公共 FileUpload 选择、校验与移除,先读入草稿,去除 UTF-8 BOM、统一 CRLF/CR 为 LF。 草稿使用公共 CodeBlock 预览并复制,也可点击“编辑内容”修改或粘贴 Markdown。

点击“替换全文”使用草稿替换当前文档内容;点击“追加到末尾”保留原文并将草稿追加在末尾, 不依赖当前选区。两种操作均可一次撤销;窗口打开期间原文被修改、文档被替换或变为只读时, 保留草稿并禁止写回。若业务需要打开另一份文档并重置身份与历史,应由宿主处理保存后调用 replaceDocument()。

“导出 Markdown”读取当前权威原文,不从 Prose DOM 或 JSON 反向生成内容。保存到后端 仍属于宿主职责;在只读状态下也可导出。

Word 导入与导出

导入 / 导出 菜单中的 Word 操作由宿主安装的转换器提供。转换器 mdDocx() 位于商业包 @quirekit/md-editor-export,基础编辑器只定义 MdDocxConverter 合同;未安装时 Word 导入、导出项隐藏:

ts

转换运行时仅在用户操作后加载。 导入接受最大 20 MB 的 .docx 文件,先转换为 Markdown 草稿,通过 CodeBlock 预览并显示报告。 它与 Markdown 导入共用“替换全文”“追加到末尾”两个按钮,均可一次撤销。 取消、转换失败、导入期间原文变更或文档变为只读时不会写回。 导出捕获打开窗口时的源码快照,转换完成后查看报告、下载 Word;只读状态仍可导出。

首版支持正文、1–6 级标题、粗体/斜体/删除线/行内代码、链接、代码块语言、基础嵌套列表、 带边框和表头底纹的简单表格、原生脚注、公式和 PNG/JPEG 图片。代码块保留语言和换行,并用底纹、边框内距增加留白。 任务状态变为可见勾选字符;默认容器和 Mermaid 使用下面的节点转换扩展。导入时复杂表格、 字体和版式会降级,批注、页眉页脚等省略并报告;导出可通过模板配置新的页眉页脚。 Word 格式和原始 Markdown 写法不保证无损。 可识别的修订删除文字被排除,插入文字保留;这不等同于完整的 Word“接受全部修订”。

行内和块级公式复用 @quirekit/math-omml,导出为可编辑的 Word 原生 OMML。重新导入时 只接受通过严格结构核对的 LaTeX;不支持的源公式保留源码,无法反推的 Word 公式保留可读数学文字, 均提供诊断。复杂公式属性、公式外围 Markdown 格式和脚注中的公式不保证保真。

脚注引用和正文写入真正的 Word 脚注,重新导入恢复为 Markdown 引用和定义,保留基础段落、 粗体、斜体等文字格式。重复引用同一定义时,导出为独立 Word 脚注并报告;未引用定义保留 为正文注释。注释内的链接保留文字和 URL,图片保留替代文字,复杂块保留源码并报告。 导入 Word 尾注会转为 Markdown 脚注并报告位置差异。普通脚注标签会规范化,不保证原标签拼写。

转换也可以独立使用 @quirekit/markdown-docx,无需挂载编辑器:

ts

markdownToLitAst() 与 litAstToMarkdown() 暴露同一中间转换阶段,方便宿主复用。 前者的 authoredParts 承载样式及文档设置;自行编译时必须随 ast 一起传入 createDocxPackagePlan(ast, { authoredParts }),确保样式与往返元数据采用同一份结果。 lossPolicy: 'strict' 会在发现损失时抛出带 diagnostics 的 MarkdownDocxLossError; 默认 best-effort 返回内容和报告。该适配包属于 QuireKit 商业组件,MSFE 的现有许可不变。

默认不请求外部图片:导出直接支持 PNG/JPEG data URI,其它来源需要显式 resolveImage(source): Promise<string | null> 返回这两种格式的 data URI。 默认模板使用 A4 页面和四边 1 英寸页边距;图片保持原始比例、只缩小不放大,按正文、列表 或嵌套单元格的实际可用范围限制尺寸。标题默认 1.1 倍行距、段后 4–6 磅,正文 1.15 倍行距、 段后 6 磅,列表项段后 2 磅;自定义转换已提供的间距或样式引用优先。 相邻表格和带框容器之间补充 8 磅的块间分隔,与已有段距共同决定可见留白; 嵌套容器内的同级块遵循相同规则,重新导入时不会因此增加空白内容。 这些外观现在可以通过导出模板配置;省略模板时保留上述默认值。 导入默认保留 data URI;可通过 storeImage({ dataUrl, alt }): Promise<string | null> 保存图片并返回持久 URL。 保存失败保留内嵌数据并报告,临时 blob: 地址不会进入结果。将这些选项与转换器一起传给 MdEditor 的 docx 属性,或传给独立转换函数。 在编辑器之外转换(例如宿主把 Word 文件导入为新文档)时,调用 mdDocx().importDocx(data, { policy, features, signal }),它使用与编辑器相同的默认转换(流程图、思维导图、 白板、容器与代码绘图),导入导出才能往返一致。宿主自定义节点转换通过 mdDocx({ extensions }) 安装。 Word 原生图表在 Markdown 中没有对应语法,导入时按图表缓存数据渲染为静态 PNG(随后同样经 storeImage 保存),每张图表报告一条 chart-rasterized;无法读取的图表族(散点、组合图、新式图表等) 替换为 [替代文字] 占位并报告 chart-omitted,不会让整个文件导入失败。宿主可通过 mdDocx({ renderChart }) 改用自己的渲染器(签名为 (chart) => Promise<string | null>),builtins: false 时不渲染图表。

PDF 与 OFD 导出

PDF 与 OFD 由可选商业包 @quirekit/md-editor-export 以导出插件的形式提供,基础编辑器不依赖它:

ts

每个插件在“导出”菜单中增加一项。导出时捕获当前源码与所选模板,生成后显示页数和转换报告,再由用户 下载;只读文档也可导出。导出窗口中的“更换”使用同一份源码重新生成,关闭或切换文档会废弃过期结果。 转换器与字体在第一次导出时才加载。

两种格式都通过临时 Classic 文档完成真正分页,再分别编码原生 PDF 与原生 OFD(不经 PDF 中转)。 正文是可选择的文字;表格、提示块、脚注、页眉页脚和动态页码使用现有排版能力,图表为图片。 公式当前使用默认数学字体输出高清图形并报告这一降级,其文字不能单独选择。自定义节点复用 已有转换器,不需要为每种格式再维护一套节点转换。

插件默认使用 @quirekit/font-pack 的便携字体:同一套字节先安装为浏览器字体用于度量,再嵌入文件。 OFD 没有标准 Courier,插件为常见代码字体嵌入 DejaVu Sans Mono 并报告替代,许可原文随 font-pack 发布。 PDF 中代码字体没有对应资源时,先解析为等宽后备字体再排版并报告。宿主可通过 fonts 选项替换整套字体, 通过 metadata 设置标题、作者等文档信息。缺字或资源失败均有诊断;lossPolicy: 'strict' 拒绝有损输出。

不需要编辑器界面时,可直接调用 @quirekit/md-editor-export/pdf 的 exportMarkdownPdf(markdown, options) 或 /ofd 的 exportMarkdownOfd,返回 data、pageCount 和 diagnostics。这时需显式提供可嵌入字体; 无浏览器环境必须提供 textMeasurer,包含公式时还需 rasterizeFormula。OFD 的 fontEmbedding 默认 subset,可设为 full。

两种格式都不承诺与 Word 在不同字体环境下逐像素一致,也不保留可往返编辑的 Markdown 元数据,不提供 Markdown 导入。PDF/A、Tagged PDF 与大文档后台线程属于后续能力。

导出模板

@quirekit/export-template 提供格式中立的配置、默认模板与严格校验,使用 MIT 许可。 模板只用于导出,不更改 Markdown 内容、选区或撤销历史,也不影响 Word 导入。 页面使用 mm;字号、段距、边框和内距使用 pt;行距明确区分倍数与固定值。下面是公开的合成配置示例:

ts

可以设置正文、H1–H6、列表、引用、代码、表格、容器、脚注、公式及图片的外观。 角色字体提供西文、东亚、复杂文字槽位;留空为主题字体。fonts.math.latin 对应 Word 的 默认数学字体,原生公式仍可编辑。模板不嵌入字体,不保证所有设备分页一致。 单节默认页眉页脚支持左中右内容及 {title}、{page}、{pages};后两者为 Word 原生动态域, 需阅读器更新后显示实际页码,过长单行文字会缩略并报告。快速样式示意不是 Word 分页预览。

MdEditor 可以直接接收 :docx="{ converter, template }",也可以由宿主接入模板库:

  • templates:实现 ExportTemplateProvider 的目录、精确版本读取与可选保存/删除服务。
  • v-model:exportStyle:当前文档的 { id, revision },由宿主与文档设置一起持久化。
  • #export-templates="{ provider, selected, choose, close }":安装宿主选择器;确认时调用 choose,取消调用 close。

同时提供 provider 与 slot 后,图标菜单显示“导出样式”;Word 和已安装的 PDF/OFD 导出自动沿用选择。 导出窗口中的“更换”保持本次源码快照并重新生成文件,关闭或切换文档废弃过期结果。 无持久化宿主时只记住当前实例;已有版本缺失或无权限会阻止导出,要求重新选择,不静默回退。 只读文档仍可选择样式和导出。扩展通过 markdownExportTemplateService 读取同一解析配置, 自定义转换明确提供的直接格式和样式引用仍然优先。

现有 MD Editor 示例 已接入模板库;中英文示例分别保存导出样式。文档站宿主 采用私有商业授权,基础编辑器和导出协议的授权保持不变。

第一方 @quirekit/export-template-library 组件和官方设计包独立采用商业授权,支持浏览、 新建、复制编辑、保存版本与显式本地存储,由商业宿主按上述接缝装配。组件授权与内容包授权分别解析, 支付、账号和生产授权校验由宿主提供;基础 Markdown/Word 导出不依赖商业包。上传 DOCX/DOTX 作为模板仍属于后续能力。

“模板管理”中,“新增模板”从默认配置开始;“基于当前模板新建”复制当前浏览的模板样式。 卡片通过主色边界、轻底色和勾选标记显示选择,点击右上角编辑按钮可修改该模板。 内置模板只读,编辑入口会创建副本并保留来源;个人模板编辑后保存为同一模板的新版本。 “当前使用”标记对应文档已经采用的版本;浏览、编辑和单独保存不会应用,点击“使用此模板”或“保存并使用”才更新文档的导出设置。

复制或编辑模板时,窗口尺寸保持稳定,切换分类后仅更新可滚动的字段区域;模板名称、 分类栏和底部保存按钮始终可见。窄屏使用紧凑预览,空间很低时优先显示编辑字段。 字段按外观、文字、段落等用途分组,数值旁直接显示单位。点击颜色块可选择预设色或打开 “更多颜色”精确调整;文字颜色可恢复“自动”,底色可设为“无填充”。加粗、斜体和对齐使用格式按钮。

自定义节点转换与往返

MD Editor 默认注册容器与三种文本绘图转换,开关跟随 containers / extras.mermaid / extras.textDiagram:

节点Word 中的内容再导入
单段容器段落底纹、四边框与边框内距校验通过时恢复容器源码
含标题、列表或嵌套块的容器单格表格底纹、边框和单元格内边距,正文仍可编辑校验通过时恢复完整容器
高亮块表情作为首行,无边框底纹,可选字体颜色校验通过时恢复高亮块源码
Mermaid、PlantUML、Graphviz/DOT从源码离屏渲染的 PNG 图片校验通过时恢复原围栏与源码

圆角和折叠交互会降级并报告。默认容器解析支持根级及容器正文中的已关闭命名围栏; 列表、引用内部的容器需要宿主扩展解析。图形渲染失败保留代码,不依赖当前视口中是否挂载预览。

源码元数据存入标准 Custom XML part,通过内容控件关联。可见内容、图片字节、脚注/尾注或样式/编号 发生变化后,导入保留当前 Word 内容;不会用过期源码覆盖 Word 修改。元数据丢失、标识重复、 版本不兼容或扩展未安装时也保留原生内容或图片。这里已验证 QuireKit 往返,尚未承诺 Word/WPS 等软件再次保存后必定保留元数据。

<MdEditor :docx="{ converter, preserveMetadata: false }" /> 可导出纯原生内容和图片; builtins: false 关闭默认节点转换,但保留宿主经 mdDocx({ extensions }) 安装的转换。基础 MSFE 包没有 DOCX 依赖。

独立适配器按需注册同一套功能。图片渲染由宿主明确提供,不隐式抓取资源:

ts

自定义功能实现 MarkdownDocxExtension.addDocx(),返回与 Classic 相同的节点转换贡献。 Word/PDF/OFD 共用 parse / prepare / 节点 codec 与模板 service;DOCX 的 package pass 和 Custom XML 恢复只适用于 Word。完整的原生业务卡片、图片渲染、组合注册、取消与失败处理见 自定义节点导出为 Word、PDF 与 OFD。

扩展必须校验 payload 版本与字段,并保留可见回退。每条恢复元数据上限为 64 KiB, 文档总计 1 MiB / 1000 条。preserveMetadata 控制内置扩展;宿主扩展自行管理其策略。

共享 Prose 类名

编辑区在实时和只读状态使用 qk-prose qk-prose--compact,MdProse 使用同一紧凑密度; 代码块使用 qk-code-block qk-prose-source。任务框复用公共 Checkbox 与 qk-prose-task-marker 组合类,保持正文行高,并与编辑时的 [x] / [ ] 共用占位宽度。 容器使用 qk-prose-container、qk-prose-container__header、qk-prose-container__body 和语义 data-tone。适配器将 CodeMirror 块映射为原生语义元素或 data-qk-prose 角色, 直接消费公共 Prose CSS。普通 DOM 阅读与编辑不各写一套皮肤。

先通过应用的 QuireKit 主题修改字体、色彩和间距。业务需要特殊容器时,在宿主作用域 下为 .qk-prose-container[data-container="你的类型"] 提供明确的变体;不要逐行画背景 或替换 CodeMirror 管理的 DOM。需要在静态阅读中复用该类型时,保留相同的容器标识。

独立的阅读视图快照

vue

MdProse 消费不可变状态并生成可丢弃的语义 DOM,不生成另一份可编辑 JSON,也不会 反向序列化 Markdown。已注册容器名称保留为 data-container,可与编辑视图共用变体。 阅读适配覆盖核心块、行内扩展、链接、图片、公式、Mermaid、PlantUML、Graphviz/DOT、定义列表、脚注和 Frontmatter。 公式与图表复用同一安全渲染器,元数据保留为源码。未注册的绘图语言仍按普通代码块显示。 第三方扩展可通过 @quirekit/md-editor/vue 的 withMdReading() 贡献阅读内容,复用原 codec 的字段校验,并由公共层处理资源取消、释放和失败回退,见自定义节点。 未知节点保留源码文本,默认 HTML 也保留为文本。components 与显式 html 策略共用 公共 Incremark reader 的合同。阅读贡献不自动提供 Word/PDF/OFD 导出能力。

直接显示文本与 AI 流式回复

无需先创建编辑器,直接把当前收到的完整原文传给 content。每次追加更新同一个字符串, 改写、清空和切换消息也使用这个属性;不要同时传 state。

vue

status 接受 receiving、complete、stopped、error,只描述传输状态。停止/失败保留 原文,后置定义仍可修正前文;没有提前冻结的“完成块”。未闭合的代码块先展示代码,闭合后 才允许 Mermaid 等预览启动。重复脚注有独立的引用锚点,重复链接定义遵守首次定义优先。

options 接收 MdEditorExtensionOptions,包括 extras、containers 和 extensions; 阅读扩展仍通过 withMdReading 注册。更换 options 对象或 identity 会释放旧会话和资源。 配置必须是无需挂载编辑器的纯配置,不支持在初始化时使用 this.editor 或接入 source provider。 错误通过 MdReadingError 上报,文本解析/配置失败的 phase 为 parse,原文作为转义文本保留。

正在准备编辑器…

例子每 30ms 追加 20 个 UTF-16 字符,末尾才给出链接和脚注定义。停止后可以一次性加载, 也可以重新开始。这里的可运行示例使用 MdProse;为兼容原合同,SSR 和客户端首帧 都输出转义原文,挂载后再解析。需要服务端语义 DOM 时传入预先接受的 state 快照,或使用公共阅读组件。额外解析工作 协作让出主线程,但不是硬实时预算;大文档 和密集引用仍有全局工作。稳定顶层块在语法、位置与依赖均未变时复用投影;增长中的块仍需重新投影。

无框架宿主可使用 MdProseStream,调用 update(content) 接受全文、advance(budget) 推进解析,再消费 state。返回 false 时由宿主调度下一个切片;类本身不创建定时器。 不要把 Incremark 的 AST renderer、HTML 执行或图表配置直接传入这个入口。

无框架装配

createMdEditor(options) 返回原始 MsfeEditor,生命周期、命令和保存方法不变。 createMdEditorExtensions(options) 返回产品扩展组合,可以交给已有的 MSFE 实例工厂。 Vue 的任务、图片、代码语言选择与折叠按钮由 vueMdEditorExtensions(locale, options, edit?) 装配,需要同时使用 MSFE Vue 的组件宿主。第三个参数可接管公式/图表编辑;直接使用 MdEditor 时这些步骤及公共弹层已完成。无框架工厂本身不挂载 Vue 工具栏或公式面板; 宿主应提供 extras.math / extras.mermaid / extras.textDiagram 的编辑回调,或使用 view: 'preview' 直接编辑活动节点的源码。

MSFE · QuireKitMarkdown 源码始终属于你。