恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

自研Markdown编辑器:从需求到实现的技术全解析

  • 首页
  • 资讯中心
  • /
  • 自研Markdown编辑器:从需求到实现的技术全解析

相关资讯

嵌入式系统错误码模块设计与实现指南 2026/9/15 3:04:55
C++开发者必备:基于问题域的崩溃堆栈与VSCode配置记录系统 2026/9/15 3:04:55
JavaScript图片预加载实战:从浏览器缓存到解码优化的完整指南 2026/9/15 3:04:55

最新资讯

大文件传输怎么选?场景拆解与工具推荐
哲学与数学的跨界探索:MHCR框架下的黎曼猜想研究
Spring Boot + Vue 共享厨师预约平台:全栈设计与实践指南
Flutter与OpenHarmony融合开发纸牌游戏实践
用JavaScript实现可视化表单设计器:从JSON Schema到低代码平台
RS485与Modbus本质区别:物理层电线 vs 协议层语言

今日推荐

GDPR下大数据架构重构与隐私保护实践
多组学数据平台架构设计与优化实践
企业主数据管理系统架构设计与实施全解析

本周热门

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化
Flutter应用改名全指南:从Android到iOS的配置与工具实践

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

自研Markdown编辑器:从需求到实现的技术全解析

发布时间:2026/9/15 3:04:55
自研Markdown编辑器:从需求到实现的技术全解析 作为 Markdown 重度用户我每天泡在编辑器里的时间比睡觉还长。这些年试过 Typora、VS Code、Obsidian各有各的好也各有各的让人抓狂。最要命的是没有一个能同时满足我对“好看”和“彪悍”的执念——要么界面美滋滋但功能软绵绵要么强得离谱却丑得伤心。折腾到最后我索性自己动手写了一个 Markdown 编辑器。这篇文章聊聊这个项目的来龙去脉、技术选型、核心功能和踩坑实录给同样动了自研念头或者正在纠结选型的朋友一点参考。先说结论这个编辑器我现在每天都在用用来写技术文档、博客草稿、读书笔记甚至周报。整个过程从零开始前后迭代了快半年。我会把从需求梳理到架构设计再到几个最棘手问题长文档性能、中文输入法、图片路径、表格编辑的排查思路都摊开讲不藏着掖着。1. 为什么一个 Markdown 重度用户会赌气写自己的编辑器1.1 我的一天几乎全泡在 Markdown 里工作日的典型状态是这样早上打开电脑先写当天的 TODOMarkdown开会记笔记Markdown写接口文档Markdown下午整理调研资料Markdown晚上写公众号草稿还是 Markdown。算下来一天至少四五个小时是在 Markdown 文档里度过的。这种使用频率下编辑器的一点小毛病都会被无限放大。比如某个渲染效果差几个像素、某个操作要多点两下鼠标、某个大文档滚动起来掉帧都会变成每天都要忍受的刺。很多人觉得编辑器能用就行但重度用户不一样我们是真的会因为一个光标定位的小问题就烦躁一整天。而且 Markdown 的生态有个很有意思的现象语法极其简单但每个人用到的子集很不一样。程序员爱写代码块和表格写作的人爱用引用和加粗学生党离不开数学公式。大众编辑器为了照顾所有人往往做成“什么都有但什么都不精”这恰恰是我受不了的根源。1.2 市面编辑器各有各的刺列个清单我把自己真实用过的几款编辑器做了一次复盘不吹不黑把痛点列在下面编辑器优点让我崩溃的点Typora界面干净实时预览体验好闭源且收费自定义能力有限大文件偶尔卡VS Code 插件功能强大插件生态丰富本质上还是代码编辑器写作体验和排版质感差一些Obsidian双链笔记逻辑好插件多太重启动慢不写笔记光写文档时有点杀鸡用牛刀Notion页面漂亮协同强不是纯 Markdown导入导出经常走样各种在线编辑器免安装要登录要联网隐私上不踏实你发现没有这些产品的痛点不是单独存在的而是“好看”和“彪悍”互相打架。Typora 算是最接近我理想的但它不是开源软件我想加一个自定义渲染规则、想改某个主题细节都无从下手。Obsidian 功能确实猛但那个启动速度和插件加载的体感始终让我觉得自己不是在写作是在运行一个大型软件。1.3 一个需求清单到底什么才是“好用”在动手写代码之前我花了两周时间列需求清单。没错不是先写代码是先在纸上想清楚自己要什么。我给自己设了一个标准如果这个功能不能让我的写作体验产生“可感知的提升”就不做如果三个功能之间有重叠只保留最核心的那个。最终清单被压缩成下面几条外观足够好看排版接近印刷品质感长时间看屏幕不累实时渲染也就是“所见即所得”但也要能一键切到纯 Markdown 源码模式支持数学公式、代码高亮、目录大纲、全文搜索这些高频硬需求图片粘贴要自动落盘成文件绝对不能偷偷变成 base64 塞进文档里单个文档几十 KB 甚至几百 KB 时编辑和滚动都不能有明显卡顿自动保存要聪明不闪存、不丢数据、不把磁盘写爆不搞私有格式文章就是一个普通的.md文件我用 Git 管理也行用网盘同步也行这份清单后来成了整个项目的“宪法”每次纠结要不要加功能就拿出来对照一下。事实证明这个动作省掉了大量不必要的返工。2. “好看”不是玄学界面、主题与排版工程2.1 设计目标让人忘记界面存在我很喜欢一句话好的工具设计是让工具消失。写作的时候你的注意力应该全部在文字上而不是在那个界面边框、那个按钮、那条滚动条上。所以我给这个编辑器的视觉设计定了一个方向——低存在感。所谓低存在感落实到界面就是默认主题不适合太花哨颜色对比度要克制字体和间距要以阅读舒适为最高优先级。很多编辑器喜欢在侧边栏、状态栏、按钮上加各种渐变和阴影这些在我眼里全是噪音。哪怕是功能面板我要求它们默认收起来。打开软件见到的是一个完整的书写页面不是一堆工具按钮。需要目录大纲就按一下快捷键呼出用完自动隐藏。这种“用完即走”的交互看似简单实际上是从 Obsidian 那种“什么都在桌上摆着”的模式里学到的反面教训。2.2 从设计令牌到主题系统主题系统是“好看”的骨架。我做的第一件事不是直接调 CSS而是把所有可变的视觉参数抽象成设计令牌Design Token。简单说就是定义一堆 CSS 变量界面里所有颜色、字体、间距、圆角都引用这些变量不出现任何硬编码值。:root { /* 背景层次 */ --bg-primary: #fefefe; --bg-secondary: #fafafa; --bg-tertiary: #f0f0f0; /* 文字层次 */ --text-primary: #1f2328; --text-secondary: #57606a; --text-tertiary: #8c959f; /* 强调色 */ --accent: #0969da; --accent-soft: rgba(9, 105, 218, 0.12); /* 排版 */ --font-serif: Source Han Serif SC, Noto Serif CJK SC, serif; --font-sans: Source Han Sans SC, Noto Sans CJK SC, sans-serif; --font-mono: JetBrains Mono, Fira Code, monospace; --line-height: 1.75; --content-width: 720px; }暗色主题不是简单把背景变黑、文字变白而是重新设计一整套对比度关系。亮色主题里最深的背景色是#fefefe暗色主题里最浅的文字色就要换成#e6edf3强调色也要从深蓝变成更亮的蓝。只有把握好这三四个层次的配比暗色主题才不会有“发光”感盯久了才不会累。主题切换我直接用了监听系统偏好和手动切换两套逻辑系统偏好变化时自动响应。这个在 CSS 里就是一行prefers-color-scheme配合我的设计令牌几乎不需要写额外的切换代码。2.3 排版实验一屏文字如何不累眼“好看”的另一个核心是排版。Markdown 编辑器本质上是把结构化的文本渲染成带样式的页面排版质量直接决定观感。我花了很多时间在几个细节上面。正文区域宽度限制在 720px 左右。这不是拍脑袋定的而是参考了大量阅读类产品的经验。太宽了行太长眼睛扫到下一行容易混太窄了分段太频繁翻页速度过快。720px 适合中文阅读默认字号 16px行高 1.75字间距加了一点点段落间距用 margin 控制而不是空行。标题的层级感靠“减法”H1 用字号加粗加大H2 字号略小但加一个底部边框H3 之后只靠字号区分不再增加装饰。引用块用左边框加柔和底色不搞大色块代码块用等宽字体加圆角和浅灰底行内代码用强调色背景加圆角但不用加粗。为了让排版在不同平台上保持一致我还在字体回退栈上做了大量工作。Windows 上优先用微软雅黑macOS 上优先用苹方Linux 上回退到思源字体。如果你跨平台用过同一个编辑器就会懂Windows 和 macOS 渲染同一段中文行高差异能直接导致滚动错位和光标跳动。后面有一章我会细讲这个坑。3. “彪悍”的核心自研实时排版与渲染管线3.1 文档的抽象语法树与双向映射外观只是皮真正让编辑器“彪悍”的是底层那套排版和渲染机制。我没打算真的从零写一个排版引擎而是站在巨人的肩膀上用成熟的 Markdown 解析库把文本解析成抽象语法树AST然后自己写渲染器把 AST 渲染成界面。整个过程分三层Markdown 源文本 ↓ 解析器parser Abstract Syntax TreeAST ↓ 渲染器renderer DOM 节点所见即所得视图为什么要中间加一层 AST因为这样我就能做到“双向映射”用户在界面上改一个字我能知道这个字对应的是 AST 里哪个节点的哪段文本反过来用户改源码我能立刻知道要重新渲染哪一块区域。这个能力是增量更新和大文档性能优化的基础。解析器我选了 remark 系列生态成熟AST 规范插件也多。渲染器我自己写因为只有自己写才能完全控制输出样式。比如我要给标题加锚点、给代码块加复制按钮、给链接加外部跳转图标这些统统可以在渲染器里注入。3.2 数学公式、代码高亮与表格编辑数学公式是很多编辑器翻车的地方。我的方案是 KaTeX选它不是因为它渲染效果最精致而是因为它的速度和体积最优。LaTeX 公式在界面上必须先经过一遍 KaTeX 渲染成 HTML再嵌入到文档流里。实时输入场景下用户每敲一个字符公式都要重新渲染一次如果这一步慢整体输入体验会立刻变得黏黏糊糊。代码高亮我对比过三种方案Prism、Highlight.js、Shiki。Shiki 用的是 VS Code 的 TextMate 语法高亮效果最接近 IDE但那套 JSON 语法文件加载起来实在太重光是加载语言定义就得好几百 KB。最终我选了 Prism自己定制了一套颜色变量让它跟亮色、暗色两套主题联动。表格是最麻烦的。大多数 Markdown 编辑器的表格都是渲染成静态 HTML 表格点击单元格后整个切到源码模式编辑体验很割裂。我做了个“双击进入网格编辑”的模式双击表格区域后每个单元格变成一个输入框撑开一个类 Excel 的编辑网格失焦后自动写回 AST 并重新渲染。虽然工作量比想象中大但这个功能一出来整个编辑器的“彪悍”名号就立住了。3.3 图片从粘贴落盘到导出图片处理是 Markdown 编辑器最容易被忽视但又最容易翻车的功能。截图之后直接 CtrlV这是写作场景里最高频的操作。很多编辑器默认把图片以 base64 的形式填入文本看着很方便实际上埋了巨大的雷。我的方案是捕获粘贴事件判断剪贴板里是否有图片文件有就自动保存到当前文档同级的assets目录文件名用时间戳加随机串然后在文档里插入相对路径。这样文档和图片都在同一个文件夹里用 Git 管理、用网盘同步都没问题换设备打开也能正常显示。同时我在设置里提供两种图片路径风格可选相对路径和纯文件名。用 Typora 的人可能知道它默认是用./assets/xxx.png这种形式我这边默认也走同样逻辑。导出时这些相对路径会统一解析成可嵌入的本地文件或 base64保证 Word、PDF 里图片不丢。4. 架构选型为什么是 Electron TypeScript 而不是别的4.1 跨平台桌面方案的取舍编辑器项目的第一步是选桌面壳子。我当时认真评估了三条路线Electron TypeScript开发效率高生态成熟内存占用稍大Tauri Rust打包体积小内存低但要额外学 RustWebView 兼容性在不同 Linux 发行版上像开盲盒纯 Web App直接用浏览器的 File System Access API免安装但浏览器兼容性和文件系统权限都是问题我最后选了 Electron TypeScript。说实话Tauri 的轻量真的很诱人但开发周期长而且我当时主业不是 Rust切语言会拖慢进度。Electron 的 V8 渲染性能对这个场景完全够用桌面 API 也齐全配合 TypeScript 的静态类型检查重构起来至少不会心里发虚。这里有一个个人建议如果你也想做同类项目不要一上来就追求“终极技术形态”先看自己手里有多少时间以及顺手的技术栈是什么。工具是拿来用的不是拿来秀肌肉的。4.2 存储策略Markdown 文件永远是唯一真实源很多笔记软件喜欢用数据库或者私有格式存内容渲染和展示再另存一份副本。我对这种事非常有戒心——万一软件打不开了我的笔记怎么办我的核心原则是磁盘上那个.md文件永远是唯一真实源界面上的所有内容都是它的投影。这样一来目录结构就是我的文档管理逻辑文件名就是标题文件夹就是分类。我可以用任何其他工具打开这些文件内容绝对可读而不是一堆加密的 sqlite 二进制。这个决定直接影响了很多后续设计不建私有索引数据库全文搜索直接扫目录里的.md文件大纲目录也从 AST 动态生成不需要额外存储。好处是换机、迁移、备份都极其简单坏处是全文搜索的性能要靠自己优化这个后面讲。4.3 自动保存与大文件保护自动保存是编辑器体验的生死线但“无脑自动保存”会带来两个问题一是频繁写盘缩短固态硬盘寿命二是写盘时的卡顿会影响输入体验。我的实现是三层策略第一层击键后 1.5 秒防抖时间到了才触发保存逻辑第二层保存前把当前内容做一次 hash和上次保存的内容做比对内容没变就直接跳过写盘第三层写盘方式不是简单writeFile而是先写到临时文件再改名替换原文件这样即使中途断电原文件也不会损坏。大文件保护这块我设置了一个阈值文档超过 1MB 自动进入“大型文档模式”。这个模式下实时预览的粒度变粗部分重型插件延迟加载同时提示用户手动关闭代码高亮或者数学公式用空间换速度。实测下来一个 2MB 的日志型文档开启大文件模式后编辑流畅度提升了将近五倍。5. 性能优化的两次关键战役长文档和中文输入法5.1 十万字文档从卡顿到跟手最早版本写完后我拿一篇十万字左右的文档做压力测试结果惨不忍睹输入一个字界面要等一两秒才刷新滚动页面时 CPU 直接飙到 100%。问题的根源在于我把整个文档的 AST 变化都反映到 DOM 上一次编辑会触发整篇文档重新渲染。解决思路是“分块渲染”。我把 AST 按块级节点拆成很多块每次编辑只重渲染变更所在的块其他块完全不动。配合虚拟滚动浏览器视图窗口外部的块直接不渲染滚动时动态回收和创建。这个方案落地后十万字文档的编辑延迟从秒级降到了毫秒级。虚拟滚动的实现坑很多。比如滚动条的高度计算要用阈值估算不然渲染内容变了滚动条长度会一直跳动又比如滚动到末尾时要准确判断“最后一块是否已经完整露出”否则会出现滚动到底部还差一段的错觉。这些细节没有一个现成库能直接帮我解决全是靠一遍遍实际体验、一点点调出来的。另外一个容易被忽略的优化是contenteditable里的选区恢复。在“所见即所得”模式下高亮、公式、代码块这些原子节点不能把光标放进去用户上下左右移动光标时要提前拦截并跳过整个原子节点。这个逻辑写不好光标就会“钻进”代码块内部整个编辑体验瞬间崩盘。5.2 中文输入法组合输入下的光标保卫战中文用户最痛苦的技术问题之一中文输入法上屏时编辑器的实时渲染会疯狂打断组合输入。你打“zhongwen”的时候预览区域会按照拼音片段疯狂猜测、重新渲染页面闪个不停更严重的是光标可能直接被重渲染冲掉字还没上屏就丢了。这个问题的本质是输入法在组合输入阶段会持续生成compositionstart到compositionend之间的一系列事件。如果编辑器每收到一个事件就触发 AST 解析和 DOM 更新那中路截胡几乎是必然的。我的解法是监听compositionstart进入“输入法组合态”暂停所有实时渲染组合期间只做文本累积不碰 AST不碰选区监听compositionend等输入法把最终字符上屏后一次性完成解析、渲染、选区恢复这套逻辑必须同时处理代码编辑器的底层操作因为用户在源码模式下的中文输入同样会出现这个问题。我一开始只处理了所见即所得模式后来测试发现源码模式也有同样症状又补了一遍。这也算是一个典型的“自己写编辑器才碰得到的坑”。6. 编辑器开发中那些“文档里查不到”的坑6.1 表格编辑与光标定位的相爱相杀表格的网格编辑模式上线后我遇到了一个非常诡异的问题当表格有合并单元格或者某一列特别宽时点击单元格定位光标光标跑到完全不相干的位置去。排查了半天最后发现根子出在contenteditable二维表格结构上。浏览器的光标定位逻辑天然是为线性文本设计的一旦 DOM 是二维表格它会在内部做个坐标转换而不同浏览器的转换公式不一致。更不要提表格单元格里的换行我以为输入 Enter 是换行浏览器直接给我新开了一行表格行整个版面全乱了。解决办法是把所有表格操作都拦在键盘事件层级。Enter 键被重写成“在单元格内部插入换行”而不是“新增表格行”Tab 键被重写成“跳到下一个单元格”方向键根据当前光标位置判断是否跨界跨界的瞬间手动计算下一个单元格的光标坐标。这些代码写起来很繁琐但每一条都是真实使用场景里磨出来的。6.2 Base64 图片一秒钟把文件变成怪兽接着前面图片处理的话题我再详细聊聊 base64 这个问题。截图粘贴后把图片编码成 base64 字符串塞进.md文件这个做法早期版本不小心放过一次进入生产代码。测试的时候发现一个只有 20 行的文档因为嵌了一张 2MB 截图整个文件膨胀到接近 3MB尤其是中文内容加 base64 混排渲染器和 Git diff 全部变慢。更隐蔽的问题是搜索。base64 字符串里面有大量无意义字符如果用户搜索某个中文关键词Markdown 全文搜索会把 base64 也遍历一遍性能直接爆炸。所以我后来加了严格规则解析图片链接时一旦发现data:image开头的内容直接跳过不索引同时在导出时提醒用户“文档中包含内嵌图片建议转成本地文件”。这个坑提醒我编辑器是给写作者用的不能因为自己图省事把底层数据结构搞得很脏。数据源干净后续功能才有做好的可能。6.3 跨平台字体渲染差异的血泪教训项目开发到后期我把编辑器打包给几位朋友测试。结果同一个文档Windows 上滚动顺滑macOS 上滚动微卡macOS 上光标定位精准Linux 上光标往下偏了半个字。这些都是字体渲染差异引发的连锁反应。核心原因是不同平台的字体指标不一样。微软雅黑和苹方在相同字号下的行高、基线位置都有区别。如果 CSS 里写死line-height: 1.75Windows 和 macOS 显示的实际高度也可能不同导致滚动容器高度算不准虚拟滚动就会出问题。我的解决办法是给每个平台单独定义一套排版变量在应用启动时检测平台类型再覆盖默认值。同时开启text-rendering: optimizeLegibility让中文笔画渲染更平滑。这个坑给我最大的教训是跨平台应用永远不要只在自己熟悉的平台上测试不同系统的渲染引擎有各自的脾气。7. 后续规划给编辑器装上更聪明的脚目前的版本已经足够日常使用但仍然有很多想做的方向。一句话总结就是“更聪明更懂写作者”。第一个方向是全文索引。目前搜索走的是文件遍历加正则匹配小目录没问题几千个文件时会有明显延迟。打算接一个轻量级倒排索引中文分词是难点想先用粗糙的二元分词顶着后续再优化。第二个方向是模板系统。写博客和写周报的排版习惯完全不同我想让编辑器支持“文档模板”新建笔记时选择模板模板定义好的标题层级、示例段落、常用代码块结构都自动生成用户只需填充内容。第三个方向是导出生态。目前已经支持 PDF、Word、HTML 和剪贴板富文本但 Word 的导出偶尔还是会有样式偏移这块准备引入更强大的转换引擎顺便支持自定义 CSS 控制导出效果。第四个方向是定位到块级引用。类似 Notion 那种“引用一个段落”的能力在 Markdown 语境下可以用块级链接实现。不过这个方案要谨慎如果做不好容易把纯文本生态搞复杂我自己还在权衡。最后一个方向是关于项目本身的哲学。做这个编辑器的过程让我明白很多“想要的功能”其实经不起推敲真正高频的永远是那几件事打开、写字、存盘、导出。把这几件事做到极致比堆一百个炫技功能更重要。我在实际使用中最常被问到的一句话是值不值得花这么多时间自研编辑器毕竟现成工具那么多。我的回答是如果你也是一个对效率和美感有执念的重度用户值得试一次。就算最后只写了个残废版本你也会在过程中重新梳理自己的工作流明白自己真正离不开的到底是哪几个功能。这种掌控感和清醒感现成工具永远给不了。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号