Skip to content

fix(scripts): keep a frontmatter field whose value ends in a line terminator - #1208

Merged
BryanFRD merged 1 commit into
mainfrom
fix/frontmatter-regex-line-terminators
Sep 27, 2026
Merged

BryanFRD merged 1 commit into
mainfrom
fix/frontmatter-regex-line-terminators

Conversation

@BryanFRD

Copy link
Copy Markdown
Contributor

Closes #1207. Follow-up to #1206, from the nit on its review, which merged before this could land on it.

-const FIELD = /^([A-Za-z_]\w*):(.*)$/;
+const FIELD = /^([A-Za-z_]\w*):([\s\S]*)$/;

#1206 claimed its rewrite changed nothing. That held for the alphabet I fuzzed, which had no line terminator in it. . excludes CR, U+2028 and U+2029 while \s includes them, so a value ending in one stopped matching and the field vanished: title:a + CR went from a to "frontmatter needs a non-empty title".

Measured on 400,000 random lines, this time with CR, U+2028 and U+2029 in the alphabet:

lines without a line terminator terminator in surrounding whitespace terminator inside the value
(.*), as merged identical 1338 fields lost identical (both drop it)
([\s\S]*), this PR identical identical 1718 fields kept that used to be dropped

So [\s\S]* never loses a field the original kept. It differs only where a terminator sits inside the value, and there the original's behaviour was an accident of what . matches rather than a rule: title: a + U+2028 + b has a title, and reporting it as missing was a false failure.

Still linear: without the m flag $ only matches at the end, so the greedy [\s\S]* runs straight there and never backtracks. 0.0 ms at 20,000 characters.

Not reachable through the normal path either way, since the block is split on \r?\n first. node scripts/validate-site-docs.mjs: 169 pages validated.

@ferrfleet ferrfleet Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. Without the m flag $ anchors at end of input only, so ([\s\S]*)$ matches greedily to the end and cannot backtrack, and trim() already strips CR/U+2028/U+2029 from the captured value, so the field comes out clean.

Checked the one case that would worry me, a value that swallows a following key: with CR-only line endings the whole block collapses to a single "line" and title:a\rdescription:b now yields a title of a\rdescription:b where before both fields vanished. It still fails validation, because description never lands in the map, so this cannot turn into a false pass. And it is unreachable regardless since FRONTMATTER requires \r?\n delimiters.

Nit, no action needed here: there is no test harness under scripts/, so the fuzzing evidence lives only in the PR body. If one ever gets added, title:a + CR is the case to pin.

@BryanFRD
BryanFRD merged commit 24e4ac0 into main Sep 27, 2026
31 checks passed
@BryanFRD
BryanFRD deleted the fix/frontmatter-regex-line-terminators branch September 27, 2026 17:31
ferrflow Bot added a commit that referenced this pull request Sep 27, 2026
## [7.26.8] - 2026-09-27

### Bug Fixes

- fix(scripts): keep a frontmatter field whose value ends in a line terminator (#1208)
- fix(scripts): stop the frontmatter field regex backtracking quadratically (#1206)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(scripts): the frontmatter regex rewrite drops a field ending in a stray CR

1 participant