fix(frontmatter): recognise empty frontmatter blocks#592
Open
MFA-G wants to merge 1 commit into
Open
Conversation
An empty frontmatter block (`---\n---\n` with no content between the delimiters) was not matched by the splitFrontmatter regex. This caused the literal `---` markers to leak into the body and hasFrontmatter to be reported as false. For subagent markdown files this even raised "No YAML frontmatter found in file". Make the inner frontmatter capture group optional so an empty block is recognised, returning an empty frontmatter string and a clean body. The only behavioural change is for the previously-unhandled empty-block case; all other inputs split identically. Add frontmatter.spec.ts covering splitFrontmatter (standard, multi-line, CRLF, no-trailing-newline, empty block, blank-line block, embedded ---, no-frontmatter, lone-delimiter) and parseYamlObject.
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes splitFrontmatter so it correctly recognizes empty YAML frontmatter blocks (---\n---\n...) at the start of markdown files, preventing delimiter leakage into the body and ensuring hasFrontmatter is reported correctly.
Changes:
- Updated the frontmatter regex to allow an empty frontmatter section between delimiters.
- Adjusted
splitFrontmatterextraction to returnfrontmatter: ''when the optional capture group is absent. - Added a new AVA spec file covering
splitFrontmatterandparseYamlObjectacross a range of inputs, including the empty-frontmatter regression.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
source/utils/frontmatter.ts |
Makes the frontmatter capture optional so ---\n---\n is treated as valid frontmatter with an empty frontmatter string. |
source/utils/frontmatter.spec.ts |
Adds coverage for empty/blank-line frontmatter handling and parseYamlObject behaviors (valid mapping, blank, scalar/array, invalid YAML). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
splitFrontmatterfailed to recognise an empty frontmatter block — a file that opens with---and closes with---on the next line, with no lines in between:The existing regex required at least one captured line between the delimiters (
([\s\S]*?)\r?\n---), so an empty block fell through to the no-frontmatter branch. Two consequences:hasFrontmatterwas reported asfalseand the literal---\n---markers leaked intobody.extractRawFrontmatterthen threwNo YAML frontmatter found in file(seesource/subagents/markdown-parser.ts), even though the file does have a (valid, empty) frontmatter block.Fix
Make the inner frontmatter capture group optional so an empty block is matched, returning an empty
frontmatterstring and a cleanbody:I verified against a matrix of inputs that the only behavioural change is the previously-unhandled empty-block case — every other input (standard, multi-line, CRLF, no trailing newline, embedded
---in the body, lone delimiter, no frontmatter) splits identically to before.Tests
Added
source/utils/frontmatter.spec.ts(the module had no spec). It coverssplitFrontmatteracross all the cases above — including a regression test for the empty block — plusparseYamlObject(valid object, nested/array values, blank input, scalar, top-level array, invalid YAML).Validation
pnpm exec ava source/utils/frontmatter.spec.ts— 15 passedpnpm run test:ava— full suite, 5775 passedpnpm run test:types— cleanpnpm exec biome lint/check(changed files) — cleanpnpm run test:knip— clean