fix(converters): stop blog footer turning the last body line into a heading#75
Conversation
…eading The footer was concatenated onto the body with no blank line, so output ended with 'last body line\n---'. CommonMark parses text immediately followed by '---' as a setext H2, so the final line of every blog post body became a heading and the intended horizontal rule was dropped. Add a blank line between the body and the footer so '---' is a thematic break.
|
@abhay-codes07 is attempting to deploy a commit to the Dodo Payments Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Pull request overview
Fixes a CommonMark rendering bug in the blog markdown converter where the footer’s --- could be parsed as a setext heading underline for the final body line, causing the rule to disappear and the last line to render as an H2.
Changes:
- Insert an extra newline between the blog post body and the footer so the footer’s
---is parsed as a thematic break, not a setext underline. - Add a regression test to ensure the output contains
last body line\n\n---(and notlast body line\n---). - Add a changeset for a patch release of
@dualmark/converters.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/converters/src/blog.ts | Adds a separating newline between body and footer to prevent setext heading parsing. |
| packages/converters/test/converters.test.ts | Adds a regression test asserting the body/footer separation behavior. |
| .changeset/blog-converter-setext-heading.md | Records the bug fix as a patch changeset for release notes/versioning. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Separate the body from the footer with a blank line. `base` ends with the | ||
| // body's last line (no trailing newline) and `footer` starts with "---"; | ||
| // without the blank line CommonMark parses "lastline\n---" as a setext H2, |
There was a problem hiding this comment.
Review: fix(converters): stop blog footer turning the last body line into a heading
Verdict: LGTM — approving.
Reviewed end-to-end and verified with a real CommonMark parser.
Root cause (confirmed on main)
The blog converter concatenated the footer directly onto the body:
return normalizeUnicode(base + footer.join("\n"));base ends with the body's last line (cleanBody trims trailing whitespace) and footer starts with "\n---", so the output contained last body line\n---. Per CommonMark, a line of text immediately followed by --- is a setext H2, not a paragraph + thematic break.
User-facing impact (verified with marked)
I rendered both variants through a real CommonMark parser:
main → "Final body line.\n---" ⇒ <h2>Final body line.</h2> (rule swallowed!)
fix → "Final body line.\n\n---" ⇒ <p>Final body line.</p><hr>
So on main, every blog post's final body line was silently promoted to a heading and the intended --- divider before the footer links vanished. This directly corrupts the markdown twin that AI clients read. The fix (inserting a blank line) resolves both symptoms.
Fix verification
Exercised blogConverter on the branch — output tail is now ... "Final body line.", "", "---", "- [More … articles]" ..., i.e. Final body line.\n\n---. The added test asserts both the presence of \n\n--- and the absence of the bad \n---\n sequence.
Tests
@dualmark/converters: 39/39 pass locally.
Minimal, correct, well-commented, changeset present. No concerns.
thepushkaraj
left a comment
There was a problem hiding this comment.
Thanks for the PR @abhay-codes07!
Summary
The blog converter joined its footer onto the body with no blank line, so the output ended with
last body line\n---. CommonMark reads that as a setext H2, so the final line of every blog post body was rendered as a heading and the horizontal rule before the footer links vanished. This adds the missing blank line.Closes #74.
Changes
packages/converters/src/blog.ts: separate the body from the footer with a blank line so the trailing---is a thematic break, not a setext underline.---, and is not glued directly to---.Type
AEO_SPEC_VERSION)Verification
bun run buildpassesbun run testpasses (converters: 39 tests)bun run typecheckpassesdualmark verify(no examples touched)/spec/: ran sync-spec (no spec files touched)Changeset
@dualmark/converters)cc @thepushkaraj @aagarwal1012. Small one, but it affects the rendered markdown of every blog post that has a body.