Skip to content

Keep a thematic break directly under the header in the body - #145

Merged
matt-edmondson merged 2 commits into
mainfrom
fix/rule-under-header-stays-in-body
Sep 28, 2026
Merged

matt-edmondson merged 2 commits into
mainfrom
fix/rule-under-header-stays-in-body

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #140

What was wrong

TrySplitFrontmatterBlocks kept consuming blocks for as long as a delimiter line followed the one that had just closed. A --- rule placed straight under the header therefore opened a second "block" that ran to the next rule anywhere in the document.

  • Case A: when the text in between was not YAML, it was silently deleted from the body by ExtractBody, RemoveFrontmatter and every rewriting API.
  • Case B: when the text in between parsed as YAML, it was moved into the header.

Change

Only the first block is taken on trust. A follow-on block is accepted only when IsFollowOnBlock holds, which requires all of the following:

  • it contains a non-empty YAML mapping (this fixes Case A, and also an empty ---/--- pair under the header), and
  • its first and last content lines are not blank (this fixes Case B).

Otherwise splitting stops, and that block and everything after it stay in the body.

Decision to review: the triage asked for an owner call on the Case B rule. I used the example rule from the issue: a follow-on block whose content opens or closes with a blank line is body text. Stacked headers written tight against their delimiters, such as ---\ntitle: A\n---\n---\nauthor: B\n---, still combine as before, and the existing CombineFrontmatter_TwoConsecutiveBlocks_… test still passes. If you'd rather drop stacked-block support entirely, that is a one-line change in IsFollowOnBlock.

Tests

DelimiterLineTests gains four tests:

  • Case A: ExtractBody and RemoveFrontmatter return the whole body, both rules included.
  • Case A: AddFrontmatter merges into the header and keeps the whole body.
  • Case B: CombineFrontmatter leaves the document unchanged, and the YAML-like paragraph is not merged into the header.
  • An empty block under the header stays in the body.

With the fix reverted, all 4 new tests fail. With the fix, the full suite passes: 157/157.

Note: #143 (for #141) also appends tests to the end of DelimiterLineTests.cs, so whichever of the two merges second will need a trivial merge at the end of that file.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KMqfUfzWj2Gmdz1EqYdnLe


Generated by Claude Code

The splitter consumed another frontmatter block whenever a delimiter
line followed the one that closed the header, so a "---" rule placed
straight under the header opened a block that ran to the next rule.
Body text in between was either deleted (when it was not YAML) or moved
into the header (when it was).

Only the first block is now taken on trust. A follow-on block must hold
a non-empty YAML mapping and must not open or close with a blank line;
otherwise it and everything after it stay in the body. Tight stacked
headers, which are supported on purpose, are unaffected.

Fixes #140

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KMqfUfzWj2Gmdz1EqYdnLe
…-stays-in-body

# Conflicts:
#	Frontmatter.Test/DelimiterLineTests.cs
@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

Development

Successfully merging this pull request may close these issues.

A --- rule on the first body line is read as a second frontmatter block: body text is deleted by ExtractBody/RemoveFrontmatter or merged into the header

1 participant