mirror of
https://github.com/larvit/adf-codec.git
synced 2026-11-12 11:48:29 +01:00
Answer stability round 1: 1 🔴, 2 🟡 (0 misread); keep a portable line parted where spanning needs !adf:text, test the depth guard, drop a dead check
This commit is contained in:
@@ -502,6 +502,8 @@ test('parts a nested list the tight spelling would swallow from the block above
|
||||
test('refuses marks and attributes nested deeper than the emitter carries', () => {
|
||||
const marks: AdfMark[] = Array.from({ length: 600 }, (_, index) => ({ type: index % 2 === 0 ? 'em' : 'strong' }))
|
||||
assert.equal(code(adfToLosslessMarkdown(document(paragraph({ marks, text: 'x', type: 'text' })))), 'unsupported-nesting-depth')
|
||||
const deepest: AdfMark[] = Array.from({ length: 20_000 }, (_, index) => ({ type: index % 2 === 0 ? 'em' : 'strong' }))
|
||||
assert.equal(code(adfToLosslessMarkdown(document(paragraph({ marks: deepest, text: 'x', type: 'text' }, { type: 'hardBreak' }, { marks: deepest, text: 'y', type: 'text' })))), 'unsupported-nesting-depth')
|
||||
let attrs: AdfMark['attrs'] = { depth: 'x' }
|
||||
for (let depth = 0; depth < 600; depth += 1) attrs = { depth: attrs }
|
||||
const deeper = (key: string, type: string): string =>
|
||||
@@ -923,7 +925,7 @@ test('spells an emphasis or link run once across the hard breaks between two nod
|
||||
assert.equal(readsBack(document(paragraph({ text: 'x', type: 'text' }, marked('.', em), hardBreak, marked('b', em)))), 'x!adf:carry{json="{\\"marks\\":[{\\"type\\":\\"em\\"}],\\"text\\":\\".\\",\\"type\\":\\"text\\"}"}\\\n_b_\n')
|
||||
})
|
||||
|
||||
test('spells an emphasis run once across the code spans, inline nodes and inline media between two nodes holding the mark', () => {
|
||||
test('spells an emphasis run once across the code spans, mentions, dates and inline media between two nodes holding the mark', () => {
|
||||
const strong: AdfMark = { type: 'strong' }
|
||||
const marked = (text: string, ...marks: AdfMark[]): AdfNode => ({ marks, text, type: 'text' })
|
||||
const mention: AdfNode = { attrs: { id: 'x', text: '@A' }, type: 'mention' }
|
||||
@@ -934,12 +936,13 @@ test('spells an emphasis run once across the code spans, inline nodes and inline
|
||||
assert.equal(readsBack(document(paragraph(marked('a ', strong), marked('c', { type: 'code' }), mention, { type: 'hardBreak' }, marked(' b', strong)))), '**a `c`!adf:mention[@A]{id=x}\\\n!adf:text{text=" "}b**\n')
|
||||
})
|
||||
|
||||
test('spells a link run once across the inline nodes between two nodes holding it, and parts it at code and inline media', () => {
|
||||
test('spells a link run once across the mentions and inline cards between two nodes holding it, and parts it at code and inline media that do not hold it', () => {
|
||||
const link: AdfMark = { attrs: { href: '/u' }, type: 'link' }
|
||||
const marked = (text: string, ...marks: AdfMark[]): AdfNode => ({ marks, text, type: 'text' })
|
||||
assert.equal(readsBack(document(paragraph(marked('a ', link), { attrs: { id: 'x', text: '@A' }, type: 'mention' }, marked(' b', link)))), '[a !adf:mention[@A]{id=x} b](/u)\n')
|
||||
assert.equal(readsBack(document(paragraph(marked('a', link), { attrs: { url: 'https://c/' }, type: 'inlineCard' }, marked('b', link)))), '[a!adf:inlineCard{url="https://c/"}b](/u)\n')
|
||||
assert.equal(readsBack(document(paragraph(marked('a', link), marked('c', { type: 'code' }), marked('b', link)))), '[a](/u)`c`[b](/u)\n')
|
||||
assert.equal(readsBack(document(paragraph(marked('a', link), { attrs: { id: 'm' }, type: 'mediaInline' }, marked('b', link)))), '[a](/u)!adf:mediaInline{id=m}[b](/u)\n')
|
||||
})
|
||||
|
||||
test('carries a hard break holding marks, which Atlassian\'s schema withholds', () => {
|
||||
|
||||
@@ -69,7 +69,6 @@ export function portableLineFallback(nodes: readonly AdfNode[], container: LineC
|
||||
const emission = lineSegments(nodes, container, path, fallbacks)
|
||||
if (!emission.ok) return emission
|
||||
if (fallbacks.carried.size > 0 || emission.value.carries !== undefined) return failure('unsupported-node-shape', 'an inline node on a portable line has no spelling but the carry', path)
|
||||
if (spannedLine(nodes, container, path, fallbacks) !== undefined) return success(undefined)
|
||||
const verdict = lineVerdict(emission.value.segments, container, 'portable', { kind: 'drop', nodes })
|
||||
return success(verdict.kind === 'line' ? undefined : verdict)
|
||||
}
|
||||
@@ -117,12 +116,14 @@ export function linePass(nodes: readonly AdfNode[], container: LineContainer, pa
|
||||
return success(segments === undefined ? { fallback: carries } : attemptLine(segments, container, fallbacks.flavour))
|
||||
}
|
||||
|
||||
// spec/flavour.md, Marks: a run spans the nodes its mark skips where the line reads back so; the line parted at them is the one whose fallbacks a pass takes.
|
||||
// spec/flavour.md, Marks: a pass keeps the spanned line only where it needs no fallback; otherwise it writes the parted line and takes that line's fallbacks.
|
||||
function spannedLine(nodes: readonly AdfNode[], container: LineContainer, path: ConvertErrorPath, fallbacks: LineFallbacks): LineAttempt | undefined {
|
||||
const spanned = spanSkippedNodes(nodes, (node, index) => carries(node, fallbacks.carried, index))
|
||||
if (spanned === nodes) return undefined
|
||||
const emission = lineSegments(spanned, container, path, fallbacks)
|
||||
if (!emission.ok || emission.value.segments === undefined) return undefined
|
||||
// A span that leaves whitespace at a line edge spells it `!adf:text`, which portable markdown lacks.
|
||||
if (fallbacks.flavour === 'portable' && emission.value.segments.some((segment) => segment.escaping === 'none' && segment.text.startsWith('!adf:'))) return undefined
|
||||
const attempt = attemptLine(emission.value.segments, container, fallbacks.flavour)
|
||||
return attempt.fallback === undefined ? attempt : undefined
|
||||
}
|
||||
|
||||
@@ -427,6 +427,8 @@ test('spells an emphasis once across the code spans and hard breaks between two
|
||||
assert.equal(portable(paragraph(text('One', em), { type: 'hardBreak' }, text('Two', em))), '_One\\\nTwo_\n')
|
||||
assert.equal(portable(paragraph(text('a', link('/u')), { type: 'hardBreak' }, text('b', link('/u')))), '[a\\\nb](/u)\n')
|
||||
assert.equal(portable(paragraph(text('Ping ', strong), { attrs: { id: 'x', text: '@A' }, type: 'mention' }, text(' now', strong))), '**Ping** @A **now**\n')
|
||||
assert.equal(portable(paragraph(text('a', link('/u')), { type: 'hardBreak' }, text(' b', link('/u')))), '[a](/u)\\\n[ b](/u)\n')
|
||||
assert.equal(portable(paragraph(text('a\n b', link('/u')))), '[a](/u)\\\n[ b](/u)\n')
|
||||
})
|
||||
|
||||
test('breaks a line at a newline and trims whitespace at every edge CommonMark strips', () => {
|
||||
|
||||
Reference in New Issue
Block a user