Skip to content
Back to skills

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
ai-agentspythongobashgitapi

Works with

  • cli
  • api
  • mcp

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned November 7, 2026

npx -y skills add 88lin/gzh-skill-kit --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of gzh-skill?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for gzh-skill
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/88lin-gzh-skill/badge)](https://www.skillsdirectory.com/skills/88lin-gzh-skill)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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 | `![说明](URL)`、`![](xxx.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;`![说明](url)`→ 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**——微信手机公众号助手会把源码里标签之间的换行/缩进误读成文字空白并转成 `&nbsp;`,导致排版错乱;手动复制粘贴不受此影响(浏览器渲染时已折叠空白)。`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 卡片,不要保留原文段又再生成一个。
- **图片说明硬造**:只有 `![说明](url)` 里真有说明文字才生成说明组件;`![](url)` 空 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 上传产生 `&nbsp;` 注入**:通过 `draft/add` 接口上传的草稿,在手机公众号助手中打开时,源码里标签之间的换行/缩进会被误读成空白并转成 `&nbsp;`,撑乱排版;手动复制粘贴不受影响。上传前先跑 `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.md5.5 KB
  • README.en.md17.5 KB
  • SKILL.md39.9 KB
  • VERSION6 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.