Answer the architecture pass: the list a blank line split, and the slot the seam names
CI / gate (push) Successful in 8s

This commit is contained in:
2026-09-01 18:20:53 +02:00
parent 2527d1e3d8
commit aae1ed4baf
12 changed files with 163 additions and 35 deletions
+13 -3
View File
@@ -176,9 +176,19 @@ function openContainer(walk: Walk, start: ContainerStart): void {
walk.stack.push(blockquote)
return
}
if (start.fresh) currentBlocks(walk).push(start.list)
start.list.items.push(blocks)
walk.stack.push({ blocks, indentation: start.indentation, kind: 'item', list: start.list })
const list = openedList(walk, start)
list.items.push(blocks)
walk.stack.push({ blocks, indentation: start.indentation, kind: 'item', list })
}
// Two lists of a kind never sit adjacent: one `- ` spelling reads them back as one (spec/flavour.md).
function openedList(walk: Walk, start: Extract<ContainerStart, { kind: 'item' }>): ListBlock {
if (!start.fresh) return start.list
const blocks = currentBlocks(walk)
const previous = blocks.at(-1)
if ((previous?.kind === 'bulletList' || previous?.kind === 'orderedList') && previous.kind === start.list.kind) return previous
blocks.push(start.list)
return start.list
}
function closeContainers(walk: Walk, depth: number): void {
@@ -390,6 +390,8 @@ test('reads a bullet list, the marker width setting the continuation', () => {
assert.deepEqual(content(markdownToAdf('- Code.\n')), [bulletList(item({ content: [text('Code.')], type: 'codeBlock' }))])
assert.deepEqual(content(markdownToAdf('- a\n* b\n')), [bulletList(item(paragraph('a')), item(paragraph('b')))])
assert.deepEqual(content(markdownToAdf('- a\n\n+ b\n')), [bulletList(item(paragraph('a')), item(paragraph('b')))])
assert.deepEqual(content(markdownToAdf('- a\n-\n\n- c\n')), [bulletList(item(paragraph('a')), item(), item(paragraph('c')))])
assert.deepEqual(content(markdownToAdf('- a\n1. b\n')), [bulletList(item(paragraph('a'))), orderedList(1, item(paragraph('b')))])
assert.deepEqual(content(markdownToAdf('-\n\n Part.\n')), [bulletList(item()), paragraph('Part.')])
})
+3 -3
View File
@@ -5,7 +5,7 @@ import type { LinkDefinitions } from './inline-content.ts'
import { carryName } from '../opaque-carry.ts'
import { commonMarkSpelling } from '../emit/adf-to-markdown.ts'
import { failure, faulted, success, type ConvertErrorPath, type Result } from '../../result.ts'
import { fenceInfo } from '../code-language.ts'
import { languageSlot } from '../code-language.ts'
import { largestNesting } from '../../nesting.ts'
import { parseBlocks } from './blocks.ts'
import { parseInlineContent } from './inline-content.ts'
@@ -85,8 +85,8 @@ function codeDirectiveNode(node: AdfNode, blocks: readonly Block[], path: Conver
if (only?.kind !== 'code') return failure('unsupported-node-shape', `${node.type} takes one fenced code block as its body`, path)
const attribute = node.attrs?.['language']
const fromFence = only.language !== ''
const info = fenceInfo(fromFence ? only.language : attribute)
if ((info !== undefined && info !== '') !== fromFence || (fromFence && attribute !== undefined)) {
const slot = languageSlot(fromFence ? only.language : attribute)
if ((slot.kind === 'fence') !== fromFence || (fromFence && attribute !== undefined)) {
return failure('unsupported-node-shape', `${node.type} spells its language in the fence info string, or in the attribute where no info string carries it back`, path)
}
const spelled = fromFence ? { ...node, attrs: { ...node.attrs, language: only.language } } : node