哈喽大家好,我是阿星👋
如果你用飞书写文章然后发公众号,
你大概率经历过这个流程:从飞书复制 → 粘贴到排版编辑器 → 格式又乱了。
所以阿星做了一个工具,飞书文档直接粘贴进来自动转换,粘贴到公众号后台,排版完好无损🚀

今天把这个工具怎么搭出来的分享一下。
整个项目参考开源项目larktomarkdown,但是它这两天挂了,我急的赶紧复现了一个。
🚀 用这段提示词搭完整个工具
直接把这段话给 Cursor 或 Claude之类的AI编程工具👇
你也可以在这段提示词里加上你的定制化需求:

复制给AI,就会得到这些代码。

跑通之后推到 GitHub,去 vercel.com 导入仓库,点 Deploy,两分钟上线可以看我之前写的。
以后写完文章粘贴进来、选主题、一键复制,排版直接到位。

🧠 先说一个大前提:微信公众号为什么这么难排版
这是整个工具存在的根本原因。
正常网页排版,你写一个样式类名(CSS class),所有用到这个类名的元素就都有了样式。但微信公众号编辑器不是正常网页------ 它会把你粘贴进来的 HTML 里所有的样式表标签( <style> )和类名(CSS class)全部删掉 ,只认写在标签里面的内联样式(inline style)。
也就是这个样子:
xml
<!-- 这个粘到微信里,样式会消失 ❌ -->
<h1 class="title">标题</h1>
<style>.title { color: blue; }</style>
<!-- 这个才能保留 ✅ -->
<h1 style="color: blue; font-size: 24px; font-weight: bold;">标题</h1>
所以这个工具的核心任务就一件事: 把所有样式写进每一个 HTML 标签的 style="" 属性里 。
这也是为什么我们的主题系统不能用常规的 CSS 写法(比如 CSS 变量、TailwindCSS 的 class)------那些在你本地预览没问题,但一粘到微信全没了。必须把每条样式直接写进每个标签里面(技术上叫「内联样式」,inline style),一个标签一个标签地注入。
理解了这一点,后面所有设计决策都说得通了。
📱 技术难点1:手机和电脑两种预览模式
预览面板有两种模式切换:
手机模式 用 CSS 样式代码画了一个手机外壳------黑色粗边框(border: 10px solid)、大圆角(border-radius: 36px)模拟手机屏幕的外观。顶部加了一个模拟状态栏(显示时间和信号图标),底部加了一个底部横条(Home Indicator,就是 iPhone 底部那个小白条)。内容区限制在手机屏幕宽度(360px),加了上下滚动。

电脑模式 把宽度放大到 780px,白底,加阴影和圆角,模拟在桌面端看文章的效果。
这个功能听起来花哨,但实际价值很大------公众号读者大部分是手机端,你在电脑上调的排版在手机上换行位置可能完全不同,标题可能太长,代码块可能超出屏幕。能切换预览就能提前发现这些问题。🤔其实阿星经常用电脑端看,这个功能就是治我的。

🎨 技术难点2:主题系统怎么做的
6 套主题(深海、烈焰、墨石、竹林、星霜、樱花),每套主题就是一份「样式配置表」(在代码里是一个 JavaScript 对象 / Theme 对象),定义了标题用什么颜色、段落行高多少、代码块什么背景色、引用块左边框什么颜色。

核心设计决策是: 一个主色贯穿全文 。
比如「深海」主题核心色是 [#0c4a6e]()(深蓝),这个颜色同时用在标题、引用块左边框、链接、加粗文字上,视觉上形成统一感。
换成「樱花」主题,核心色变成 [#ec4899]()(粉色),整篇文章的调调就全变了。

切换主题其实就是切换这个对象,预览区重新渲染一遍,每个元素的内联样式跟着变。
🔄 技术难点3:飞书粘贴进来的内容怎么处理
用户从飞书复制内容粘贴到编辑器里,浏览器通过剪贴板接口(Clipboard API)拿到的其实是一段 HTML 代码(就是网页的源代码格式)。我们要把这段 HTML 转成 Markdown(一种简洁的写作格式),再由工具渲染成公众号能用的排版。
听起来就是一个格式转换的事,有一个现成的开源工具叫 turndown 可以做。但飞书的 HTML 有几个坑,不处理就出问题:
坑1:图片 URL 藏在奇怪的地方。 正常的 <img> 标签,图片地址在 src 属性里。但飞书的图片地址藏在 data-origin-src 或者 data-token-src 这种自定义属性里,src 里放的可能是一个内部代理地址,直接拿会拿不到图。处理方式是按优先级读:先读 data-origin-src,没有就读 data-token-src,最后才读 src。
坑2:表格里的内容包含竖线。 Markdown 表格用 | 分隔每一列。如果表格里的文字本身包含 | 这个字符,格式就乱了------Markdown 解析器会以为你在这里分了一列。解决方式是把内容里的 | 转义成 \|。
坑3:最容易出错的地方,加粗文字会断裂。 飞书导出的 HTML 经常把一段加粗文字拆成两个紧挨着的加粗标签(<strong>)。直接转换会出现连续的星号符号( )导致格式错乱。需要把相邻的加粗标签合并成一个完整的。这还不够,大家需要亲自试试才行。我虽然交代了也出错了好几遍。
你不需要自己写这些规则。给 AI 的提示词里说清楚这三个坑就行。
AI 生成完,你用一段飞书文档粘贴进去测试,看转换结果对不对就行。
📋 技术难点4:「复制到公众号」怎么实现的
这是整个工具的核心按钮。点击之后做三件事:
第一步:找到预览区的内容。 代码会自动定位到预览区里渲染好的文章 DOM 元素(通过一个叫 .markdown-body 的类名标记------这是 GitHub 带起来的行业约定命名,大多数 Markdown 渲染工具都用这个名字,代码写法是 document.querySelector('.markdown-body'))。
第二步:把样式塞进每个标签。 调用一个叫 processHtmlForWeixin() 的函数,遍历文章里的所有标签,把当前主题的样式一条一条写进去(就是前面说的「内联化」)。同时做一些微信特有的适配:图片限制最大宽度(max-width: 100%)防止超出屏幕,表格边框合并(border-collapse: collapse)防止出现双线,代码块指定等宽字体确保对齐。
第三步:写入剪贴板。 这里有个关键------复制的时候不能用「纯文本」方式(clipboard.writeText())。纯文本复制粘贴到微信编辑器里所有格式都丢了。必须用「富文本」方式复制(技术上叫写入 text/html 类型,用 clipboard.write() + ClipboardItem),这样粘贴时格式才能保留:
sql
const blob = new Blob([processedHtml], { type: 'text/html' });
await navigator.clipboard.write([
new ClipboardItem({ 'text/html': blob })
]);
这样粘贴到微信编辑器里,富文本格式就保留了。
一个注意点:这个剪贴板接口(Clipboard API)只有 Chrome 和 Edge 完整支持,Safari 部分支持,Firefox 不支持。如果用户浏览器不兼容,按钮要能显示错误提示。👉所以最好还是提醒用户去chrome里使用。
如果这篇文章对你有帮助,请随手点赞、在看、转发三连,让更多人看到。

**
**
