Refuse the nested lists a tight spelling swallows, and name the mark that failed
CI / gate (push) Successful in 4s

This commit is contained in:
2026-08-25 10:02:22 +02:00
parent 91d5cd6c43
commit 480176fd21
5 changed files with 52 additions and 17 deletions
+11 -1
View File
@@ -28,7 +28,12 @@ function emitBlocks(nodes: readonly AdfNode[], inListItem: boolean, path: Conver
if (listTypes.includes(node.type) && previous.type === node.type) {
return failure('unspellable-adjacent-lists', `two adjacent ${node.type} nodes read back as one list`, nodePath)
}
output += inListItem && listTypes.includes(node.type) ? '\n' : '\n\n'
if (inListItem && listTypes.includes(node.type)) {
if (!interruptsParagraph(node)) {
return failure('unspellable-line-start', `a ${node.type} that cannot interrupt the block above it has no tight spelling`, nodePath)
}
output += '\n'
} else output += '\n\n'
}
const block = emitBlock(node, nodePath, depth)
if (!block.ok) return block
@@ -38,6 +43,11 @@ function emitBlocks(nodes: readonly AdfNode[], inListItem: boolean, path: Conver
return success(output)
}
function interruptsParagraph(node: AdfNode): boolean {
if (node.type === 'orderedList') return false
return ((node.content ?? [])[0]?.content ?? []).length > 0
}
function emitBlock(node: AdfNode, path: ConvertErrorPath, depth: number): Result<string> {
if (node.type === 'blockquote') return emitBlockquote(node, path, depth)
if (node.type === 'bulletList' || node.type === 'orderedList') return emitList(node, path, depth)