MarkText 的 muya 编辑器内核 ROADMAP 解读:从 2020 年块系统到 2023 年 TypeScript 重构的完整演进

发布时间:2026/9/5 20:41:47
MarkText 的 muya 编辑器内核 ROADMAP 解读:从 2020 年块系统到 2023 年 TypeScript 重构的完整演进 MarkText 的 muya 编辑器内核 ROADMAP 解读从 2020 年块系统到 2023 年 TypeScript 重构的完整演进【免费下载链接】marktextA simple and elegant markdown editor, available for Linux, macOS and Windows.项目地址: https://gitcode.com/gh_mirrors/ma/marktext本篇技术文章以 packages/muya/docs/ROADMAP.md 为核心完整梳理 muyamarktext 的 Markdown 编辑内核包名muyajs/core的路线图2020 年 6–8 月按月推进的块block能力构建目标以及 2023 年 1.0.0 版本围绕 TypeScript 化、代码设计、浏览器兼容、文档与 CI/CD、测试五大方向的规划清单。读完本文你能对照源码逐项验证路线图的实际落地情况并掌握在本仓库中运行构建、单元、规范符合性与 Playwright E2E 测试的完整命令。muya 在 MarkText 中的定位muya 是 marktext monorepo 中的编辑器引擎位于 packages/muya由上游 JS 实现迁移为 TypeScript 重写并作为muyajs/core组织。桌面端渲染器直接消费muyajs/core作为编辑内核而遗留的 JS 引擎packages/muyajs正在退役。根据 packages/muya/CLAUDE.md 的描述packages/muya是自闭环包拥有自己的工具链ESLint/antfu、stylelint、madge、vitest仓库根 ESLint 明确忽略packages/muya/**。从源码结构看muya 的核心架构与路线图条目直接对应入口 packages/muya/src/muya.ts 导出Muya类UI 插件通过静态Muya.use(Plugin, options)注册muya.init()时实例化Editor.init()调用 registerBlocks()在构建根ScrollPage前注册全部块类型块继承体系为TreeNode → Parent → (Content | Format)具体块分布在src/block/{commonMark,gfm,extra,content}文档状态JSONState基于ot-json1暴露invert/compose/transform架构上为 OT 协同编辑预留了空间行内渲染走自定义lexer/rules管线并经snabbdom渲染虚拟 DOM集成 KaTeX、Prism、Mermaid、Vega/Vega-Lite 与 PlantUML。2020 年月目标块系统的三阶段演进ROADMAP 下半部分记录了 2020 年 6 月、7 月、8 月三个月的阶段性目标。这一部分是 muya 从能输入到全功能的能力清单且绝大多数条目已完成勾选。下文按月份继承原清单并结合当前源码标注佐证。2020 年 6 月三种基础块原始目标清单支持 GFM 与 CommonMark 规范的行内样式行内图片不支持本地图片与图片编辑菜单atx 与 setext 两种标题引用块blockquote水平分割线行内样式格式化方式与格式工具箱各类事件处理backspace、delete、arrow、tab、enter、input 等多段落选中与删除段落拖拽普通段落。对照当前源码src/block/commonMark/下即对应这批基础块paragraph、atxHeading、setextHeading、blockQuote、thematicBreak、codeBlock、html等统一经 src/block/index.ts 中ScrollPage.register(...)注册。事件处理方面Editor持有经 RxJS 合并的 DOM 事件流click、input、keydown、keyup、compositionstart/end并路由到活跃块的处理函数——这正是各类事件处理条目在 TS 重写后的实现形态。2020 年 7 月更多块支持输入与输出原始目标清单行内与段落的复制粘贴多选段落复制粘贴有序列表、无序列表、任务列表列表拖拽并把完成项自动移至末尾代码块HTML 块表格块历史记录undo/redo与其他文件类型markdown 与 html的输入输出。这些能力在当前代码中的落点列表与任务列表src/block/gfm/taskList.ts 同目录下的orderList、bulletList、listItemcommonMark 侧与TaskListItem、TaskListCheckbox附件节点表格块src/block/gfm/table/下的Table、TableInner、TableRow、Cell、TableCellContent代码块与 HTML 块src/block/commonMark/codeBlock与src/block/commonMark/html含htmlContainer、htmlPreview历史记录src/history/模块并配有src/history/__tests__/单测输入输出src/state/下的markdownToState.ts经marked解析、stateToMarkdown.ts序列化回 Markdown、markdownToHtml.ts/htmlToMarkdown.ts经turndownjoplin-turndown-plugin-gfm桥接 HTML剪贴板src/clipboard/模块包含paste.ts、copyData.ts、cut.ts及 27 个单测文件。2020 年 8 月全功能版本原始目标清单数学公式块mermaidflowchart、sequence划掉后续弃用footnote原清单未勾选front matter上标、下标、数学公式等行内元素段前菜单paragraph front menu快速插入菜单quick insert menu。对照现状数学公式块src/block/extra/math/MathBlock、MathContainer、MathPreviewKaTeX 在 package.json 依赖中图表块src/block/extra/diagram/DiagramBlock、DiagramContainer、DiagramPreview图表渲染集成在src/utils/diagram/front mattersrc/block/extra/frontmatter/并有src/block/__tests__/frontMatter.spec.ts单测footnote原 2020 清单中唯一未勾选项。当前 CHANGELOG.md 0.2.0 版本记录了 footnote complete — block class UI tool click wiring HTML backref且 src/block/index.ts 已注册Footnote来自src/block/extra/footnotee2e 中另有e2e/tests/blocks/footnote-scenarios.spec.ts场景测试——可以推断该遗留项已在 TS 重写后补齐段前菜单与快速插入菜单对应 UI 插件src/ui/paragraphFrontButton/、src/ui/paragraphFrontMenu/、src/ui/paragraphQuickInsertMenu/经Muya.use(...)由宿主注册。2023 年 1.0.0 目标逐项对照当前落地状态ROADMAP 上半部分是 2023 年 v1.0.0 的规划分为 Optimization、Better Code Design、Compatibility、Documents、CI and CD、Test 六个方向。下面逐项继承原清单并给出仓库内的可验证证据。Optimization支持 TypeScript原清单两项将 JS 代码转换为 TS 代码P0——已完成补全所有缺失类型no any支持 TS 编译严格模式eslint --fix 无错误P0。证据整个packages/muya/src已是 TypeScript构建脚本为tsc vite build见 package.json 的build与lint:types: tsc --noEmit。关于第二项的no any从 e2e 侧规范看e2e/README.md 明确写道该项目禁止anyts/no-explicit-any: error并且 e2e 类型声明通过 e2e/types.d.ts 以Window.muya?: Muya的形式避免window as any。主包侧则由 antfu 配置的 ESLint 与tsc --noEmit把关因此补全类型这一项可以认为在工程规范层面已实质推进具体完成度以pnpm -C packages/muya lint:types的实际输出为准。Better Code Design更好的代码设计原清单七项把最新 marked 打补丁并入 muyaP0移除 axios、XMLHttpRequest 等用 constructor mixin 替换 property mixin图表弃用 sequence 与 flowchart优化 turndown service 以获得更好的粘贴体验优化 markdownToHtml 的 UI 样式移除无用代码是否使用 DI依赖注入是否用 TSX 替换 snabbdom生态更好、更易读。逐项源码佐证marked 补丁化packages/muya/src/utils/marked/ 是一个成体系的本地化 marked 集成包含lexBlock.ts、walkTokens.ts、frontMatter.ts、compatibleTaskList.ts、extensions/等而非直接调用 npm 包默认行为——即patch the latest marked to muya的落地形态。marked与marked-highlight仍出现在 package.json 依赖中补丁层构建在其上。移除 axios / XMLHttpRequest在packages/muya/src内检索axios|XMLHttpRequest无任何命中证实该条目完成——引擎不再在核心中做网络请求。constructor mixin 替换 property mixinpackages/muya/src/block/mixins/containerQueryBlock.ts 与 packages/muya/src/block/mixins/leafQueryBlock.ts 即这两个 constructor mixin应用于块类以提供queryBlock/路径解析CLAUDE.md 也明确指出 this was a deliberate switch away from property mixins与 ROADMAP 条目互相印证。弃用 sequence 与 flowchart当前图表链路保留 mermaid含 sequence/flowchart 的 e2e 测试e2e/tests/diagrams/中仍有sequence.spec.ts、flowchart.spec.ts等场景用于回归从源码结构看2020 年清单中划掉的旧 flowchart/sequence 独立实现对应 muyajs 时代的 Snap.svg 方案已被弃用统一收敛到src/utils/diagram/的渲染器集成。turndown 优化src/utils/turndownService/目录承载定制化的 turndown 封装配合src/state/htmlToMarkdown.ts完成 HTML→Markdown 的粘贴转换turndown与joplin-turndown-plugin-gfm均在依赖中。未决项markdownToHtml 样式清理、DI、TSX 替换 snabbdom 三项在原清单中未勾选。从当前源码结构看渲染层仍为snabbdomsnabbdom-to-html依赖列表可见UI 插件体系仍围绕src/ui/baseFloat/组织即 TSX 替换尚未发生。Compatibility浏览器兼容原清单三项兼容 FirefoxP0SafariP0EdgeP0。证据E2E 配置 packages/muya/e2e/playwright.config.ts 配了 Chromium/Firefox/WebKit 三浏览器矩阵e2e/README.md 说明了本地pnpm --filter muya-e2e e2e:firefox/e2e:webkit的运行方式CImuya-e2e.yml目前只跑 ChromiumFirefox WebKit 在 WebKit 相关的引擎无关改写BACKLOG Phase 3落地前暂不纳入 CI 矩阵。Safari 与 Edge 在仓库中未见专门的适配/测试痕迹与原清单未完成状态一致。Documents文档原清单项官网docs、demoP0、文档P0、代码注释。从 monorepo 结构看packages/website/目录提供了文档站含content/docs/end-user/21 篇用户文档与content/docs/dev/12 篇开发文档与首页演示packages/muya/examples/是消费muyajs/core的 Vite 演示工程。muya 自身则通过 CLAUDE.md、README.md、CHANGELOG.md 与 e2e 的 README.md / BACKLOG.md 构成文档面。因此 ROADMAP 中website(docs, demo)一项在仓库层面已有对应实体是否视为完成取决于原项目对对外发布站点的定义。CI and CD构建与发布原清单三项优化构建流程用 vite 替换 webpack 并用 rollup 构建加快开发流程用 vite 替换 webpack新增 GitHub Action合并/推送 master 后自动修改 package.json 版本号、打 tag 并发布新版本到 npm。证据vite 替换 webpackpackages/muya/vite.config.ts 即当前构建配置package.json 的build脚本为tsc vite build产物为lib/{es,umd,cjs}与lib/typesvite-plugin-dts负责声明文件laynezh/vite-plugin-lib-assets负责图标与字体资源路由开发侧examples与e2e/host均跑 Vite dev server。CI 侧仓库.github/workflows/下已有muya-build.yml、muya-test.yml、muya-spec.yml、muya-e2e.yml、muya-lint.yml、muya-circular.yml等一整套 muya 专属流水线madge 循环依赖检查pnpm -C packages/muya check-circular即madge --circular src/index.ts也在 CI 中强制执行。npm 自动发布CLAUDE.md 明确说明上游的 release-it 发布链路未迁入本 monorepo——marktext 不使用 husky/commitlintmuyajs/core不从本仓库发布。因此原清单最后这一项在当前仓库语境下不适用/未完成版本号package.json 中0.2.0与 CHANGELOG.md 目前由上游节奏维护。Test测试原清单两项单元测试P1e2e 测试Optional。这两项在原 ROADMAP 时间点尚未完成但在当前仓库中均已实质建成且规模远超Optional级别单元测试vitest 单测与源码同目录放置在src/**/__tests__/下覆盖 block、clipboard27 个文件、selection11 个文件、state26 个文件、history、event、inlineRenderer、search、utils 等模块。CHANGELOG.md 0.2.0 记录了 test coverage 1 → 386 tests (43 files)。运行方式pnpm -C packages/muya test单文件pnpm -C packages/muya exec vitest run path/to/file.test.ts。规范符合性测试test/spec/是 CommonMark 0.31 GFM 0.29-gfm 的 fixture 套件test:spec脚本独立 vitest 配置 vitest.spec.config.ts。基线由 test/spec/expected-failures.json 锁死——清单内用例若突然通过、或清单外用例若开始失败套件都会报错合规度只允许上升。基线数据见 test/spec/conformance.mdCommonMark 87.7% / GFM 86.3%PR-6a 时点。E2E 测试packages/muya/e2e/ 是基于 Playwright 的真实浏览器套件自带独立宿主页e2e/host/#editor 工具栏按钮测试按smoke/、typing/、inline/、ui/、editing/、blocks/、diagrams/、drag/、export/、stability/、a11y/等分类组织。常用命令从仓库根执行pnpm install # 一次性安装拉取 playwright/test pnpm e2e # 全矩阵 — Chromium Firefox WebKit pnpm e2e:ui # Playwright UI 模式推荐用于调试 pnpm --filter muya-e2e e2e:firefox # 仅 Firefox pnpm --filter muya-e2e exec playwright install firefox webkit # 一次性下载浏览器 pnpm --filter muya-e2e exec playwright show-report # 查看失败报告e2e README 还沉淀了四条针对 muya contenteditable 场景的实战约定值得写 Playwright 测试的读者注意page.keyboard.type在delay: 0时会丢字符——muya 的 content-change 管线每次按键同步重渲染超过 4 个字符的输入应使用tests/helpers/keyboard.ts中的slowType()每字符 30ms浮动插件用opacity: 0隐藏而非display: noneexpect(...).toBeHidden()无效需断言计算后的 opacitygetMarkdown()在最后一次击键后异步读取 state读 Markdown 前先用expect(domNode).toContainText(...)作为同步屏障优先用公共 APIgetMarkdown/getState/getTOC断言而非 DOM 正则——Markdown 序列化是确定性的snabbdom 输出则可能漂移。路线图全景核对表把 ROADMAP 原清单汇总为一张当前状态核对表状态以本仓库源码与文档为准方向条目原状态当前仓库证据OptimizationJS 转 TS完成整个src/为 TStsc vite buildOptimizationno any / strict未完成e2e 侧ts/no-explicit-any: error主包以lint:types ESLint 把关Code Designmarked 补丁化完成src/utils/marked/本地集成层Code Design移除 axios/XHR完成src/内无相关引用Code Designconstructor mixin完成src/block/mixins/*.tsCode Design弃用 sequence/flowchart完成图表统一收敛至src/utils/diagram/ mermaid 等Code Designturndown 优化完成src/utils/turndownService/ GFM 插件Code DesignmarkdownToHtml 清理 / DI / TSX未完成渲染层仍为 snabbdomUI 体系未变CompatibilityFirefox完成e2e firefox 矩阵 CI 配置CompatibilitySafari / Edge未完成仓库中无相应适配证据Documents官网 / 文档推进中monorepo 含packages/website与examplesCI/CDvite 替换 webpack完成vite.config.ts、e2e/examples 均 ViteCI/CDGitHub Action 自动发 npm未完成muyajs/core不从本仓库发布CLAUDE.mdTest单元测试已完成vitest386 tests / 43 files0.2.0 changelogTeste2e 测试已完成Playwright 全套件Chromium/Firefox/WebKit 矩阵验证路线如何在本仓库亲手核对以下命令均从仓库根目录执行用于验证本文所述各项落地情况# 类型检查与 lint对应 no any / strict 条目 pnpm -C packages/muya lint:types pnpm -C packages/muya lint # 循环依赖检查CI 强制项 pnpm -C packages/muya check-circular # 单元测试 / 覆盖率 pnpm -C packages/muya test pnpm -C packages/muya coverage # CommonMark/GFM 规范符合性含 expected-failures.json 回归门 pnpm -C packages/muya test:spec pnpm -C packages/muya test:spec:commonmark pnpm -C packages/muya test:spec:gfm # E2E需要一次 playwright install firefox webkit pnpm -C packages/muya/e2e e2e # 构建产物lib/{es,umd,cjs} lib/types pnpm -C packages/muya build # 演示工程 pnpm -C packages/muya/examples dev:demo环境要求Node ≥ 20.19与 marktext 根工程一致构建目标chrome70来自 CLAUDE.md 与 package.json 的engines声明。小结packages/muya/docs/ROADMAP.md 记录的不只是一份待办清单而是 muya 内核从 2020 年逐月堆块能力到 2023 年面向 1.0 的系统性重构的完整演进轨迹2020 年的三个阶段目标已在src/block/的块注册体系、src/state/的 Markdown/HTML 双向转换、src/clipboard/与src/history/中留下清晰对应物2023 年的六大方向中TypeScript 转换、marked 补丁化、constructor mixin、turndown 优化、vite 构建、单元与 E2E 测试均已落地并有可执行命令验证而 Safari/Edge 兼容、markdownToHtml 清理、DI 与 TSX 化、npm 自动发布则仍是明确标注的开放项。沿本文给出的源码路径与命令逐条核对即可把路线图与实现现状一一对齐。【免费下载链接】marktextA simple and elegant markdown editor, available for Linux, macOS and Windows.项目地址: https://gitcode.com/gh_mirrors/ma/marktext创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考