diff --git a/docs/decisions.md b/docs/decisions.md index 883d68d..4e87ed2 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -526,8 +526,9 @@ and its issues and Actions are off. Push to GitHub only. ## The formats are API -2026-08-23, strict input 2026-09-01, content models 2026-09-16, the maintainer. Goal 1. -Valid while consumers store what the library emits. +2026-08-23, strict input 2026-09-01, content models 2026-09-16, the maintainer; what a carry +element shows 2026-10-28, the systems-architect. Goal 1. Valid while consumers store what the +library emits. The emitted markdown and HTML are contracts. After 1.0: previously-emitted output parsing differently, or not at all, is MAJOR; new syntax while old output still round-trips is MINOR. @@ -536,6 +537,12 @@ container is the model, not the syntax — so giving a spelled node's model cont taking it away, is MAJOR whatever ADF's own schema does. Input reads the canonical directive spelling alone — spacing, key order, each value's spelling — since loosening it later is MINOR. +What an HTML carry element shows is part of that contract too. `htmlToAdf` refuses a carry element +showing anything but what `adfToHtml` shows for its node, so an edit there is refused rather than +lost (Goal 7). A change to what a carry element shows, in `src/html/carry-content.ts` or in the +`src/adf/shown-text.ts` it shares with portable markdown, makes HTML an earlier release wrote +unreadable: MAJOR after 1.0, and a `MIGRATION.md` entry before. + The error surface is a contract too; `README.md` §The errors states it to the consumer, and the types in `src/result.ts` hold its shape. diff --git a/src/html/carry-content.ts b/src/html/carry-content.ts index 558233d..36f9c29 100644 --- a/src/html/carry-content.ts +++ b/src/html/carry-content.ts @@ -9,7 +9,7 @@ import { shownValue } from './escaping.ts' // The content a carry element shows of one block; `code` the code block holding it, if any. type ShownBlock = { code: AdfNode | undefined; html: string } -// What a carry element shows of the node it holds: in a `
`, each block's content as a `

`, a code block's as `

`; in a ``, the blocks parted by `
`. +// What a carry element shows of the node it holds, and all `htmlToAdf` accepts there, so a change here breaks reading stored HTML (docs/decisions.md §The formats are API): in a `
`, each block's content as a `

`, a code block's as `

`; in a ``, the blocks parted by `
`. export function carryContent(node: AdfNode, tag: 'div' | 'span'): string { if (tag === 'span') return shownBlocks(node, '
').map(({ html }) => html).join('
') return shownBlocks(node, '\n').map(({ code, html }) => (code === undefined ? `

${html}

` : `
${html}
`)).join('') diff --git a/todo.md b/todo.md index e1a270d..854b5a1 100644 --- a/todo.md +++ b/todo.md @@ -31,7 +31,7 @@ | 68 | 0.4.0 | | defect | **Carry a non-text inline node holding `content` or `text`, a block holding `text`, and a leaf block holding `content`.** | 2 | 1 | 2 | 3 | 3 | 1 by 2 | 13.1 | | 127 | 0.4.0 | | principle | **Hold what `entity-references.test.ts`, `json-text.test.ts` and `result.test.ts` check by asserting outcomes, so none reads source text.** | 2 | 2 | 1 | 3 | 3 | code health by 2 | 13.1 | | 144 | 0.4.0 | | | **Give every container `docker-runner.sh` and `publish.sh` start a memory limit and an equal swap limit, sized from the largest a gate leg measurably needs.** | 1 | 1 | 1 | 1 | 2 | code health by 1 | 8.7 | -| 143 | 0.4.0 | | defect | **Keep, in `adfToPortableMarkdown`, the link around a note and the target of a link marking a card, so a linked stored image or card writes every target.** | 2 | 1 | 2 | 3 | 3 | 7 by 1 | 6.5 | +| 143 | 0.4.0 | | defect | **Keep, in `adfToPortableMarkdown`, the link around a note and the target of a link marking a card, so a linked stored image or card writes every target.** | 2 | 1 | 3 | 4 | 3 | 7 by 1 | 6.5 | | 112 | 0.4.0 | | | **Pad a GFM pipe table's short rows with empty cells, read its body rows holding no pipe, and read a one-column table without leading pipes in `portableMarkdownToAdf`.** | 2 | 1 | 2 | 3 | 3 | 4 by 4 | 6.2 | | 80 | 0.4.0 | | | **Name the node's path and the attribute key when `not-an-adf-document` refuses a node inside the document.** | 2 | 1 | 2 | 3 | 3 | 6 by 4 | 6.0 | | 81 | 0.4.0 | | | **Fail the gate unless the README's error tables list exactly the codes `ConvertErrorCode` holds.** | 1 | 1 | 1 | 1 | 2 | 3 by 2 | 4.2 | @@ -259,6 +259,10 @@ links the card's URL, as its text, to the mark's target (`docs/decisions.md` §T Move the choice of where a card's text and a note link into `src/adf/shown-text.ts`, beside `shownImage`'s for an image, so both writers render one answer. +Leave what an HTML carry element shows unchanged, or ship the change as a breaking HTML change with +a `MIGRATION.md` entry: `htmlToAdf` refuses any other content, so HTML stored by an earlier release +would no longer read (`docs/decisions.md` §The formats are API). + ### 112. Pad a GFM pipe table's short rows with empty cells, read its body rows holding no pipe, and read a one-column table without leading pipes in `portableMarkdownToAdf`. GFM pads a short row with empty cells, reads a line holding no `|` after a table as a row, and