如果想在 V2EX 获得更好的推广效果,欢迎了解 PRO 会员机制:
https://www.v2ex.com/pro/about

如果你经常使用铜币置顶主题,持有 V2EX Solana Token 会在每日签到时获得额外铜币:
https://www.v2ex.com/solana
1244943563
V2EX  ›  推广

做了三年 ProseMirror 后,我用四个月自研排版引擎实现 WPS / Google Docs 替代品,整套框架 MIT 开源

  •  3
     
  •   1244943563 · Oct 28 · 3108 views

    先别急着划走,这不是概念图,也不是拼出来的截图。

    打开 https://quirekit.com/demo/classic-editor,首屏就是一个真实的编辑器:一页一页的纸,打字、换行、表格跨页、切换 Canvas / SVG 渲染,全都是实时的。

    演示里的 DOCX 导出、页眉页脚等是商业 Word 组件,编辑器框架、排版引擎和编辑器本身是开源的。

    先交代下背景:我做 ProseMirror 相关的产品已经三年了,被问得最多的一句就是“能不能像 Word 一样一页一页地排”。可开源的富文本编辑器基本都做不到。今年 6 月我决定自己从头写,四个月下来,做出了 QuireKit。

    它不是某一个编辑器,而是一整套编辑器生态:

    • 最底层是两套编辑器框架,写法都是 Tiptap 风格:一套基于 ProseMirror ,API 兼容 Tiptap ;一套基于 CodeMirror ,专门做 Markdown ;
    • 中间是自研的排版引擎、Canvas / SVG / HTML 等多种视图,以及一套统一的 UI 组件库;
    • 最上层是能直接用的编辑器:分页文档、块编辑器、Markdown 编辑器,还有公式、思维导图、白板、流程图这些周边编辑器。

    每一层都可以单独拿去用,也可以整套组合起来。一句话说它能干嘛:用它,你可以在自己的网页应用里嵌入一个像 WPS 、Google Docs 那样的文档编辑器。

    先说做出了什么

    1. 浏览器里真正分页的文档编辑器

    做过在线文档的都知道,浏览器只会排一条无限长的页面。想要“一页一页的纸”,常见做法是排完再量高度、手动切页,内容一改就全乱。

    QuireKit 的分页编辑器不靠 DOM 排版:断行、分页、光标、选区全部自己算,再画到 Canvas 或 SVG 上。屏幕上看到的分页,就是打印出来的分页。

    • 表格可以跨页,表头自动重复
    • 公式、流程图、思维导图、白板直接放进页面里一起排版
    • 暗黑模式、中英文界面切换
    • 长文档只绘制看得见的页,滚动不卡

    操作面板也不是摆设。我按 Word 的功能区逐项对过一遍:开始、插入、页面、引用、审阅、视图,加上右键菜单、格式设置面板、表格和图片的上下文工具,已经有 350+ 功能能直接在界面上点出来用,还在继续补。

    DOCX 往返也打通了:Word 、WPS 写的文档导进来,可以接着改,再导出成 DOCX ,拿回 Word 里继续用。

    PDF 和 OFD 导出也是自研的:不走浏览器打印,直接复用分页排版画出来的那一份绘制指令,屏幕上一页什么样,导出的 PDF / OFD 就是什么样。OFD 是国产版式文件格式,政务、公文场景用得多。

    DOCX 往返和 PDF / OFD 导出属于商业的 Word 组件,开发和评估免费。

    2. 块编辑器

    不需要分页的场景,比如笔记、知识库,用块编辑器:拖拽、斜杠菜单、表格、目录都有。

    它解决了一个用过 contenteditable 的人都踩过的坑:你选中一段字,去工具栏输个链接,选区就没了。 在 QuireKit 里,光标和选区是自己画的,焦点跑到输入框,选区照样在。

    3. Markdown 编辑器:原文一个字不丢

    MD Editor 有四种视图:文档、实时预览、源码、阅读。前三种都能直接编辑,改的都是同一份 Markdown 原文,中间没有转成 JSON 再转回来,所以保存时你没碰过的行,一个字符都不会变。

    大文档也不怕。我给 Markdown 解析器加了一个“复用证明”,编辑时直接跳过没变的部分。1 MiB 的文档连续输入 20 次,实测:

    工作量 优化前 优化后
    语法树访问 107,760 1,380 (**少了 98.7%**)
    语法树比较 153,940 660 (**少了 99.6%**)

    4. 一整套周边编辑器,单独也能用

    公式、思维导图、白板、文本绘图( Mermaid / PlantUML / Graphviz )、流程图、图表、多维表格,每一个都是独立的包,不用整个编辑器也能单独装。

    5. 自己设计的 UI 组件库

    编辑器的操作界面比一般后台复杂得多:字体菜单、颜色选择、表格右键菜单、格式设置对话框、缩放、快捷键提示……为了让分页文档、块编辑器、Markdown 编辑器和这些周边编辑器用起来是同一种手感,我单独设计了一套 UI 组件库( Vue + UnoCSS ),颜色、间距、字号都由同一套设计令牌管理,亮色和暗黑两套主题一键切换。

    上面截图里所有的按钮、菜单和面板,都来自这套组件库,它同样是 MIT 开源的,可以单独用在你自己的项目里: https://design.quirekit.com

    再说说最难的一块:中文输入法

    Canvas 上没有输入框,中文输入法是最难啃的骨头。拼音还没确认的时候,字要先显示出来、把后面的内容往后推,但又不能进撤销历史、不能同步给协作者。

    我的做法是:输入法组合期间,用一份“临时文档状态”去排版和绘制,等你按下确认才真正写进文档。

    浏览器在输入法上的坑非常多,事件数据为空、组合结束事件不来、确认后重复插入……这套处理我单独做成了 @quirekit/ime 包,其他 Canvas 编辑器也能直接拿去用。

    底层:两套 Tiptap 风格的编辑器框架

    • **ProseMirror 线:@quirekit/core**。保留 ProseMirror 的文档模型、命令、插件、协同,API 兼容 Tiptap ,目标是迁移一个 Tiptap 扩展时,主要只需把 @tiptap/core 的导入换成 @quirekit/core。不同的是视图层:除了原生的 DOM 视图,还能挂自己排版的 Canvas / SVG 视图(分页文档用的就是它),以及自己管光标和选区的 HTML 视图(块编辑器用的就是它)。
    • CodeMirror 线:MSFE。基于 CodeMirror 和 Lezer ,Markdown 原文就是文档,扩展和命令的写法也是 Tiptap 风格。MD Editor 构建在它上面。

    两套框架的成品共用一套 UI 组件库,所以分页文档、块编辑器、Markdown 编辑器看起来是一家人。熟悉 Tiptap 的话,两条线都能很快上手。

    能用吗?怎么用?

    几行代码就能把 Markdown 编辑器放进 Vue 项目:

    npm install @quirekit/md-editor@alpha
    
    <script setup lang="ts">
    import { MdEditor } from '@quirekit/md-editor/vue'
    import '@quirekit/md-editor/styles.css'
    </script>
    
    <template>
      <MdEditor markdown="# Hello" label="Document" />
    </template>
    

    块编辑器和分页编辑器分别是 @quirekit/block-editor、@quirekit/classic-editor。

    整套生态里开源的部分,MIT 许可,闭源商用也可以:两套编辑器框架、Canvas / SVG 排版引擎和各种视图、UI 组件库、分页 / 块 / Markdown 三个编辑器,以及公式、导图、白板这些周边编辑器。Word 兼容能力( DOCX 往返、PDF/OFD 导出、审阅等)是单独的商业组件,开发和评估免费,不用它们也能完整使用编辑器。

    目前是 alpha ,API 还会变,欢迎来试、来挑刺:

    觉得有意思的话,点个 Star 就是对我最大的支持。

    50 replies  •  2026-10-31 23:25:01 +08:00
    MHPSY
        1
    MHPSY  
       Oct 28
    体验了一把 很完善 star 了
    iawes
        2
    iawes  
       Oct 28
    看起来很牛逼,虽然不知道我用不用得到,先一键三连
    honkew
        3
    honkew  
       Oct 28
    感觉渲染的不够清晰 不知道是不是错觉
    1244943563
        4
    1244943563  
    OP
       Oct 28
    @honkew 你是对的,我忘记加 2 倍清晰度了,感谢感谢,我在官网接入的问题
    jinxgogo
        5
    jinxgogo  
       Oct 28
    之前用过 ProseMirror ,点了
    hydraegret
        6
    hydraegret  
       Oct 28
    好强大 star
    RexKang
        7
    RexKang  
       Oct 28
    真给力~~
    GGbeng1
        8
    GGbeng1  
       Oct 28
    必须点赞,早期移植 onlyoffice 费心费力
    zl157394168
        9
    zl157394168  
       Oct 28
    只有之前深入做过编辑器、canvas 相关的,才知道这个开源项目有多牛逼,太强了👍
    donggenmu
        10
    donggenmu  
       Oct 28
    我在公司就是负责编辑器项目的,只能说很牛逼了,学习了
    menglizhi2333
        11
    menglizhi2333  
       Oct 28
    同样做编辑器,知道这有多艰难,题主能将作品开源,实在太牛了
    1244943563
        12
    1244943563  
    OP
       Oct 28
    @menglizhi2333 感谢认可,共同学习
    1244943563
        13
    1244943563  
    OP
       Oct 28
    @donggenmu 感谢认可
    1244943563
        14
    1244943563  
    OP
       Oct 28
    @GGbeng1 哈哈哈 感谢感谢
    1244943563
        15
    1244943563  
    OP
       Oct 28
    @RexKang 必须的,技术平权时代来了
    1244943563
        16
    1244943563  
    OP
       Oct 28
    @hydraegret 感谢感谢
    1244943563
        17
    1244943563  
    OP
       Oct 28
    @jinxgogo 非常感谢
    davidoff567
        18
    davidoff567  
       Oct 28
    nb , 已 start
    aimuz
        19
    aimuz  
       Oct 28
    这个语气,很像 AI 写的描述
    passive
        20
    passive  
       Oct 28 via Android
    技术上我赞同,但是难道就我觉得这些截图排版丑吗?
    1244943563
        21
    1244943563  
    OP
       Oct 28
    @aimuz 你说的没错,我给他大纲,让他写,写完让他改,自己写不了一点 哈哈哈哈哈
    1244943563
        22
    1244943563  
    OP
       Oct 28
    @passive ┭┮﹏┭┮ 模型能帮我把图合起来不需要人来合并就很不错了,我不会有过高的要求
    1244943563
        23
    1244943563  
    OP
       Oct 28
    @davidoff567 感谢
    bihui
        24
    bihui  
       Oct 28
    厉害可以商用吗
    viweei
        25
    viweei  
       Oct 29
    👍 看你的描述,输入端是用 Canvas 绘制了,为什么还依赖 vue? 直接从原生搓不是更好么
    1244943563
        26
    1244943563  
    OP
       Oct 29
    @viweei vue 只是用来做 UI 的,框架层并不依赖 vue ,也不依赖 UI ,想要基于底层做个示范的成品出来,于是做了一套生态,全都搓肯定不现实,有好几个图形编辑器,数学编辑器,还有 markdown block-editor 😂,选择某个 UI 框架是必要的,之前想过是 web component ,但是还不知道结果会怎么样,还是选择成熟的稳一点
    1244943563
        27
    1244943563  
    OP
       Oct 29
    @bihui 框架层可以,目前有 145 个开源的包,还有一部分留给商业化做了后路,不过用框架费点时间精力是能搓出来一模一样的东西的
    jiuzhougege
        28
    jiuzhougege  
       Oct 31
    赞一个
    1244943563
        29
    1244943563  
    OP
       Oct 31
    @jiuzhougege 感谢
    v2eing
        30
    v2eing  
       Oct 31
    真厉害,必须给个赞。
    1244943563
        31
    1244943563  
    OP
       Oct 31
    @v2eing 哈哈哈 感谢感谢
    firefox12
        32
    firefox12  
       Oct 31
    我看不懂啊, 就是想问一下,一些在我心中的疑惑, 你这个是一个自己写的 排版渲染系统 还是基于浏览器的系统?我的理解 如果是你独立写的,可以无缝 平移到 windows linux mac 上做一个客户端,还是说是建立在浏览器上的 chrome , 那么不同的浏览器 会不会不一样 比如 firefox, 这种。 如果是独立的渲染系统 生成的标准的 svg, 那么就不会受到 css 渲染规则的影响,无论哪个平台 那个系统都应该一样吧。

    还有就是 doc365 所作的过程也让我很迷惑, 那时候用 doc365, 网页上就基本上能和本地 word 有 1:1 的效果了,但是本地 word 的资源是很大的, 一个浏览器是怎么做到的, 我监控了流量 发现 并没有太多 rpc 和服务器交互,那种复杂的渲染效果,后端是怎么告诉前端的? 我的理解是 后端用 word 的核心 把排版算好,然后生成对应的 css 传给前端,然后前端渲染 是这样吗? 那你这个是不是也和 doc365 一样, 或者说 你也可以做一个一样的 doc365?
    1244943563
        33
    1244943563  
    OP
       Oct 31
    @firefox12 这是基于网页端的,排版写了一套类似 flutter 的 api 统一的语法,渲染有多套,有 svg canvas 这个是可视的,另外其实还有两套,一个是 pdf ,用了 pdfkit ,将同一套写法通过 pdf 的渲染器生成 pdf,自己写了一套 ofd 类似 pdfkit 的 js 库,还能渲染成 ofd ,这两套渲染完直接是生成文件导出的。我没看懂你说的建立在浏览器上的 chrome 是什么意思,我只能这么解释。

    这一套没有任何服务端,纯前端,所有的包是支持纯浏览器操作的,目前部署的就是这样。上面的这个类似 flutter 的语法会绑定各个适配器,例如 canvas, svg, pdf, ofd ,分别是一套适配器,不跟什么平台绑定,不会说换一个系统就变化。

    另外我跟 docx 转换也不是通过 canvas 相关的东西,我自己写了一套 litast ,这个开源的,它直接把 docx 解析成类似 prosemirror json 的 ast ,然后我基于这一套 ast 写了转换引擎,可以不依赖任何服务,在浏览器或者 node 去跑,把 prosemirror 的 json 转为 ast 再转为 word ,完全没有什么平台限制,全自研。

    不过这一套转换引擎暂时没有开源,只开源了 litast 的 ast 标准包,我开源了 145 个包,给自己留了 65 个做商业化后路。不过任何人都能基于 litast 去做转换引擎。我还在思考是不是留给自己的太多了,是否要再开源一些。

    不知道是否能解答你的疑问
    1244943563
        34
    1244943563  
    OP
       Oct 31
    @1244943563 在这一套体系下,所有的布局完全不依赖任何 css ,转换也不依赖任何中间层,我曾经被 aspose 转换折磨的要死要活,因为我们曾经的编辑器基于 tiptap ,布局也是 css ,我们跟 word 的转换依赖 aspose 转的 html ,结果会丢很多东西,docx 不可能做到准确的双向互转。因此我设计了一个 ast 作为中转标准,docx 与 quirekit 都依赖这一层进行互转。基于 litast 做了 lit-docx 库,它可以在纯浏览器端运行,不依赖任何服务端。也可以纯 node 运行,纯 server 端,将 quirekit json 转为 word 。其实 quirekit 的硬核技术是非常多的。如果大家有什么好奇的,可以在这里提问
    firefox12
        35
    firefox12  
       23h 43m ago
    这是基于网页端的,排版写了一套类似 flutter 的 api 统一的语法,渲染有多套,有 svg canvas 这个是可视的,另外其实还有两套,一个是 pdf ,用了 pdfkit ,将同一套写法通过 pdf 的渲染器生成 pdf,自己写了一套 ofd 类似 pdfkit 的 js 库,还能渲染成 ofd ,这两套渲染完直接是生成文件导出的。我没看懂你说的建立在浏览器上的 chrome 是什么意思,我只能这么解释。

    这一套没有任何服务端,纯前端,所有的包是支持纯浏览器操作的

    所以 ie chrome firefox 会有一样的结果吗? 我的理解一套 office 在 win7 win10 上跑出来的显示是一样的,但是同一套 css 在不同浏览器的效果可能都不一样。

    你这个是会做出一些 css 让浏览器去渲染出来 还是生成一些渲染 canvas 的指令 在 canvas 上纯绘图? 如果是前者 就会有不同浏览器不一样情况出现吧,如果是后者 那么就算是 ie6 也应该是一样的效果吧。

    如果是生成一些 canvas 指令的话, 是不是能全部放在后端,指令到后端 后端算好,把指令传到前端 前端绘制 显示,前端操作,浏览器什么也不做,把指令到后端 后端处理,再给绘制命令。 这样的话,好像前端 只需要很简单就可以了吧。一切都在后端。这些操作也可以全部用 rust java 来做。而不需要 node.js 。

    个人理解。
    firefox12
        36
    firefox12  
       23h 30m ago
    pretext 就是 4 月份 很火的那个, 你做的事情和它是不是很类似? 它是快速计算绘制页面, 你的最终产物也是这样?
    1244943563
        37
    1244943563  
    OP
       23h 25m ago
    IE 不可能支持的,更不要说 IE6 了,这个其实没有考虑在客户目标群体中,这里我也不会测试 IE ,chrome firefox 旧版本说实话没测过,在能正常现代浏览器都可以,因为 canvas 是画出来的,svg 也是。另外 classic-editor 是基于底层我做出来的示范成品项目,用了 vue3 ,从框架层来说,就与 IE 无缘。按道理我没有专门要求浏览器,chrome firefox safari 正常都行。firefox 我没有专门测试,我自己的测试是 chrome ,safari 会有时候打开看,ios 手机端 safari 也试过,没什么大问题.

    canvas 这里跟 css 没什么大关系,非要说有关系就是产品层布局有 css ,我没有理解你说 win7 win10 要表达的意义,你可以了解一下 canvas ,它是 js 操作绘制指令的。都是前端的,跟后端毫无关系。关于你说指令给到后端,前端绘制,我难以理解。canvas 本身就是执行 js 绘制的,跟 java node 无关,当前体系也不需要 node 。是浏览器 runtime 环境执行的。

    关于这个原理,我只能解释到这里😂,如果需要在 IE6 去跑,那几乎无解,windows 新版现在连 IE11 都不带了,IE6 是我 15 年上大学时候大家还讨论过一年兼容的产品,后续没听有人提起过
    firefox12
        38
    firefox12  
       23h 17m ago
    @1244943563 明白了, 你还是依赖 chrome, 和我理解的跨平台还是不一样。我以为什么都不需要 后端可以透明存在
    1244943563
        39
    1244943563  
    OP
       23h 6m ago
    @firefox12 不好意思,我没看懂你的思路与想法😂 我们跟后端毫无关系,并且不依赖 chrome ,可以纯浏览器运行,也可以脱离浏览器无界面使用 nodejs 编写,转换。但是你要看,我不知道脱离浏览器还能用什么看,您可以整理下思路,用 AI 分析下代码,应该能得出比评论区更有用结论。
    firefox12
        40
    firefox12  
       22h 29m ago
    https://imgur.com/undefined ai 整理了一下 我以为你做的是这样的东西
    firefox12
        41
    firefox12  
       22h 28m ago
    1244943563
        42
    1244943563  
    OP
       22h 16m ago
    @firefox12 是的,目前就是独立排版引擎,不依赖浏览器,canvas svg 只是排版引擎在浏览器端的一个载体,pdf ofd 文件是另一个载体,这两个完全不依赖任何浏览器,直接依靠排版引擎绘制生成。关于你图中提到的文字塑形,我的方案中使用开源的 harfbuzz.js 进行文本塑形,canvas svg 可选浏览器自身文本塑形。所有文本位置,都是引擎计算,不是靠 css ,css 实现不了这套方案。
    Heanes
        43
    Heanes  
       21h 38m ago
    厉害了
    unhappy224
        44
    unhappy224  
       21h 22m ago
    lz 很厉害,我们之前公司就想要这一套,后面选择的是 BlockSuite + yjs 协同,不需要做 doc 兼容都是无尽的坑,真真切切体会到前端做富文本多难(特别是细节,例如你说的中文输入法)。做成这样真的很佩服
    1244943563
        45
    1244943563  
    OP
       21h 0m ago
    @unhappy224 输入法做成了开源的 @quirekit/ime ,不光编辑器再用,配套的思维导图,数学公式编辑器组件都在用,这个有点恶心,确实很多坑,很难保证在所有设备上不出问题。
    yanheqi
        46
    yanheqi  
       17h 38m ago
    很厉害,已经点 star 了
    1244943563
        47
    1244943563  
    OP
       17h 16m ago
    @yanheqi 哈哈哈 感谢感谢
    firefox12
        48
    firefox12  
       16h 24m ago
    @1244943563 所以我很奇怪 如果是独立的引擎,浏览器显示内容理论上就应该如同显示一张图片,为什么 ie 会不支持呢? 而且也不应该存在不同浏览器显示不一致的问题,他们只是显示了一张 canvas, 理论上 所有的浏览器应该都能支持 而且效果都应该一样。 只是我个人的一点见解。

    总之这肯定是很厉害的,当年和做 wps 的同事一起聊天过,这个排版引擎是最麻烦也是最难的。你删掉或者添加一个字后面所有的内容都要重新排版 重新计算。
    1244943563
        49
    1244943563  
    OP
       15h 11m ago
    @firefox12 IE 不支持不是因为 IE 自身无法支持比较新的 js 语法,是语言层面的问题,以及我们的 UI 层使用了 Vue3 ,我们的编辑器无法直接跑在 IE 上,不是因为引擎的问题。引擎是独立引擎,这样讲你会好理解一点。就像最新的 C++,无法直接在 win98 上运行,因为 win98 是被淘汰的系统。同样 IE 是被淘汰的浏览器,从语言层面来讲,他就无法执行最新的 js 语法,也没办法支持最新标准的 css ,因此无论我们能不能生成 canvas 指令,在 IE 上都没办法执行,canvas API 本身也是与时俱进的,渲染方案什么的,IE 本身也达不到要求,同一套指令,是否能执行,是否执行结果一致,这个是 IE 它自身的问题。
    目前 windows 完全放弃自家的 IE 产品,标配 Edge ,从源头来讲,Windows 也知道 IE 不是新时代的产物,他自己已经维持不下去了。像现在的 Wps 在线版,都是没办法兼容远古浏览器的。这样说你应该能明白了。
    firefox12
        50
    firefox12  
       13h 45m ago
    @1244943563 恩 我能明白这个意思,我确认是独立的引擎,不依赖 css, chrome, 但是你现在又表示 ie 因为太老 因为 css 的支持问题,会无法使用。ie 其实不是最重要的点,而是我认为一个独立的引擎应该不受这些条件的影响。 就像 win98 上面装了 adobe 的 pdf 阅读器,2026年出品的 pdf 只要版本支持 也是可以在 win98 的 pdf 阅读器上显示出来的。

    但是最终我问了下ai我觉得 ai 的这个解释 能解释这一切, 就是 ie 为什么不支持 vue3 而支持 vue2, 理论上 vue 只是一段 js, ie 是有 js 引擎的,所以 ie 能支持 vue3 才对,但是 ie  不支持 vue3 但是支持 ie2, 因为 vue3 使用了 proxy 机制,监听事件变化。  ie 里面没有这个东西,所以运行不了。  vue2 使用了  Object.defineProperty(),  ie 支持  Object.defineProperty()  所以 ie 就支持 vue2. 你的排版引擎模块是不需要 css 的,但是最终显示的时候 还是借助了 css, chrome. 你的开发 node. css 这些在 ie 上无法很好支持 所以没办法支持 ie 。
      我认为你的引擎应该分为排版和显示2个模块,排版是不需要的,最终显示需要 chrome 和 css 所以不支持 ie 。
    我比较武断地认为,已经排版好的信息渲染出来 应该是很简单的事情,所有的浏览器应该都很轻松支持。大概这里存在知识上的 gap 吧。

    好了  forget   it.
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2252 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 68ms · UTC 05:10 · PVG 13:10 · LAX 22:10 · JFK 01:10
    ♥ Do have faith in what you're doing.