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:
+6
-5
@@ -1,6 +1,6 @@
|
||||
# State
|
||||
|
||||
**Verified against:** `d67cfd1` on 2026-07-30 — update this line every change.
|
||||
**Verified against:** `ff62729` on 2026-07-30 — update this line every change.
|
||||
If this file disagrees with the code, the code is right and this file is a bug.
|
||||
|
||||
## Inventory
|
||||
@@ -15,7 +15,8 @@ If this file disagrees with the code, the code is right and this file is a bug.
|
||||
| `internal/render/chrome.go` | the engine's own words: phrase table, month names, digits, and the `t`/`num`/`day` template funcs (ADR-0034) | 105 |
|
||||
| `internal/render/templates/` | reference theme: `base.html`, `page.html`, `list.html`, `shortcodes.html`, `theme.css` (ADR-0026) | — |
|
||||
| `internal/ext/shortcodes/` | first feature: `{{< name key="value" >}}` block parser and node renderer, rendering through a theme fragment (ADR-0036). `figure`, `gallery`, `include` | 315 |
|
||||
| `cmd/khosra/wire.go` | the only list of enabled features (`extensions.md`) | 19 |
|
||||
| `internal/ext/widows/` | second feature: joins the last two words of a paragraph or heading with a non-breaking space, over the tree so code spans are safe | 108 |
|
||||
| `cmd/khosra/wire.go` | the only list of enabled features (`extensions.md`) | 20 |
|
||||
| `internal/web/resolve.go` | URL → (key, lang, page, tag) or a canonical redirect: language prefix, `/en/…` fork guard, pagination, tags, trailing slash | 112 |
|
||||
| `internal/web/web.go` | handler: resolve, look up with fallback, section and tag listings, sequence, `/static/` (misses and refusals alike answer 404), degrade on failure | 152 |
|
||||
| `cmd/khosra/main.go` | flags, wiring, startup — the only place things are assembled | 53 |
|
||||
@@ -24,7 +25,7 @@ If this file disagrees with the code, the code is right and this file is a bug.
|
||||
Serves a bundle at `/{section}/{slug}/`, a paginated listing per section, tag listings global and
|
||||
section-narrowed, sequence navigation and a series archive on any nested bundle, and `static/` verbatim.
|
||||
Chrome text, dates and digits render in English or Bengali; authored text is untouched but for typographic
|
||||
smoothing (ADR-0034). This repo holds engine source only — the site root is external and passed with
|
||||
smoothing and widow prevention (ADR-0034). This repo holds engine source only — the site root is external and passed with
|
||||
`-site` (ADR-0011).
|
||||
|
||||
Frontmatter the parser lifts today: `title`, `date`, `tags`, `aliases`, `order`. Every other key in
|
||||
@@ -40,12 +41,12 @@ this change*.
|
||||
|
||||
| Counter | Now | Extraction due at | What it buys |
|
||||
|---|---|---|---|
|
||||
| Render transforms — **page-level only** | 0 | **3** | Stage pipeline (ordered `func(ctx,*Page) error`). Parse-phase work does *not* count and must not: goldmark's extender list is already an ordered pipeline for it, so typography and shortcodes compose there (`cmd/khosra/wire.go`) and a second pipeline beside it would be pure duplication. This counts transforms over the assembled page, which nothing hosts yet — OpenGraph and JSON-LD (queue 15) are the first candidates |
|
||||
| Render transforms — **page-level only** | 0 | **3** | Stage pipeline (ordered `func(ctx,*Page) error`). Parse-phase work does *not* count and must not: goldmark's extender list is already an ordered pipeline for it, so typography, shortcodes and widows compose there (`cmd/khosra/wire.go`) and a second pipeline beside it would be pure duplication. This counts transforms over the assembled page, which nothing hosts yet — OpenGraph and JSON-LD (queue 15) are the first candidates |
|
||||
| Routing cases | 5 | **2** — done | Resolver at `internal/web/resolve.go`: bundle, language prefix, pagination, tag, section-narrowed tag |
|
||||
| Collection pages | 4 | **1** — done | Query primitive: `content.Query{Section, Tag, Lang}` + `Site.Run`. The fourth — a series archive — resolves through `Site.Sequence` instead: membership is structural and the sort ascends, so it shares the index but not the Query |
|
||||
| Views / output formats | 2 | **2** — due | Two template sets exist (bundle, listing); the View layer is Arc 2's third item |
|
||||
| Effects | 0 | **2** | Effect runner + trigger wiring (change / schedule / demand) |
|
||||
| Extensions | 1 | **3** | Extension registry (`extensions.md`). The wire file arrived with the first feature rather than the registry — `cmd/khosra/wire.go`, one line, no struct |
|
||||
| Extensions | 2 | **3** | Extension registry (`extensions.md`). The wire file arrived with the first feature rather than the registry — `cmd/khosra/wire.go`, one line, no struct |
|
||||
| Interface implementations | — | **2** | The interface itself |
|
||||
| Non-stdlib dependencies | 3 direct | budget in `scripts/budgets.env` | — |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user