Preserve the line breaks that space out page sections

Page content separates its major sections with leading <br><br>, which
the old site renders as a blank line before each section heading. Those
breaks were being lost, leaving every section butted up against the
previous one.

Two causes. The content contains malformed `</br>` closing tags, which
browsers treat as a line break but an HTML parser discards, so they
never survived the HTML->Markdown conversion; they're now rewritten to
<br />. And Markdown drops a hard break at the start of a paragraph, so
turndown now emits literal <br /> tags instead of the trailing-two-space
form -- inline, with no trailing newline, since a lone tag on its own
line starts a raw HTML block (CommonMark type 7) and would stop the rest
of the paragraph being parsed as Markdown at all.

Verified against the live old site: paragraph count, <br> count, bold
heading count and per-paragraph break placement now all match exactly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 19:29:39 -04:00
co-authored by Claude Opus 5
parent 289a5b3118
commit 63c2f6c0e7
31 changed files with 278 additions and 555 deletions
+19 -2
View File
@@ -33,10 +33,27 @@ const NAV_DEST = path.join(ROOT, 'src/data/nav.json');
const turndown = new TurndownService({ headingStyle: 'atx', codeBlockStyle: 'fenced' });
// Emit literal <br /> rather than Markdown's trailing-two-spaces hard break. Markdown drops a
// hard break at the start of a paragraph, and this content uses leading breaks deliberately to
// space out sections -- raw tags survive that round-trip, and render identically.
// Deliberately no trailing newline: a lone tag on its own line starts a raw HTML block
// (CommonMark type 7), which would stop the rest of the paragraph being parsed as Markdown.
turndown.addRule('lineBreak', {
filter: 'br',
replacement: () => '<br />',
});
// This DB's post_content has literal backslash-n sequences from a past export/import,
// not real newlines -- normalize before treating it as HTML/text.
// not real newlines -- normalize before treating it as HTML/text. The content also contains
// malformed `</br>` closing tags, which browsers (and therefore the old site) render as a
// line break, but an HTML parser drops -- rewrite them so those breaks survive.
function fixLiteralNewlines(text) {
return text.replace(/\\r\\n/g, '\n').replace(/\\n/g, '\n').replace(/\r\n/g, '\n').replace(/\r/g, '\n');
return text
.replace(/\\r\\n/g, '\n')
.replace(/\\n/g, '\n')
.replace(/\r\n/g, '\n')
.replace(/\r/g, '\n')
.replace(/<\/br\s*>/gi, '<br />');
}
// Classic-editor content is stored without <p> tags and rendered through WordPress's