prevent widows, as the second feature package

The last two words of a paragraph or heading are joined by a non-breaking space,
so one word never falls alone onto its own line. Deferred from entry 11 for the
right reason: over rendered HTML this cannot tell prose from an escaped code span,
so it had to wait for a tree transform.

The interesting failure is worth keeping: written against goldmark alone it passed
six tests, and did nothing in the real engine. The typographer splits a text run
wherever it looks for a substitution, so a paragraph ending "hand." arrives as two
text nodes and the last of them holds no space at all. A version that inspects
only the last child therefore finds nothing to join. It now takes the whole
trailing run of text nodes, stopping at a line break or any markup, and there is a
regression test that builds both extensions together — the only configuration that
would have caught it.

The joined text becomes a String node, which carries its own bytes: a segment is
an offset into bytes every node shares, so editing the source in place is not
possible. That path still escapes, and a test says so, since otherwise this
transform would be an injection route.

PhaseMarkup is now empty in extensions.md, and honestly so: everything expected
there turned out to belong either earlier or later.
This commit is contained in:
2026-07-31 02:12:08 +06:00
parent 0bffef2aac
commit ff6272974e
7 changed files with 215 additions and 8 deletions
+7
View File
@@ -0,0 +1,7 @@
// Package widows keeps the last word of a paragraph or heading from falling alone onto its own line.
//
// Contributes: a Markdown AST transformer (PhaseParse).
// Cascade keys: none.
// Contract fields: none — it changes one space in the text, and nothing a theme reads.
// Not doing: hyphenation, orphans, balancing headings across lines — those are the theme's typography.
package widows