Skip to content

Recognise frontmatter delimiters only as whole lines at the top of a document - #135

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/132-133-line-based-delimiters
Sep 26, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/132-133-line-based-delimiters

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #132
Fixes #133

The triage on #133 asked for both fixes in one PR, because they share a root cause.

What was wrong

ExtractFrontmatterObjects split the whole document on every --- followed by a newline:

Change

  • New TrySplitFrontmatterBlocks:
    • Line-based parsing. The first line opens a block, and the block closes at the next line that is exactly ---; trailing whitespace is allowed.
    • A closing delimiter at the end of input counts.
    • Further blocks are consumed only while they follow directly. The body is everything after the last block consumed.
    • Lines split on CRLF, LF and CR wherever they occur, so the existing mixed-line-ending test still passes.
    • Blocks and body are sliced from the original text, so the body keeps its bytes exactly.
  • AddFrontmatter guard, as the triage asked: when frontmatter is present but can't be read, the document comes back unchanged instead of being overwritten. An empty block (---\n---) still gets the new properties.
  • An unclosed opening --- is now treated as no frontmatter. Before, everything after it was parsed as a block.

Tests

New DelimiterLineTests, 8 cases, covering each acceptance item:

  • Horizontal rules around note: hi stay in the body, for both ExtractBody and CombineFrontmatter (exact output).
  • A foo--- value mid-line.
  • The two-block combine case, with an exact expected output and no duplicated author: B.
  • Frontmatter-only input with no trailing newline, for both ExtractFrontmatter and AddFrontmatter (keeps title and author).
  • An unreadable block is left untouched, and an empty block still gets new properties.

Against the original Frontmatter.cs, 6 of the 8 new tests fail. The other two cover behaviour that already worked and must not regress. With the fix, all 153 tests pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VpbpayL5Kw99JfbzgkJfKa


Generated by Claude Code

…document

The document was split on every "---" followed by a newline, anywhere in
the text. This caused four problems:

- A markdown horizontal rule pair around a "key: value" paragraph was
  merged into the header.
- A value such as "foo---" split the header mid-line.
- CombineFrontmatter merged the second block into the header and also
  left it in the body.
- A closing "---" at the very end of the file was not recognised, so
  AddFrontmatter then overwrote the properties it could not see.

Frontmatter is now parsed line by line. The first line opens a block,
and the block closes at the next line that is exactly "---" (trailing
whitespace allowed), including one at the end of the input. Further
blocks are taken only while they follow directly. Every CRLF, LF and CR
ending is recognised, so mixed-ending documents still parse.

AddFrontmatter no longer treats frontmatter it cannot read as empty. It
returns the document unchanged, so a parsing gap can't lose properties.

Fixes #132
Fixes #133

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VpbpayL5Kw99JfbzgkJfKa
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants