【免费下载链接】raphael-publish
Raphael Publish - 公众号排版大师 | 现代 Markdown 排版引擎
Raphael Publish 是一款专为微信公众号打造的免费开源 Markdown 排版工具,核心由 markdown-it 渲染引擎、30 套主题样式注入系统与 highlight.js 代码高亮链路组成。本文带你用 5 分钟看懂它的渲染全链路:从一段 Markdown 文本进入编辑器,到最终一键粘贴进公众号后台,中间究竟经历了哪些关键步骤。
渲染引擎全链路总览:一条 HTML 的诞生之旅
很多新手只知道"输入 Markdown、看到排版",却不知道背后其实是一条四级流水线。打开 src/App.tsx 的核心渲染逻辑,每次内容或主题变化时都会依次执行:
- 预处理:
preprocessMarkdown()清洗 Markdown 原文 - 解析渲染:
md.render()由 markdown-it 转成 HTML,代码块在此刻完成高亮 - 主题注入:
applyTheme()把选中主题的 CSS 逐元素写入内联样式 - 索引标记:
markElementIndexes()附加点击定位用的元数据
这条流水线定义在 src/lib/markdown.ts,是理解整个引擎的钥匙。
第 1 站:markdown-it 预处理,先给 Markdown"洗个澡"
从飞书、Word、Notion 粘贴来的文本常常"带病":加粗符号里夹着空格、星号被拆成碎片、甚至出现*** *** ***这种畸形分割线。直接交给解析器,轻则样式丢失,重则整段渲染错乱。
preprocessMarkdown() 就是为此设计的防错层,它主要做四件事:
| 问题 | 处理方式 |
|---|---|
* * *、- - -被空格拆散的分割线 | 归一化为标准的***、--- |
加粗标记中间夹空格(** **) | 合并为正常文本 |
| 4 个以上连续星号 | 直接清除,防止误触发分割线 |
至**-5%**。这类紧贴标点开头的加粗 | 插入零宽字符,确保加粗能正确闭合 |
💡 第 4 点是很多 Markdown 引擎的"隐形坑":当
**紧跟标点时,markdown-it 会认为这不是加粗开头。预处理层用零宽分隔符悄悄修好了它,用户完全无感。
第 2 站:代码高亮,highlight.js 的回调艺术
Raphael Publish 没有单独再写一遍高亮流程,而是把 highlight.js 直接嵌进 markdown-it 的构造函数。在 markdown.ts 第 6-26 行可以看到:
- 通过
highlight回调,每当 markdown-it 遇到围栏代码块,就用hljs.highlight(str, { language: lang })即时着色 - 语言不存在或解析失败时,自动降级为
escapeHtml,保证代码永远安全转义 - 返回值里还悄悄塞了一个"红绿灯"装饰——三个 macOS 风格的小圆点,让代码块瞬间有了"终端质感"
这一步的巧妙之处在于顺序:高亮必须在主题注入之前完成。因为下一站要对每个span高亮 token 单独写入微信兼容的内联颜色,早一步高亮,晚一步注入,链路才干净。
第 3 站:主题样式注入,30 套主题如何"长"在 HTML 上
微信编辑器会剥掉 class 和外部样式表,只保留内联 style。所以 Raphael Publish 放弃了常规的"写一份 CSS、切个类名"做法,而是采用了更硬核的逐元素内联注入方案。
主题系统位于 src/lib/themes/,结构一目了然:
- 主题定义:classic.ts(经典)、modern.ts(潮流)、extra.ts(更多风格)
- 统一数据模型:types.ts 中,每个主题就是
id + name + styles 字典 - 汇总入口:index.ts 把三组主题合并为
THEMES数组供全局取用
styles字典的键是 CSS 选择器(h1、blockquote、code…),值是完整的 CSS 声明字符串。applyTheme() 拿到字典后,用DOMParser把 HTML 解析成文档,遍历每个选择器命中的元素,把样式追加进各自的style属性,最后整体包进一个带容器样式的div返回。
除了"贴样式",applyTheme 还承担了三项精细化工程:
- 多图网格重塑:连续的纯图片段落会被两两合并为
.image-grid并排网格(第 91-170 行),这是"朋友圈式"多图画面的来源 - 列表标记修复:Tailwind 的 preflight 会抹掉原生列表圆点,这里用
list-style-type: disc/circle/square !important按层级显式补回 - 高亮色覆盖:内置一份 GitHub 浅色
hljsLight色板(第 202-233 行),把每个高亮 span 的颜色强制写成内联样式——这一步正是"复制进公众号后代码依然是彩色的"的秘密
第 4 站:微信兼容层,让 HTML 在公众号后台"落地存活"
复制按钮背后还有一道makeWeChatCompatible(),它针对微信编辑器的种种"怪癖"做了五重加固:
- 根节点换成
<section>:微信对 section 包裹的样式接受度最高 - flex 转 table:微信大量场景忽略 flex,图片网格被改写成 table 布局,杜绝并排图塌陷
- 列表拍平:
<li>里嵌套的<p>降级为<span>,修复深层嵌套渲染错乱 - 字体强制下发:把容器的 font-family、line-height、color 手工分发到每个文本块,抵御微信"继承劫持"
- 图片转 Base64:所有外链图片 fetch 后内联为 data URL,彻底告别"此图片来自第三方"报错
全链路复盘:一张表看懂架构分层
| 阶段 | 关键函数 | 所在文件 | 解决的问题 |
|---|---|---|---|
| 预处理 | preprocessMarkdown | src/lib/markdown.ts | 粘贴文本脏数据 |
| 解析+高亮 | md.render | src/lib/markdown.ts | Markdown 转 HTML、代码着色 |
| 主题注入 | applyTheme | src/lib/markdown.ts | 内联样式、多图网格、色板覆盖 |
| 索引标记 | markElementIndexes | src/lib/markdownIndexer.ts | 预览点击反查 Markdown 位置 |
| 微信兼容 | makeWeChatCompatible | src/lib/wechatCompat.ts | 图片 Base64、布局降级 |
分层设计是这个引擎最值得借鉴的地方:核心渲染保持"纯净",点击定位、微信兼容都作为可拆卸的增强层叠加在外层,互不污染——这正是 markdownIndexer.ts 文件头注释反复强调的设计原则。
写在最后:这套渲染思路还能用在哪些场景
如果你在自研富文本工具或公众号助手,Raphael Publish 的三级思路可以直接抄作业:先用预处理兜底脏输入、再用内联样式对抗目标平台的样式剥离、最后用兼容层处理平台怪癖。配套的单元测试覆盖了 markdown.test.ts、htmlToMarkdown.test.ts 等核心模块,也值得参考其测试边界划分。想要动手体验,运行pnpm install后执行pnpm dev即可启动本地开发环境(见 README.md)。
【免费下载链接】raphael-publish
Raphael Publish - 公众号排版大师 | 现代 Markdown 排版引擎
相关推荐
5分钟快速上手:Stable Diffusion最强AI换脸插件ReActor完全指南
5分钟快速上手:Stable Diffusion最强AI换脸插件ReActor完全指南 sd webui reactor是一款功能强大的AI人脸替换插件,专为S
人工智能计算机视觉AI 应用markdown-it深度解析:打造高性能Markdown渲染引擎的完整指南
markdown it深度解析:打造高性能Markdown渲染引擎的完整指南 你是否曾为Markdown渲染性能不足而困扰?是否需要一个既强大又灵活的解析器来支
前端终极指南:VNote代码高亮引擎原理解析,让Markdown编辑更出彩
终极指南:VNote代码高亮引擎原理解析,让Markdown编辑更出彩 VNote是一款基于Qt开发的免费开源笔记应用,专注于提供卓越的Markdown编辑体验
桌面应用文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考