The finding
Observation, not a defect — filing it for triage rather than acting on it.
The #162 sweep looked for frontmatter-splitting copies across scripts/. It found the two the card named (content-lint.mjs, lib/post-dates.mjs, now consolidated into scripts/lib/frontmatter.mjs) and two more the card did not:
| Where |
Shape |
Fails on a bad fence? |
YAML |
scripts/lib/frontmatter.mjs (after #162) |
startsWith('---\n') + indexOf('\n---', 4) |
yes — reports no-opening-fence / no-closing-fence, caller throws |
js-yaml, in the caller |
scripts/gen-zh-hant.mjs:168 splitFrontmatter(source) |
/^---\n[\s\S]*?\n---\n/ |
no — falls back to { head: '', body: source } |
none (head is copied verbatim) |
scripts/lib/wechat-html.mjs:43 splitFrontmatter(src) |
/^---\n([\s\S]*?)\n---\n?/ |
no — falls back to { data: {}, body: src } |
none — single-line scalars read with /^(\w+):\s*(.+)$/ |
scripts/new-post.mjs has no copy: it only writes a frontmatter template. scripts/to-wechat.mjs has no copy either; it delegates to lib/wechat-html.mjs.
Why they were left alone
Both differences look deliberate, and #162 was a pure consolidation card that was explicitly not allowed to ship a behaviour change:
- Neither is a gate.
gen-zh-hant.mjs must still rewrite a body it cannot read a head from, and the WeChat exporter must still produce HTML — so both tolerate what the lint copy rejects. Routing either through the shared helper would turn a tolerated file into a failing one.
wechat-html.mjs deliberately avoids js-yaml because it only ever wants title / description / author, and its comment says so: "Minimal frontmatter splitter — single-line scalars only".
- Both require a newline after the closing fence (
\n---\n), which the shared helper does not — a file ending exactly at \n--- splits under content-lint.mjs and does not split under these two.
The differences are now recorded in a comment at the bottom of scripts/lib/frontmatter.mjs, so the next reader finds them documented rather than discovering them. This issue exists so the decision is on record too.
What a triage might decide
- Leave both — they serve different jobs and the difference is documented. Cheapest, and the status quo.
- Give the helper a tolerant mode (
splitFrontmatter(source, { strict: false })) and route all four through it, so there is one fence definition with two failure policies. This is a behaviour change for whichever file today falls in the gap, and needs its own equivalence table across pnpm gen:zh-hant and pnpm wechat.
- Leave
wechat-html.mjs alone permanently — a regex scalar reader is not a frontmatter parser and should not pretend to be one; only gen-zh-hant.mjs is a candidate.
Not urgent either way: nothing is broken today, and the two weak splitters agree with each other.
Found while implementing #162. scripts/gen-zh-hant.mjs was read-only for that round (owned by #194).
Generated by Claude Code
The finding
Observation, not a defect — filing it for triage rather than acting on it.
The #162 sweep looked for frontmatter-splitting copies across
scripts/. It found the two the card named (content-lint.mjs,lib/post-dates.mjs, now consolidated intoscripts/lib/frontmatter.mjs) and two more the card did not:scripts/lib/frontmatter.mjs(after #162)startsWith('---\n')+indexOf('\n---', 4)no-opening-fence/no-closing-fence, caller throwsjs-yaml, in the callerscripts/gen-zh-hant.mjs:168splitFrontmatter(source)/^---\n[\s\S]*?\n---\n/{ head: '', body: source }scripts/lib/wechat-html.mjs:43splitFrontmatter(src)/^---\n([\s\S]*?)\n---\n?/{ data: {}, body: src }/^(\w+):\s*(.+)$/scripts/new-post.mjshas no copy: it only writes a frontmatter template.scripts/to-wechat.mjshas no copy either; it delegates tolib/wechat-html.mjs.Why they were left alone
Both differences look deliberate, and #162 was a pure consolidation card that was explicitly not allowed to ship a behaviour change:
gen-zh-hant.mjsmust still rewrite a body it cannot read a head from, and the WeChat exporter must still produce HTML — so both tolerate what the lint copy rejects. Routing either through the shared helper would turn a tolerated file into a failing one.wechat-html.mjsdeliberately avoidsjs-yamlbecause it only ever wantstitle/description/author, and its comment says so: "Minimal frontmatter splitter — single-line scalars only".\n---\n), which the shared helper does not — a file ending exactly at\n---splits undercontent-lint.mjsand does not split under these two.The differences are now recorded in a comment at the bottom of
scripts/lib/frontmatter.mjs, so the next reader finds them documented rather than discovering them. This issue exists so the decision is on record too.What a triage might decide
splitFrontmatter(source, { strict: false })) and route all four through it, so there is one fence definition with two failure policies. This is a behaviour change for whichever file today falls in the gap, and needs its own equivalence table acrosspnpm gen:zh-hantandpnpm wechat.wechat-html.mjsalone permanently — a regex scalar reader is not a frontmatter parser and should not pretend to be one; onlygen-zh-hant.mjsis a candidate.Not urgent either way: nothing is broken today, and the two weak splitters agree with each other.
Found while implementing #162.
scripts/gen-zh-hant.mjswas read-only for that round (owned by #194).Generated by Claude Code