/** * Make one item's prose safe to publish, and make its references clickable. * * The body used to carry no item prose at all, and the reason was three real hazards. Two * of them are properties of GitHub's renderer and one is a property of this feature's own * marker scanner: * * - **Marker injection.** The item↔issue link is an HTML comment. An item that quotes one * would stamp a second marker onto a different issue, and `indexByMarker` then refuses * the whole run as ambiguous — or, before that guard existed, retitled the wrong issue. * - **Notification side effects.** `@name` and `#123` notify people and cross-link issues * the instant they are published. A sync is not a reason for somebody's inbox to move. * - **Field limits.** GitHub caps a body at 65,536 characters, so the prose needs a budget * (that half lives in `body.ts`). * * The rejected alternative was to publish nothing and make the reader follow a link, which * is what shipped in v1.21.0 and what this instance exists to undo: a body carrying no * item-specific words is a redirect, and thirty of them on a board are thirty copies of one * paragraph. * * **Everything here is code-aware, and that is the whole design.** Measured over this * project's 76 items on 2026-09-07, 40 of the 41 hazard spans are inside a fence or an * inline code span — `@clack/prompts`, `actions/checkout@v4`, colour hexes like `#0891b2` * — and exactly one is in prose. A rule that ignored code would corrupt forty spans in * order to defuse one. See `markdown.ts`. * * Requirements: richer-issue-bodies/AC-9, richer-issue-bodies/AC-10, * richer-issue-bodies/AC-11, richer-issue-bodies/AC-12, richer-issue-bodies/AC-29 * * @module */ export interface SanitizeContext { /** Item id → repo-relative path. An empty map disables reference linking entirely. */ itemPaths: ReadonlyMap; /** Repo-relative path → absolute URL, or null when coordinates are unknown. */ fileUrl: ((relPath: string) => string) | null; } /** * Sanitize and enrich an item body for publication. * * Four rules, and the **order is load-bearing**, because two of them insert text a later * rule must not re-examine: * * 1. Item references become links. This runs first because it is the only rule that * deliberately rewrites a code span, and because the link it emits contains no `@`, `#` * or `