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

Answer stability round 3: the portable writer merges adjacent nested task lists after the split, so it never writes !adf:listBreak

This commit is contained in:
2026-10-09 13:30:04 +02:00
committed by Lillem4n
parent cd6cb8bece
commit 335c3fbc70
2 changed files with 5 additions and 17 deletions
@@ -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')
@@ -296,28 +296,14 @@ function reduceTaskList(node: AdfNode, reduction: Reduction): Result<AdfNode[]>
}
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'
}