A calm place to write long-form, and publish it to the open social web. skypress.blog/
0

Configure Feed

Select the types of activity you want to include in your feed.

at trunk 47 lines 2.5 kB View raw View rendered
1# 0018 — The article render pipeline lives in one render-article module 2 3- **Status:** Accepted 4- **Date:** 2026-06-10 5- **Scope:** the article render pipeline (`src/lib/reader/render-article.ts`, the 6 article page, `src/lib/feed/publication-feed.ts`) 7 8## Context 9 10Turning a stored block tree into safe HTML takes three calls in one load-bearing 11order — `resolveBlobImageUrls``renderBlocks``sanitizeArticleHtml` — plus the 12plain-text fallback (`doc.textContent || blocksToText( blocks )`). The ordering is the 13AGENTS.md #6b invariant (sanitise is the LAST step before injection), but no module 14owned it: the article page and the feed builder each assembled it by hand. A third 15read surface (AMP, email, embeds) would have had to re-learn the order, and getting it 16wrong ships unsanitised PDS HTML. Decision 0016 sealed route *resolution* behind 17`read-context.ts` and explicitly deferred this orthogonal deepening. 18 19## Decision 20 21One deep module, `src/lib/reader/render-article.ts`: 22 23```ts 24renderArticle( doc, { pdsUrl, did } ) { html, text } 25``` 26 27- It accepts the document-value slice (`textContent` + `content.blocks`) rather than 28 raw blocks, so the text fallback concentrates here too. `read-context.ts`'s 29 `SkyDocumentValue` and the feed's `FeedDocumentValue` both satisfy the 30 `RenderableDocument` parameter structurally — no adapter layer. 31- The pipeline-order invariant gains locality: it lives once, behaviourally tested in 32 `render-article.test.ts` (a `<script>` in block content never survives; blob-backed 33 image URLs are rebuilt against the author's current PDS before render). 34- Like `render.ts` underneath, the module is dependency-free — it must never import 35 `@wordpress/*` (Decision 0003). It wraps `render.ts`, sitting beside it; render 36 fidelity stays locked by `render.test.ts`, untouched. 37- The article page and `buildPublicationFeedXml` are now callers; 38 `publication-feed.ts` stays a pure transform. New read surfaces get sanitisation for 39 free by construction — AGENTS.md rule 6(b) now points here. 40 41## Consequences 42 43- `resolveBlobImageUrls`, `renderBlocks`, and `sanitizeArticleHtml` keep their own 44 unit suites; no page or transform should compose them by hand again 45 (`_[rkey].meta.test.ts` pins the article page's delegation). 46- A surface needing different rendering rules (e.g. email's stricter tag set) extends 47 this module's interface rather than re-assembling the pipeline at the call site.