From d1091994a93d277e4034c1528ec7ccb226123506 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Fri, 9 Oct 2026 13:30:04 +0200 Subject: [PATCH] Answer stability round 3: the portable writer merges adjacent nested task lists after the split, so it never writes !adf:listBreak --- .../portable/adf-to-portable-markdown.test.ts | 2 ++ .../portable/adf-to-portable-markdown.ts | 20 +++---------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/markdown/portable/adf-to-portable-markdown.test.ts b/src/markdown/portable/adf-to-portable-markdown.test.ts index bb3120d..1ab0539 100644 --- a/src/markdown/portable/adf-to-portable-markdown.test.ts +++ b/src/markdown/portable/adf-to-portable-markdown.test.ts @@ -134,6 +134,8 @@ test('spells a task list as a bullet list whose items lead with their state', () assert.equal(portable(node('taskList', {}, blockTask, codeTask)), '- [x] First.\n\n Second.\n- [ ]\n\n```\nx\n```\n') const parent = node('blockTaskItem', { state: 'TODO' }, said('q'), said('q2')) assert.equal(portable(node('taskList', {}, parent, node('taskList', {}, task('DONE', 'n')), task('DONE', 'B'))), '- [ ] q\n\n q2\n - [x] n\n- [x] B\n') + const holding = node('blockTaskItem', { state: 'TODO' }, said('A'), node('taskList', {}, task('TODO', 'c'))) + assert.equal(portable(node('taskList', {}, holding, node('taskList', {}, task('TODO', 'd')), task('TODO', 'B'))), '- [ ] A\n - [ ] c\n - [ ] d\n- [ ] B\n') const listTask = node('blockTaskItem', { state: 'DONE' }, bulletList(item(said('a')))) assert.equal(portable(node('taskList', {}, task('TODO', ''), listTask, node('taskList', {}, task('TODO', 'b')))), '- \\[ ]\n- \\[x]\n- a\n- \\[ ] b\n') assert.equal(portable(node('taskList', {}, task('DONE', 'a'), node('taskList', {}, task('TODO', '')))), '- [x] a\n - [ ]\n') diff --git a/src/markdown/portable/adf-to-portable-markdown.ts b/src/markdown/portable/adf-to-portable-markdown.ts index a700323..b96c6e4 100644 --- a/src/markdown/portable/adf-to-portable-markdown.ts +++ b/src/markdown/portable/adf-to-portable-markdown.ts @@ -296,28 +296,14 @@ function reduceTaskList(node: AdfNode, reduction: Reduction): Result } const regular = isTask(kept[0]?.child) && kept.every(({ child }) => isTask(child) || child.type === 'taskList') const tasks: AdfNode[] = [] - let nested: AdfNode[] = [] for (const { blocks, child } of kept) { - if (!regular) { - const standsAlone = !isTask(child) && child.type !== 'taskList' - for (const block of standsAlone ? [{ content: blocks, type: 'listItem' }] : blocks) tasks.push(block) - continue - } - if (isTask(child)) { - pushMerged(tasks, nested) - nested = [] - } - for (const block of blocks) (isTask(child) ? tasks : nested).push(block) + const standsAlone = !regular && !isTask(child) && child.type !== 'taskList' + for (const block of standsAlone ? [{ content: blocks, type: 'listItem' }] : blocks) tasks.push(block) } - pushMerged(tasks, nested) - if (regular) return success(splitTaskList({ content: tasks, type: 'taskList' })) + if (regular) return success(splitTaskList({ content: tasks, type: 'taskList' }).map((block) => (block.type === 'taskList' ? { ...block, content: mergedLists(nodeContent(block)) } : block))) return success(listOf(nodeContent(tasksAsText({ content: tasks, type: 'taskList' })), 'bulletList')) } -function pushMerged(tasks: AdfNode[], nested: readonly AdfNode[]): void { - for (const block of mergedLists(nested)) tasks.push(block) -} - function isTask(node: AdfNode | undefined): boolean { return node?.type === 'taskItem' || node?.type === 'blockTaskItem' }