Keep the info string to the languages it carries back, and name the invariant's one exception
CI / gate (push) Successful in 5s

This commit is contained in:
2026-08-27 16:02:05 +02:00
parent 1ec991d64a
commit ab799b883d
5 changed files with 23 additions and 13 deletions
+4 -1
View File
@@ -69,6 +69,9 @@ test('spells a code block language no info string holds as an attribute', () =>
assert.equal(language('a`b'), ':::codeBlock {language="a\\u0060b"}\n```\n```\n:::\n')
assert.equal(language(' sql'), ':::codeBlock {language=" sql"}\n```\n```\n:::\n')
assert.equal(language('adf'), ':::codeBlock {language="\\u0026#97;df"}\n```\n```\n:::\n')
assert.equal(language('foo\\+bar'), ':::codeBlock {language="foo\\\\+bar"}\n```\n```\n:::\n')
assert.equal(language('a\u0000b'), ':::codeBlock {language="a\\u0000b"}\n```\n```\n:::\n')
assert.equal(language('a\tb'), ':::codeBlock {language="a\\tb"}\n```\n```\n:::\n')
})
test('refuses a link destination CommonMark cannot spell', () => {
@@ -165,7 +168,7 @@ test('refuses a node whose content model the canonical form cannot emit', () =>
assert.equal(code(adfToMarkdown(document({ content: [{ content: [{ text: 'lost', type: 'text' }], text: 'x', type: 'text' }], type: 'codeBlock' }))), 'unsupported-node-shape')
})
test('spells a list its own markers cannot hold as a directive', () => {
test('spells a list its own content shape cannot hold as a directive', () => {
assert.equal(markdown(adfToMarkdown(document({ content: [paragraph()], type: 'bulletList' }))), ':::bulletList\n::paragraph\n:::\n')
assert.equal(markdown(adfToMarkdown(document({ type: 'bulletList' }))), ':::bulletList\n:::\n')
assert.equal(markdown(adfToMarkdown(document({ attrs: { order: 2 }, content: [], type: 'orderedList' }))), ':::orderedList {order=2}\n:::\n')
+3 -3
View File
@@ -7,7 +7,7 @@ import { emitInlineLine } from './markdown-inline.ts'
import { tryPipeTable } from './markdown-pipe-table.ts'
import { carriedBlock, carryName } from './opaque-carry.ts'
import { failure, success, type ConvertErrorPath, type Result } from './result.ts'
import { holdsEntityReference, holdsNullCharacter, isThematicBreak } from './commonmark-grammar.ts'
import { holdsControlCharacter, holdsEntityReference, holdsNullCharacter, isThematicBreak } from './commonmark-grammar.ts'
import { carriesOnly, isAdfDocument } from './adf-document.ts'
import { largestNesting } from './nesting.ts'
import { fencedCodeBlock } from './backtick-runs.ts'
@@ -187,11 +187,11 @@ function codeBlockText(node: AdfNode, path: ConvertErrorPath): Result<string> {
return success(text)
}
// spec/flavour.md, The CommonMark blocks: the languages an info string holds, the absent one as the empty string.
// spec/flavour.md, The CommonMark blocks.
function fenceInfo(language: JsonValue | undefined): string | undefined {
if (language === undefined) return ''
if (typeof language !== 'string' || language === '' || language === carryName) return undefined
if (/[`\n\r]/.test(language) || language !== language.trim() || holdsEntityReference(language)) return undefined
if (/[`\\]/.test(language) || holdsControlCharacter(language) || language !== language.trim() || holdsEntityReference(language)) return undefined
return language
}