5c: the build, the freeze audit and the release pipeline
CI / gate (push) Successful in 11s
CI / publish (push) Has been skipped

This commit is contained in:
2026-09-03 20:25:41 +02:00
parent 839e48d5dc
commit d9056973a1
25 changed files with 298 additions and 79 deletions
+7 -3
View File
@@ -1,8 +1,8 @@
import type { AdfAttributes } from '../../adf/document.ts'
import type { AttributeVocabulary } from '../../adf/attribute-vocabulary.ts'
import type { DirectiveAttributes } from '../directive-syntax.ts'
import { attributeValue, spellAttributeValue } from '../directive-syntax.ts'
import { failure, success, type ConvertErrorPath, type Result } from '../../result.ts'
import { attributeNestingFault, attributeValue, spellAttributeValue } from '../directive-syntax.ts'
import { failure, faulted, success, type ConvertErrorPath, type Result } from '../../result.ts'
export type Elsewhere = { key: string; slot: 'argument' | 'content' }
@@ -22,7 +22,11 @@ export function readVocabulary(
const kind = Object.hasOwn(vocabulary, key) ? vocabulary[key] : undefined
if (kind === undefined) return failure('unsupported-node-shape', `${type} holds no ${key} attribute: this one spells it`, path)
const read = attributeValue(spelled.decoded, kind)
if (read === undefined) return failure('unsupported-node-shape', `the ${key} attribute of ${type} is no ${kind}`, path)
if (read === undefined) {
const deep = attributeNestingFault(spelled.decoded, kind, key, type)
if (deep !== undefined) return faulted(deep, path)
return failure('unsupported-node-shape', `the ${key} attribute of ${type} is no ${kind}`, path)
}
const spelling = spellAttributeValue(read)
if (spelling !== spelled.spelling) return failure('unsupported-node-shape', `${type} spells its ${key} attribute as ${key}=${spelling}`, path)
attrs[key] = read.value
+3 -1
View File
@@ -3,7 +3,7 @@ import type { BlockDirective } from '../../adf/block-directives.ts'
import type { ConvertFault } from '../../result.ts'
import type { DirectiveAttributes, DirectiveValue } from '../directive-syntax.ts'
import type { Elsewhere } from './directive-attributes.ts'
import { attributeValue, directiveLineEscape, inlineDirectiveEscape, spellAttributeValue, unknownDirectiveFault } from '../directive-syntax.ts'
import { attributeNestingFault, attributeValue, directiveLineEscape, inlineDirectiveEscape, spellAttributeValue, unknownDirectiveFault } from '../directive-syntax.ts'
import { blockArgument } from '../block-directive-arguments.ts'
import { blockDirective } from '../../adf/block-directives.ts'
import { carryName } from '../opaque-carry.ts'
@@ -94,6 +94,8 @@ function slotText(content: readonly AdfNode[]): string | undefined {
function readMarks(type: string, spelled: DirectiveValue, path: ConvertErrorPath): Result<AdfMark[]> {
const read = attributeValue(spelled.decoded, 'json')
const deep = read === undefined ? attributeNestingFault(spelled.decoded, 'json', marksAttribute, type) : undefined
if (deep !== undefined) return faulted(deep, path)
const marks = read === undefined || spellAttributeValue(read) !== spelled.spelling ? undefined : readMarkValues(read.value)
if (marks === undefined) {
return failure('unsupported-node-shape', `the ${marksAttribute} attribute of ${type} is its marks array in canonical JSON: this one is not`, path)
+8 -2
View File
@@ -431,12 +431,18 @@ test('names the attribute a node holds no reading for', () => {
assert.equal(content(markdownToAdf(':::table {isNumberColumnEnabled=yes}\n:::\n')), 'unsupported-node-shape: the isNumberColumnEnabled attribute of table is no boolean')
assert.equal(content(markdownToAdf('::media {width=true}\n')), 'unsupported-node-shape: the width attribute of media is no number')
assert.equal(content(markdownToAdf(':::tableCell {colwidth="[340,"}\n:::\n')), 'unsupported-node-shape: the colwidth attribute of tableCell is no json')
const deep = `${'['.repeat(largestNesting + 2)}${']'.repeat(largestNesting + 2)}`
assert.equal(content(markdownToAdf(`:::tableCell {colwidth="${deep}"}\n:::\n`)), 'unsupported-node-shape: the colwidth attribute of tableCell is no json')
assert.equal(content(markdownToAdf(':::panel info {panelType=note}\nx\n:::\n')), 'unsupported-node-shape: panel spells its panelType attribute as the directive argument, never in {attrs}')
assert.equal(content(markdownToAdf('Part :mention{id=b1c2 text=A}.\n')), 'unsupported-node-shape: mention spells its text attribute in the content slot, never in {attrs}')
})
test('names the depth an attribute value nests past, never the kind the JSON reads as', () => {
const nested = (levels: number): string => `${'['.repeat(levels)}1${']'.repeat(levels)}`
const deeper = (key: string, type: string): string => `unsupported-nesting-depth: the ${key} attribute of ${type} nests deeper than the ${largestNesting} levels the parser carries`
assert.equal(content(markdownToAdf(`:::tableCell {colwidth="${nested(largestNesting + 1)}"}\n:::\n`)), deeper('colwidth', 'tableCell'))
assert.equal(content(markdownToAdf(`::rule {marks="${nested(largestNesting + 1)}"}\n`)), deeper('marks', 'rule'))
assert.equal(content(markdownToAdf(`::media {width="${nested(largestNesting + 1)}"}\n`)), 'unsupported-node-shape: the width attribute of media is no number')
})
test('names the attribute value spelled outside the canonical form', () => {
assert.equal(content(markdownToAdf('::rule {localId="a-1"}\n')), 'unsupported-node-shape: rule spells its localId attribute as localId=a-1')
assert.equal(content(markdownToAdf('::media {width="20.0"}\n')), 'unsupported-node-shape: media spells its width attribute as width=20')