diff --git a/CHANGELOG.md b/CHANGELOG.md index a591365..6e548ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,8 @@ `type`: text holding an unescaped `!adf:` and a code fence whose info string opens `adf:` are claimed, and `adf` is an ordinary code block language. Convert stored markdown per `MIGRATION.md`. - **Breaking:** `markdownToAdf` and `plainMarkdownToAdf` read markdown holding no block as a - document whose `content` is empty, as Atlassian's schema requires; `!adf:doc {content=none}` spells a document holding no - `content` key. + document whose `content` is empty, as Atlassian's schema requires; `!adf:doc {content=none}` + spells a document holding no `content` key. - `markdownToAdf(adfToMarkdown(doc))` deep-equals `doc`: two adjacent text nodes a reader would join are parted by `!adf:textBreak{}`, an empty `attrs`, `content` or `marks` is spelled `{attrs=empty}`, `{content=empty}` or `{marks=empty}`, `-0` is spelled `-0`, and a `codeBlock` diff --git a/README.md b/README.md index 2196a61..bf3c06c 100644 --- a/README.md +++ b/README.md @@ -212,14 +212,13 @@ Serves Goals 1, 3 and 4. `0.2.0`, well-formed HTML means what the HTML standard says, read or written. The bullets below name every exception. - Plain CommonMark is valid input to `markdownToAdf` apart from the raw HTML `unmappable-html` - names, with four carve-outs — literal text matching directive, pipe-table or strikethrough - syntax, and a code fence whose info string opens `adf:`, is claimed (escapable — `spec/flavour.md`) - — and one gap: a CommonMark image fits only as - 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 library's - canonical spelling, which round-trips byte-identically — where it converts back at all: a parse - succeeding is no promise of that, so keep the source until the way back succeeds. - ``` ` `` ` ``` reads cleanly and then refuses. + names, with four carve-outs — literal text matching directive, pipe-table or strikethrough syntax, + and a code fence whose info string opens `adf:`, are claimed (escapable — `spec/flavour.md`) — and + one gap: a CommonMark image fits only as 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 library's canonical spelling, which round-trips byte-identically — + where it converts back at all: a parse succeeding is no promise of that, so keep the source until + the way back succeeds. ``` ` `` ` ``` reads cleanly and then refuses. - Four CommonMark spellings parse without an error and build a document the reference implementation renders differently: `[](/url)` and `[]()` stay literal text against CommonMark's empty link, a list continuing past a marker change stays one list against CommonMark's two, a diff --git a/corpus/README.md b/corpus/README.md index 6ae3974..3629e43 100644 --- a/corpus/README.md +++ b/corpus/README.md @@ -19,7 +19,8 @@ One directory per contract kind: model), `unspellable` (parses but the flavour has no spelling) or `pending` (a parser gap). JSON is two-space indent, keys sorted, and a document read back must deep-equal the fixture's -(`docs/decisions.md` §Equality is deep). `spec.json` is the vendored, upstream machine-readable suite, byte-exact from -[spec.commonmark.org](https://spec.commonmark.org/0.31.2/spec.json) (CommonMark 0.31.2, © John -MacFarlane, [CC-BY-SA-4.0](https://creativecommons.org/licenses/by-sa/4.0/)), and is not -re-serialized by the corpus gate. +(`docs/decisions.md` §Equality is deep). `spec.json` is the vendored, upstream machine-readable +suite, byte-exact from [spec.commonmark.org](https://spec.commonmark.org/0.31.2/spec.json) +(CommonMark 0.31.2, © John MacFarlane, +[CC-BY-SA-4.0](https://creativecommons.org/licenses/by-sa/4.0/)), and is not re-serialized by the +corpus gate. diff --git a/spec/flavour.md b/spec/flavour.md index e9a35b5..f0f9e57 100644 --- a/spec/flavour.md +++ b/spec/flavour.md @@ -4,10 +4,11 @@ The grammar of the extended markdown `adfToMarkdown` emits and `markdownToAdf` p CommonMark is a subset apart from raw HTML (below), with four carve-outs: literal text that matches directive syntax below or reads as a pipe table is claimed by the flavour, a matched `~~` pair spells `strike` (escape the `!adf:`, `|` or `~` to keep it literal), and a code fence whose info -string opens `adf:` is the opaque carry (The opaque carry says how to keep it code) — and one gap: a CommonMark -image fits only as its own title-less paragraph — mid-text and titled images are named errors. The -emitted form is contract (`docs/decisions.md` §The formats are API). Per-node syntaxes build on this -grammar in the sections below. +string opens `adf:` is the opaque carry (wrap it as a bare fence in `!adf:codeBlock +{language="adf:…"}` to keep it code) — and one gap: a CommonMark image fits only as its own +title-less paragraph — mid-text and titled images are named errors. The emitted form is contract +(`docs/decisions.md` §The formats are API). Per-node syntaxes build on this grammar in the sections +below. ## Canonical form @@ -446,8 +447,8 @@ Attributes and the carry fallback read as in the block sections, the carry in it the nodes below, `emoji`, `mention` and `status` spell their `text` attribute in the content slot as plain text: `[]` is the empty string, absent content is the absent attribute, non-empty content parsing to anything but one text node carrying neither marks, attributes nor content is a named -error, and so is a `text` key in `{attrs}`. An enclosing mark spelling does not reach into the slot. The rest take no content, -`!adf:text` included; content on a node that takes none is a named error. +error, and so is a `text` key in `{attrs}`. An enclosing mark spelling does not reach into the slot. +The rest take no content, `!adf:text` included; content on a node that takes none is a named error. - `date` — Attributes: `localId` (string), `timestamp` (string, epoch milliseconds). - `emoji` — Attributes: `id` (string), `localId` (string), `shortName` (string, `:name:`), `text` @@ -527,14 +528,14 @@ that depth: `attrs: {}` differs from no `attrs`, and a directive spells it `{att breaks at every node the emitter carries, so no emitted carry sits inside a mark spelling. An inline node whose marks no nesting spells — a mark type not listed here, an attrs key its -spelling does not list, a value that is not the spelling's type, an attribute the spelling needs -and the mark lacks, an empty `attrs` on a mark CommonMark spells, an order putting a code span outside another mark, `code` over anything but a -text node or over text holding a newline, or a spelling CommonMark's flanking rules cannot open or -close where the run sits (`un**-real**istic`), or one CommonMark's matching pairs elsewhere — the -intra-word `*` runs together with a neighbouring `**`, and the multiple-of-3 rule can leave the -merged run's pairing to another delimiter — rides the inline carry whole. An opaque carry inside a -mark spelling is a named error in input: the carry restores its node exactly, marks included -(`docs/decisions.md` §Unknown nodes ride the carry). +spelling does not list, a value that is not the spelling's type, an attribute the spelling needs and +the mark lacks, an empty `attrs` on a mark CommonMark spells, an order putting a code span outside +another mark, `code` over anything but a text node or over text holding a newline, or a spelling +CommonMark's flanking rules cannot open or close where the run sits (`un**-real**istic`), or one +CommonMark's matching pairs elsewhere — the intra-word `*` runs together with a neighbouring `**`, +and the multiple-of-3 rule can leave the merged run's pairing to another delimiter — rides the +inline carry whole. An opaque carry inside a mark spelling is a named error in input: the carry +restores its node exactly, marks included (`docs/decisions.md` §Unknown nodes ride the carry). ``` !adf:textColor[**Overdue**]{color="#ae2e24"}, H!adf:subsup[2]{type=sub}O, !adf:underline[signed].