Review nit: the attempt names the fallback it takes, so no arm is reached by elimination
CI / gate (push) Successful in 28s
CI / publish (push) Has been skipped

This commit is contained in:
2026-09-20 17:57:13 +02:00
parent ee10b63fe7
commit 8b5e05f5a9
+5 -8
View File
@@ -30,10 +30,7 @@ type InlineContext = {
type InlineRun = { index: number; kind: 'marked'; mark: AdfMark; nodes: AdfNode[] } | { index: number; kind: 'plain'; node: AdfNode } type InlineRun = { index: number; kind: 'marked'; mark: AdfMark; nodes: AdfNode[] } | { index: number; kind: 'plain'; node: AdfNode }
type LineAttempt = type LineAttempt = { fallback: NodeRange | 'opening-link'; line?: undefined } | { fallback?: undefined; line: string }
| { carry: NodeRange; line?: undefined; openingLinkAsDirective?: undefined }
| { carry?: undefined; line?: undefined; openingLinkAsDirective: true }
| { carry?: undefined; line: string; openingLinkAsDirective?: undefined }
type LineFallbacks = { carried: Set<number>; openingLinkAsDirective: boolean } type LineFallbacks = { carried: Set<number>; openingLinkAsDirective: boolean }
@@ -80,12 +77,12 @@ function emitLine(nodes: readonly AdfNode[], container: LineContainer, path: Con
if (attempt.value.line !== undefined) { if (attempt.value.line !== undefined) {
return success({ line: attempt.value.line, openingLinkAsDirective: fallbacks.openingLinkAsDirective, segments: emission.value.segments }) return success({ line: attempt.value.line, openingLinkAsDirective: fallbacks.openingLinkAsDirective, segments: emission.value.segments })
} }
const taken = takeFallback(fallbacks, attempt.value.carry ?? 'opening-link', path) const taken = takeFallback(fallbacks, attempt.value.fallback, path)
if (!taken.ok) return taken if (!taken.ok) return taken
} }
} }
// emitLine ends because each fallback is takeable once: a pass taking none re-emits the line it just emitted. // A pass taking no fallback re-emits the line it just emitted, so refusing loses no spelling.
function takeFallback(fallbacks: LineFallbacks, fallback: NodeRange | 'opening-link', path: ConvertErrorPath): Result<null> { function takeFallback(fallbacks: LineFallbacks, fallback: NodeRange | 'opening-link', path: ConvertErrorPath): Result<null> {
if (fallback === 'opening-link') { if (fallback === 'opening-link') {
if (fallbacks.openingLinkAsDirective) return failure('unsupported-node-shape', 'an opening link spelled as a directive still reads as a link definition, so the line has no spelling left', path) if (fallbacks.openingLinkAsDirective) return failure('unsupported-node-shape', 'an opening link spelled as a directive still reads as a link definition, so the line has no spelling left', path)
@@ -108,8 +105,8 @@ function lineSegments(nodes: readonly AdfNode[], container: LineContainer, path:
function attemptLine(segments: readonly InlineSegment[], container: LineContainer, path: ConvertErrorPath): Result<LineAttempt> { function attemptLine(segments: readonly InlineSegment[], container: LineContainer, path: ConvertErrorPath): Result<LineAttempt> {
const assembled = assembleInlineLine(segments, container) const assembled = assembleInlineLine(segments, container)
if (assembled.openingLinkAsDirective) return success({ openingLinkAsDirective: true }) if (assembled.openingLinkAsDirective) return success({ fallback: 'opening-link' })
if (assembled.unspellableRun !== undefined) return success({ carry: assembled.unspellableRun }) if (assembled.unspellableRun !== undefined) return success({ fallback: assembled.unspellableRun })
for (const [index, single] of assembled.line.split('\n').entries()) { for (const [index, single] of assembled.line.split('\n').entries()) {
if (container === 'paragraph' && claimsLine(single, index === 0 ? 'first' : 'later')) { if (container === 'paragraph' && claimsLine(single, index === 0 ? 'first' : 'later')) {
return failure('unspellable-line-start', `block parsing would claim the emitted line ${JSON.stringify(single)}`, path) return failure('unspellable-line-start', `block parsing would claim the emitted line ${JSON.stringify(single)}`, path)