Back to skills
SKILL.md
gzh-skill
ASecurity首次使用须进粉丝群激活,激活后仅限个人非商业使用。微信公众号文章排版引擎,将 Markdown 转换为可直接粘贴到公众号编辑器的 HTML。主题风格从 references/theme-index.md 注册的自定义主题库中选取,自动章节编号、关键词下划线标记、引言卡片、目录导航、代码块、图片/GIF、作者签名。支持 Markdown / Word(.docx) / PDF / 纯文本输入(非 Markdown 先自动归一化),也支持"一键自动排版"(自动推断结构+选主题),还支持根据用户描述/参考图生成自定义主题组件库并保存本地复用,支持"先标注再排版"的两阶段模式(产出可检查、可修正、可重渲染的标注版 Markdown),并可选用微信 API 把排版产物直传公众号草稿箱(scripts/wechat_draft.py)。触发场景:(1) 用户提到"公众号排版""公众号文章""微信排版""gzh",(2) 用户想把文章(md/docx/pdf/纯文本)转成公众号 HTML,(3) 用户说"自动排版""一键排版"公众号内容,(4) 用户想为公众号排版"生成新主题/自定义风格/按这...
- 3 stars
- 0 votes
- 0 copies
- 0 views
- Added November 7, 2026
Works with
Security analysis
100/100Pro scans all 4 files and shows the line behind each finding
npx -y skills add 88lin/gzh-skill-kit --agent claude-codeAre you the author of gzh-skill?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/88lin-gzh-skill)---
name: gzh-skill
license: LicenseRef-GzhSkillKit-NonCommercial-1.1 (see LICENSE)
description: 首次使用须进粉丝群激活,激活后仅限个人非商业使用。微信公众号文章排版引擎,将 Markdown 转换为可直接粘贴到公众号编辑器的 HTML。主题风格从 references/theme-index.md 注册的自定义主题库中选取,自动章节编号、关键词下划线标记、引言卡片、目录导航、代码块、图片/GIF、作者签名。支持 Markdown / Word(.docx) / PDF / 纯文本输入(非 Markdown 先自动归一化),也支持"一键自动排版"(自动推断结构+选主题),还支持根据用户描述/参考图生成自定义主题组件库并保存本地复用,支持"先标注再排版"的两阶段模式(产出可检查、可修正、可重渲染的标注版 Markdown),并可选用微信 API 把排版产物直传公众号草稿箱(scripts/wechat_draft.py)。触发场景:(1) 用户提到"公众号排版""公众号文章""微信排版""gzh",(2) 用户想把文章(md/docx/pdf/纯文本)转成公众号 HTML,(3) 用户说"自动排版""一键排版"公众号内容,(4) 用户想为公众号排版"生成新主题/自定义风格/按这张图做一套组件库",(5) 用户说"先标注""两步排版""标注后再排"进入两阶段模式,(6) 用户说"上传草稿箱""API 发布""自动发布"把排版结果直传公众号草稿箱。不用于生成普通网页/落地页/PPT(用前端或 PPT 类 skill)。
---
# 公众号文章排版 Skill
把一篇 Markdown 文章转换为可直接复制粘贴进微信公众号编辑器、且粘贴后样式不丢失的 HTML。
核心资产是 `references/` 下的**主题组件库**(每套一个主题:设计变量 + 各组件完整 HTML + 模板骨架 + 映射规则)外加 1 套**通用增量库**(代码块 / 图片·GIF / 小标签标题,所有主题共用)。主题清单以 `references/theme-index.md` 为单一来源。本 SKILL.md 只负责流程与决策,**具体 HTML 代码一律从组件库取,不要凭记忆手写**。
## 使用许可
本项目仅限个人非商业使用,详见 [LICENSE](LICENSE)。遇到明确的商业用途,说明限制并停止相关操作;正常个人使用直接继续,不反复确认。文章讨论商业话题不等于商用。本项目著作权人对其自有作品的开发和许可调整不受此限制。
## 使用前检查(全部主题通用)
开始排版、两阶段标注或渲染、自定义主题生成、草稿上传前,先运行:
```bash
python "<SKILL_ROOT>/scripts/fan_access.py" status
```
退出码为 0 才继续;未激活时按脚本给出的主页链接,引导用户加入「AI生产力实验室(仅粉丝)」领取 6 位字母数字激活码(不区分大小写),完成激活后再继续。用户提供激活码时用 `activate --stdin` 或 `activate --code-file <文件路径>` 输入,不把码写入仓库、命令行参数或文章。具体步骤见 [激活说明](docs/activation.md)。
一次激活后长期使用,后续只检查本地凭证,不重复询问。用户仅说“已进群”不能代替校验,也不要通过生成新码或修改校验配置代替激活。全自动、指定主题与续接渲染同样执行检查;仓库维护、校验测试和画廊构建不受此检查限制。
## 更新提醒与手动更新
完成排版、主题生成或草稿上传后,在交付回复前运行:
```bash
python "<SKILL_ROOT>/scripts/check_update.py"
```
脚本每 7 天最多检查一次正式 Release 的版本附件,官方请求超时或失败时尝试 `https://ghfast.top/` 镜像,两边均失败则安静跳过;不影响本次任务。已提醒版本保存在用户目录,同一版本只提醒一次。**有输出时,将这句提醒放在最终回复末尾;没有输出就直接交付,不声称“已是最新版”。** 不要把提醒写进文章、预览页或公众号草稿。仅答疑、任务失败及仓库维护时不检查。
**只有用户明确要求更新这个技能,才执行更新。** “自动排版 / 不用问”不包含更新授权。更新时沿用原安装方式,先备份并保留用户自定义或修改的主题、本地配置及激活记录,处理差异后再替换官方文件;不得用强制覆盖或清理目录的方式丢弃用户改动。完成后重新读取新版 `SKILL.md`,核对 `VERSION` 并做必要校验。
更新应使用正式 Release 对应的标签版本。官方更新包下载慢或失败时,在同一公开下载链接前加 `https://ghfast.top/`,例如 `https://ghfast.top/https://github.com/88lin/gzh-skill-kit/archive/refs/tags/v1.0.0.zip`(替换为实际标签);不要向镜像发送访问令牌或激活码,也不要修改用户的全局 Git 配置。下载后先在技能目录外解压核对版本,再按上述规则保留本地改动。
## 工作流
### 0. 输入与格式归一化
用户可能给:Markdown 文本或 `.md` 路径(直接进第 1 步)、`.docx`、`.pdf`、`.txt`/无标记纯文本、网页富文本。**非 Markdown 输入必须先读 [references/format-normalize.md](references/format-normalize.md) 按其规则转成 Markdown 草稿并做结构确认**(docx 用 `scripts/extract_docx.py`,PDF 用 Read 分页读取+清噪,纯文本按标题启发式推断结构)。什么都没给时,向用户索要。
用户说「直接排 / 自动排 / 一键 / 不用问」时进**全自动模式**:跳过结构确认与选主题提问,自动推断结构、按题材自选主题、排版校验,交付时附决策说明(章节结构、自拟标题、选题理由)。
### 1. 选主题(自动推荐制)
读 [references/theme-index.md](references/theme-index.md)(主题信息的单一来源)。**据文章题材主动推荐最契合的主题**,再让用户一步确认——推荐但不擅自定死:
- **用户已在请求里指定主题** → 直接用,不问。
- **题材有明确契合** → 单问确认:「建议用 XX(理由),确认还是换一套?」选项给推荐项 + 1~2 个备选 + "看全部"。题材→主题契合参考 theme-index"适用场景"列:
- 轻松向内容 / 日常分享 / 教程 / 清单 / 测评(可爱、轻快、卡片感强)→ 软糖
- 随笔 / 年度总结 / 方法论 / 读书笔记(温柔、纸感、卡片柔和)→ 奶油泡芙
- 通用教程 / 测评 / 清单 / 工具盘点 / 知识整理 / 方法论拆解(信息密度高)→ 摸鱼绿
- AI 工具 / 开发教程 / 产品说明 / 技术工作流(冷静清晰、信息密度高)→ 科技钴蓝
- 深度分析 / 观点 / 力量感话题 → 红白色系
- 设计 / 科技评论 / 专业观点 / 高端品牌 → 石墨极简风
- 禅意 / 极简生活 / 深度随笔 → 留白禅意风
- 工具对比 / 创意评测(票据视觉隐喻)→ 摸鱼票据风
- 艺术评论 / 品牌叙事 / 人物特稿 / 展册式深度内容 → 克莱因蓝艺术展册
- **无明显倾向** → 默认首选 theme-index 第一行(软糖)作为推荐项放第一位,用 AskUserQuestion 让用户在几套里选(主题多于 4 套时先按气质分组问,再问该组下主题)。
- **全自动模式**(用户明说「直接排 / 一键 / 不用问」)→ 不提问,自动选题材最契合主题或默认第一行,交付时说明选择理由。
- **用户对现有主题都不满意 / 想要新风格** → 走「自定义主题生成」流程(见下节),生成并登记后再回到本步选用。
- **theme-index 为空** → 停止排版,告知用户需要先添加主题风格(可走「自定义主题生成」)。
用户定下主题后,才进入该主题内部的组件匹配(第 3、4 步:判定文章类型 → 按该主题的配方表选组件组合)。
### 2. 读组件库(两份)
(1) 据 theme-index 中该主题的"组件库文件"列,Read 该主题专属组件库 `references/theme-{标识}.md`(含引言卡、章节标题、正文标记、签名等主题专属组件)。
(2) **同时 Read 通用增量库** `references/common-components.md`——代码块、图片/GIF、小标签标题这三类所有主题共用,套用当前主题主色即可。
后续生成完全依据这两份组件库,HTML 一律从中取、不要手写。
### 3. 解析 Markdown 结构
| 元素 | 识别规则 |
|------|---------|
| 文章标题 | `# 标题` 或 frontmatter `title` |
| 开头引言 | 文章最开头的 `> 引用` 块 |
| 章节标题 | `## 标题` |
| 子章节 | `### 标题` |
| 加粗 / 高亮 / 下划线 | `**文字**` / `==文字==` / `<u>文字</u>` 或 `++文字++` |
| 引用段落 | 非开头的 `> 文字` |
| 图片 / GIF | ``、``(GIF 与图片同样处理) |
| 超链接 / 脚注 | `[text](url)`(非图片)→ 正文 `text` + 上标 `[n]`,按首次出现顺序编号;文末生成「参考资料」列表与之对应(通用库 4a/4b) |
| 代码 / 命令 / Prompt | ` ``` 围栏代码块 ``` `、行内 `` `code` `` |
| 分割线 / 列表 | `---`、`***` / `- 项` 或 `1. 项` |
| 表格 | `\|` 分隔的 Markdown 表格(常来自 docx 转换)→ 优先用主题库的表格/卡片组件(主题库映射规则为准) |
**解析完结构后,判定文章类型**(取主导类型,可复合):教程/操作指南、盘点/工具清单、观点/深度分析、访谈/人物特稿、数据复盘/报告、生活/情感随笔、案例实战。判定依据:步骤和命令多→教程;并列条目多→盘点;引语和人物叙事多→访谈;数字和对比多→数据;论证推演多→观点。
### 4. 按配方选组件组合 → 装配 HTML
**先查所选主题库的「文章类型 → 组件组合配方」表**,按文章类型确定本篇的核心组件组合与点缀组件——不要拿到组件库就逐段随机选组件,配方保证同类文章的排版气质稳定。配方之外的元素再按主题库映射规则表补充。
然后依主题库的**"完整文章模板骨架"章节**装配,把每个 Markdown 元素替换为对应组件:
- **骨架顺序以主题库为准**,不同主题骨架可能不同,不要套用其它主题的骨架。
- **页面底色不能只放在最外层容器**:微信公众号编辑器可能剥离最外层 `<section>` 的 `background`(纯色、渐变都可能丢)。最外层可以保留宽度、字体、行高等全局属性,但正文各内容区块(封面/引言、目录、章节卡片、分割装饰、图片区、签名区、互动区等)必须各自带 `background` 或等价底色样式;即使外层容器被剥掉,任一区块也不能变成无底色的裸内容。组件库已为独立区块补上主题底色;若将正文组件放入有色卡片,按卡片底色调整,避免新增色块。`transparent`、`background-position` 不算底色。
- **减少文字背景渐变,但保留主题原貌**:按[微信规范 4.1.2](https://developers.weixin.qq.com/doc/service/guide/product/plugin_spec.html#_4-1-2),深色模式会把渐变混合成纯色,可能影响文字可读性。优先用视觉接近的非渐变实现;荧光笔/笔刷保留底部半高亮的面积、颜色、字重和间距,可用无模糊内阴影实现,不能直接换成整块底色或彩色文字。主题原有的纯色标签、胶囊仍按原设计保留。内阴影替代同样需要在微信真机深色模式核对文字与色带的可读性,去掉渐变不代表已经通过深色模式验证。卡片底色取接近原渐变整体明度的颜色,避免机械取最深或最浅色。无文字装饰可保留渐变;校验 WARN 是逐项评估提醒,不是为了清零而改变主题设计的理由。必要效果若无可靠替代,保留并说明需在微信深色模式验证。
- **行内标记按语义到所选组件库里找对应组件**(组件编号各库不统一,一律以语义为准、不要套固定编号):`**加粗**`→主色加粗;`==高亮==`→主题原有高亮;`<u>文字</u>` 或 `++文字++`→下划线;`~~文字~~`→荧光笔(底部半高亮,主题另有指定时从其约定);`>引用`→引用高亮块。
- 来自**通用增量库**的组件:` ``` 代码块 ``` `→ 1a 深色 / 1b 浅色代码块(**语言可识别时默认按通用库 1x 的 token 调色板做语法高亮**,语言未知保持单色),行内 `` `code` ``→ 1c;``→ 2a 图片(有说明才加说明组件)、`.gif`→ 2b GIF;需要突出的**小标题/强调**→ 3a 左竖条小标题或 3b 药丸标签,金句→ 3d、提示旁注→ 3e。**优先级:先查主题库映射规则表**——该主题有等价语义组件(如自己的金句/提示块)就用主题库版本保持气质一致;主题库没有对应组件时才用通用库 3x 并按其换色规则换成主题色。
- **超链接转脚注(通用库 4a/4b)**:正文里每个 `[text](url)`(非图片)→ 先收集:按**首次出现顺序**给每个不同 `(text,url)` 对编号 `[1] [2] …`,重复出现的同对复用同一编号;装配时把链接替换为 `text` + 通用库 4a 上标角标 `[n]`(套主题主色);文末正文最后一段之后、作者签名之前,用通用库 4b 生成「参考资料」列表,顺序与正文 `[n]` 一一对应、复用编号只列一次。锚文本为空时用 title 或域名作标签。文中无超链接时不生成此区块。**不要把外链留成可点击的 `<a>`**(公众号正文外链不可点)。
- **一篇文章只用所选主题的那一套组件**,不跨主题混用。
- **强调与小标题用"小标签/左竖条",不要用虚线框**:要突出一个小标题或一段内容时,用左竖条小标题(3a)、药丸标签(3b)、左竖条金句/提示块(3d/3e);**不要用四周虚线框(`dashed` border)套一个标题**,那样笨重抢戏。
### 5. 校验合规(强制)
把生成的 HTML 写入目标文件后,**必须运行校验脚本**,ERROR 清零才算完成:
```bash
# 用脚本所在 skill 的绝对路径调用,HTML 参数也用其实际路径(两者目录通常不同)
<SKILL_ROOT>/scripts/validate_gzh_html.py <生成的.html 的实际路径>
```
它确定性地检查平台禁用项和 `<span leaf>` 包裹。报 ERROR 就回到第 4 步修;**半角标点 WARNING 同样要修复到 0 再交付**(这是实际使用中最高频的返工点)。
### 6. 输出
**产物格式:纯 `<section>…</section>` 正文片段,从全局容器开始,不要包 `<!DOCTYPE>`/`<html>`/`<head>`/`<body>`**——公众号编辑器只接受正文片段,多余的文档外壳会被丢弃或干扰粘贴。
1. **干净正文文件**:HTML 保存到当前工作目录,文件名 `{原文件名}_排版_{主题中文名}({英文标识}).html`(英文标识 = theme-index 组件库文件名去掉 `theme-` 前缀与 `.md` 后缀)。这份用于校验和手动粘贴兜底。
2. **带「复制」按钮的预览页**(让用户一键复制,免去手动全选):
```bash
<SKILL_ROOT>/scripts/wrap_preview.py <上面的干净正文.html>
```
产出 `{...}_预览.html`——浏览器打开后右上角有「复制到公众号」按钮,点一下即把渲染后的富文本复制到剪贴板(等价 Ctrl+A/Ctrl+C),再到公众号编辑器 Ctrl/⌘+V 粘贴。按钮和脚本只在预览外壳里、**不在被复制的 section 内**,所以粘到公众号的仍是干净合规正文。
3. **交付路线(二选一)**:
- **方向一 · 手动粘贴(默认)**——告知用户:**打开 `{...}_预览.html` → 点右上角「复制」→ 公众号编辑器粘贴**;并给出干净正文文件路径作为兜底。附校验脚本结论(已通过 / 剩余 warning)。
- **方向二 · API 上传草稿(可选)**——用户明确说"上传草稿箱 / API 发布 / 自动发布"时,按下方「API 上传草稿」小节执行。
#### API 上传草稿(可选交付方式)
用户说要"上传草稿箱 / API 发布 / 自动发布"(且已配好公众号 appid/secret)→ 用 `<SKILL_ROOT>/scripts/wechat_draft.py` 把第 5 步校验通过的 HTML 直接推入草稿箱。
**前提:必须先压缩 HTML**——微信手机公众号助手会把源码里标签之间的换行/缩进误读成文字空白并转成 ` `,导致排版错乱;手动复制粘贴不受此影响(浏览器渲染时已折叠空白)。`upload_and_cleanup()` 内部已自动压缩。
**方式 A(推荐)**:
```python
import sys; sys.path.insert(0, '<SKILL_ROOT>/scripts')
from wechat_draft import upload_and_cleanup
from pathlib import Path
article = Path('<校验通过的干净正文.html>').resolve()
media_id, nbsp = upload_and_cleanup(
cover_path='封面.jpg', # 必填,草稿 API 不接受空封面;脚本自动压到 ≤64KB,建议 900×383(2.35:1)
title='文章标题', digest='摘要',
html_content=article.read_text(encoding='utf-8'),
base_dir=article.parent
)
# 返回 nbsp > 0 时:from wechat_draft import cleanup_draft_nbsp, get_token
# cleanup_draft_nbsp(get_token(), media_id)
```
**方式 B(手动)**:先 `<SKILL_ROOT>/scripts/minify_gzh_html.py <正文.html>` 压缩,再用压缩产物调 `create_draft`。
**凭据配置**:`~/.wechat_config.json` 存 `{"WECHAT_APP_ID": "...", "WECHAT_APP_SECRET": "..."}`;可用环境变量 `WECHAT_CONFIG_FILE` / `WECHAT_TOKEN_FILE` / `WECHAT_COVER_PATH` 覆盖默认路径。access_token 缓存在本地文件并绑定 AppID,过期、切换账号、缓存损坏或读取不含 AppID 的旧缓存时自动刷新。
**正文图片**:本地/相对图片按 `base_dir` 定位,先检查存在性,再经 `media/uploadimg` 上传并替换 URL;HTTP(S) URL 原样保留,需确保可访问。CLI 优先用 `--html-file 正文.html`,自动以该文件目录解析图片;正文中的字面量 `\n` 不解码。
**上传后验证(强制)**:Python 与 CLI 都用 `draft/get` 回读,逐字比较标题(包括 emoji),统计正文 nbsp。失败抛出 `DraftVerificationError`,携带已创建的 `media_id`;CLI 退出码 2。此时只用 `verify_draft(token, media_id, title)` 重试验证,不重新创建。异常连续 nbsp 可用 `cleanup_draft_nbsp` 清理;它保留单个有意空白及作者、原文链接、留言设置,并回读确认连串空白消失且单个 nbsp 数量未改变,未生效仍抛出验证异常。解析响应必须用 `json.loads(r.content.decode('utf-8'))`,不要用 `r.json()`(部分微信接口按 ISO-8859-1 返回,`r.json()` 会造成双重解码乱码)。
两条路线不要混用:方向一的预览/兜底用未压缩的原始 HTML;方向二上传压缩后产物。
## 两阶段排版模式(`--annotate`)
当用户说"先标注"/"输出标注文件"/"两步排版"/"标注后再排",或显式传 `--annotate`,则进入两阶段模式:**分析标注 → 机械渲染**,中间产物 `_annotated.md` 是一个可检查、可手动修正、可重渲染的富标记文件。
格式规范详见 [references/annotated-format.md](references/annotated-format.md)。下面只规定行为。
### 触发
- "先标注"/"输出标注文件"/"标记一下"/"两步排版"/"标注后再排"
- 显式传 `--annotate`
- 全自动模式下也可组合使用("直接排,但先给我看标注文件"→ 阶段 1 自动跑完,阶段 2 等用户确认)
- **不触发**:普通"排版"/"gzh"/"公众号排版"请求——仍走默认一阶段流程(第 0–6 步)
### 阶段 1:分析标注 → `_annotated.md`
执行现在第 0–4 步的**分析部分**(格式归一化、选主题、读组件库、解析 Markdown 结构、判定文章类型),但**不生成 HTML**。分析结果写入标注文件:
1. **写 frontmatter**:`gzh_type`、`gzh_theme`、`gzh_toc`、`gzh_tags`、`gzh_author`、`gzh_bio`,格式严格按 [annotated-format.md](references/annotated-format.md)
2. **标章节编号**:`##` → `## 01`、`## 02`、`## ∞`,原文标题文字不动
3. **标行内标记**:每段 1–3 个短语加 `++下划线++`,核心锚点加 `**加粗**`(全文 ≤ 5),开头引言里的关键词加 `==高亮==`——包裹原文词语,不改文字
4. **标点半角转全角**:正文半角 `, . ! ? " '` → 全角 `, 。 ! ? "" ''`,代码块内不动
5. **追加尾部签名区**:文件末尾追加签名段,有作者信息则填入,无则 `{{作者名}}` 占位
6. **不改原文文字**:标记语法只包裹、不替换;编号只加前缀;签名区是追加,不插入原文中间
**阶段 1 的输出**:
```markdown
标注完成:`{原标题}_annotated.md`
已写入决策:
- 主题:摸鱼绿(理由:教程类文章,信息密度高)
- 章节:N 个,编号 01–0N(末章结语用 ∞)
- 关键词标记:每段 1–3 处下划线
- 作者:{{作者名}}(用户未提供,请替换)
标注文件与原稿的差异只有:frontmatter、编号前缀、标记语法、尾部签名区。
原文文字未改。你可以检查、修改标注,满意后说"渲染"进入阶段 2。
```
### 阶段 2:机械渲染 → HTML
用户确认标注文件后(说"渲染"/"继续排版"/"生成 HTML"/"排出来"),读取 `_annotated.md`,**禁止再做任何分析**。渲染阶段只做逐元素 HTML 翻译:
1. **frontmatter 是唯一决策源**:`gzh_type` → 配方表、`gzh_theme` → 主题库、`gzh_toc` → 目录组件、`gzh_tags` → 英文标签——不重推断
2. **章节编号照搬**:读到 `## 01` 就用 `01`,读到 `## ∞` 就用 `∞`,不重算
3. **标记语义映射**:`++` → 主题下划线组件、`==` → 高亮组件、`**` → 主色加粗、`~~` → 荧光笔、`<u>` → 下划线
4. **引言区分**:开头 `>` 块 → 引言卡组件,非开头 `>` 块 → 引用高亮块
5. **其余元素**:代码块、图片、列表、表格按现有主题库映射规则机械转换
6. **校验 + 输出**:跑第 5–6 步(校验 + 产物输出),同默认流程
渲染完成的交付说明:
> 排版完成。产物由 `_annotated.md`(标注文件)经阶段 2 机械翻译生成,渲染阶段未做任何分析或推断。
### 标注文件的复用
- **换主题重排**:改 `_annotated.md` frontmatter 里的 `gzh_theme`,重新跑阶段 2——零分析成本,秒级出 HTML
- **修正标注**:直接在 `_annotated.md` 里增删 `++`/`==`/`**` 标记、改编号前缀、改目录、改署名,再跑阶段 2
- **可脚本化**:阶段 2 从标注文件到 HTML 的转换是确定性映射,理论上可用非 LLM 脚本实现,彻底杜绝幻觉
### 一阶段 vs 两阶段对比
| | 默认(一阶段) | `--annotate`(两阶段) |
|---|---|---|
| 分析次数 | 1 次(渲染时) | 1 次(标注时) |
| 渲染时分析 | 有,可能误判/遗漏 | 无,机械翻译 |
| 中间产物 | 无 | `_annotated.md`(可审计、可修正) |
| 修正成本 | 全文重排 | 改标注文件 → 机械重渲染 |
| 换主题 | 全文重排 | 改 `gzh_theme` → 机械重渲染 |
| 内容保真 | 靠 LLM 遵守指令 | diff 原稿 vs 标注稿即可验证:只应有编号前缀 + 标记语法 + 签名区 |
## 生成时的智能处理(这些是本 skill 的特色,必须做)
1. **章节自动编号**:按 `##` 出现顺序分配 `01/02/03…`;末章若为结语/总结类,用主题库指定的结语编号变体(如 `∞`),主题库未指定时沿用数字编号。
2. **英文标签**:据中文章节标题生成英文标签(实测→TEST、教程→TUTORIAL、总结→SUMMARY、思考→THOUGHTS…),主题库有对应槽位时使用。
3. **正文关键词下划线(核心特色)**:对**每个正文段落**主动找出 1–3 个最重要的短语,用该主题的下划线 CSS(见 theme-index)标记。优先标核心观点、结论、关键数据、专有名词;短语 4–15 字;整段无要点可不标。即使原文没有任何加粗也要主动加下划线——它是出现频率最高的基础标记。**密度宁少勿多**:一段最多 2 处、多数段落 1 处即可,绝不整段满是标记——到处是重点等于没有重点。
4. **引言关键词高亮**:识别开头金句里的核心词,用高亮组件标记。
4b. **术语纯色标注**:英文术语/型号(如 ESP32-S3、MCP、Flash)在**首次出现**时用主题主色纯色标注(不加粗、无下划线),重复出现不再标——既帮读者锚定术语,又不制造重复噪点。
4c. **长段自动拆短**:正文单段超过约 3 句或 120 字时,在句号处拆成多个短段(每段 1~3 句),**文字一字不改**,只拆不删不加——移动端阅读大段密字极易劝退,短段落节奏是公众号阅读的基本盘。
5. **目录提取**:从所有 `##` 取前 3 个作为导读/目录要点(主题库有目录组件时)。
6. **开头引言卡署名**:按文章的**作者或主题**而定——文章有署名就写"—— 作者名",没有明确作者就用与主题相关的简短落款或直接省略。**不要固定写"茉灵智库"**(尾部签名区同样用 `{{作者名}}` 占位,见第 7 条)。
7. **尾部作者签名区(作者自填,仅末尾一处)**:**默认不写死任何人名**,用占位署名让用户替换成自己的。
- 第一句(作者介绍):`我是 {{作者名}},{{一句话简介,如:热衷于分享 AI 观察与干货}}`——用户在请求/偏好里给了署名或简介就直接填入;没给就**保留 `{{作者名}}` / `{{简介}}` 占位**,并在交付时提示用户替换成自己的署名。
- 第二句(互动引导,通用可保留原样):`如果你觉得今天这篇有收获,欢迎**点赞、转发、推荐**三连,我们下篇见`(公众号阅读界面三连顺序为「点赞 / 转发 / 推荐」,与官方界面从左到右一致;旧称「在看」已被官方更名为「推荐」)
- **原文末尾已有作者签名段**(如"我是 XXX…")→ 直接沿用原文的署名,不替换成占位。
8. **列表转换**:按主题库映射规则处理;无专属列表组件时转为带缩进的正文段落。
9. **中文全角标点**:正文标点一律用全角(,。!?:;""''()—— …),不要用半角 `, . ! ? :` 和英文直引号 `" '`。**生成 HTML 时就直接写弯引号""'',不要先写直引号再事后替换**——原文里的直引号在转写时当场转换。**例外**:代码块、行内代码、英文专名/URL/代码标识符内部保持原样。
10. **全局排版基线(字体 / 字号 / 三连顺序,所有主题统一)**:
- **字体**:正文与组件默认使用苹果字体栈 `-apple-system,BlinkMacSystemFont,'PingFang SC','Hiragino Sans GB','Microsoft YaHei',sans-serif`(衬线主题以 `'Songti SC','Noto Serif SC',Georgia,'Times New Roman',serif` 起头);代码用 `'SF Mono',Consolas,Monaco,monospace`。
- **字号**:正文主字号 **16px 起**(组件库已按 15–18px 档标注,不要压回 14px);小标签/角标 10–13px;标题 17–24px。整体观感"稍大更易读"。
- **文末三连顺序**:互动文案与按钮顺序固定为「**点赞、转发、推荐**」(与公众号阅读界面从左到右一致;"在看"为旧称,现叫"推荐",永远排在转发之后)。
## 视觉层级(3 层递进,所有主题通用)
| 层级 | 作用 | 频率 | 手段 |
|------|------|------|------|
| 锚点层 | 最强锚点:产品名/步骤/CTA/核心金句 | 全文 ≤ 5 处 | 主色加粗、深色底白字引用 |
| 标记层 | 正文关键词,每段 1–3 处 | 高频 | 下划线标记 |
| 容器层 | 引用块、概念标签、长句强调 | 按需 | 浅底引用、荧光笔、徽章 |
## 平台红线(核心,完整检查交给校验脚本)
- **禁止**:`<style>`/`<script>`/`<div>`、`class`/`id` 属性、`position:fixed/absolute/sticky`、`float`、`@media`/`@keyframes`、`display:grid`、CSS 变量、外部字体/CSS。
- **禁止**:**可点击的 `<a href>`**——公众号正文外链不可点,留 `<a>` 只会被过滤成裸 URL(超链接一律转脚注,见通用库 4a/4b)。
- **SVG 可用但有边界**:**静态**内联 SVG(`path`/`polygon`/`polyline`/`rect`/`circle` 描边图标、`<text>`/`<tspan>` 标注)实测发布后能保留,直接用;**不要用 SMIL 动画**(`<animate>`/`<animateTransform>`/`<animateMotion>`/`<set>`)、`<script>`、外部 `url(#id)` 引用——这些会被过滤。
- **必须**:样式全部内联 `style`;所有文字节点用 `<span leaf="">文字</span>` 包裹(否则粘贴后样式丢失)。
- **可用**:`display:flex`(有限)、`linear-gradient`(文字背景需按必要性评估)、`border-radius`、`box-shadow`、`<section>/<p>/<span>/<strong>/<img>/<h3>`。`figure`/`figcaption` 谨慎使用(可能被改写)。
## 移动端适配(多端一致,不靠 @media)
公众号禁用 `@media`,无法写媒体查询断点,但电脑端(阅读器约 677px 宽)和手机端(约 350–400px 宽)都要排版正常。办法是**全程用"流式/弹性"写法,让布局随宽度自然收缩,而不是为某个宽度写死**:
- **容器宽度只用 `max-width` + 百分比,不写死内容 `width:NNNpx`**:全局容器 `max-width:677px;margin:0 auto` 在手机上自动收窄;卡片/引用块等用 `margin` 留边白,不给具体 px 宽。唯一例外是小图标/头像这类**本就要固定尺寸**的装饰(`width:40px;height:40px` 等,`component_lint.py` 只对 ≥150px 报警)。
- **显式指定文字对齐**:中文文章全局容器写 `text-align:left`,子区块保留原有 `center`、`right`、`justify`,避免依赖默认值。[微信规范 1.6](https://developers.weixin.qq.com/doc/service/guide/product/plugin_spec.html#_1-6-text-align) 指出 `start/end` 存在跨端解析差异。本项目在 Chromium 中读取真实剪贴板 HTML,观察到未指定对齐的内容可能被写成 `text-align:start`(回归用例:`tests/browser_preview.py`);这是本项目实测,不是规范原文或所有浏览器的行为保证。完整文章校验会提醒顶层区块漏写,预览外壳的默认左对齐不代替正文自身设置;临时片段可加 `--fragment` 允许继承,装配后仍须按完整文章校验。兼容修复只明确原对齐方向,不统一改成左对齐;右向左内容须按实际阅读方向单独设置。
- **多列 flex 必须能换行或等分**:并排卡片用 `flex:1`(弹性等分,自动变窄)或 `flex-wrap:wrap` + 百分比 `flex-basis`(窄屏自动换到下一行);**不要**写固定 px 宽的并排块。表格类内容优先转卡片/列表。
- **行内标签/徽章留底部空隙**:`display:inline-block` 的标签、徽章加 `margin-bottom`(如 4–6px),窄屏换行后才不会贴着上一行文字。
- **图片一律 `max-width:100%;height:auto`**(见 Gotchas),不放固定宽。
- **长英文/URL 防溢出**:可能超长的纯文本(URL、代码行)所在元素加 `word-break:break-all`。
> 这些规则的确定性兜底在 `component_lint.py`(固定宽 ≥150px 未配 max-width 报 WARN);`@media`/`float`/`grid`/定位 等则由 `validate_gzh_html.py` 强制拦截。
> 两关现在的覆盖面:`component_lint.py` 查组件库里的 `white-space:pre` / `div` / `class` / `id` / `style` / `position` / `grid` / CSS 变量 / `@media`、**属性引号转义 `\"`**、**`<a href>`**、**SVG SMIL 动画**、**漏 `<span leaf>`**,并把 `docs/gallery` 的示例产物一并纳管;`validate_gzh_html.py` 查产物的同样禁用项,外加**空输入**、**漏 `<span leaf>`(ERROR)**、**半角 `, . ; : ! ?`**。**两关都不允许 `<a href>` 与 SVG 动画**——发现就说明组件库或产物有问题,改到 0 再交付。
>
> 注:**静态**内联 SVG(图标/流程图)实测可保留,两关都不拦;被拦的只是 SMIL 动画与外部 `url(#id)` 引用。带 `leaf` 属性的元素(含 SVG 的 `<tspan leaf="">`)一律视为已包裹。
## Gotchas(真实排版踩过的坑)
- **漏 `<span leaf>` 包裹**是最常见致命错——粘贴到公众号后样式整片丢失。靠第 5 步校验脚本兜底,别跳过。**组件库里 `{{占位}}` 这类文字必须写成 `<span leaf="">{{占位}}</span>`**,否则模型照抄组件时就会一起把裸文本抄进产物。
- **组件库里属性引号被转义成 `\"`** 会让样式在第一个空格处被截断(`style=\"max-width:677px;margin:0 auto\"` 只剩 `max-width`)。从组件库复制 HTML 时若看到 `\"`,说明源文件已损坏,先修组件库。
- **SVG 只做静态的**:静态内联 SVG 实测能过(图标、流程图都行,见 tech-cobalt 的 footer-cta);一旦加 SMIL 动画或外部 `url(#id)` 引用就会被过滤。不确定时优先用静态图形。
- **外层容器 `background` 粘贴后丢失**:微信公众号编辑器会剥离最外层 `<section>` 的 `background` 属性(包括纯色和渐变)。不要把页面底色/整体背景只放在顶层容器上——正文的每个内容区块(章节、分割装饰、签名区、互动区等)都要独立加 `background` 或等价底色,确保任一区块被剥离外层后仍保留自己的底色。
- **下划线:逐段落实、每段 1–3 个短语**。不要整段划线(失去焦点),也不要有的段标有的段漏;列表项里的关键描述同样要标。**密度宁少勿多**:一段最多 2 处、多数段落 1 处即可——到处是标记等于没有重点。
- **长段不拆**:正文单段超过约 3 句或 120 字时,在句号处拆成 1~3 句的短段再排(文字一字不改,只拆不删不加)——移动端大段密字极易劝退。
- **章节编号错乱**:严格按 `##` 顺序,不要跳号;结语编号变体只用于末章,中间章节不能用。
- **签名区有且仅有末尾一个**:用固定文案,不在中间或多处出现;原文末尾若已有作者签名/"点赞/在看/推荐/转发三连"类段落("在看"为旧称,现公众号界面为"推荐"),识别并**并入**这唯一的签名区/CTA 卡片,不要保留原文段又再生成一个。
- **图片说明硬造**:只有 `` 里真有说明文字才生成说明组件;`` 空 alt 不要编造说明。
- **图片自适应、不铺满**:`<img>` 一律 `max-width:100%;height:auto;display:block;margin:0 auto`——按图片自身尺寸显示、居中,大图缩到容器宽、小图保持原尺寸。**不用 `width:100%`**(会把小图也拉伸变糊);只有表格 / 封面卡 / 流程图这类布局元素才用 `width:100%`。
- **图片容器别套 overflow:hidden 内层**:带边框的图片卡(白底 + border + padding)里,`<img>` 直接放容器内,不要再套一层 `<section style="overflow:hidden">`——公众号编辑器会剥离嵌套 section 的 overflow/border-radius,图片会跑出边框外。圆角裁剪靠容器 `padding` 让图片不贴角实现(通用库 2a/2b、红白组件 14 已按此修正)。
- **跨主题混用组件**:一篇文章只用所选主题 + 通用库的组件,不从其它主题借组件。
- **锚点层滥用**:最强强调全文 ≤ 5 处,到处加粗等于没有重点。
- **原文内容遗漏**:每个段落、每张图都要转换,不得漏;不要自行增删原文实质内容。
- **占位图残留**:签名区/CTA 组件里若带名片图占位(如 `<img src="...名片或引导图URL">`),没有真实图片 URL 时整行删掉,不要把占位符留在产物里。
- **目录是精选不是全量**:前言导读/目录组件展示**精选的 3 个核心看点**,不是完整章节列表;章节多于 3 个时挑最重要的 3 个,不要硬塞或误导读者以为只有 3 章。
- **不用虚线框**:突出标题/强调用小标签或左竖条(通用库 3a–3e),不要用 `border:…dashed` 四周虚线框包标题。**例外**:主题库明确定义的虚线组件(如摸鱼绿的 quote-box 引用框、oneliner-card 亮点卡)是该主题的风格特征,按主题库用法正常使用。
- **标点别混半角**:正文出现半角逗号句号、英文直引号 `"` `'` 都要改成全角;但代码块/行内代码内的半角符号保持原样,不要"全角化"代码。
- **代码/Prompt 必须用代码块**:文章里的代码、命令、提示词用通用库代码块组件(1a/1b),不要塞进普通段落或引用块,否则缩进和等宽会丢失。**语言可识别的代码块默认做语法高亮**(关键字/字符串/注释/数字按通用库 1x 调色板着色),整片单色是缺省失误;纯文本/prompt 不强行上色。
- **代码块要紧凑、忌大空白**:用通用库 1a/1b 的"每行一个 `<p style=\"margin:0\">`"写法,**绝不用 `white-space:pre`**——它会把 HTML 源码里 span 前的缩进和行间换行原样渲染成大左缩进 + 空行;缩进只用全角空格 ` `,行距靠 `line-height:1.6`。
- **待补素材居中**:`【插入…】`、待录屏 / GIF / 视频 / 成果图等占位,用通用库 **2c 居中素材占位板块**(浅底柔虚线框 + 居中图标与说明),不要用左对齐的提示块。
- **外链勿留 `<a>`**:正文 Markdown 超链接 `[text](url)` 一律转通用库 4a 上标角标 + 4b 文末参考资料列表(URL 纯文本展示),**不要输出可点击的 `<a href>`**——公众号正文外链不可点击,留 `<a>` 只会被过滤成裸 URL。编号与文末列表必须一一对应,重复 URL 复用同一编号。
- **API 上传产生 ` ` 注入**:通过 `draft/add` 接口上传的草稿,在手机公众号助手中打开时,源码里标签之间的换行/缩进会被误读成空白并转成 ` `,撑乱排版;手动复制粘贴不受影响。上传前先跑 `scripts/minify_gzh_html.py` 压缩(`scripts/wechat_draft.py` 的 `upload_and_cleanup()` 内部已自动压缩并回查 nbsp 计数),见第 6 步「方向二」。
## 自定义主题生成(第二条工作流)
用户想要内置主题之外的新风格(说「生成一套新主题 / 自定义风格 / 按这张参考图做一套组件库」,或对现有主题都不满意)时,**读 [references/theme-generator.md](references/theme-generator.md) 并严格按其流程执行**:
1. **收集偏好**:主题描述必填(或参考图),名称/ID/五色/字体/三类 TAG/圆角/阴影可空则自动补全;一次问全,不逐字段追问。
2. **生成区块库 HTML**:用 theme-generator.md 末尾的【生成提示词】原样执行,产出 45~75 个 Block 的完整区块库,保存到 `assets/theme-previews/{theme-id}.html`——全部区块在同一页面连续排布,用户浏览器打开**整页一次浏览**确认风格,不逐块展示确认。
3. **转换 + 登记**:用户确认风格后,转换为标准 `references/theme-{标识}.md`(**必须补 `<span leaf="">` 包裹、去掉预览用 id、补齐五章节**,规则详见 theme-generator.md 第三步),登记 theme-index.md,跑 `component_lint.py` 到 0 ERROR。
4. 交付后该主题即成为常驻可选主题,后续排版与内置主题完全同权。
生成阶段以提示词规则为准;转换进主题库阶段以本文件「平台红线」和「添加新主题的规范」为准(两者冲突时后者优先,因为主题库直接决定排版产物)。
## 添加新主题的规范
新主题以 `references/theme-{英文标识}.md` 命名,内容必须包含:
1. **设计变量速查表**(主色/浅底/深字/标题色/正文色/分割线色等)
2. **各组件完整 HTML**(内联样式 + `<span leaf="">` 包裹,遵守上面"平台红线")
3. **完整文章模板骨架**(组件装配顺序;若有目录/导航组件,明确其相对封面/引言的位置;不要依赖最外层容器的 `background`,每个正文区块必须自带底色)
4. **文章类型 → 组件组合配方表**(每种文章类型的核心组件组合 + 点缀组件,配方是排版气质稳定的关键)
5. **Markdown → 组件映射规则表**
添加后在 `references/theme-index.md` 登记一行(主题名 / 主色 / 适用场景 / 组件库文件 / 正文下划线 CSS),并跑 `python3 scripts/component_lint.py .` 确认组件库无反模式(0 ERROR)。
> 触发与主题选择的回归用例见 `references/eval-cases.md`(维护时用于回归核对,不影响单次生成)。
Files in this skill
- CONTRIBUTING.md
- README.en.md
- SKILL.md
- VERSION
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.