公众号排版主题工作室(都爆鸭)用于帮助用户把公众号文章的排版样式(配色、标题条、引用卡、图注、分割线等)按口语描述改成想要的样子,本地即时预览,最后把这份主题存回服务端设为默认,按需再落一份本机 theme 文件。
一、用途与定位 排版在本质是一份声明式的 themeJson,由配色 palette 和每个标签的 inline-style 模板组成。渲染器按它把 Markdown 确定性地渲染成公众号内联样式 HTML。使用者的工作是把用口语描述的排版需求生成或修改为合法的 themeJson,本地自检并预览,再把它存回服务端。本 skill 交付的是一套排版主题,决定「以后每篇长什么样」,它本身不负责发文。
二、三条硬红线 红线 1 · 微信兼容:标题装饰只能挂在有文字的元素自身。公众号编辑器会 strip 掉「没有文字、纯靠 inline-block 宽高 + background 撑色块的空 section/span」。因此标题引导条、强调竖条、下划线这类装饰必须作为 inline style 直接写在标题元素自身,不能用独立的空装饰块。正确做法是把 border-left、border-bottom、padding 写在 h2 等标题元素自己的 style 里;错误做法是用 wrapBefore 注入空的 section 当色条。 红线 2 · 微信兼容:不要用 decorations.articleWrap 给整篇正文包一个浅底加圆角的卡片外框,公众号正文里它会变成一道突兀的边框,articleWrap.before 与 after 留空字符串。想要呼吸感用段间距(margin、line-height)和局部卡片实现。 红线 3 · 安全:themeJson 会内联进公众号草稿,服务端会拒收不合法主题,POST、PUT、render 都会 validateTheme,不通过直接返回 400。
三、themeJson 校验规则 top-level 只允许 meta、palette、page、elements、decorations、components,其余键为硬错。palette 值必须像颜色(#hex、rgb()、hsl()、具名色、{{token}}),8 个标准键为 text、heading、accent、accent2、muted、bgSoft、border、link。page 键为 fontFamily、fontSize、lineHeight、letterSpacing、color,值都是字符串。elements.<tag>.style 是 inline CSS,不能含 < 或 >。六条硬红线要求任何字符串都不得出现 script、style、class=、src=、javascript:、onX= 等。整个 themeJson 不超过 64KB。
四、服务端主题 CRUD 与渲染契约 所有请求用用户自己的密钥走 Bearer 鉴权,也支持登录 cookie 会话。基址默认 https://doubaoya.com,可用 DOUBAOYA_BASE_URL 覆盖。响应统一信封包含 success、requestId、data、error,成功读 data,失败读 error.code 与 error.message。 接口与方法:GET /api/wechat/theme 读当前默认主题;GET /api/wechat/themes 列出自己的主题加内置主题目录;POST /api/wechat/render 把 Markdown 渲染为公众号 HTML,免费不扣点;POST /api/wechat/theme 新建主题,isDefault 为 true 时置为默认;PUT /api/wechat/theme/:id 改已有主题,仅限本人的;DELETE /api/wechat/theme/:id 删主题,仅限本人的。 要点:主题行字段包括 id、userId、name、themeJson、isDefault、createdAt、updatedAt。render 的主题解析优先级为 themeJson(传了就用这份)大于 themeId 大于我的默认主题大于兜底 benya-clean。一人一默认,isDefault 为 true 时服务端在事务里把其他主题的 isDefault 置反。name 缺省为「我的主题」,PUT 只更新传了的字段。themeId 非法返回 400 UNKNOWN_THEME,themeJson 不合法返回 400 UNSAFE_THEME、VALIDATION_ERROR 或 THEME_TOO_LARGE。
五、闭环步骤
- 读起点主题:从当前默认或某个内置主题起步,推荐从 benya-clean 起步,它已按红线 1 与红线 2 改造过。本 skill 也自带一个 WeChat-safe 起手模板 themes/theme.example.json(暖橘编辑风)。
- 按用户口语描述改 themeJson,把「换成暖橘色、标题要竖条、引用做成卡片、字再大一点」等翻译成合法 themeJson,改配色最省事,只动 palette 八个键,其余用 {{token}} 自动跟随。
- 本地先自检:node scripts/validate-theme.mjs /tmp/my-theme.json,exit 0 表示合法,与���务端安全边界同源同规则。
- 预览两条路:路 a 用 API 渲染并保存本地 HTML 打开,render 返回的 HTML 与最终存进草稿的正文逐字一致;路 b 是本地实时换肤工作台(可选,需已装 wechat-article-pipeline)。
- 落地生效范围:服务端默认主题决定 doubaoya.com 网页排版工作室和 POST /api/wechat/render 渲染出来的 HTML;wechat-article-pipeline 发文时的主题按 --theme、config.json 里的 mdTheme、服务端编译主题、项目默认的顺序取。存回服务端设为默认是主路。仍需落本机文件的情形包括发文时钉着本机主题、离线或拉取失败要兜底、或使用不带自动拉取的旧版 pipeline。
六、themeJson 结构速查 top-level 五段加进阶 components,包含 meta、palette、page、elements、decorations。{{token}} 插值会先从 palette、再从 page 取值。elements 支持的标签为 h1、h2、h3、h4、p、blockquote、ul、ol、li、img、hr、strong、em、del、a、code、pre,按标签深合并。每个 element 字段包含 style、wrapBefore、wrapAfter、li.marker、img.figureStyle、captionStyle、hr.html。标题装饰用 border-left、border-bottom、padding 写进标题自身 style。
七、前置条件与下一步 需要 Node 18 及以上(内置 fetch)、curl、jq。需要一个 doubaoya.com 账号和一条 DOUBAOYA_API_KEY。渲染与存主题都免费不扣点。真正发文走 wechat-article-pipeline。用户终态决定是否为终点:只要改默认排版就到此结束;还要排版正文进草稿箱则需 wechat-article-pipeline;已有图文只想进草稿箱则需 wechat-draft-publish;正文未写需 wechat-hot-write;正文未过违禁词需 wechat-banned-words。