3
0
mirror of https://github.com/larvit/adf-codec.git synced 2026-11-13 20:28:28 +01:00

Answer prose round 1: 0 🔴, 6 🟡; list unsupported-node-shape causes as sub-items with their remedies

This commit is contained in:
2026-10-14 12:57:15 +02:00
committed by Lillem4n
parent dd8dabc9e8
commit 39a7f16b95
3 changed files with 26 additions and 24 deletions
+24 -22
View File
@@ -452,31 +452,33 @@ Every call can raise these:
| --- | --- | --- |
| `engine-limit` | in every call: a conversion that passes the longest array, `Map` or `Set` the JavaScript engine builds, or that the engine reports as out of memory; on JavaScriptCore (Bun, Safari), also one that passes its longest string, 2^31 − 1 characters | retry once; if it repeats, writing: set the document aside, keeping the ADF and passing it over or showing it read-only; reading: shorten the markdown, or nest its lists and quotes less deeply |
| `unsupported-nesting-depth` | blocks, marks, an attribute's JSON or a carried node's JSON nest past 500 levels | keep the ADF and pass the document over, or show it read-only; flatten the input where you are the one who wrote it |
| `unsupported-node-shape` | a node the call cannot read or write in its shape; the list below names each cause | the list below names each cause's remedy |
| `unsupported-node-shape` | each cause listed below the table | the remedy beside each cause below |
`unsupported-node-shape` fires on these causes:
- **Reading, in `losslessMarkdownToAdf`**: markdown spells a node with an attribute, value,
argument or body its type does not take, or without one it needs, puts a line ending or a null
character in an `emoji`, `mention` or `status` content slot, wraps a directive mark around nothing
or only hard breaks, writes as a directive a node or mark the lossless flavour spells as
CommonMark, or puts a reserved directive out of place: `!adf:textBreak{}` parting nothing,
`!adf:doc` anywhere but as the whole document. Fix what the message names;
- **Reading, in `losslessMarkdownToAdf`.** Fix what the message names;
[`spec/flavour.md`](https://github.com/larvit/adf-codec/blob/main/spec/flavour.md) lists every
type's attributes and body. For a line ending in a content slot, replace it with a space or write
the node as `!adf:carry`; for a null character there, write the node as `!adf:carry`.
type's attributes and body. The markdown:
- spells a node with an attribute, value, argument or body its type does not take, or without
one it needs;
- puts a line ending or a null character in an `emoji`, `mention` or `status` content slot:
replace a line ending with a space, or, for either, write the node as `!adf:carry`;
- wraps a directive mark around nothing or only hard breaks;
- writes as a directive a node or mark the lossless flavour spells as CommonMark;
- puts `!adf:textBreak{}` where it parts nothing, or `!adf:doc` anywhere but as the whole
document.
- **Writing, in `adfToLosslessMarkdown`**: a node not riding the carry that carries one mark type
twice, a block or a non-text inline node holding `text`, or a leaf block or a non-text inline node
holding `content`. Fix what the message names in the ADF.
holding `content`. Keep the ADF and show the document read-only; where you built the ADF, fix
what the message names.
- **Writing, in `adfToPortableMarkdown`**: a line or task list the portable writer cannot spell.
This is a bug in this library: report it.
- **Past the longest string**: in both writers, a document whose markdown would be longer than
536870888 characters, V8's longest string, on every engine, and in `adfToPortableMarkdown` also a
document whose text alone is that long, edge whitespace included; in `losslessMarkdownToAdf`, a
directive whose plain CommonMark would be that long; in every call, a conversion that passes V8's
or SpiderMonkey's longest string. Writing, set the document aside, keeping the ADF and passing it
over or showing it read-only; reading, shorten the markdown, or nest its lists and quotes less
deeply.
- **Past the engine's longest string**:
- a writer's markdown would pass 536870888 characters, V8's longest string, on every engine;
- in `adfToPortableMarkdown`, the document's text alone would, edge whitespace included;
- in `losslessMarkdownToAdf`, a directive's plain CommonMark would;
- in every call, a conversion passes V8's or SpiderMonkey's longest string.
When writing, set the document aside: keep the ADF, and pass it over or show it read-only. When
reading, shorten the markdown, or nest its lists and quotes less deeply.
## The guarantees
@@ -518,9 +520,9 @@ Serves [Goals](#goals) 1, 4 and 5.
the outer brackets literal text, which the spec requires and the reference itself breaks, nesting
one `<a>` in the other.
- Not every document converts back: `adfToLosslessMarkdown` refuses a document nesting past 500
levels, the causes `unsupported-node-shape` lists, and a conversion `engine-limit`
stops. Show the refusal and keep the document read-only; saving markdown you could not produce is the loss the round-trip exists to
stop.
levels, a document meeting a writing or longest-string cause `unsupported-node-shape` lists, and
a conversion `engine-limit` stops. Show the refusal and keep the document read-only; saving
markdown you could not produce is the loss the round-trip exists to stop.
- Both readers narrow GFM's pipe table. A body row whose cell count differs from the header's is
an error result, where GFM pads or cuts it. A line holding no `|` ends the table, where GFM reads
it as a row.
+1 -1
View File
@@ -134,7 +134,7 @@ function readNamedMark(type: string, text: string, index: number, path: ConvertE
const vocabulary = markVocabularies.get(name)
if (vocabulary === undefined) return failure('unsupported-node-shape', `the ${marksAttribute} attribute of ${type} names ${name}, no mark the flavour lists: write the marks as their JSON array, marks="[{\\"type\\":\\"${name}\\"}]"`, path)
const start = index + name.length
// A quoted value holds no directive, so a malformed pair takes no escape hint.
// These {attrs} sit inside the quoted marks value, where no directive opens, so a malformed pair takes no escape hint.
const attributes = text.charAt(start) === '{' ? readAttributes(text, start, attributePairCause) : { value: { attributes: new Map<string, DirectiveValue>(), end: start } }
if (attributes.fault !== undefined) {
return failure('unsupported-node-shape', `the ${name} mark in the ${marksAttribute} attribute of ${type}: ${attributes.fault.message}`, path)
+1 -1
View File
@@ -227,7 +227,7 @@ document's whole tree. Give the node's path, and name its type and the attribute
`emitLeaf` (`emit/inline-line.ts`) and `emitDirectiveBlock` (`emit/adf-to-markdown.ts`)
refuse these with `unsupported-node-shape`, though `isAdfDocument` accepts them and the carry
round-trips them; `docs/decisions.md` §The code list gives a cause the carry answers no code. Drop
them from the emitting half of the README's `unsupported-node-shape` row. Found by the README-goals
them from the README's `unsupported-node-shape` cause "Writing, in `adfToLosslessMarkdown`". Found by the README-goals
audit, 2026-10-04.
### 75. Make the generated-markdown property write block carries as `adf:` fences, canonical and hostile.