fix(wiki): give the preamble its own field instead of overloading heading==""
Second review pass on PR #103 found a third bug in the same file: the preamble fix from the prior commit represented "content before the first ## heading" as a section with heading=="" — which collides with a literal degenerate `## ` (marker, no title text; strings.TrimPrefix also yields ""). Two entries sharing one key in Merge's idx map means one loses lookup visibility. Reproduced: a has only a preamble, b introduces a genuinely new degenerate `## ` section — Merge's idx wrongly reports it as "already exists" (it's really a's unrelated preamble) and never adds it, so b's section vanishes from the output entirely. Fixed by giving parseSections a dedicated preamble return value instead of folding it into the sections slice. It can no longer collide with anything, degenerate or otherwise, because it's no longer keyed by heading at all. Merge and rebuildContent updated to thread it through directly. No other caller of parseSections/rebuildContent in this repo. Also fixed a doc-comment left misplaced by the prior commit (appendNew's comment had drifted onto canonicalLine, inserted between them). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -73,6 +73,24 @@ func TestMerge_PreservesOnDiskContentWithNoSectionHeadings(t *testing.T) {
|
||||
"on-disk content with no ## headings must survive the merge, not be replaced wholesale by the fresh extraction")
|
||||
}
|
||||
|
||||
func TestMerge_DegenerateEmptyHeadingDoesNotCollideWithPreamble(t *testing.T) {
|
||||
// Second review pass on #103: representing the preamble as a section with
|
||||
// heading=="" collides with a literal `## ` (marker, no title text) —
|
||||
// strings.TrimPrefix("## ", "## ") is also "". `a` has only a preamble
|
||||
// (no degenerate heading of its own); `b` introduces a genuinely new
|
||||
// degenerate `## ` section. Because both key to "", Merge's idx thinks
|
||||
// b's section "already exists" in a (it's really just a's unrelated
|
||||
// preamble) and never adds it — b's section vanishes from the output
|
||||
// entirely, not merged, not kept, not appended.
|
||||
a := Page{Path: "p.md", Content: "---\ntitle: X\n---\n\nAn intro paragraph.\n\n## Definition\n\nA thing.\n"}
|
||||
b := Page{Path: "p.md", Content: "---\ntitle: X\n---\n\n## \n\nA genuinely new degenerate section's body.\n\n## Definition\n\nA thing.\n"}
|
||||
|
||||
got := Merge(a, b)
|
||||
assert.Contains(t, got.Content, "An intro paragraph.", "a's own preamble must survive")
|
||||
assert.Contains(t, got.Content, "A genuinely new degenerate section's body.",
|
||||
"b's degenerate section is new content, not a collision with a's unrelated preamble — it must not be silently dropped")
|
||||
}
|
||||
|
||||
func TestMerge_PreservesPreambleBeforeFirstHeading(t *testing.T) {
|
||||
a := Page{Path: "wiki/x.md", Content: "---\ntitle: X\n---\n\nAn intro paragraph before the first heading.\n\n## Definition\n\nA thing.\n"}
|
||||
b := Page{Path: "wiki/x.md", Content: "---\ntitle: X\n---\n\n## Definition\n\nA thing.\n"}
|
||||
|
||||
Reference in New Issue
Block a user