From a8e9fb9fbd21f4a54ae66488f337731c1e5bd7e6 Mon Sep 17 00:00:00 2001 From: JunghwanNA <70629228+shaun0927@users.noreply.github.com> Date: Thu, 16 Apr 2026 14:25:27 +0900 Subject: [PATCH] simplify: unify stepRichInlineLine/Stats and remove containsCJKText wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove stepRichInlineLineStats, a ~130-line near-duplicate of stepRichInlineLine. The only difference was whether the optional collectFragment callback fired — passing undefined achieves the same result. PR #132 demonstrated the drift risk by having to apply the same overflow guard to both functions in parallel. Also inline the single-call-site containsCJKText() wrapper, which was a passthrough to the already-public isCJK(). Similar to the isCJK dedup in PR #118. Neither change affects behavior. All 84 tests pass. --- src/analysis.ts | 6 +- src/rich-inline.ts | 135 +-------------------------------------------- 2 files changed, 2 insertions(+), 139 deletions(-) diff --git a/src/analysis.ts b/src/analysis.ts index 4abdac4..62e800b 100644 --- a/src/analysis.ts +++ b/src/analysis.ts @@ -158,10 +158,6 @@ const keepAllGlueChars = new Set([ '\uFEFF', ]) -function containsCJKText(text: string): boolean { - return isCJK(text) -} - function endsWithKeepAllGlueText(text: string): boolean { const last = getLastCodePoint(text) return last !== null && keepAllGlueChars.has(last) @@ -1211,7 +1207,7 @@ function mergeKeepAllTextSegments(segmentation: MergedSegmentation): MergedSegme const start = segmentation.starts[i]! if (kind === 'text') { - const textContainsCJK = containsCJKText(text) + const textContainsCJK = isCJK(text) const textCanContinue = canContinueKeepAllTextRun(text) if (pendingTextParts !== null && pendingContainsCJK && pendingCanContinue) { diff --git a/src/rich-inline.ts b/src/rich-inline.ts index a0007ca..1111530 100644 --- a/src/rich-inline.ts +++ b/src/rich-inline.ts @@ -386,139 +386,6 @@ function stepRichInlineLine( return lineWidth } -function stepRichInlineLineStats( - flow: InternalPreparedRichInline, - maxWidth: number, - cursor: RichInlineCursor, -): number | null { - if (flow.items.length === 0 || cursor.itemIndex >= flow.items.length) return null - - const safeWidth = Math.max(1, maxWidth) - let lineWidth = 0 - let remainingWidth = safeWidth - let itemIndex = cursor.itemIndex - - lineLoop: - while (itemIndex < flow.items.length) { - const item = flow.items[itemIndex]! - if ( - !isLineStartCursor(cursor) && - cursor.segmentIndex === item.endSegmentIndex && - cursor.graphemeIndex === item.endGraphemeIndex - ) { - itemIndex++ - cursor.segmentIndex = 0 - cursor.graphemeIndex = 0 - continue - } - - const gapBefore = lineWidth === 0 ? 0 : item.gapBefore - const atItemStart = isLineStartCursor(cursor) - - if (item.break === 'never') { - if (!atItemStart) { - itemIndex++ - cursor.segmentIndex = 0 - cursor.graphemeIndex = 0 - continue - } - - const occupiedWidth = item.naturalWidth + item.extraWidth - const totalWidth = gapBefore + occupiedWidth - if (lineWidth > 0 && totalWidth > remainingWidth) break lineLoop - - lineWidth += totalWidth - remainingWidth = Math.max(0, safeWidth - lineWidth) - itemIndex++ - cursor.segmentIndex = 0 - cursor.graphemeIndex = 0 - continue - } - - const reservedWidth = gapBefore + item.extraWidth - if (lineWidth > 0 && reservedWidth >= remainingWidth) break lineLoop - - if (atItemStart) { - const totalWidth = reservedWidth + item.naturalWidth - if (totalWidth <= remainingWidth) { - lineWidth += totalWidth - remainingWidth = Math.max(0, safeWidth - lineWidth) - itemIndex++ - cursor.segmentIndex = 0 - cursor.graphemeIndex = 0 - continue - } - } - - const availableWidth = Math.max(1, remainingWidth - reservedWidth) - const lineEnd: LineBreakCursor = { - segmentIndex: cursor.segmentIndex, - graphemeIndex: cursor.graphemeIndex, - } - const lineWidthForItem = stepPreparedLineGeometry(item.prepared, lineEnd, availableWidth) - if (lineWidthForItem === null) { - itemIndex++ - cursor.segmentIndex = 0 - cursor.graphemeIndex = 0 - continue - } - if (cursor.segmentIndex === lineEnd.segmentIndex && cursor.graphemeIndex === lineEnd.graphemeIndex) { - itemIndex++ - cursor.segmentIndex = 0 - cursor.graphemeIndex = 0 - continue - } - - if ( - lineWidth > 0 && - atItemStart && - gapBefore > 0 && - endsInsideFirstSegment(lineEnd.segmentIndex, lineEnd.graphemeIndex) - ) { - const freshLineEnd: LineBreakCursor = { - segmentIndex: 0, - graphemeIndex: 0, - } - const freshLineWidth = stepPreparedLineGeometry( - item.prepared, - freshLineEnd, - Math.max(1, safeWidth - item.extraWidth), - ) - if ( - freshLineWidth !== null && - ( - freshLineEnd.segmentIndex > lineEnd.segmentIndex || - ( - freshLineEnd.segmentIndex === lineEnd.segmentIndex && - freshLineEnd.graphemeIndex > lineEnd.graphemeIndex - ) - ) - ) { - break lineLoop - } - } - - lineWidth += gapBefore + lineWidthForItem + item.extraWidth - remainingWidth = Math.max(0, safeWidth - lineWidth) - - if (lineEnd.segmentIndex === item.endSegmentIndex && lineEnd.graphemeIndex === item.endGraphemeIndex) { - itemIndex++ - cursor.segmentIndex = 0 - cursor.graphemeIndex = 0 - continue - } - - cursor.segmentIndex = lineEnd.segmentIndex - cursor.graphemeIndex = lineEnd.graphemeIndex - break - } - - if (lineWidth === 0) return null - - cursor.itemIndex = itemIndex - return lineWidth -} - export function layoutNextRichInlineLineRange( prepared: PreparedRichInline, maxWidth: number, @@ -625,7 +492,7 @@ export function measureRichInlineStats( } while (true) { - const lineWidth = stepRichInlineLineStats(flow, maxWidth, cursor) + const lineWidth = stepRichInlineLine(flow, maxWidth, cursor) if (lineWidth === null) { return { lineCount,