diff --git a/corpus/README.md b/corpus/README.md index 722a3e3..2137c61 100644 --- a/corpus/README.md +++ b/corpus/README.md @@ -4,8 +4,7 @@ One directory per contract kind: - `round-trip/` — `.json` + `.md`: the markdown `adfToMarkdown` must emit for that document, byte for byte, and that `markdownToAdf` must read back to it (AGENTS.md §2). Grouped - by node family: `commonmark-subset/`, `block-nodes/`, `inline-nodes/`, `opaque-carry/`, - `combinations/`. + by node family. - `normalization/` — `.md` + `.json`: markdown input, and the document `markdownToAdf` must build from it. One-way; the markdown is not canonical. - `errors/` — `.md`: markdown input that must not convert. A `.error` beside it diff --git a/corpus/round-trip/commonmark-subset/code-block-trailing-whitespace.json b/corpus/round-trip/commonmark-subset/code-block-trailing-whitespace.json new file mode 100644 index 0000000..9a7cca0 --- /dev/null +++ b/corpus/round-trip/commonmark-subset/code-block-trailing-whitespace.json @@ -0,0 +1,18 @@ +{ + "content": [ + { + "attrs": { + "language": "markdown" + }, + "content": [ + { + "text": "Line one \nLine two", + "type": "text" + } + ], + "type": "codeBlock" + } + ], + "type": "doc", + "version": 1 +} diff --git a/corpus/round-trip/commonmark-subset/code-block-trailing-whitespace.md b/corpus/round-trip/commonmark-subset/code-block-trailing-whitespace.md new file mode 100644 index 0000000..fd992ce --- /dev/null +++ b/corpus/round-trip/commonmark-subset/code-block-trailing-whitespace.md @@ -0,0 +1,4 @@ +```markdown +Line one +Line two +``` diff --git a/corpus/round-trip/commonmark-subset/ordered-list-order.json b/corpus/round-trip/commonmark-subset/ordered-list-order.json index c7d1fbe..1364f28 100644 --- a/corpus/round-trip/commonmark-subset/ordered-list-order.json +++ b/corpus/round-trip/commonmark-subset/ordered-list-order.json @@ -15,6 +15,15 @@ } ], "type": "paragraph" + }, + { + "content": [ + { + "text": "Grade 8.8.", + "type": "text" + } + ], + "type": "paragraph" } ], "type": "listItem" diff --git a/corpus/round-trip/commonmark-subset/ordered-list-order.md b/corpus/round-trip/commonmark-subset/ordered-list-order.md index 163e5a2..c36ddfc 100644 --- a/corpus/round-trip/commonmark-subset/ordered-list-order.md +++ b/corpus/round-trip/commonmark-subset/ordered-list-order.md @@ -1,4 +1,6 @@ 9. Bolt M8 + + Grade 8.8. 10. Nut M8 Zinc-plated. diff --git a/spec/flavour.md b/spec/flavour.md index 40cfbf7..537931e 100644 --- a/spec/flavour.md +++ b/spec/flavour.md @@ -38,11 +38,12 @@ normalizes to it through the round-trip. CommonMark autolink (absolute URI). - Paragraphs on one line — no soft wrapping; a soft line break in input becomes a single space. - Entity references in input decode to their characters; output backslash-escapes only where text - would otherwise parse as syntax: escape the leading delimiter of a construct that would - otherwise open, re-scan from there, and repeat — with the opener literal the closer parses as - text, so `*not emphasis*` is `\*not emphasis*`, one backslash. -- Blocks separated by one blank line, no trailing whitespace, single trailing newline; a document - with no blocks is the empty string. + would otherwise parse as syntax, scanning the assembled line rather than each text node: escape + the leading delimiter of a construct that would otherwise open, re-scan from there, and repeat — + with the opener literal the closer parses as text, so `*not emphasis*` is `\*not emphasis*`, one + backslash. +- Blocks separated by one blank line, no trailing whitespace outside a code block's content, + single trailing newline; a document with no blocks is the empty string. ## Directives diff --git a/todo.md b/todo.md index 6d7fd5b..d5b6a80 100644 --- a/todo.md +++ b/todo.md @@ -23,12 +23,22 @@ detail is settled at its own milestone. - [ ] **1d — Corpus start** (§10): checked-in fixtures per spec'd node, in `corpus/`, one directory per contract kind (`corpus/README.md`). **Blocked on the maintainer** (§15), not to be guessed: Canonical form has no totality - guard — a `paragraph`, `heading`, `blockquote` or `codeBlock` carrying a `localId`, or a - `blockquote` carrying marks, has no spelling that keeps it, and picking one (directive - sections for the six CommonMark block nodes, or the opaque carry) is a permanent format - decision (§8). Its three collision sites stay out of the corpus until then: an `orderedList` - starting at 1, a `codeBlock` whose info string is empty, and `media` with an empty `alt` — - each a choice between the absent attribute and the empty value. + guard. Per `@atlaskit/adf-schema` 57.1.0 every block node it spells — `blockquote`, + `bulletList`, `codeBlock`, `heading`, `listItem`, `orderedList`, `paragraph`, `rule` — + carries a `localId` with no spelling, `codeBlock` also `hideLineNumbers`, `uniqueId` and + `wrap`, `blockquote` also marks, and `hardBreak` `text` and `localId` with no section for + the carry fallback to reach. Picking one (directive sections for those nodes, or the opaque + carry) is a permanent format decision (§8). Three collision sites are held out of the corpus + meanwhile, each a choice between the absent attribute and the empty value: a `codeBlock` + whose info string is empty and `media` with an empty `alt`, which one "exactly that shape" + rule — as the CommonMark image already uses — could settle together, and an `orderedList` + starting at 1, independent of the totality answer since `order: 9` keeps the markdown form + either way. **Also blocked**: the link rule covers destination spaces only, so two shapes + break §2 silently — href `https://example.com/a)b` emits `[t](https://example.com/a)b)`, + read back as href `…/a` plus literal `b)`; title `He said "hi"` emits + `[t](u "He said "hi"")`, which holds no title. Two defensible spellings each — angle + brackets or a backslash escape, and for titles `'…'` or `(…)` besides — so §8 leaves the + pick here. - [ ] **1d1 — The CommonMark subset**: blockquote, bulletList, codeBlock, heading, orderedList, paragraph, rule, listItem, hardBreak, text, code spans, and the `code`, `em`, `link`, `strike` and `strong` marks — one mark per text node; nesting is 1d5's.