From 7bab478729eb3d101ee824e9e54012e50beaa5d7 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Sat, 3 Oct 2026 16:22:54 +0200 Subject: [PATCH] Keep an empty doc content in editor-normal ADF, as the schema requires --- docs/decisions.md | 4 ++-- src/markdown/plain/adf-to-plain-markdown.ts | 2 +- src/markdown/plain/editor-normal.test.ts | 5 +++-- src/markdown/plain/editor-normal.ts | 2 ++ 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/decisions.md b/docs/decisions.md index 5feca6d..6005569 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -42,8 +42,8 @@ adjacent text nodes, an empty `attrs`, `content` or `marks`, and `-0`. Neither s CommonMark's spelling stays wherever a document holds none of those shapes. The plain reader builds what is written, as `markdownToAdf` does. Only the plain writer is lossy: its reduction reads and writes editor-normal ADF — adjacent text nodes of identical marks and no attributes merged, `-0` as -`0`, and an empty `attrs`, `content` or `marks` the absent key — so two documents the editor holds -equal write the same plain markdown. +`0`, and an empty `attrs`, `content` or `marks` the absent key, but the doc's `content` — so two +documents the editor holds equal write the same plain markdown. ## `!adf:textBreak{}` parts text CommonMark would join diff --git a/src/markdown/plain/adf-to-plain-markdown.ts b/src/markdown/plain/adf-to-plain-markdown.ts index f324ba3..256f97c 100644 --- a/src/markdown/plain/adf-to-plain-markdown.ts +++ b/src/markdown/plain/adf-to-plain-markdown.ts @@ -58,7 +58,7 @@ export function reduceToPlain(document: AdfDocument): Result { const raw = reduceBlocks(nodeContent(document), { depth: 0, memo: new Map(), path: [] }) return !raw.ok && raw.error.code === blocks.error.code ? raw : blocks } - return success({ content: nodeContent(toEditorNormal({ content: blocks.value, type: 'doc', version: 1 })).slice(), type: 'doc', version: 1 }) + return success(toEditorNormal({ content: blocks.value, type: 'doc', version: 1 })) } function reduceBlocks(nodes: readonly AdfNode[], reduction: Reduction): Result { diff --git a/src/markdown/plain/editor-normal.test.ts b/src/markdown/plain/editor-normal.test.ts index 65ede45..3eb32e7 100644 --- a/src/markdown/plain/editor-normal.test.ts +++ b/src/markdown/plain/editor-normal.test.ts @@ -50,14 +50,15 @@ test('reads negative zero as zero, as JSON does', () => { ) }) -test('reads an empty attrs object, marks array or content array as the absent key', () => { +test('reads an empty attrs object, marks array or content array as the absent key, but on doc', () => { const paragraph: AdfNode = { attrs: {}, content: [{ attrs: {}, marks: [], text: 'a', type: 'text' }, { marks: [{ attrs: {}, type: 'em' }], text: 'b', type: 'text' }], marks: [], type: 'paragraph' } assert.deepEqual(toEditorNormal({ content: [paragraph, { content: [], type: 'rule' }], type: 'doc', version: 1 }), { content: [{ content: [{ text: 'a', type: 'text' }, { marks: [{ type: 'em' }], text: 'b', type: 'text' }], type: 'paragraph' }, { type: 'rule' }], type: 'doc', version: 1, }) - assert.deepEqual(toEditorNormal({ content: [], type: 'doc', version: 1 }), { type: 'doc', version: 1 }) + assert.deepEqual(toEditorNormal({ content: [], type: 'doc', version: 1 }), { content: [], type: 'doc', version: 1 }) + assert.deepEqual(toEditorNormal({ type: 'doc', version: 1 }), { type: 'doc', version: 1 }) }) test('normalizes blocks and mark attributes nesting far past the levels a recursive walk survives', () => { diff --git a/src/markdown/plain/editor-normal.ts b/src/markdown/plain/editor-normal.ts index e50f56c..74b3a74 100644 --- a/src/markdown/plain/editor-normal.ts +++ b/src/markdown/plain/editor-normal.ts @@ -28,6 +28,8 @@ export function toEditorNormal(document: AdfDocument): AdfDocument { return holder }) } + // ADF's schema requires content on doc, so an empty one stays. + if (document.content !== undefined && normal.content === undefined) normal.content = [] return normal }