# Ni Formatter

> 泥巴猪的公众号排版 skill。文章写完之后，给它「穿衣」——注入排版意图，让视觉效果匹配内容。当用户说「帮我排版」「这篇文章排一下」「加排版」「穿衣服」「文章写好了排个版」「公众号排版」时触发。也适用于用户给一篇 markdown 文章、说「弄得好看点」「该加点格式了」的场景。覆盖 AI / 工程化管理 / DevOps / 架构 四个领域的公众号长文。不适用于还没写完的文章（先去 ni-writer）、短内容、纯文本无需排版的场景。

- Skill: `ttttstc/ni-formatter` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add ttttstc/ni-formatter`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ttttstc/ni-formatter/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: ttttstc (https://skillmd.com/u/ttttstc)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/ttttstc/ni-formatter

---


# ni-formatter — 排版（给文章穿衣）

> 这是泥巴猪的公众号创作套件里的排版 skill。它在文章写完之后工作，不在写作之前。

你现在的任务是给一篇写好的文章「穿衣服」。**排版是穿衣，不是枷锁**——它只美化输出，不改写内容、不约束作者。

## 这个 skill 在管线里的位置

ni-writer 写完 `article.md` 之后，ni-formatter 给它注入排版意图，产出 `formatted.md`。下游 ni-draft 再把这些意图渲染成微信兼容的 HTML。

ni-formatter 不渲染最终样式，它只在文章里**标注「这里该是什么排版模块」**，用 HTML 注释承载意图。

## 原则

- **排版在写作之后**：绝不反过来约束写作。
- **不堆模块**：5 模块是上限不是目标。找不到合适触发点就不放，模块是给重点用的，不是给装饰用的。
- **不改正文**：注释只包裹，一个字都不动。去掉所有 `:::xxx` 注释，文章必须仍完整可读。
- **verdict 必存在且全文 = 1**：没核心论点锚点不输出。
- **不要求一致性**：每篇文章可以有不同的排版选择。

## 输入

**独立运行模式**：
- 用户给一个 `article.md` 路径，或直接粘贴文章
- 同时需要**文章的核心论点**（一句话）——verdict 模块要用。如果用户没给，问一句：「这篇文章的核心论点是哪一句？我要用它来定位 verdict 模块。」

**被 workflow 调度模式**：
- workflow 注入 `article.md` 和 `insight.md` 路径，核心论点从 `insight.md` 读
- 注入 `output_path`，按注入路径写

## 5 模块最小集

正文阶段只用这 5 个模块。够用，不多。

| 模块 | 作用 | 数量上限 | 触发场景 |
|------|------|---------|---------|
| **part** | 章节分段 | ≤ 文章 H2 数 | 技术文章的主要阶段按需使用；不按 H2 逐个添加 |
| **callout** | 提示 / 警告 / 重点 | ≤ 3 | 技术警告、易踩坑、反直觉判断 |
| **quote** | 引用 / 核心判断 | ≤ 2 | 可核实引文、确需独立强调且已完成论证的判断 |
| **steps** | 步骤流程 | ≤ 1 | 落地路径、操作流程 |
| **verdict** | 核心判断 | = 1 | insight 的核心论点对应处 |

**总模块数上限：5。**

禁止：任何模块超上限、模块与文章类型不匹配（纯抒情文章塞 steps）、重复模块。

## 注释语法

排版意图用 HTML 注释承载。下游 ni-draft 据此渲染。

| 模块 | 语法 |
|------|------|
| part | 在 H2 标题前单独一行：`<!-- :::part 标题文字 -->`（原 H2 标题保留不动） |
| callout | `<!-- :::callout warning -->` 段落内容 `<!-- ::: -->`（类型可选 warning / info / tip） |
| quote | `<!-- :::quote -->` 引用内容 `<!-- ::: -->` |
| steps | `<!-- :::steps -->` 步骤列表 `<!-- ::: -->` |
| verdict | `<!-- :::verdict -->` 核心判断句 `<!-- ::: -->` |

注释只**包裹**原文，不改写原文。每个模块的转译规则、触发判断、正反例见 `references/layout-modules.md`。

## 选模块决策算法

```
1. 判断文章类型（从 article.md 内容推断，拿不准就问用户）
2. 必选：verdict（来自核心论点）
3. 按文章类型挑候选模块：
   - 技术方法论型（沉淀 + 深水区合并） → +part，steps / callout 按真实内容选择
   - 技术思辨型                       → +part / callout（按主要论证阶段选择）
   - 发现分享型                       → +quote / callout（按需）
   - 产品体验和评价型                 → +quote / callout（按需）
   - 人生哲学随笔型                   → 默认少加，quote 按需
4. 总数检查 ≤ 5
5. 没有 verdict 不输出（必须有核心论点锚点）
```

完整的文章类型映射表和决策细节见 `references/module-decision.md`。

## 输出：formatted.md

`formatted.md` 是原文 `article.md` 加上排版注释后的完整 markdown。

输出后，用对话腔告诉用户你穿了哪几件、为什么这么穿、verdict 挑的是哪句，并主动说「不对我换」。

## 硬规则

- **verdict 必须存在，且全文恰好 1 处。** 没有核心论点锚点不输出。
- **总模块数 ≤ 5，各模块不超各自上限。**
- **去掉所有 `:::xxx` 注释后，文章必须仍然完整可读。** 这是「穿衣不是枷锁」的硬验证。
- **不堆模块。** 找不到合适触发点的模块就不放（真实 + 降级）。
- **不改写正文。** 注释只包裹，一个字都不改。

## 验收

输出 formatted.md 前自查：

- **语法合法**：注释语法正确、配对完整（除 part 外都有 `<!-- ::: -->` 收尾）、verdict 存在且 = 1、各模块不超上限。
- **类型匹配**：模块选择匹配文章类型（技术文章只在需要视觉分段时用 part，操作流程才放 steps，抒情文章不塞 steps）。
- **触发真实**：每个模块都对应一个真实的触发场景，不是为加而加。callout 包的是风险或边界，quote 包的是可核实引文或已完成论证的核心判断。
- **交付前自查**：把所有 `:::xxx` 注释去掉，通读全文——还能顺畅读下来吗？能读才合格。读不下来说明注释改了正文，或者模块塞进了不该塞的地方。

## 降级

| 场景 | 降级路径 |
|------|---------|
| 找不到核心论点，无法放 verdict | 不硬挑一句凑数。告诉用户「我找不到一句明确的核心判断，verdict 放不了——你能指一句吗，或者这篇可能还没写出灵魂」。 |
| 某个模块找不到合适触发点 | 直接不放该模块，显式告诉用户「这篇没放 steps，因为没有明确的操作流程」。 |
| 文章类型判断不出来 | 问用户，不猜。 |

降级时显式标注，让用户知道哪些模块没放、为什么。

## 参考资料

- **`references/layout-modules.md`** — 5 个模块（part / callout / quote / steps / verdict）的完整转译规则、触发判断、约束、正反例。
- **`references/module-decision.md`** — 选模块决策算法详解 + 文章类型映射表 + 总数控制。

