32 - a mark's attribute depth is counted from its value, the marks spelling refusing its own
This commit is contained in:
@@ -375,11 +375,16 @@ test('refuses marks and attributes nested deeper than the emitter carries', () =
|
||||
assert.deepEqual(toEditorNormal(read.value), document(node))
|
||||
}
|
||||
|
||||
assert.equal(markdown(adfToMarkdown(document(paragraph({ marks: [{ attrs, type: 'em' }], text: 'x', type: 'text' })))), deeper('depth', 'em', largestNesting - 3))
|
||||
assert.equal(markdown(adfToMarkdown(document(paragraph({ marks: [{ attrs, type: 'em' }], text: 'x', type: 'text' })))), deeper('depth', 'em'))
|
||||
assert.equal(
|
||||
markdown(adfToMarkdown(document(paragraph({ marks: [{ attrs: { deep: nested(largestNesting) }, type: 'em' }], text: 'x', type: 'text' })))),
|
||||
`unsupported-nesting-depth: a carried node's JSON nests deeper than the ${largestNesting} levels its position leaves`,
|
||||
)
|
||||
assert.equal(markdown(adfToMarkdown(document(paragraph(card(largestNesting + 1))))), deeper('data', 'inlineCard'))
|
||||
assert.deepEqual(path(adfToMarkdown(document(paragraph(card(largestNesting + 1))))), [])
|
||||
roundTrips(paragraph(card(largestNesting)))
|
||||
assert.equal(markdown(adfToMarkdown(document(marked(largestNesting - 2)))), deeper('deep', 'em', largestNesting - 3))
|
||||
assert.equal(markdown(adfToMarkdown(document(marked(largestNesting - 2)))), deeper('marks', 'panel'))
|
||||
assert.deepEqual(path(adfToMarkdown(document(marked(largestNesting - 2)))), ['content', 0])
|
||||
roundTrips(marked(largestNesting - 3))
|
||||
})
|
||||
|
||||
|
||||
@@ -147,9 +147,10 @@ function emitDirectiveBlock(node: AdfNode, model: BlockNodeModel, path: ConvertE
|
||||
if (node.text !== undefined) return failure('unsupported-node-shape', `a ${node.type} carries no text: this one holds text`, path)
|
||||
if (blockDirectiveForm(node.type) === 'leaf' && nodeContent(node).length > 0) return failure('unsupported-node-shape', `a ${node.type} holds no content: this one holds some`, path)
|
||||
if (model.contentModel === 'code') return emitCodeDirective(node, model, path, depth)
|
||||
const opener = spellBlockDirectiveOpener(node, model)
|
||||
const opener = spellBlockDirectiveOpener(node, model, path)
|
||||
if (opener === undefined) return commonMarkLine(carriedBlock(node, path, depth))
|
||||
return emitDirectiveBody(node, model, opener, path, walkBody)
|
||||
if (!opener.ok) return opener
|
||||
return emitDirectiveBody(node, model, opener.value, path, walkBody)
|
||||
}
|
||||
|
||||
function emitDirectiveBody(node: AdfNode, model: BlockNodeModel, opener: string, path: ConvertErrorPath, walkBody: () => Result<Walk>): Result<EmittedBlock> {
|
||||
@@ -186,11 +187,12 @@ function tryCodeBlock(node: AdfNode, path: ConvertErrorPath): Result<EmittedBloc
|
||||
|
||||
function emitCodeDirective(node: AdfNode, model: BlockNodeModel, path: ConvertErrorPath, depth: number): Result<EmittedBlock> {
|
||||
const slot = languageSlot(nodeAttrs(node)['language'])
|
||||
const opener = spellBlockDirectiveOpener(node, model, slot.kind === 'attribute' ? [] : ['language'])
|
||||
const opener = spellBlockDirectiveOpener(node, model, path, slot.kind === 'attribute' ? [] : ['language'])
|
||||
if (opener === undefined) return commonMarkLine(carriedBlock(node, path, depth))
|
||||
if (!opener.ok) return opener
|
||||
const text = codeBlockText(node, path)
|
||||
if (!text.ok) return text
|
||||
return success(directivePair(node, opener, fencedCodeBlock(slot.kind === 'fence' ? slot.info : '', text.value)))
|
||||
return success(directivePair(node, opener.value, fencedCodeBlock(slot.kind === 'fence' ? slot.info : '', text.value)))
|
||||
}
|
||||
|
||||
function codeBlockText(node: AdfNode, path: ConvertErrorPath): Result<string> {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import type { AdfNode } from '../../adf/document.ts'
|
||||
import type { BlockNodeModel } from '../../adf/block-nodes.ts'
|
||||
import { attributeNestingMessage, nodeAttrs, nodeMarks } from '../../adf/document.ts'
|
||||
import { blockArgument } from '../block-directive-arguments.ts'
|
||||
import { failure, success, type ConvertErrorPath, type Result } from '../../result.ts'
|
||||
import { isBareToken, spellAttributes, spellDirectiveOpener, spellJsonAttribute, spellVocabulary } from '../directive-syntax.ts'
|
||||
import { markValues, marksAttribute } from '../block-directive-marks.ts'
|
||||
import { nodeAttrs, nodeMarks } from '../../adf/document.ts'
|
||||
import { overNested } from '../../json-value.ts'
|
||||
import { vocabularyPairs } from '../../adf/attribute-vocabulary.ts'
|
||||
|
||||
export function spellBlockDirectiveOpener(node: AdfNode, model: BlockNodeModel, spelledByBody: readonly string[] = []): string | undefined {
|
||||
export function spellBlockDirectiveOpener(node: AdfNode, model: BlockNodeModel, path: ConvertErrorPath, spelledByBody: readonly string[] = []): Result<string> | undefined {
|
||||
const argumentAttribute = blockArgument(node.type)
|
||||
const slot = bareArgument(node, argumentAttribute)
|
||||
if (slot === undefined) return undefined
|
||||
@@ -15,8 +17,12 @@ export function spellBlockDirectiveOpener(node: AdfNode, model: BlockNodeModel,
|
||||
if (pairs === undefined) return undefined
|
||||
const spelledPairs = spellVocabulary(pairs)
|
||||
const marks = nodeMarks(node)
|
||||
if (marks.length > 0) spelledPairs.push([marksAttribute, spellJsonAttribute(markValues(marks))])
|
||||
return spellDirectiveOpener(node.type, slot.argument, spellAttributes(spelledPairs))
|
||||
if (marks.length > 0) {
|
||||
const values = markValues(marks)
|
||||
if (overNested(values)) return failure('unsupported-nesting-depth', attributeNestingMessage(marksAttribute, node.type), path)
|
||||
spelledPairs.push([marksAttribute, spellJsonAttribute(values)])
|
||||
}
|
||||
return success(spellDirectiveOpener(node.type, slot.argument, spellAttributes(spelledPairs)))
|
||||
}
|
||||
|
||||
// `undefined` where the argument slot holds a value no bare token spells.
|
||||
|
||||
Reference in New Issue
Block a user