From 6681bec391866798e94e1978671b7db232b2b49e Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Tue, 29 Sep 2026 12:13:11 +0200 Subject: [PATCH] 35b - review: runs as a non-empty tuple, no item for a stray child reducing to nothing, 42 filed --- src/markdown/emit/inline-line.ts | 8 ++++---- src/markdown/emit/plain-reduction.ts | 2 +- todo.md | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/markdown/emit/inline-line.ts b/src/markdown/emit/inline-line.ts index 265da48..6e719e0 100644 --- a/src/markdown/emit/inline-line.ts +++ b/src/markdown/emit/inline-line.ts @@ -38,7 +38,7 @@ type LineAttempt = { fallback: NodeRange | 'opening-link'; line?: undefined } | type LineFallbacks = { carried: Set; flavour: Flavour; openingLinkAsDirective: boolean } -export type PlainLineFallback = { kind: 'claimed-line'; line: number; text: string } | { kind: 'opening-link' } | { kind: 'unspellable-run'; run: MarkRun; runs: MarkRun[] } +export type PlainLineFallback = { kind: 'claimed-line'; line: number; text: string } | { kind: 'opening-link' } | { kind: 'unspellable-run'; runs: [MarkRun, ...MarkRun[]] } export function emitInlineLine(nodes: readonly AdfNode[], container: LineContainer, path: ConvertErrorPath, flavour: Flavour): Result { const emitted = emitLine(nodes, container, path, flavour) @@ -120,7 +120,7 @@ function lineSegments(nodes: readonly AdfNode[], container: LineContainer, path: function attemptLine(segments: readonly InlineSegment[], container: LineContainer, path: ConvertErrorPath, flavour: Flavour): Result { const verdict = lineVerdict(segments, container, flavour) if (verdict.kind === 'opening-link') return success({ fallback: 'opening-link' }) - if (verdict.kind === 'unspellable-run') return success({ fallback: verdict.run }) + if (verdict.kind === 'unspellable-run') return success({ fallback: verdict.runs[0] }) if (verdict.kind === 'claimed-line') return failure('unspellable-line-start', `block parsing would claim the emitted line ${JSON.stringify(verdict.text)}`, path) return success({ line: verdict.text }) } @@ -129,8 +129,8 @@ function attemptLine(segments: readonly InlineSegment[], container: LineContaine function lineVerdict(segments: readonly InlineSegment[], container: LineContainer, flavour: Flavour): PlainLineFallback | { kind: 'line'; text: string } { const assembled = assembleInlineLine(segments, container, flavour) if (assembled.openingLinkAsDirective) return { kind: 'opening-link' } - const [run] = assembled.unspellableRuns - if (run !== undefined) return { kind: 'unspellable-run', run, runs: assembled.unspellableRuns } + const [run, ...others] = assembled.unspellableRuns + if (run !== undefined) return { kind: 'unspellable-run', runs: [run, ...others] } const lines = assembled.line.split('\n') const claimed = container === 'paragraph' ? lines.findIndex((single, index) => claimsLine(single, index === 0 ? 'first' : 'later')) : -1 return claimed === -1 ? { kind: 'line', text: assembled.line } : { kind: 'claimed-line', line: claimed, text: lines[claimed] ?? '' } diff --git a/src/markdown/emit/plain-reduction.ts b/src/markdown/emit/plain-reduction.ts index 72af133..a1072eb 100644 --- a/src/markdown/emit/plain-reduction.ts +++ b/src/markdown/emit/plain-reduction.ts @@ -285,7 +285,7 @@ function reduceTaskList(node: AdfNode, reduction: Reduction): Result const reduced = isTask(child) ? reduceTask(child, at) : reduceStanding(child, at) if (!reduced.ok) return reduced if (!regular) { - const standsAlone = !isTask(child) && child.type !== 'taskList' + const standsAlone = !isTask(child) && child.type !== 'taskList' && reduced.value.length > 0 for (const block of standsAlone ? [{ content: reduced.value, type: 'listItem' }] : reduced.value) tasks.push(block) continue } diff --git a/todo.md b/todo.md index b0473bd..80498cb 100644 --- a/todo.md +++ b/todo.md @@ -34,6 +34,10 @@ paragraph of 2000 × `un` plus `**-r**`: each run its flanking cannot spell re-emits the whole line before riding the carry, quadratic in the runs (Goal 9), and the plain reduction's `spellableLine` drops one mark per re-emit the same way. Make both linear. +- **42 — Trim a text leaf's trailing blanks in linear time.** `plain-inline.ts`'s `leafEdges` finds + the trail with an unanchored `/[ \t]*$/`, quadratic in a run of blanks inside one leaf: a + paragraph of `a`, 80 000 spaces, `b` takes 6.5 s in `adfToPlainMarkdown` (Goal 9). Scan backward, + as the expand title's trim does. - **34 — Read emphasis flanking by the whole character beside an astral symbol.** Check whether `line-escaping.ts`'s `charAt` and the parser's flanking read one UTF-16 unit beside an astral symbol — a lone surrogate is neither punctuation nor symbol, where CommonMark reads `😀` as