From 5e05fa6f3032b8f2be8f397d5b462b5851c86774 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Sun, 11 Oct 2026 20:52:31 +0200 Subject: [PATCH] Answer stability round 2: the advice names the array limit, the guard's test names both, and the decision rewraps --- CHANGELOG.md | 4 ++-- README.md | 2 +- docs/decisions.md | 8 ++++---- src/result.test.ts | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec6598d..5e75771 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,8 +87,8 @@ engine builds, on V8 about 537 million characters, or about 134 million in one text node: `adfToLosslessMarkdown` and `adfToPortableMarkdown` refuse it as `unsupported-node-shape`, where they threw. -- Fix compact JSON in an `adf:` fence: `losslessMarkdownToAdf` refuses it as - `unsupported-node-shape`, where a megabyte of deeply nested JSON threw. +- Fix deeply nested compact JSON in an `adf:` fence: `losslessMarkdownToAdf` refuses it as + `unsupported-node-shape`, like any compact JSON there, where a megabyte of it threw. - Add `adfToPortableMarkdown` and `portableMarkdownToAdf`, a lossy pair converting ADF to and from markdown GitHub, GitLab and Obsidian render: alerts, callouts, task lists, `==highlights==` and pipe tables. A task item keeps its paragraphs, then its nested task lists; the rest of the item, diff --git a/README.md b/README.md index d833de7..a52d597 100644 --- a/README.md +++ b/README.md @@ -442,7 +442,7 @@ The emitter raises these, and so does a parse, which asks the emitter how to spe | Code | Fires when | What you can do | | --- | --- | --- | | `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` | parsing, in `losslessMarkdownToAdf`: markdown spells a node with an attribute, value, argument or body its type does not take, or without one it needs, 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. Emitting, 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`. Emitting, in `adfToPortableMarkdown`: a line or task list the portable writer cannot spell, a bug in this library. Emitting, in both writers: a document whose markdown would be longer than the longest string or array the JavaScript engine builds — on V8, about 537 million characters of markdown, or about 134 million in one text node | 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 portable line or task list, report it. Past the engine's longest string, keep the ADF and pass the document over, or show it read-only | +| `unsupported-node-shape` | parsing, in `losslessMarkdownToAdf`: markdown spells a node with an attribute, value, argument or body its type does not take, or without one it needs, 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. Emitting, 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`. Emitting, in `adfToPortableMarkdown`: a line or task list the portable writer cannot spell, a bug in this library. Emitting, in both writers: a document whose markdown would be longer than the longest string or array the JavaScript engine builds — on V8, about 537 million characters of markdown, or about 134 million in one text node | 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 portable line or task list, report it. Past the engine's longest string or array, keep the ADF and pass the document over, or show it read-only | ## The guarantees diff --git a/docs/decisions.md b/docs/decisions.md index 75d2aa4..18c2976 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -462,10 +462,10 @@ handles one cause alike whichever node, attribute or direction raised it. - A non-finite number takes two codes: `unsupported-node-shape` parsing, `not-an-adf-document` emitting — no document holds one, so no round-trip crosses them (2026-09-23). - A document whose markdown would be longer than the longest string or array the JavaScript engine - builds is `unsupported-node-shape` at the document's path, in either writer: the document does not - convert, and the bound is the engine's own. A carried node reaches it on about 1 MB of deeply nested JSON, - since the block carry indents two spaces a level; `todo.md` item 107 spells it in a length linear - in its JSON (2026-10-11). + builds is `unsupported-node-shape` at the document's path, in either writer: the document does + not convert, and the bound is the engine's own. A carried node reaches it on about 1 MB of + deeply nested JSON, since the block carry indents two spaces a level; `todo.md` item 107 spells + it in a length linear in its JSON (2026-10-11). - The markdown readers and `htmlToAdf` refuse a value that is not a string as `not-a-string`, at position `{ line: 1, offset: 0 }` with an empty path: no existing code reads true of it, and `not-an-adf-document` names the emitters' input (2026-10-05). diff --git a/src/result.test.ts b/src/result.test.ts index 55749b6..7dd1918 100644 --- a/src/result.test.ts +++ b/src/result.test.ts @@ -36,7 +36,7 @@ test('every ConvertErrorCode is the code of a production call site, and every ca assert.deepEqual(calledCodes(), declaredCodes()) }) -test('refuses where SpiderMonkey runs out of string, and lets a stack overflow or any other throw through', () => { +test('refuses where the engine runs out of string or array, and lets a stack overflow or any other throw through', () => { const overflow = new Error('allocation size overflow') overflow.name = 'InternalError' assert.deepEqual(