canghe-format-markdown
Formats plain text or markdown files with frontmatter, titles, summaries, headings, bold, lists, and code blocks. Use when user asks to "format markdown", "beautify article", "add formatting", or improve article layout. Outputs to {filename}-formatted.md.
1How It Works & Mechanism
Clear division of labor: Content analysis and formatting are handled by Claude (LLM) in Steps 1–6, while the script only performs typesetting fixes in the final step (Step 7).
Claude performs content analysis and formatting (Steps 1-6), then runs the script for typography fixes (Step 7).
Detect content type first: If any of frontmatter, headings, bold, lists, code blocks, or blockquotes are matched, it is classified as markdown; it is treated as plain text only when none match.
| Has `---` YAML frontmatter | Markdown |
When markdown is detected, present the user with three choices: optimize formatting, keep as is, or run typesetting fixes only (the latter directly modifies the original file).
1. Optimize formatting (Recommended)
Auto-populate frontmatter: Write metadata fields such as title, slug, summary, and coverImage into YAML, with summary generated by the model as a 100–150 character abstract.
| `summary` | Generate engaging summary (100-150 characters) |
Heading deduplication: If the first line of the body is an H1, it is extracted into the frontmatter title and removed from the body to prevent duplicate H1 headings.
2. If first line is H1 → extract to frontmatter `title`, remove H1 from body
The output name is fixed to {original-filename}-formatted.md, and existing artifacts with the same name are backed up with a timestamp before overwriting.
mv "{filename}-formatted.md" "{filename}-formatted.backup-$(date +%Y%m%d-%H%M%S).md"
The typesetting script main.ts reads the file, processes it according to options, and writes it back in place; the processing is a deterministic string/AST transformation.
writeFileSync(filePath, formattedContent, "utf-8");
The script provides multiple typesetting toggles: CJK emphasis fixes, CJK/English spacing, ASCII to full-width quotes, and frontmatter YAML formatting.
| `scripts/quotes.ts` | Replace ASCII quotes with fullwidth quotes |
Spacing fixes are not implemented internally, but invoked via execSync calling the external npx autocorrect-node CLI.
execSync(`npx autocorrect-node --fix "${filePath}"`, { stdio: "inherit" });
The script depends on the remark ecosystem (remark-cjk-friendly / remark-frontmatter / remark-gfm / unified, etc.) and uses a YAML library to read and write frontmatter.
"remark-cjk-friendly": "^1.1.0",
2Core Capabilities
3External Dependencies
| Kind | Dependency / Endpoint |
|---|---|
| cli | bun / npx(npx -y bun 运行 main.ts) |
| package | autocorrect-node(npx 第三方 CLI,由 autocorrect.ts 调起) |
| package | remark 生态(remark-cjk-friendly / remark-frontmatter / remark-gfm / unified 等) |
| network | registry.npmjs.org(依赖与 npx 包拉取来源) |
4Recommended Governance & Evidence
- scripts/: Execute local scripts or commands: scripts/main.ts (run via npx -y bun: read file → typesetting processing → write back in place)
- 网络端点: Declared external network access: registry.npmjs.org (npx fetches autocorrect-node and bun dependencies on first run; npx package version is not locked in this repository)
- 本地工作目录: File I/O and artifact output: {filename}-formatted.md (formal output artifact)
5Second-Pass Verification
- [ok] 无业务网络请求,仅 npx 拉包 — §3 URL 命中集中在 package-lock.json 的 registry/赞助链接;脚本无业务端点调用,唯一外发是 npx 拉 autocorrect-node。
- [ok] 本地读写与原地修改 — main.ts 以 readFileSync/writeFileSync 同路径读写;SKILL.md 的「Typography fixes only」路径直接改原文件,无副本。
- [ok] CJK 排版三能力 — emphasis(remark-cjk-friendly)、spacing(autocorrect-node)、quotes(quotes.ts 全角替换)三项在脚本职责与 SKILL.md 选项中均有对应。
- [ok] execSync 命令注入面 — autocorrect.ts 用模板串把 filePath 插进 shell 命令;同类 baoyu 版用 spawnSync(npxCmd, [...args]) 的数组形式,本版更弱,已记入 injection_surface 与 risks。
- [ok] 无凭证读取 — 目录内无 env/keychain/cookie 读取;仅检查 EXTEND.md 偏好文件是否存在(非凭证)。
- [ok] 与 baoyu 同型实现的差异 — canghe 版无 references/ 与分析底稿,目录更精简(7 文件);排版脚本形态由 spawnSync 改为 execSync。
- [ok] 依赖可复现性 — remark 生态在 package.json/package-lock.json/bun.lock 有锁定;但 npx autocorrect-node 未锁定具体版本。
6Verdict & Scenarios
535df884a21e0d2e…