29: the README states the raw HTML rule once #115

Merged
lilleman merged 1 commits from readme-raw-html into main 2026-09-20 23:26:28 +02:00
3 changed files with 30 additions and 25 deletions
Showing only changes of commit 0c8fd36ef8 - Show all commits
+14 -15
View File
@@ -29,9 +29,9 @@ In priority order.
2. **Three formats, ADF the hub.** ADF, one markdown flavour, one HTML dialect, markdown↔HTML 2. **Three formats, ADF the hub.** ADF, one markdown flavour, one HTML dialect, markdown↔HTML
composing through ADF — four conversions to keep correct, never a fifth, and never a fourth composing through ADF — four conversions to keep correct, never a fifth, and never a fourth
format. format.
3. **Plain CommonMark is input.** Markdown written for something else converts — the three 3. **Plain CommonMark is input.** Markdown written for something else converts — the exceptions
carve-outs and the one gap below are the whole of the exception — and every spelling the below are the whole of them — and every spelling the flavour claims on top of CommonMark is
flavour claims on top of CommonMark is escapable, so the flavour is opt-in. escapable, so the flavour is opt-in.
4. **Output a person can edit.** A node CommonMark can spell gets that spelling; the directive 4. **Output a person can edit.** A node CommonMark can spell gets that spelling; the directive
form carries only what CommonMark cannot hold. form carries only what CommonMark cannot hold.
5. **Failures are values.** Nothing throws, and `code` is a closed list — as much a contract as 5. **Failures are values.** Nothing throws, and `code` is a closed list — as much a contract as
@@ -118,7 +118,7 @@ Parsing — `markdownToAdf`, and `htmlToAdf` at `0.2.0`:
| `malformed-directive` | an `!adf:` the grammar cannot read — a prefix completing no directive, an unclosed container, `[content]` or `{attrs}`, a closer with no container of its name open, a leaf given a body, `{attrs}` out of order or duplicated, invalid JSON in a `carry` | write the spelling the message names, or escape the prefix — `\!adf:`, block and inline alike — to keep it literal text | | `malformed-directive` | an `!adf:` the grammar cannot read — a prefix completing no directive, an unclosed container, `[content]` or `{attrs}`, a closer with no container of its name open, a leaf given a body, `{attrs}` out of order or duplicated, invalid JSON in a `carry` | write the spelling the message names, or escape the prefix — `\!adf:`, block and inline alike — to keep it literal text |
| `malformed-pipe-table` | a pipe row that is no pipe table — a missing or ragged `---` delimiter row, an alignment colon in it, or a row not opening with a pipe | open every row with a pipe and give the delimiter row the header's cell count; to keep the lines literal text instead, escape the leading pipe of every one — escaping a single row leaves the next to open a fresh table and fail the same way | | `malformed-pipe-table` | a pipe row that is no pipe table — a missing or ragged `---` delimiter row, an alignment colon in it, or a row not opening with a pipe | open every row with a pipe and give the delimiter row the header's cell count; to keep the lines literal text instead, escape the leading pipe of every one — escaping a single row leaves the next to open a fresh table and fail the same way |
| `unknown-directive-name` | a directive whose name is no node or mark this version spells | check the name in `spec/flavour.md`, or escape the prefix as `\!adf:`; the spelling itself is well formed, so a later minor may give the name meaning | | `unknown-directive-name` | a directive whose name is no node or mark this version spells | check the name in `spec/flavour.md`, or escape the prefix as `\!adf:`; the spelling itself is well formed, so a later minor may give the name meaning |
| `unmappable-html` | the markdown holds a raw HTML tag, comment or processing instruction | remove it or write it in the flavour — ADF holds no raw-HTML node, and the element mapping lands at `0.2.0` | | `unmappable-html` | the input holds an HTML construct the documented element set does not map, a comment and a processing instruction among them — at this version that is every raw HTML construct in markdown, the element set landing at `0.2.0` | remove the construct, or write what it holds in the flavour |
| `unmappable-image` | an image sits inside other content that is not another image's description, or carries a title | give the image a paragraph of its own and drop the title | | `unmappable-image` | an image sits inside other content that is not another image's description, or carries a title | give the image a paragraph of its own and drop the title |
Emitting — `adfToMarkdown`, and `adfToHtml` at `0.2.0`: Emitting — `adfToMarkdown`, and `adfToHtml` at `0.2.0`:
@@ -144,13 +144,13 @@ emit refuses:
- `markdownToAdf(adfToMarkdown(doc))` equals `doc` — unknown node types included, carried opaquely - `markdownToAdf(adfToMarkdown(doc))` equals `doc` — unknown node types included, carried opaquely
(AGENTS.md §3). (AGENTS.md §3).
- Plain CommonMark is valid input to `markdownToAdf` apart from the raw HTML below, with three - Plain CommonMark is valid input to `markdownToAdf` apart from the raw HTML `unmappable-html`
carve-outs — literal text matching directive, pipe-table or strikethrough syntax is claimed names, with three carve-outs — literal text matching directive, pipe-table or strikethrough
(escapable — `spec/flavour.md`) — and one gap: a CommonMark image fits only as its own syntax is claimed (escapable — `spec/flavour.md`) — and one gap: a CommonMark image fits only as
title-less paragraph; mid-text and titled images are error results, save an image inside its own title-less paragraph; mid-text and titled images are error results, save an image inside
another's description, which flattens into the alt text. Converting back yields the another's description, which flattens into the alt text. Converting back yields the library's
library's canonical spelling, which round-trips byte-identically — where it converts back at canonical spelling, which round-trips byte-identically — where it converts back at all: a parse
all: a parse succeeding is no promise of that, so keep the source until the way back succeeds. succeeding is no promise of that, so keep the source until the way back succeeds.
``` ` `` ` ``` reads cleanly and then refuses. ``` ` `` ` ``` reads cleanly and then refuses.
- Four CommonMark spellings parse without an error and build a document the reference - Four CommonMark spellings parse without an error and build a document the reference
implementation renders differently: `[](/url)` and `[]()` stay literal text against CommonMark's implementation renders differently: `[](/url)` and `[]()` stay literal text against CommonMark's
@@ -160,8 +160,6 @@ emit refuses:
text, which the spec requires and the reference itself breaks, nesting one `<a>` in the other. text, which the spec requires and the reference itself breaks, nesting one `<a>` in the other.
The first three are pinned `pending` in `corpus/commonmark-spec/exceptions.json`; the suite The first three are pinned `pending` in `corpus/commonmark-spec/exceptions.json`; the suite
holds no example of the fourth. holds no example of the fourth.
- Raw HTML in markdown input is an error result, never a silent drop — a tag, a comment and a
processing instruction alike. ADF holds no raw-HTML node; the element mapping ships at `0.2.0`.
- Not every document converts back: `adfToMarkdown` is partial on valid ADF — a text node holding - Not every document converts back: `adfToMarkdown` is partial on valid ADF — a text node holding
a carriage return, or a paragraph line beginning with a code span whose backticks read back as a a carriage return, or a paragraph line beginning with a code span whose backticks read back as a
fence. Show the refusal and keep the document read-only; saving markdown you could not produce fence. Show the refusal and keep the document read-only; saving markdown you could not produce
@@ -175,8 +173,9 @@ emit refuses:
- A document nested deeper than 500 levels is an error result, not a stack overflow. - A document nested deeper than 500 levels is an error result, not a stack overflow.
- The emitted formats are semver surface (AGENTS.md §8). - The emitted formats are semver surface (AGENTS.md §8).
- **`0.2.0`** — `htmlToAdf(adfToHtml(doc))` equals `doc`; fidelity HTML cannot express rides - **`0.2.0`** — `htmlToAdf(adfToHtml(doc))` equals `doc`; fidelity HTML cannot express rides
`data-*` attributes. Foreign HTML maps a documented element set, an unmappable element is an `data-*` attributes. Foreign HTML maps a documented element set, which markdown's raw HTML reads
error, and well-formed HTML only — no tag-soup recovery. through as well, and a construct outside it is an error; well-formed HTML only — no tag-soup
recovery.
## The package ## The package
+15
View File
@@ -928,6 +928,21 @@ The done `todo.md` items in full, as they were written. `todo.md` keeps a one-li
directive-spelled opening link leaves the first segment with no node range for `escape` to directive-spelled opening link leaves the first segment with no node range for `escape` to
ask about — so both are uncovered branches like the repo's other guards, 98.92% to 98.84% ask about — so both are uncovered branches like the repo's other guards, 98.92% to 98.84%
against the floor of 98. against the floor of 98.
- [x] **29 — The README reads raw HTML as refused for good (`0.2.0`).** §Goals 3 says "the three
carve-outs and the one gap below are the whole of the exception" and §The guarantees says
"Raw HTML in markdown input is an error result", both reading as settled, where
`spec/flavour.md` §Raw HTML in input says the opposite: `markdownToAdf` routes each construct
through the foreign HTML element mapping, and only a construct without one is refused. The
spec stands — commonplace markdown is accepted, and every tool writes some HTML (the
maintainer, 2026-09-20). So rewrite the two README texts to name the exception that survives
6 and 7, a construct outside the documented element set, and state it in one place, since
three already spell this one rule. `markdown-to-adf.ts:73` and `inline-content.ts:158` are
the whole of the refusal and already say "at this version"; 7 is what makes them route.
**Done** (2026-09-20): the rule has one home, the `unmappable-html` row, naming the element
set and what its absence covers at this version; §Goals 3 bounds the exceptions without
listing them, the standalone raw-HTML guarantee goes, and the `0.2.0` guarantee says
markdown's raw HTML reads the same set. That guarantee's "never a silent drop" went with it:
6 settled that `<script>` and `<style>` drop whole, so the claim does not survive 7.
## 5 — Ship `0.1.0` ## 5 — Ship `0.1.0`
+1 -10
View File
@@ -40,16 +40,6 @@ panel says the next reader pays for.
29 and 30 come from 17's prose pass (2026-09-20). 29 reads first because every goal is what a later 29 and 30 come from 17's prose pass (2026-09-20). 29 reads first because every goal is what a later
ask is settled against, 19's included; 30 sits beside 25, the other chunk rereading AGENTS.md. ask is settled against, 19's included; 30 sits beside 25, the other chunk rereading AGENTS.md.
- [ ] **29 — The README reads raw HTML as refused for good (`0.2.0`).** §Goals 3 says "the three
carve-outs and the one gap below are the whole of the exception" and §The guarantees says
"Raw HTML in markdown input is an error result", both reading as settled, where
`spec/flavour.md` §Raw HTML in input says the opposite: `markdownToAdf` routes each construct
through the foreign HTML element mapping, and only a construct without one is refused. The
spec stands — commonplace markdown is accepted, and every tool writes some HTML (the
maintainer, 2026-09-20). So rewrite the two README texts to name the exception that survives
6 and 7, a construct outside the documented element set, and state it in one place, since
three already spell this one rule. `markdown-to-adf.ts:73` and `inline-content.ts:158` are
the whole of the refusal and already say "at this version"; 7 is what makes them route.
- [ ] **30 — AGENTS.md says each thing once (`0.2.0`).** §15's ask protocol — name the class, cite - [ ] **30 — AGENTS.md says each thing once (`0.2.0`).** §15's ask protocol — name the class, cite
the earlier asks of it, never "A or B?" — is the rule reviewers cite most and has no heading, the earlier asks of it, never "A or B?" — is the rule reviewers cite most and has no heading,
two thirds down a 50-line section in a file with no index. Give it one. §15 also offers "the two thirds down a 50-line section in a file with no index. Give it one. §15 also offers "the
@@ -302,6 +292,7 @@ ask is settled against, 19's included; 30 sits beside 25, the other chunk reread
- [x] **17 — A machine-enforced size ratchet (`0.2.0`).** - [x] **17 — A machine-enforced size ratchet (`0.2.0`).**
- [x] **18 — The subtree the directive spelling asks about (`0.2.0`).** - [x] **18 — The subtree the directive spelling asks about (`0.2.0`).**
- [x] **28 — `emitLine`'s retry loop cannot spin (`0.2.0`).** - [x] **28 — `emitLine`'s retry loop cannot spin (`0.2.0`).**
- [x] **29 — The README reads raw HTML as refused for good (`0.2.0`).**
## The ADF inventory to cover ## The ADF inventory to cover