ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

从零开发一款好看又彪悍的 Markdown 编辑器

从零开发一款好看又彪悍的 Markdown 编辑器 作为 Markdown 重度用户我每天有大量时间花在编辑器上写技术文档、维护项目 README、记录读书笔记、起草公众号文章甚至写邮件草稿都在用 Markdown。这几年我几乎把主流的 Markdown 工具试了个遍Typora、VS Code、Obsidian、Notion、语雀、Bear 都用过。说实话每个工具都有自己的闪光点但真要找一个“既好看又彪悍”的编辑器我始终没找到完美答案。TYpora 颜值在线但闭源而且定制能力有限VS Code 功能强大但默认的 Markdown 预览体验始终差点意思Notion 能协作但根本不算纯 Markdown 编辑器导出格式也经常水土不服。在这种长期“凑合”的状态下我最终下定决心自己动手开发一款真正符合自己写作习惯的 Markdown 编辑器。这篇文章不聊广告也不打算报一堆功能清单。我想从一个开发者的角度把这款编辑器从想法到落地的完整过程拆开来讲为什么我要自己造轮子、界面和性能要怎么平衡、表格和数学公式这些老大难问题如何解决、导出 PDF 和 Word 时踩了哪些坑、以及最后我总结出来的排查技巧。如果你也是 Markdown 深度用户或者正打算开发自己的效率工具这篇文章应该能给你不少真实可用的参考。1. 为什么一个重度用户会决定自己写编辑器1.1 现有编辑器的“最后一公里”问题先说说我平时的使用场景。我会同时维护好几个技术项目每个项目都有 README、CHANGELOG、docs 目录下的若干 Markdown 文档另外还有个人博客、笔记库、产品文档。这些文档有的需要频繁更新有的只需要偶尔翻出来改一改。看起来很简单但组合起来就暴露出不少问题。最大的问题是“预览与编辑割裂”。VS Code 的 Markdown 预览是双栏左右并排左边写右边看思路经常被打断。Typora 能做到所见即所得但是它在处理超大文件时比如几千行的 CHANGELOG 或者几万字的电子书草稿性能会明显下降滚动的时候卡顿感很重。Obsidian 的图谱功能很酷但它的核心是笔记管理不是通用编辑器离开 Vault 环境就基本用不了。Notion 更像数据库它的 Markdown 支持是阉割过的表格和代码块的处理经常不符合我预期。更麻烦的是格式转换。写完一份 Markdown 文档后我经常要交付给不同的人给开发同事看要发 GitHub给运营同学看要转 Word给客户看要转 PDF。现有工具在转换这条链路上要么依赖网络服务要么输出样式一塌糊涂。网上很多人在问“VS Code 要将 Markdown 文件导出为 PDF 需要下载 PrinceXML如何操作”这说明大家都被这个问题卡过。其实不是大家不会装软件而是现有方案确实过于繁琐让人望而却步。我一直觉得一个真正好用的 Markdown 编辑器不应该只解决“语法高亮”和“预览”这两个点它应该把“写作-预览-导出-管理”整个流程都打磨顺畅。可惜没有现成工具完全满足我所以只能自己动手。1.2 开发目标好看是第一生产力彪悍是生存底线在动手之前我给这款编辑器定了两个关键词“好看”和“彪悍”。“好看”不是指花里胡哨的皮肤而是指界面布局、字体排印、颜色对比度、动画过渡都要让人觉得舒服。文字工作者一天要在编辑器里待好几个小时如果界面让人眼睛疲劳功能再强也白搭。我见过太多功能丰富的工具UI 却像 2005 年的论坛用起来动力全无。“彪悍”则是指性能和功能不能掉链子打开几万行的文档不能卡表格和公式要渲染得又快又准图片粘贴不能乱路径导出格式要稳定。深层次的意思是这个编辑器要能应对真实工作场景而不是只能写写几百字的备忘录。我给自己定了几条硬性指标启动时间不超过 2 秒打开 5MB 的 Markdown 文件无明显卡顿输入延迟低于 100ms支持 GFM 表格、数学公式、任务列表、Mermaid 流程图注项目内部支持但本文不画图一键导出 PDF 和 docx图片粘贴自动保存并处理路径。这些指标看起来基础但每一项目前在主流工具中都有短板全部实现其实很有挑战。2. 整体设计与技术选型2.1 编辑器内核为什么选择 CodeMirror 而不是自研或 Monaco编辑器内核是整个项目的地基。我一开始也动过“自己写一个文本编辑器”的念头但很快打消了。文本编辑器的复杂度远超常规认知光标管理、IME 输入法、选区处理、撤销重做、折行逻辑、剪贴板兼容……每一项都是深坑。强行自研会让整个项目陷入基础工作的泥潭很长时间都无法触及真正想做的 Markdown 体验优化。所以我把目光放在成熟内核上主要候选是 CodeMirror 和 Monaco Editor。Monaco 是 VS Code 的内核功能强大但它体积不小而且它的设计主要面向代码编辑场景对 Markdown 这种混合内容的定制不如 CodeMirror 灵活。CodeMirror 6 采用模块化架构按需加载性能和扩展性都更符合我的需求。它提供的 view 层和 state 层分离方便我自定义文档模型、装饰器、自动补全等能力。经过对比后我选择了 CodeMirror 6 作为编辑内核。在实际开发中CodeMirror 6 带来的好处是实打实的。它支持虚拟滚动文档超大文件不至于一次渲染整个 DOM它还提供了非常强大的 decoration 机制可以在不破坏原文的前提下在编辑器内直接渲染 Markdown 效果这是实现“类 Typora 所见即所得”的关键。当然CodeMirror 6 的学习曲线比较陡官方文档有时偏抽象但一旦理解其核心模型定制空间非常大。2.2 渲染层与预览同步把 Markdown 变成“活”的文档有了编辑器内核之后接下来要解决的是 Markdown 渲染。我采用了解析与渲染分离的架构先用解析器把 Markdown 文本转换成 AST抽象语法树再把 AST 渲染为 HTML 或编辑器内的装饰元素。解析器我选了 remark 生态它基于 unified 框架插件丰富支持 GFM、数学公式、脚注、目录等扩展语法。对于渲染层在预览面板中使用 React 来操作 DOM状态管理使用 zustand轻量且性能好。最重要的设计决策是“单一数据源”。编辑器内的 Markdown 原文始终是唯一权威状态预览面板和编辑器内的装饰效果都从这份原文派生。用户要么直接改 Markdown 源码要么通过富文本操作间接修改源码但最终落盘的永远是原文字符串。这样设计能避免像某些笔记软件那样内部数据模型和实际导出的 Markdown 不一致的问题。标题锚点、目录生成、代码块复制按钮、任务列表 checkbox 交互、表格列对齐等细节都是在渲染层实现的。为了让编辑器体验更顺畅我让编辑器内光标所在段落以纯文本展示光标移开后自动渲染为格式化样式类似于流行编辑器的“源码/富文本混合模式”。这样既能保持 Markdown 的透明性又能在阅读时获得富文本的视觉享受。2.3 数据与文件管理既要本地优先又要多端同步文件管理是一个非常容易被低估的模块。现有工具往往在“文件管理”上两极分化一种是不管文件只提供一个打开/保存按钮另一种是锁定专用数据目录坚持所有文件必须导入库中。我的目标很明确尊重用户自己的文件夹结构直接以普通文件方式打开目录但不强制迁移用户的任何数据。为此我设计了基于文件系统访问 API 的目录工作区。用户打开一个文件夹后编辑器会递归扫描其中的 Markdown 文件并进行索引建立一个虚拟文件树。文件树支持大纲预览、标签过滤、文件名搜索。由于所有操作都是直接针对真实文件用户随时可以用其他工具打开同一目录不会产生数据孤岛。多端同步方面我支持将工作区配置和最近文件列表同步到本地网盘目录或者通过自定义脚本与 Git 联动。由于核心文件始终是纯文本 Markdown任何同步手段都能正常工作不需要依赖私有云服务。这里有一个很关键的体验设计自动保存。我采用“防抖保存 草稿备份”策略用户停止输入 800ms 后自动保存同时每 5 分钟生成一个备份文件存放在工作区的.md_backup隐藏目录中。万一遇到编辑器崩溃或误操作可以从备份恢复。在实际使用中这个机制帮我避免过好几次惨剧比如写了大半天忘记保存或者不小心覆盖了重要段落。3. 核心功能拆解与实现细节3.1 实时渲染与打字机模式让光标永远停留在视觉中心实时渲染是 Markdown 编辑器体验的分水岭。传统双栏预览的问题是眼睛要在两个区域之间来回移动写作节奏会被干扰。我实现的是“精确同步光标滚动”光标在编辑区移动时预览区自动滚动到对应段落高亮当前正在撰写的内容。这样不需要手动拖动滚动条就能保持上下文连续。打字机模式是一个非常受欢迎的功能尤其在长文写作中。开启后当前光标所在行会垂直居中于编辑器视窗。这个功能看起来简单但还要处理好“光标移动到文档开头/结尾时不能强制居中导致内容超出边界”的边界情况。我参考了 Typora 的实现加入了平滑滚动动画但动画时长控制在 100ms 以内避免打扰输入节奏。为了减少视觉跳跃当光标行接近视窗边缘时才触发居中否则不滚动保证大部分时间内页面稳定。另外我实现了一个“写作专注模式”它会将非当前段落的不透明度降低到 30%只突出当前段落。配合柔和的主题色写作时注意力能更集中。这种细腻的交互不会出现在功能列表里但实际体验影响很大。3.2 表格与数学公式两个最容易翻车的场景表格是 Markdown 中最容易出问题的语法因为它需要严格的列对齐而且不同解析器的容错能力差异很大。GFM 表格虽然流行但仅支持单行表头、简单对齐单元格里不能渲染复杂块级元素。我在开发中做了三层处理。第一层是“输入辅助”。当用户输入一行类似| a | b |并回车时编辑器自动插入|---|---|分隔行生成一个完整的表格骨架。用户只需要在单元格之间 Tab 跳转输入内容即可。第二层是“格式化与校验”。我写了一个格式化插件能够自动调整表格各列的宽度将空格填充到每列单元格中让源码看起来也是对齐的。第三层是“预览容错”。即使源码里表格的管道符不齐、空格混乱渲染层也会尝试用自定义的表格解析逻辑尽量修复并展示而不是直接抛错。这个容错机制在实际使用时非常省心尤其是从网页或 Word 复制表格内容时粘贴过来的文本通常带有大量空格和额外管道符。数学公式方面我选用 KaTeX 作为渲染引擎。它比 MathJax 快很多对前端交互更友好。但 KaTeX 对 LaTeX 语法的支持范围有限某些高级命令会报错。为了解决这个问题我给编辑器的公式语法做了实时校验当用户输入不完整的公式时比如$x^2$缺少结束符编辑器会高亮错误区域并给出提示同时配置了 KaTeX 的strict模式让未知命令以红色显示而不是渲染成空白。这样用户能第一时间发现公式错误而不是到最后导出时才看到一堆乱码。3.3 图片粘贴与路径处理一张图逼疯强迫症图片路径问题在 Markdown 里是老大难网上一搜铺天盖地都是“markdown 图片路径”相关问题。传统 Markdown 编辑器插入本地图片时通常会生成![](C:\Users\...\Desktop\xxx.png)这种绝对路径。一旦文件移动或发给别人图片就全部挂掉。我在设计时重点解决这个问题。我的方案是“图片粘贴自动保存到资源目录”。当用户从剪贴板粘贴图片时编辑器会先将图片数据保存到工作区的assets文件夹中并自动生成相对路径插入文档。比如工作区根目录为myblog文章路径为myblog/posts/hello.md粘贴图片后自动保存为myblog/assets/hello/1.png并插入![](../assets/hello/1.png)。这样整个文件夹移动、打包、上传到 Git 仓库都不会产生路径失效问题。此外我还增加了一个“路径感知”功能。当用户手动输入的图片路径不存在时编辑器会在文件树中查找最相似的文件并给出路径补全建议。当图片被移动或重命名时编辑器也会检测到引用失效在状态栏提示用户修复。这些功能虽然实现起来有一定工作量但对日常写作体验的提升非常显著。3.4 一键导出 PDF / Word从 Markdown 到交付物的最后一公里导出需求往往决定了 Markdown 编辑器能否进入正式工作流。我在导出方面花了不少心思也踩了很多坑。PDF 导出我最初尝试了直接调用浏览器打印接口但控制不了页边距和页眉页脚中文换行也经常出问题。后来我改成了“HTML 中间层 Chrome 无头浏览器打印”的方案先把 Markdown 渲染成带完整 CSS 样式的 HTML再通过 Puppeteer 调用无头 Chrome 生成 PDF。这套方案的好处是排版稳定字体颜色、表格边框、代码块高亮都能做到与预览效果一致。为了支持自定义页边距、纸张大小、页面页码等功能我还在 HTML 模板中嵌入了打印 CSS 的规则比如page { size: A4; margin: 2cm; }和相关media print样式。导出 Word 则是另一套逻辑。docx 格式本质是 Office Open XML不能直接把 HTML 塞进去。我使用解析后的 AST按块级元素转换成 docx 的 paragraph 和 table 结构。代码块使用等宽字体并添加浅灰色底纹表格使用网格线样式标题自动套用 Word 的内置 Heading 样式这样导出的 Word 文档在大纲视图里也能正常显示导航结构。有一个比较容易忽略的细节是中文字体在 Word 中需要设置w:eastAsia字体否则中文会显示为默认宋体与编辑器里的观感差异极大。我专门在生成 docx 时设置了字体映射表比如正文使用“思源宋体”或“Noto Serif SC”代码使用“JetBrains Mono”。4. 美观设计把编辑器做成“作品”而不是“工具”4.1 主题系统浅色、深色、护眼模式的设计逻辑一个编辑器好不好看第一印象来自主题。我在开发主题系统时并没有直接提供十几个花花绿绿的皮肤而是精心打磨了三个主题明亮白、夜间黑、护眼绿。明亮白主题适用于光线充足的办公室场景背景色选择的是带一点点暖灰的#FAFAF8而不是纯白。纯白背景在长时间阅读时容易产生刺眼感暖灰能缓解视觉疲劳。文字颜色使用接近纯黑但更柔和的#1F2328。夜间黑主题则避免使用纯黑背景为#1E1E2E文字为#CDD6F4并通过调整代码块、表格边框、链接颜色等细节保证暗色模式下对比度达标。护眼绿主题借鉴了古典墨水屏的配色背景是#F4F1E8文字是#4A4A45适合长时间阅读写作。主题切换并不仅仅是改两个颜色变量。不同主题下代码高亮方案、选中文字背景色、光标颜色、当前行高亮、滚动条颜色都要联动调整。为此我设计了一个基于 CSS 变量的主题 token 体系所有颜色都通过语义变量引用比如--editor-bg、--text-primary、--code-inline-bg。这样新增一个主题只需要定义一套变量不用去改组件逻辑。4.2 排版细节行高、字距、代码块样式如何影响写作体验写作体验在微观层面由排版决定。我在开发中花了大量时间调整视觉细节因为“好看”并不只是颜色搭配更受字体、行高、间距影响。正文的中文字号我设置为 16px行高 1.75段落间距 0.8em。英文和数字使用 Inter 字体中文使用系统默认字体栈PingFang SC、Microsoft YaHei、Noto Sans CJK SC这样能保证跨平台观感一致。代码块的样式也不能敷衍。行内代码的背景色使用当前主题的浅灰色并加了一点圆角和细微的内边距。块级代码的行高设置为 1.6字号比正文小一号并使用专门的代码字体JetBrains Mono 或 Cascadia Code。代码块顶部增加了语言标识的小标签和复制按钮但不抢正文的注意力。标题层级是 Markdown 文档的骨架我特意强化了标题的层级视觉差异。一级标题字体最大加粗带一条较宽的底部边框二级标题字号次之但增加了一点左侧竖线装饰。列表和引用块的缩进、间距也经过统一规划避免从大标题到正文再到列表之间的间距忽大忽小。这些细节准确地说是一种“排版洁癖”但对阅读体验的提升是潜移默化的。4.3 界面布局编辑区、预览区、文件树的平衡界面布局我在开发中推翻过三次。第一版采用了比较激进的沉浸式布局把文件树完全隐藏但实际使用中发现切文件特别别扭第二版变成了全功能三栏布局文件树编辑器预览虽然功能齐全但小屏笔记本上被挤压得厉害最终第三版采用了可配置布局默认是两栏左侧为文件树和编辑器右侧为预览区但预览区宽度可拖拽。对于喜欢纯编辑的极简主义者也可以一键隐藏文件树和预览进入全屏写作模式。在顶栏和状态栏的设计上我没有堆砌太多按钮。顶栏只保留“工作区名称、当前文件路径、搜索框、导出菜单”状态栏显示当前行号、列号、文件大小、编码格式、Git 分支状态。这样界面看起来干净但必要信息一个不少。工具栏虽然可以提升一键式操作效率但如果放太多会形成干扰所以我更倾向于把功能放入菜单或快捷键而不是全部铺在界面上。5. 实操过程与关键代码思路5.1 核心解析流程Markdown AST 与增量渲染开发过程中我逐渐意识到 Markdown 编辑器的核心难点不是解析而是“如何高效地把 Markdown 源码变成页面上的视觉反馈”。如果每次用户敲一个字符都全量解析、全量渲染文档稍长就会卡顿。我采用了解析渲染分离、增量更新的架构。具体来说编辑器内维护一份文档字符串解析器通过remark生成 AST然后自定义了一个 React 组件树把 AST 对应到可视化元素。当用户输入时CodeMirror 会提供增量变更事件我根据变更位置在 AST 中进行局部替换而不是全量重建 AST。比如只在某个段落内部新增了几个字符就只更新该段落的解析结果。这里用一个简单的思路示意function applyDelta(tree: Node, from: number, to: number, text: string) { // 遍历 AST 找到影响范围所在的叶节点 // 对叶节点段落内的文本进行局部更新 // 若影响范围跨越多个节点则合并重建这部分子树 // 返回更新后的树并记录需要重新渲染的节点集合 }渲染层同样采用细粒度更新。只有在 AST 中发生变化的节点其对应的 DOM 元素才被更新。为了做到这一点我给每个块级节点分配了一个稳定 ID然后通过 React 的key机制来精准定位需要更新的元素。代码块的语法高亮、数学公式的重新渲染也只在对应节点中触发。这样即使一个上万行的文档单次输入也只会引起一到两个 DOM 节点的变化性能表现非常稳定。5.2 性能优化长文档输入不卡顿的几种手段长文档卡顿是 Markdown 编辑器最容易挨骂的问题之一。除了增量渲染之外我还试过几种优化手段其中一些效果显著。第一是虚拟滚动。对于预览区如果文档有几千个块级节点直接用普通列表渲染会造成大量 DOM 节点。我引入了虚拟滚动列表只渲染视口内以及视口上下一定缓冲区域内的节点其他节点用占位空间替代。这样 DOM 节点数量控制在几十个左右滚动性能大幅提升。第二是防抖渲染大块内容。对于代码块、数学公式、大型表格这类“渲染成本高”的节点我不会在输入的过程中每敲一个字符就重新渲染。比如数学公式输入过程中我用一个简单的纯文本预览输入完成后约 400ms 再启动 KaTeX 完整渲染。代码块的语法高亮也采用类似策略否则长代码块输入时会一直高亮计算造成明显延迟。第三是文档读写优化。打开大文件时我使用流式读取并按行建立索引而不是一次性将整个文件转成字符串对象。保存时也不直接全量写文件而是先写入临时文件再原子替换原文件避免进程中断导致文件损坏。这些操作放在 Web Worker 中执行进一步减轻了主线程的压力保证编辑器界面始终流畅。5.3 快捷键与自动补全把编辑器调教成自己顺手的样子作为一个每天都在键盘前工作的人快捷键对我来说是效率的核心。编辑器内置了整套常见的 Markdown 快捷键例如CtrlB加粗、CtrlI斜体、CtrlK插入链接、CtrlShiftC插入代码块、CtrlShiftK插入图片。这些快捷键并不是简单地插入标记符号而是会智能判断当前光标是否已经在符号范围内。比如光标在**粗体**内部时按CtrlB会自动去掉加粗标记而不是重复添加。自动补全模块为输入体验增色不少。当我输入[并连续输入几个字符时编辑器会弹出当前工作区中文件名的补全列表方便插入相对路径链接。输入![](时自动列出当前资源目录下与已输入内容匹配的图片文件。语法补全方面表格的列数、任务列表的复选框以及行尾的换行行为都要做特殊处理。比如在列表项末尾回车时新行会自动继承列表项的标记连续两次回车才会退出列表。这些细节看起来不起眼但对输入节奏的影响非常大。由于支持自定义快捷键我还允许用户把常用的片段映射为快捷词。比如输入code加 Tab会自动展开为// code snippet这种“快捷词 Tab 展开”机制极大地加快了模板写作的效率。6. 常见问题与排查技巧实录6.1 表格语法永远对不齐试试这些检查方法用过 Markdown 的人几乎都会在表格上翻车。我最初自己写表格时也经常遇到列对不齐、渲染乱掉的情况。排查表格式问题我总结了一个检查清单。分隔行是否至少有三个短横线|---|---|是最基本的骨架缺少分隔行整个表格就不会被解析。列数是否一致表头、分隔行、每一行的单元格数量都必须相同否则解析器会按最多的列数补齐或按最少的丢弃。是否在代码块内使用了管道符管道符|在代码块或行内代码中需要转义为\|否则会被误判为表格分隔符。是否使用了不规范的空格某些从富文本复制过来的表格会在单元格前后带有多余空格一般不影响解析但如果空格内混有全角空格就可能出问题。在编辑器内部我提供了一个“格式化表格”命令可以一键将当前表格对齐。如果用户更习惯手写表格可以把这份检查清单当作口诀记一下能少走很多弯路。6.2 数学公式渲染空白一个反斜杠引发的血案数学公式报错最让人头疼的情况是明明看着像正确的 LaTeX渲染出来却是空白。我排查过大量问题后发现绝大多数错误来自几个容易被忽略的细节。一是转义问题。Markdown 本身也用反斜杠转义比如\\表示一个普通反斜杠所以如果你在数学公式中写了\frac在 Markdown 解析时可能会被吃掉一个反斜杠。解决方案是在 Markdown 源文件中写\\frac或者把公式放在代码块中。二是不匹配的定界符。$...$和$$...$$如果左右不匹配KaTeX 会拒绝渲染。三是行内公式中包含了特殊字符比如下划线、星号会被 Markdown 语法提前解析导致公式结构错乱。我给编辑器加了一个公式预览错误提示栏当检测到 KaTeX 渲染失败时会把错误信息展示在公式旁而不是静默隐藏。这样作者能立刻定位到哪一行公式出了问题排查成本大大降低。6.3 图片路径失效相对路径、绝对路径与资源文件夹图片路径问题不只是新手会遇到老用户也常踩坑。使用相对路径时需要注意 Markdown 文件所在目录和图片目录之间的层级关系。假设你的文档在/docs/guide.md图片在/docs/assets/foo.png那么在文档中要写![](assets/foo.png)而不是![](images/foo.png)。如果文档在/docs/sub/guide.md而图片在/docs/assets/foo.png就需要写![](../assets/foo.png)。绝对路径比如D:\myblog\public\img\foo.png在本地环境下没问题但一旦上传到 GitHub 或者部署到网站路径就失效了。我推荐的方案是使用相对路径并且按照“每篇文章一个资源子目录”的方式组织资源文件例如assets/文章名/图片序号.png。这样即使整个目录打包发送图片也不会丢。在编辑器中用户可以直接拖拽图片到文档中编辑器会自动复制图片到资源目录并生成相对路径。如果发现手动输入的路径失效编辑器会在图片位置显示一个占位图标并在状态栏提示“图片加载失败”双击占位图还能弹出路径修复面板。6.4 导出 PDF 字体缺失为什么别人电脑上排版全乱了导出 PDF 时遇到的另一个高频问题是字体缺失。在 Windows 上默认中文字体通常是宋体或微软雅黑在 macOS 上是苹方在 Linux 上可能是 Noto Sans CJK。如果你的文档指定了某个字体而目标阅读者的电脑上没有安装那么 PDF 中的字体就会回退到默认字体排版错乱几乎是必然的。我通过两个手段解决这个问题。一是在导出 PDF 时将字体文件直接嵌入 PDF。Puppeteer 打印时会携带 WOFF/TTF 字体资源所以只要 HTML 模板正确引用了本地字体文件生成的 PDF 就能在不同系统上保持一致观感。二是在 HTML 模板中设置合理的字体回退栈让每个系统都能至少找到一款风格接近的字体。比如body { font-family: Inter, PingFang SC, Microsoft YaHei, Noto Sans CJK SC, Source Han Sans SC, sans-serif; }这样做能保证即便在完全陌生的系统上打开也不会渲染出奇形怪状的排版。对于 Word 导出也有类似问题我会在导出时显式嵌入常用中文字体以免换台电脑后 Word 里中文全部变成默认宋体。7. 后续扩展与个人心得7.1 从编辑器到写作工作台还可以加些什么开发到目前的版本编辑器已经能较好地解决我日常写作和文档交付的需求。但我也很清楚它距离一个“完整的写作工作台”还有明显距离。下一步我计划加入更多能力包括集中管理文档标签和关键词的元数据面板、基于全文搜索的快速跳转、以及更强大的导出模板系统。另外我还在考虑支持 Git 可视化操作让用户直接在编辑器内查看文件变更、提交代码而不必切换到第三方客户端。有一个我特别想做的功能是“内容复用模块”。写作过程中经常需要插入类似的代码片段、表格或者提示框如果能预先构建一组常用模块写作时只需输入模块名并 Tab 补全效率能提升很多。类似 Notion 的“模板按钮”理念但完全基于 Markdown 语法透明地展开不引入私有格式。7.2 我踩过最深的一个坑渲染状态与源码不同步最后分享一个我开发中踩过最深的坑。早期版本我为了保证富文本编辑体验在编辑器内部使用了独立的渲染状态每次用户操作都先修改渲染状态再把状态同步回 Markdown 源码。这个设计在初期看起来很美好但一旦遇到复杂的输入场景比如输入法组合字符、拖拽多选区、自动补全就会出bug界面看到的内容和源码不一致保存后 Markdown 被搞乱用户完全不知道问题出在哪一步。后来我彻底推翻了这套设计所有交互都回到“直接修改 Markdown 源码再重新解析渲染”这条路上。虽然改动更大但数据一致性得到了根本保证。这也算是一个重要的经验编辑器内部可以有自己的优化但最终存储和交换的格式必须是最初的源文本不能出现另一个“隐藏的真相”。如果你也在开发类似的工具我建议你尽早确定好数据流方向把所有交互都收敛到“源码是唯一事实来源”这条原则上后续会少掉无数头疼的问题。Markdown 的透明性正是它的魅力所在作为编辑器开发者我应该珍惜并保持这种透明性而不是在它上面叠加一层不透明的黑盒。从最初的一个小工具原型到现在能够陪伴我每天写作的编辑器这个过程本身让我受益很多。它让我重新审视了自己对效率工具的诉求也让我更加坚信一个好的写作工具必须能透明地反映内容本身同时又不打扰思路。希望我的这些经验和踩坑记录能对同样在寻找“趁手工具”的你有所帮助。
返回列表