5b3: surface the refusal an inline directive body holds
CI / gate (push) Successful in 8s

This commit is contained in:
2026-09-03 19:33:25 +02:00
parent aa177d1f8e
commit 440dab5430
4 changed files with 11 additions and 2 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
The grammar of the extended markdown `adfToMarkdown` emits and `markdownToAdf` parses. Plain
CommonMark is a subset with three carve-outs: literal text that matches directive syntax below or
shapes a pipe table is claimed by the flavour, and a matched `~~` pair spells `strike` (escape the
reads as a pipe table is claimed by the flavour, and a matched `~~` pair spells `strike` (escape the
`:`, `|` or `~` to keep it literal) — and one gap: a CommonMark image fits only as its own
title-less paragraph — mid-text and titled images are named errors. The emitted form is contract
(AGENTS.md §8). Per-node syntaxes build on this grammar in the sections below.
@@ -203,6 +203,14 @@ test('names the pipe table whose rows open with no pipe', () => {
assert.deepEqual(path(markdownToAdf('Part.\n\na | b\n--- | ---\n')), ['content', 1])
})
test('gives back the refusal an inline body holds, never the shape check above it', () => {
const bare = 'malformed-pipe-table: a pipe table opens every row with `|`: this one does not; \\| keeps a pipe literal text'
assert.equal(content(markdownToAdf(':::caption\na | b\n--- | ---\n:::\n')), bare)
assert.deepEqual(position(markdownToAdf(':::caption\na | b\n--- | ---\n:::\n')), { line: 2, offset: 11 })
assert.equal(code(markdownToAdf(':::caption\n| a |\n:::\n')), 'malformed-pipe-table')
assert.equal(content(markdownToAdf(':::caption\n- a\n:::\n')), 'unsupported-node-shape: caption takes one paragraph as its body: this body is not one')
})
test('reads the separator that parts two adjacent lists of one kind', () => {
const parted = [bulletList(item(paragraph('a'))), bulletList(item(paragraph('b')))]
assert.deepEqual(content(markdownToAdf('- a\n\n::listBreak\n\n- b\n')), parted)
+1
View File
@@ -134,6 +134,7 @@ function tableNode(rows: readonly string[][], definitions: LinkDefinitions, path
function inlineBodyNode(node: AdfNode, blocks: readonly Block[], definitions: LinkDefinitions, path: ConvertErrorPath): Result<AdfNode> {
if (blocks.length === 0) return failure('unsupported-node-shape', `an empty ${node.type} takes the leaf form, ::, never an empty container`, path)
const only = blocks.length === 1 ? blocks[0] : undefined
if (only?.kind === 'fault') return positioned(faulted(only.fault, path), only.position)
if (only?.kind !== 'paragraph') return failure('unsupported-node-shape', `${node.type} takes one paragraph as its body: this body is not one`, path)
return positioned(contentNode(node, only.text, definitions, path), only.position)
}
+1 -1
View File
@@ -4,7 +4,7 @@ import { backslashEscape, claimsPipeLine, trimSpace } from './commonmark-grammar
const alignmentCell = /^:-+:?$|^-+:$/
const delimiterCell = /^-+$/
// spec/flavour.md, Tables: the cells of a row the leading `|` no claim read, GFM's form without it.
// spec/flavour.md, Tables: the cells of a row no leading `|` claimed — GFM's form without the outer pipes.
export function barePipeCells(line: string): string[] | undefined {
const cells = splitPipeCells(line, 0)
return cells.length > 1 ? cells : undefined