关于 wechat-article-formatter
wechat-article-formatter 将 Markdown 文章排版为带样式的 HTML,并发布到微信公众号草稿。它会把图片上传至微信,并使用官方草稿 API 保留行内样式。
主要功能
- 01使用 bm.md 样式渲染 Markdown
- 02将文章图片上传至微信 CDN
- 03用 CDN 地址替换图片路径
- 04通过官方 API 发布草稿
- 05提取摘要并确定作者信息
适用场景
- 01将 Markdown 文章排版为公众号内容
- 02准备文章图片和封面素材
- 03将排版后的文章发布为公众号草稿
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ iamzifei/ wechat-article-formatter-skill --skill wechat-article-formatter安装后在 Claude Code 中输入/wechat-article-formatter确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.mdREADME.zh-CN.md.gitignorestyles/custom.css详细介绍
微信公众号文章排版与发布
使用 bm.md 样式排版 Markdown 文章,并通过官方 API 直接发布到微信公众号草稿箱。
概述
- 读取 Markdown 文件(通常是文章目录中的
wechat.md) - 通过
media/uploadimgAPI 将本地图片上传到微信 CDN - 将 Markdown 中的本地图片路径替换为微信 CDN URL
- 通过 bm.md API 和自定义 CSS 将 Markdown 渲染为带样式的 HTML
- 通过官方
draft/addAPI 发布到微信草稿箱
重要:不要使用第三方发布 API(例如微绿 wechat-publish)。它们会移除内联 CSS 样式。始终直接使用微信官方 draft/add API。
凭据
从 ~/.env 读取:
| 变量 | 用途 |
|---|---|
WECHAT_APP_ID | 微信公众号 AppID |
WECHAT_APP_SECRET | 微信公众号 AppSecret |
如果未找到,请提示用户提供凭据并保存到 ~/.env。
工作流
步骤 1:确定输入文件
用户会提供 Markdown 文件路径(例如文章目录中的 wechat.md)。
查找文章目录以确定:
promotion.md→ 提取摘要_attachments/→ 本地图片- 对话上下文中的品牌配置 → 作者姓名
步骤 2:获取微信 Access Token
params = urlencode({
'grant_type': 'client_credential',
'appid': WECHAT_APP_ID,
'secret': WECHAT_APP_SECRET
})
# GET https://api.weixin.qq.com/cgi-bin/token?{params}
如果出现错误 40164(IP 不在白名单中),请指引用户前往:mp.weixin.qq.com → 设置与开发 → 基本配置 → IP白名单 添加该 IP。
步骤 3:将图片上传到微信 CDN
重要:在同一会话中上传所有图片。之前会话中的微信 CDN URL 可能会过期。
使用 media/uploadimg API 上传正文内的图片:
# POST https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={token}
# Content-Type: multipart/form-data
# Body: media=@image_file
# Response: {"url": "http://mmbiz.qpic.cn/..."}
使用 material/add_material API 上传封面/缩略图:
# POST https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={token}&type=image
# Content-Type: multipart/form-data
# Body: media=@cover_image
# Response: {"media_id": "...", "url": "..."}
对于远程图片(例如 https://i.ibb.co/...),请先下载,再上传到微信 CDN。
上传后,在渲染前将 Markdown 中所有本地/远程图片路径替换为微信 CDN URL。
步骤 4:使用 bm.md 渲染
从 {{SKILL_DIR}}/styles/custom.css 读取自定义 CSS。
重要:将 JSON 负载写入临时文件,并使用 curl -d @file,以避免 Shell 转义问题。
payload = json.dumps({
"markdown": md_content,
"markdownStyle": "green-simple",
"codeTheme": "kimbie-light",
"customCss": css_content,
"enableFootnoteLinks": True,
"openLinksInNewWindow": True,
"platform": "wechat"
}, ensure_ascii=False)
# Write to /tmp/bm-payload.json, then:
# curl -s -X POST https://bm.md/api/markdown/render \
# -H "Content-Type: application/json" \
# -d @/tmp/bm-payload.json
ensure_ascii=False 至关重要——否则中文字符会变成 \uXXXX 转义序列。
步骤 5:发布到微信草稿箱
draft_payload = json.dumps({
"articles": [{
"title": title,
"author": author, # e.g. "在悉尼和稀泥"
"thumb_media_id": thumb_media_id, # from Step 3 material upload
"content": html, # from Step 4 bm.md render
"digest": digest, # from promotion.md, max ~60 Chinese chars
"need_open_comment": 1, # enable comments
"only_fans_can_comment": 0, # allow all users to comment
"original_article_type": 1, # declare as original content
"reward_wording": "喜欢这篇文章,请我喝杯咖啡", # enable tipping
"creation_source_type": 1 # 个人观点,仅供参考
}]
}, ensure_ascii=False).encode('utf-8')
# POST https://api.weixin.qq.com/cgi-bin/draft/add?access_token={token}
默认发布设置:
| 字段 | 值 | 说明 |
|---|---|---|
need_open_comment | 1 | 开启评论 |
only_fans_can_comment | 0 | 所有用户均可评论 |
original_article_type | 1 | 声明为原创 |
reward_wording | "喜欢这篇文章,请我喝杯咖啡" | 开启赞赏 |
creation_source_type | 1 | 个人观点,仅供参考 |
从 promotion.md 提取摘要:
查找 ## 文章摘要 章节,提取文本并截断至约 60 个中文字符(微信限制为 120 字节)。
作者确定顺序(采用首个匹配项):
- 用户明确指定
- 品牌配置中的
author字段 - 品牌配置中的
品牌名称字段
步骤 6:报告结果
WeChat Publishing Complete!
Title: {title}
Author: {author}
Digest: {digest}
Original: ✓ declared
Tipping: ✓ enabled
Comments: ✓ open to all
Images: {N} uploaded to WeChat CDN
media_id: {media_id}
→ Preview at: https://mp.weixin.qq.com (内容管理 → 草稿箱)
微信 Markdown 内容顺序
编写微信 Markdown 时,内容元素应按以下顺序排列:
1. 关注引导文字 (e.g. 👆 「关注」加「星标」...)
2. 封面图 (cover image)
3. --- 分隔线
4. 正文内容 (article body with inline images)
5. --- 分隔线
6. 作者介绍 (about author section)
7. --- 分隔线
8. 推广区块 (promo blockquote with image)
9. --- 分隔线
10. 互动引导 (engagement CTA)
应从 Markdown 中移除 H1 标题——微信会使用 title 字段显示标题。
常见问题
| 问题 | 解决方案 |
|---|---|
中文显示为 \uXXXX | 在所有 json.dumps() 调用中使用 ensure_ascii=False |
| 图片无法显示 | 在同一会话中上传;不要重复使用旧的 CDN URL |
| 样式被移除(显示为纯文本) | 使用微信官方 draft/add API,而非第三方 API |
40164 IP 白名单错误 | 前往 mp.weixin.qq.com → 基本配置 → IP白名单 添加当前 IP |
45004 摘要过长 | 摘要保持在 60 个中文字符以内 |
40007 media_id 无效 | 先通过 material/add_material 上传封面,以获取 thumb_media_id |
> [!NOTE] 渲染异常 | 将 GitHub 提示转换为普通的 > 引用块,以便在微信中显示 |
bm.md API 参考
渲染:POST https://bm.md/api/markdown/render
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
markdown | string | 必填 | Markdown 内容 |
markdownStyle | string | ayu-light | 样式 ID(使用 green-simple) |
codeTheme | string | kimbie-light | 代码高亮主题 |
customCss | string | "" | 作用域限定为 #bm-md 的自定义 CSS |
enableFootnoteLinks | boolean | true | 将链接转换为脚注 |
openLinksInNewWindow | boolean | true | 在新窗口中打开链接 |
platform | string | html | 目标平台:html、wechat、zhihu、juejin |
可用样式:ayu-light、bauhaus、blueprint、botanical、green-simple、maximalism、neo-brutalism、newsprint、organic、playful-geometric、professional、retro、sketch、terminal
样式功能
自定义 CSS(styles/custom.css)提供:
- Optima/Microsoft YaHei 字体
- 绿色强调色(rgb(53, 179, 120))
- H2 标题:黑色背景上的白色文字
- 粗体文字:绿色
- 引用块:绿色左边框
- 带交替行颜色的响应式表格
- 深色背景的代码块
依赖项
- 微信公众号 API 凭据(
~/.env) - bm.md 渲染服务(无需身份验证)
- 位于
{{SKILL_DIR}}/styles/custom.css的自定义 CSS
新手上路(用户不知道该输入什么时,走这里)
触发:/公众号排版 新手、「这个怎么用」「第一次用」「能干嘛」「带我走一遍」,
以及用户输入了技能名却没有给任何任务的时候。
这个模式的铁律:不假设、不索取。用户可能什么都没准备, 不要一上来就问他要文件、要 API key、要具体需求。按下面四步走:
一、先说清楚这是什么(三句话以内)
一句话:把 Markdown 排成公众号能直接用的样式。 公众号编辑器不认 Markdown,手动调格式很费时间, 这个技能把排版做完,还能换主题。
二、给编号选项,让他按回车就能继续
不要问开放式问题(「你想做什么?」对新手是负担)。给 3 个选项加一个默认:
想先看哪个?(直接回车 = 1)
1. 先看看排出来长什么样(示例)
2. 排我的这篇 Markdown
3. 有哪些主题可以选
三、直接演示一遍,边做边解释
选完立刻做给他看,用示例数据,不需要他提供任何东西。 每做完一步,加一行「💡 刚才发生了什么」,一句话说明这步的意义。
四、毕业
演示完只问一个是非题:「要不要用你自己的文章真跑一遍?」
答是就进正常流程;答否就告诉他随时回来输 /公众号排版 新手。