The markdown canon lost `hardBreak` nodes in three pm->md->pm sub-cases where
the two-space ` \n` form does not survive re-import via marked:
1. Trailing at end of a paragraph — the top-level `.trim()` strips the trailing
` \n`, and even a non-last paragraph's trailing break sits before the `\n\n`
block gap, so marked drops it.
2. Consecutive breaks (`a<hardBreak><hardBreak>b`) — the whitespace-only middle
line reads as a paragraph separator, splitting the run into two paragraphs.
3. Inside a GFM table cell — the single-line cell collapses the break to a space.
Emit `<br>` (inline HTML break) in exactly those positions: marked passes it
through and generateJSON rebuilds a hardBreak in every context, including table
cells. renderInlineChildren now picks `<br>` for a break that is the last inline
child or is followed by another break; a safe mid-paragraph break keeps the
byte-stable ` \n` form (golden output unchanged). Footnote bodies are skipped
(their `^[…]` form already collapses breaks to spaces). The table-cell case
converts the ` \n` marker to `<br>` before the newline collapse.
Adds pm->md->pm count/position round-trip tests for all three sub-cases plus a
mid-paragraph regression guard.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>