postext 0.3.6 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/canvas-backend/blockRender.d.ts +3 -0
- package/dist/canvas-backend/blockRender.d.ts.map +1 -0
- package/dist/canvas-backend/blockRender.js +176 -0
- package/dist/canvas-backend/blockRender.js.map +1 -0
- package/dist/canvas-backend/decorations.d.ts +6 -0
- package/dist/canvas-backend/decorations.d.ts.map +1 -0
- package/dist/canvas-backend/decorations.js +106 -0
- package/dist/canvas-backend/decorations.js.map +1 -0
- package/dist/{canvas-backend.d.ts → canvas-backend/index.d.ts} +2 -2
- package/dist/canvas-backend/index.d.ts.map +1 -0
- package/dist/canvas-backend/index.js +66 -0
- package/dist/canvas-backend/index.js.map +1 -0
- package/dist/knuthPlass/breakpoints.d.ts +6 -0
- package/dist/knuthPlass/breakpoints.d.ts.map +1 -0
- package/dist/knuthPlass/breakpoints.js +284 -0
- package/dist/knuthPlass/breakpoints.js.map +1 -0
- package/dist/knuthPlass/constants.d.ts +8 -0
- package/dist/knuthPlass/constants.d.ts.map +1 -0
- package/dist/knuthPlass/constants.js +8 -0
- package/dist/knuthPlass/constants.js.map +1 -0
- package/dist/knuthPlass/index.d.ts +12 -0
- package/dist/knuthPlass/index.d.ts.map +1 -0
- package/dist/knuthPlass/index.js +11 -0
- package/dist/knuthPlass/index.js.map +1 -0
- package/dist/knuthPlass/pretextAdapter.d.ts +12 -0
- package/dist/knuthPlass/pretextAdapter.d.ts.map +1 -0
- package/dist/knuthPlass/pretextAdapter.js +178 -0
- package/dist/knuthPlass/pretextAdapter.js.map +1 -0
- package/dist/knuthPlass/richAdapter.d.ts +26 -0
- package/dist/knuthPlass/richAdapter.d.ts.map +1 -0
- package/dist/knuthPlass/richAdapter.js +189 -0
- package/dist/knuthPlass/richAdapter.js.map +1 -0
- package/dist/{knuthPlass.d.ts → knuthPlass/types.d.ts} +1 -31
- package/dist/knuthPlass/types.d.ts.map +1 -0
- package/dist/knuthPlass/types.js +5 -0
- package/dist/knuthPlass/types.js.map +1 -0
- package/dist/knuthPlass/utils.d.ts +2 -0
- package/dist/knuthPlass/utils.d.ts.map +1 -0
- package/dist/knuthPlass/utils.js +4 -0
- package/dist/knuthPlass/utils.js.map +1 -0
- package/dist/measure/cache.d.ts +5 -0
- package/dist/measure/cache.d.ts.map +1 -0
- package/dist/measure/cache.js +38 -0
- package/dist/measure/cache.js.map +1 -0
- package/dist/measure/canvas.d.ts +8 -0
- package/dist/measure/canvas.d.ts.map +1 -0
- package/dist/measure/canvas.js +30 -0
- package/dist/measure/canvas.js.map +1 -0
- package/dist/measure/font.d.ts +19 -0
- package/dist/measure/font.d.ts.map +1 -0
- package/dist/measure/font.js +34 -0
- package/dist/measure/font.js.map +1 -0
- package/dist/measure/index.d.ts +7 -0
- package/dist/measure/index.d.ts.map +1 -0
- package/dist/measure/index.js +6 -0
- package/dist/measure/index.js.map +1 -0
- package/dist/measure/plain.d.ts +13 -0
- package/dist/measure/plain.d.ts.map +1 -0
- package/dist/measure/plain.js +167 -0
- package/dist/measure/plain.js.map +1 -0
- package/dist/measure/rich.d.ts +25 -0
- package/dist/measure/rich.d.ts.map +1 -0
- package/dist/measure/rich.js +246 -0
- package/dist/measure/rich.js.map +1 -0
- package/dist/measure/types.d.ts +28 -0
- package/dist/measure/types.d.ts.map +1 -0
- package/dist/measure/types.js +2 -0
- package/dist/measure/types.js.map +1 -0
- package/dist/parse/blockParser.d.ts +28 -0
- package/dist/parse/blockParser.d.ts.map +1 -0
- package/dist/parse/blockParser.js +302 -0
- package/dist/parse/blockParser.js.map +1 -0
- package/dist/parse/index.d.ts +4 -0
- package/dist/parse/index.d.ts.map +1 -0
- package/dist/parse/index.js +3 -0
- package/dist/parse/index.js.map +1 -0
- package/dist/parse/inlineFormatting.d.ts +12 -0
- package/dist/parse/inlineFormatting.d.ts.map +1 -0
- package/dist/parse/inlineFormatting.js +90 -0
- package/dist/parse/inlineFormatting.js.map +1 -0
- package/dist/parse/inlineMath.d.ts +29 -0
- package/dist/parse/inlineMath.d.ts.map +1 -0
- package/dist/parse/inlineMath.js +141 -0
- package/dist/parse/inlineMath.js.map +1 -0
- package/dist/parse/sourceMapping.d.ts +12 -0
- package/dist/parse/sourceMapping.d.ts.map +1 -0
- package/dist/parse/sourceMapping.js +130 -0
- package/dist/parse/sourceMapping.js.map +1 -0
- package/dist/{parse.d.ts → parse/types.d.ts} +2 -25
- package/dist/parse/types.d.ts.map +1 -0
- package/dist/parse/types.js +2 -0
- package/dist/parse/types.js.map +1 -0
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +34 -276
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/buildBlockKind.d.ts +33 -0
- package/dist/pipeline/buildBlockKind.d.ts.map +1 -0
- package/dist/pipeline/buildBlockKind.js +82 -0
- package/dist/pipeline/buildBlockKind.js.map +1 -0
- package/dist/pipeline/buildHelpers.d.ts +47 -0
- package/dist/pipeline/buildHelpers.d.ts.map +1 -0
- package/dist/pipeline/buildHelpers.js +169 -0
- package/dist/pipeline/buildHelpers.js.map +1 -0
- package/dist/pipeline/buildMeasurement.d.ts +27 -0
- package/dist/pipeline/buildMeasurement.d.ts.map +1 -0
- package/dist/pipeline/buildMeasurement.js +49 -0
- package/dist/pipeline/buildMeasurement.js.map +1 -0
- package/package.json +1 -1
- package/dist/canvas-backend.d.ts.map +0 -1
- package/dist/canvas-backend.js +0 -370
- package/dist/canvas-backend.js.map +0 -1
- package/dist/knuthPlass.d.ts.map +0 -1
- package/dist/knuthPlass.js +0 -665
- package/dist/knuthPlass.js.map +0 -1
- package/dist/measure.d.ts +0 -61
- package/dist/measure.d.ts.map +0 -1
- package/dist/measure.js +0 -512
- package/dist/measure.js.map +0 -1
- package/dist/parse.d.ts.map +0 -1
- package/dist/parse.js +0 -653
- package/dist/parse.js.map +0 -1
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { prepareWithSegments, layoutNextLine, } from '@chenglou/pretext';
|
|
2
|
+
import { createBoundingBox } from '../vdt';
|
|
3
|
+
import { hyphenateText } from '../hyphenate';
|
|
4
|
+
import { pretextSegmentsToItems, computeBreakpoints, reconstructPretextLines, } from '../knuthPlass';
|
|
5
|
+
import { SOFT_HYPHEN } from './types';
|
|
6
|
+
import { cleanSoftHyphens, normalSpaceWidthFor } from './canvas';
|
|
7
|
+
function extractSegments(prepared, start, end) {
|
|
8
|
+
const result = [];
|
|
9
|
+
let hyphenated = false;
|
|
10
|
+
for (let i = start.segmentIndex; i < end.segmentIndex; i++) {
|
|
11
|
+
const seg = prepared.segments[i];
|
|
12
|
+
const w = prepared.widths[i];
|
|
13
|
+
if (seg === SOFT_HYPHEN) {
|
|
14
|
+
// If this is the last segment before the break, mark as hyphenated
|
|
15
|
+
if (i === end.segmentIndex - 1)
|
|
16
|
+
hyphenated = true;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (seg.trim().length === 0) {
|
|
20
|
+
result.push({ kind: 'space', text: seg, width: w });
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
result.push({ kind: 'text', text: seg, width: w });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Check if the break point is at a soft hyphen
|
|
27
|
+
if (!hyphenated && end.segmentIndex < prepared.segments.length) {
|
|
28
|
+
if (prepared.segments[end.segmentIndex] === SOFT_HYPHEN) {
|
|
29
|
+
hyphenated = true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Trim trailing spaces
|
|
33
|
+
while (result.length > 0 && result[result.length - 1].kind === 'space') {
|
|
34
|
+
result.pop();
|
|
35
|
+
}
|
|
36
|
+
return { segments: result, hyphenated };
|
|
37
|
+
}
|
|
38
|
+
function findLastTextSegmentIndex(segments) {
|
|
39
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
40
|
+
if (segments[i].kind === 'text')
|
|
41
|
+
return i;
|
|
42
|
+
}
|
|
43
|
+
return -1;
|
|
44
|
+
}
|
|
45
|
+
function getHyphenWidth(prepared) {
|
|
46
|
+
// Use discretionaryHyphenWidth from pretext internals
|
|
47
|
+
const core = prepared;
|
|
48
|
+
if (core.discretionaryHyphenWidth && core.discretionaryHyphenWidth > 0) {
|
|
49
|
+
return core.discretionaryHyphenWidth;
|
|
50
|
+
}
|
|
51
|
+
return 5; // fallback
|
|
52
|
+
}
|
|
53
|
+
export function computeJustifiedSpaceRatio(segments, lineMaxWidth, normalSpaceWidth, textAlign, isLastLine) {
|
|
54
|
+
if (textAlign !== 'justify' || isLastLine || normalSpaceWidth <= 0)
|
|
55
|
+
return undefined;
|
|
56
|
+
let wordWidth = 0;
|
|
57
|
+
let spaceCount = 0;
|
|
58
|
+
for (const s of segments) {
|
|
59
|
+
if (s.kind === 'space')
|
|
60
|
+
spaceCount++;
|
|
61
|
+
else
|
|
62
|
+
wordWidth += s.width;
|
|
63
|
+
}
|
|
64
|
+
if (spaceCount === 0)
|
|
65
|
+
return undefined;
|
|
66
|
+
const justifiedSpaceWidth = (lineMaxWidth - wordWidth) / spaceCount;
|
|
67
|
+
return justifiedSpaceWidth / normalSpaceWidth;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Measure a text block: break it into lines within maxWidthPx
|
|
71
|
+
* and return VDTLine data with bounding boxes.
|
|
72
|
+
*
|
|
73
|
+
* The returned lines have bbox positions relative to the block origin (0,0).
|
|
74
|
+
* The pipeline will offset them to absolute page coordinates later.
|
|
75
|
+
*/
|
|
76
|
+
export function measureBlock(text, font, maxWidthPx, lineHeightPx, options) {
|
|
77
|
+
if (text.trim() === '') {
|
|
78
|
+
return { lines: [], totalHeight: 0 };
|
|
79
|
+
}
|
|
80
|
+
const shouldHyphenate = options?.hyphenate ?? false;
|
|
81
|
+
const indentPx = options?.firstLineIndentPx ?? 0;
|
|
82
|
+
const hanging = options?.hangingIndent ?? false;
|
|
83
|
+
const textAlign = options?.textAlign ?? 'left';
|
|
84
|
+
const processedText = shouldHyphenate ? hyphenateText(text) : text;
|
|
85
|
+
const prepared = prepareWithSegments(processedText, font);
|
|
86
|
+
const normalSpaceWidth = textAlign === 'justify' ? normalSpaceWidthFor(font) : 0;
|
|
87
|
+
// Knuth-Plass optimal line breaking path
|
|
88
|
+
if (options?.optimal && textAlign === 'justify') {
|
|
89
|
+
const maxStretchRatio = options.maxStretchRatio ?? 1.5;
|
|
90
|
+
const minShrinkRatio = options.minShrinkRatio ?? 0.8;
|
|
91
|
+
const items = pretextSegmentsToItems(prepared, normalSpaceWidth, maxStretchRatio, minShrinkRatio);
|
|
92
|
+
const lineWidthFn = (li) => {
|
|
93
|
+
const isFirst = li === 0;
|
|
94
|
+
const indent = indentPx > 0
|
|
95
|
+
? (hanging ? (isFirst ? 0 : indentPx) : (isFirst ? indentPx : 0))
|
|
96
|
+
: 0;
|
|
97
|
+
return maxWidthPx - indent;
|
|
98
|
+
};
|
|
99
|
+
const lineIndentFn = (li) => {
|
|
100
|
+
const isFirst = li === 0;
|
|
101
|
+
return indentPx > 0
|
|
102
|
+
? (hanging ? (isFirst ? 0 : indentPx) : (isFirst ? indentPx : 0))
|
|
103
|
+
: 0;
|
|
104
|
+
};
|
|
105
|
+
const runtPenalty = options.runtPenalty ?? 0;
|
|
106
|
+
const runtMinWidth = runtPenalty > 0
|
|
107
|
+
? (options.runtMinCharacters ?? 0) * normalSpaceWidth
|
|
108
|
+
: 0;
|
|
109
|
+
const breaks = computeBreakpoints(items, {
|
|
110
|
+
lineWidth: lineWidthFn,
|
|
111
|
+
normalSpaceWidth,
|
|
112
|
+
maxStretchRatio,
|
|
113
|
+
minShrinkRatio,
|
|
114
|
+
runtPenalty,
|
|
115
|
+
runtMinWidth,
|
|
116
|
+
});
|
|
117
|
+
if (breaks.length > 0) {
|
|
118
|
+
const kpLines = reconstructPretextLines(items, breaks, prepared, lineHeightPx, lineWidthFn, lineIndentFn, normalSpaceWidth, textAlign);
|
|
119
|
+
return { lines: kpLines, totalHeight: kpLines.length * lineHeightPx };
|
|
120
|
+
}
|
|
121
|
+
// Fallback to greedy if K-P produced no breaks
|
|
122
|
+
}
|
|
123
|
+
const lines = [];
|
|
124
|
+
let cursor = { segmentIndex: 0, graphemeIndex: 0 };
|
|
125
|
+
let y = 0;
|
|
126
|
+
let lineIndex = 0;
|
|
127
|
+
while (true) {
|
|
128
|
+
// First line indent: indent line 0 only. Hanging indent: indent all lines except 0.
|
|
129
|
+
const isFirstLine = lineIndex === 0;
|
|
130
|
+
const lineIndent = indentPx > 0
|
|
131
|
+
? (hanging ? (isFirstLine ? 0 : indentPx) : (isFirstLine ? indentPx : 0))
|
|
132
|
+
: 0;
|
|
133
|
+
const lineMaxWidth = maxWidthPx - lineIndent;
|
|
134
|
+
const line = layoutNextLine(prepared, cursor, lineMaxWidth);
|
|
135
|
+
if (line === null)
|
|
136
|
+
break;
|
|
137
|
+
const nextCursor = line.end;
|
|
138
|
+
const isLastLine = layoutNextLine(prepared, nextCursor, lineMaxWidth) === null;
|
|
139
|
+
const { segments, hyphenated } = extractSegments(prepared, cursor, nextCursor);
|
|
140
|
+
if (hyphenated) {
|
|
141
|
+
const lastTextIdx = findLastTextSegmentIndex(segments);
|
|
142
|
+
if (lastTextIdx >= 0) {
|
|
143
|
+
const lastSeg = segments[lastTextIdx];
|
|
144
|
+
segments[lastTextIdx] = {
|
|
145
|
+
kind: 'text',
|
|
146
|
+
text: lastSeg.text + '-',
|
|
147
|
+
width: lastSeg.width + getHyphenWidth(prepared),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const justifiedSpaceRatio = computeJustifiedSpaceRatio(segments, lineMaxWidth, normalSpaceWidth, textAlign, isLastLine);
|
|
152
|
+
lines.push({
|
|
153
|
+
text: hyphenated ? cleanSoftHyphens(line.text) + '-' : cleanSoftHyphens(line.text),
|
|
154
|
+
bbox: createBoundingBox(lineIndent, y, line.width, lineHeightPx),
|
|
155
|
+
baseline: y + lineHeightPx * 0.8,
|
|
156
|
+
hyphenated,
|
|
157
|
+
segments,
|
|
158
|
+
isLastLine,
|
|
159
|
+
...(justifiedSpaceRatio !== undefined ? { justifiedSpaceRatio } : {}),
|
|
160
|
+
});
|
|
161
|
+
cursor = nextCursor;
|
|
162
|
+
y += lineHeightPx;
|
|
163
|
+
lineIndex++;
|
|
164
|
+
}
|
|
165
|
+
return { lines, totalHeight: y };
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=plain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plain.js","sourceRoot":"","sources":["../../src/measure/plain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { MathRender } from '../math/types';
|
|
2
|
+
import type { InlineSpan } from '../parse';
|
|
3
|
+
import type { MeasuredBlock, MeasureBlockOptions } from './types';
|
|
4
|
+
export interface RichBreakPoint {
|
|
5
|
+
charIndex: number;
|
|
6
|
+
widthBefore: number;
|
|
7
|
+
}
|
|
8
|
+
export interface RichToken {
|
|
9
|
+
text: string;
|
|
10
|
+
bold: boolean;
|
|
11
|
+
italic: boolean;
|
|
12
|
+
kind: 'text' | 'space';
|
|
13
|
+
width: number;
|
|
14
|
+
breakPoints?: RichBreakPoint[];
|
|
15
|
+
hyphenWidth?: number;
|
|
16
|
+
/** When present, this token is an atomic math formula. `text` is a single
|
|
17
|
+
* `\uFFFC` placeholder and `width` is the math render's widthPx. */
|
|
18
|
+
mathRender?: MathRender;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Measure a rich text block with mixed font weights.
|
|
22
|
+
* Uses canvas measureText for per-token measurement and greedy line-breaking.
|
|
23
|
+
*/
|
|
24
|
+
export declare function measureRichBlock(spans: InlineSpan[], normalFont: string, boldFont: string, italicFont: string, boldItalicFont: string, maxWidthPx: number, lineHeightPx: number, options?: MeasureBlockOptions): MeasuredBlock;
|
|
25
|
+
//# sourceMappingURL=rich.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rich.d.ts","sourceRoot":"","sources":["../../src/measure/rich.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAQ3C,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAIlE,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;yEACqE;IACrE,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAoFD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,UAAU,EAAE,EACnB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,aAAa,CA6Lf"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { createBoundingBox } from '../vdt';
|
|
2
|
+
import { hyphenateText } from '../hyphenate';
|
|
3
|
+
import { richTokensToItems, computeBreakpoints, reconstructRichLines, } from '../knuthPlass';
|
|
4
|
+
import { SOFT_HYPHEN } from './types';
|
|
5
|
+
import { cleanSoftHyphens, measureTextWidth, normalSpaceWidthFor } from './canvas';
|
|
6
|
+
import { computeJustifiedSpaceRatio } from './plain';
|
|
7
|
+
/**
|
|
8
|
+
* Tokenize inline spans into word/space tokens with bold/italic flags and measured widths.
|
|
9
|
+
*/
|
|
10
|
+
function tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont, shouldHyphenate) {
|
|
11
|
+
const tokens = [];
|
|
12
|
+
for (const span of spans) {
|
|
13
|
+
// Math spans are atomic: a single non-breaking box with the render's
|
|
14
|
+
// widthPx. Kind 'text' is correct (not 'space') so trimming trailing
|
|
15
|
+
// spaces from a line doesn't drop the formula.
|
|
16
|
+
if (span.math && span.mathRender) {
|
|
17
|
+
tokens.push({
|
|
18
|
+
text: span.text,
|
|
19
|
+
bold: span.bold,
|
|
20
|
+
italic: span.italic,
|
|
21
|
+
kind: 'text',
|
|
22
|
+
width: span.mathRender.widthPx,
|
|
23
|
+
mathRender: span.mathRender,
|
|
24
|
+
});
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const text = shouldHyphenate ? hyphenateText(span.text) : span.text;
|
|
28
|
+
const font = span.bold && span.italic
|
|
29
|
+
? boldItalicFont
|
|
30
|
+
: span.bold
|
|
31
|
+
? boldFont
|
|
32
|
+
: span.italic
|
|
33
|
+
? italicFont
|
|
34
|
+
: normalFont;
|
|
35
|
+
// Split on word boundaries while preserving spaces
|
|
36
|
+
const parts = text.match(/\S+|\s+/g);
|
|
37
|
+
if (!parts)
|
|
38
|
+
continue;
|
|
39
|
+
for (const part of parts) {
|
|
40
|
+
const isSpace = part.trim().length === 0;
|
|
41
|
+
if (!isSpace && part.includes(SOFT_HYPHEN)) {
|
|
42
|
+
const clean = part.replace(/\u00AD/g, '');
|
|
43
|
+
const cleanWidth = measureTextWidth(clean, font);
|
|
44
|
+
const breakPoints = [];
|
|
45
|
+
let priorSoft = 0;
|
|
46
|
+
for (let i = 0; i < part.length; i++) {
|
|
47
|
+
if (part[i] === SOFT_HYPHEN) {
|
|
48
|
+
const cleanIdx = i - priorSoft;
|
|
49
|
+
breakPoints.push({
|
|
50
|
+
charIndex: cleanIdx,
|
|
51
|
+
widthBefore: measureTextWidth(clean.slice(0, cleanIdx), font),
|
|
52
|
+
});
|
|
53
|
+
priorSoft++;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
tokens.push({
|
|
57
|
+
text: clean,
|
|
58
|
+
bold: span.bold,
|
|
59
|
+
italic: span.italic,
|
|
60
|
+
kind: 'text',
|
|
61
|
+
width: cleanWidth,
|
|
62
|
+
breakPoints,
|
|
63
|
+
hyphenWidth: measureTextWidth('-', font),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
tokens.push({
|
|
68
|
+
text: part,
|
|
69
|
+
bold: span.bold,
|
|
70
|
+
italic: span.italic,
|
|
71
|
+
kind: isSpace ? 'space' : 'text',
|
|
72
|
+
width: measureTextWidth(part, font),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return tokens;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Measure a rich text block with mixed font weights.
|
|
81
|
+
* Uses canvas measureText for per-token measurement and greedy line-breaking.
|
|
82
|
+
*/
|
|
83
|
+
export function measureRichBlock(spans, normalFont, boldFont, italicFont, boldItalicFont, maxWidthPx, lineHeightPx, options) {
|
|
84
|
+
const plainText = spans.map((s) => s.text).join('');
|
|
85
|
+
if (plainText.trim() === '') {
|
|
86
|
+
return { lines: [], totalHeight: 0 };
|
|
87
|
+
}
|
|
88
|
+
const shouldHyphenate = options?.hyphenate ?? false;
|
|
89
|
+
const indentPx = options?.firstLineIndentPx ?? 0;
|
|
90
|
+
const hanging = options?.hangingIndent ?? false;
|
|
91
|
+
const textAlign = options?.textAlign ?? 'left';
|
|
92
|
+
const tokens = tokenizeSpans(spans, normalFont, boldFont, italicFont, boldItalicFont, shouldHyphenate);
|
|
93
|
+
const normalSpaceWidth = textAlign === 'justify' ? normalSpaceWidthFor(normalFont) : 0;
|
|
94
|
+
if (tokens.length === 0) {
|
|
95
|
+
return { lines: [], totalHeight: 0 };
|
|
96
|
+
}
|
|
97
|
+
// Knuth-Plass optimal line breaking path
|
|
98
|
+
if (options?.optimal && textAlign === 'justify') {
|
|
99
|
+
const maxStretchRatio = options.maxStretchRatio ?? 1.5;
|
|
100
|
+
const minShrinkRatio = options.minShrinkRatio ?? 0.8;
|
|
101
|
+
const items = richTokensToItems(tokens, normalSpaceWidth, maxStretchRatio, minShrinkRatio);
|
|
102
|
+
const lineWidthFn = (li) => {
|
|
103
|
+
const isFirst = li === 0;
|
|
104
|
+
const indent = indentPx > 0
|
|
105
|
+
? (hanging ? (isFirst ? 0 : indentPx) : (isFirst ? indentPx : 0))
|
|
106
|
+
: 0;
|
|
107
|
+
return maxWidthPx - indent;
|
|
108
|
+
};
|
|
109
|
+
const lineIndentFn = (li) => {
|
|
110
|
+
const isFirst = li === 0;
|
|
111
|
+
return indentPx > 0
|
|
112
|
+
? (hanging ? (isFirst ? 0 : indentPx) : (isFirst ? indentPx : 0))
|
|
113
|
+
: 0;
|
|
114
|
+
};
|
|
115
|
+
const runtPenalty = options.runtPenalty ?? 0;
|
|
116
|
+
const runtMinWidth = runtPenalty > 0
|
|
117
|
+
? (options.runtMinCharacters ?? 0) * normalSpaceWidth
|
|
118
|
+
: 0;
|
|
119
|
+
const breaks = computeBreakpoints(items, {
|
|
120
|
+
lineWidth: lineWidthFn,
|
|
121
|
+
normalSpaceWidth,
|
|
122
|
+
maxStretchRatio,
|
|
123
|
+
minShrinkRatio,
|
|
124
|
+
runtPenalty,
|
|
125
|
+
runtMinWidth,
|
|
126
|
+
});
|
|
127
|
+
if (breaks.length > 0) {
|
|
128
|
+
const kpLines = reconstructRichLines(items, breaks, tokens, lineHeightPx, lineWidthFn, lineIndentFn, normalSpaceWidth, textAlign);
|
|
129
|
+
return { lines: kpLines, totalHeight: kpLines.length * lineHeightPx };
|
|
130
|
+
}
|
|
131
|
+
// Fallback to greedy if K-P produced no breaks
|
|
132
|
+
}
|
|
133
|
+
const lines = [];
|
|
134
|
+
let y = 0;
|
|
135
|
+
let tokenIdx = 0;
|
|
136
|
+
let lineIndex = 0;
|
|
137
|
+
while (tokenIdx < tokens.length) {
|
|
138
|
+
const isFirstLine = lineIndex === 0;
|
|
139
|
+
const lineIndent = indentPx > 0
|
|
140
|
+
? (hanging ? (isFirstLine ? 0 : indentPx) : (isFirstLine ? indentPx : 0))
|
|
141
|
+
: 0;
|
|
142
|
+
const lineMaxWidth = maxWidthPx - lineIndent;
|
|
143
|
+
const lineTokens = [];
|
|
144
|
+
let lineWidth = 0;
|
|
145
|
+
let lineHyphenated = false;
|
|
146
|
+
// Consume leading spaces at line start (skip them)
|
|
147
|
+
while (tokenIdx < tokens.length && tokens[tokenIdx].kind === 'space') {
|
|
148
|
+
tokenIdx++;
|
|
149
|
+
}
|
|
150
|
+
// Greedy: add tokens until we overflow
|
|
151
|
+
while (tokenIdx < tokens.length) {
|
|
152
|
+
const token = tokens[tokenIdx];
|
|
153
|
+
if (lineWidth + token.width <= lineMaxWidth) {
|
|
154
|
+
lineTokens.push(token);
|
|
155
|
+
lineWidth += token.width;
|
|
156
|
+
tokenIdx++;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
// Doesn't fit. Try to split at a soft-hyphen.
|
|
160
|
+
if (token.kind === 'text' && token.breakPoints && token.breakPoints.length > 0) {
|
|
161
|
+
const remaining = lineMaxWidth - lineWidth;
|
|
162
|
+
const hyphenW = token.hyphenWidth ?? 0;
|
|
163
|
+
let chosen = null;
|
|
164
|
+
for (const bp of token.breakPoints) {
|
|
165
|
+
if (bp.widthBefore + hyphenW <= remaining)
|
|
166
|
+
chosen = bp;
|
|
167
|
+
else
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
if (chosen) {
|
|
171
|
+
lineTokens.push({
|
|
172
|
+
text: token.text.slice(0, chosen.charIndex) + '-',
|
|
173
|
+
bold: token.bold,
|
|
174
|
+
italic: token.italic,
|
|
175
|
+
kind: 'text',
|
|
176
|
+
width: chosen.widthBefore + hyphenW,
|
|
177
|
+
});
|
|
178
|
+
lineWidth += chosen.widthBefore + hyphenW;
|
|
179
|
+
lineHyphenated = true;
|
|
180
|
+
const chosenIdx = chosen.charIndex;
|
|
181
|
+
const chosenWidth = chosen.widthBefore;
|
|
182
|
+
const residualBreakPoints = token.breakPoints
|
|
183
|
+
.filter((bp) => bp.charIndex > chosenIdx)
|
|
184
|
+
.map((bp) => ({ charIndex: bp.charIndex - chosenIdx, widthBefore: bp.widthBefore - chosenWidth }));
|
|
185
|
+
tokens[tokenIdx] = {
|
|
186
|
+
text: token.text.slice(chosenIdx),
|
|
187
|
+
bold: token.bold,
|
|
188
|
+
italic: token.italic,
|
|
189
|
+
kind: 'text',
|
|
190
|
+
width: token.width - chosenWidth,
|
|
191
|
+
...(residualBreakPoints.length > 0
|
|
192
|
+
? { breakPoints: residualBreakPoints, hyphenWidth: token.hyphenWidth }
|
|
193
|
+
: {}),
|
|
194
|
+
};
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// No viable split. If line is empty, force-fit this token; else break to next line.
|
|
199
|
+
if (lineTokens.length === 0) {
|
|
200
|
+
lineTokens.push(token);
|
|
201
|
+
lineWidth += token.width;
|
|
202
|
+
tokenIdx++;
|
|
203
|
+
}
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
if (lineTokens.length === 0)
|
|
207
|
+
break;
|
|
208
|
+
// Trim trailing spaces from line tokens
|
|
209
|
+
while (lineTokens.length > 0 && lineTokens[lineTokens.length - 1].kind === 'space') {
|
|
210
|
+
lineWidth -= lineTokens[lineTokens.length - 1].width;
|
|
211
|
+
lineTokens.pop();
|
|
212
|
+
}
|
|
213
|
+
// Check if this is the last line
|
|
214
|
+
// Skip remaining leading spaces to check if there's more content
|
|
215
|
+
let peekIdx = tokenIdx;
|
|
216
|
+
while (peekIdx < tokens.length && tokens[peekIdx].kind === 'space') {
|
|
217
|
+
peekIdx++;
|
|
218
|
+
}
|
|
219
|
+
const isLastLine = peekIdx >= tokens.length;
|
|
220
|
+
// Build segments for justified rendering
|
|
221
|
+
const segments = lineTokens.map((t) => ({
|
|
222
|
+
kind: t.mathRender ? 'math' : t.kind,
|
|
223
|
+
text: cleanSoftHyphens(t.text),
|
|
224
|
+
width: t.width,
|
|
225
|
+
bold: t.bold || undefined,
|
|
226
|
+
italic: t.italic || undefined,
|
|
227
|
+
...(t.mathRender ? { mathRender: t.mathRender } : {}),
|
|
228
|
+
}));
|
|
229
|
+
const lineText = lineTokens.map((t) => cleanSoftHyphens(t.text)).join('');
|
|
230
|
+
const contentWidth = lineTokens.reduce((sum, t) => sum + t.width, 0);
|
|
231
|
+
const justifiedSpaceRatio = computeJustifiedSpaceRatio(segments, lineMaxWidth, normalSpaceWidth, textAlign, isLastLine);
|
|
232
|
+
lines.push({
|
|
233
|
+
text: lineText,
|
|
234
|
+
bbox: createBoundingBox(lineIndent, y, contentWidth, lineHeightPx),
|
|
235
|
+
baseline: y + lineHeightPx * 0.8,
|
|
236
|
+
hyphenated: lineHyphenated,
|
|
237
|
+
segments,
|
|
238
|
+
isLastLine,
|
|
239
|
+
...(justifiedSpaceRatio !== undefined ? { justifiedSpaceRatio } : {}),
|
|
240
|
+
});
|
|
241
|
+
y += lineHeightPx;
|
|
242
|
+
lineIndex++;
|
|
243
|
+
}
|
|
244
|
+
return { lines, totalHeight: y };
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=rich.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rich.js","sourceRoot":"","sources":["../../src/measure/rich.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAG3C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACnF,OAAO,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;AAoBrD;;GAEG;AACH,SAAS,aAAa,CACpB,KAAmB,EACnB,UAAkB,EAClB,QAAgB,EAChB,UAAkB,EAClB,cAAsB,EACtB,eAAwB;IAExB,MAAM,MAAM,GAAgB,EAAE,CAAC;IAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,qEAAqE;QACrE,qEAAqE;QACrE,+CAA+C;QAC/C,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACjC,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO;gBAC9B,UAAU,EAAE,IAAI,CAAC,UAAU;aAC5B,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACpE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM;YACnC,CAAC,CAAC,cAAc;YAChB,CAAC,CAAC,IAAI,CAAC,IAAI;gBACT,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,IAAI,CAAC,MAAM;oBACX,CAAC,CAAC,UAAU;oBACZ,CAAC,CAAC,UAAU,CAAC;QAEnB,mDAAmD;QACnD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC;YACzC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;gBAC1C,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBACjD,MAAM,WAAW,GAAqB,EAAE,CAAC;gBACzC,IAAI,SAAS,GAAG,CAAC,CAAC;gBAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC;wBAC5B,MAAM,QAAQ,GAAG,CAAC,GAAG,SAAS,CAAC;wBAC/B,WAAW,CAAC,IAAI,CAAC;4BACf,SAAS,EAAE,QAAQ;4BACnB,WAAW,EAAE,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC;yBAC9D,CAAC,CAAC;wBACH,SAAS,EAAE,CAAC;oBACd,CAAC;gBACH,CAAC;gBACD,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,KAAK;oBACX,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE,UAAU;oBACjB,WAAW;oBACX,WAAW,EAAE,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC;iBACzC,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;oBAChC,KAAK,EAAE,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC;iBACpC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAmB,EACnB,UAAkB,EAClB,QAAgB,EAChB,UAAkB,EAClB,cAAsB,EACtB,UAAkB,EAClB,YAAoB,EACpB,OAA6B;IAE7B,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC5B,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IACvC,CAAC;IAED,MAAM,eAAe,GAAG,OAAO,EAAE,SAAS,IAAI,KAAK,CAAC;IACpD,MAAM,QAAQ,GAAG,OAAO,EAAE,iBAAiB,IAAI,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,OAAO,EAAE,aAAa,IAAI,KAAK,CAAC;IAChD,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,MAAM,CAAC;IAC/C,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;IACvG,MAAM,gBAAgB,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IACvC,CAAC;IAED,yCAAyC;IACzC,IAAI,OAAO,EAAE,OAAO,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAChD,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,GAAG,CAAC;QACvD,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,GAAG,CAAC;QACrD,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC;QAC3F,MAAM,WAAW,GAAG,CAAC,EAAU,EAAE,EAAE;YACjC,MAAM,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC;YACzB,MAAM,MAAM,GAAG,QAAQ,GAAG,CAAC;gBACzB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjE,CAAC,CAAC,CAAC,CAAC;YACN,OAAO,UAAU,GAAG,MAAM,CAAC;QAC7B,CAAC,CAAC;QACF,MAAM,YAAY,GAAG,CAAC,EAAU,EAAE,EAAE;YAClC,MAAM,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC;YACzB,OAAO,QAAQ,GAAG,CAAC;gBACjB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjE,CAAC,CAAC,CAAC,CAAC;QACR,CAAC,CAAC;QACF,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC;QAC7C,MAAM,YAAY,GAAG,WAAW,GAAG,CAAC;YAClC,CAAC,CAAC,CAAC,OAAO,CAAC,iBAAiB,IAAI,CAAC,CAAC,GAAG,gBAAgB;YACrD,CAAC,CAAC,CAAC,CAAC;QACN,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,EAAE;YACvC,SAAS,EAAE,WAAW;YACtB,gBAAgB;YAChB,eAAe;YACf,cAAc;YACd,WAAW;YACX,YAAY;SACb,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,oBAAoB,CAClC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EACnC,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,SAAS,CACvD,CAAC;YACF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;QACxE,CAAC;QACD,+CAA+C;IACjD,CAAC;IAED,MAAM,KAAK,GAAc,EAAE,CAAC;IAC5B,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,OAAO,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QAChC,MAAM,WAAW,GAAG,SAAS,KAAK,CAAC,CAAC;QACpC,MAAM,UAAU,GAAG,QAAQ,GAAG,CAAC;YAC7B,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACzE,CAAC,CAAC,CAAC,CAAC;QACN,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC;QAE7C,MAAM,UAAU,GAAgB,EAAE,CAAC;QACnC,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,cAAc,GAAG,KAAK,CAAC;QAE3B,mDAAmD;QACnD,OAAO,QAAQ,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAE,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACtE,QAAQ,EAAE,CAAC;QACb,CAAC;QAED,uCAAuC;QACvC,OAAO,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAE,CAAC;YAEhC,IAAI,SAAS,GAAG,KAAK,CAAC,KAAK,IAAI,YAAY,EAAE,CAAC;gBAC5C,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACvB,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC;gBACzB,QAAQ,EAAE,CAAC;gBACX,SAAS;YACX,CAAC;YAED,8CAA8C;YAC9C,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/E,MAAM,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;gBAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;gBACvC,IAAI,MAAM,GAA0B,IAAI,CAAC;gBACzC,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;oBACnC,IAAI,EAAE,CAAC,WAAW,GAAG,OAAO,IAAI,SAAS;wBAAE,MAAM,GAAG,EAAE,CAAC;;wBAClD,MAAM;gBACb,CAAC;gBACD,IAAI,MAAM,EAAE,CAAC;oBACX,UAAU,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,GAAG;wBACjD,IAAI,EAAE,KAAK,CAAC,IAAI;wBAChB,MAAM,EAAE,KAAK,CAAC,MAAM;wBACpB,IAAI,EAAE,MAAM;wBACZ,KAAK,EAAE,MAAM,CAAC,WAAW,GAAG,OAAO;qBACpC,CAAC,CAAC;oBACH,SAAS,IAAI,MAAM,CAAC,WAAW,GAAG,OAAO,CAAC;oBAC1C,cAAc,GAAG,IAAI,CAAC;oBAEtB,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;oBACnC,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;oBACvC,MAAM,mBAAmB,GAAG,KAAK,CAAC,WAAW;yBAC1C,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,GAAG,SAAS,CAAC;yBACxC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,GAAG,SAAS,EAAE,WAAW,EAAE,EAAE,CAAC,WAAW,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC;oBACrG,MAAM,CAAC,QAAQ,CAAC,GAAG;wBACjB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;wBACjC,IAAI,EAAE,KAAK,CAAC,IAAI;wBAChB,MAAM,EAAE,KAAK,CAAC,MAAM;wBACpB,IAAI,EAAE,MAAM;wBACZ,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,WAAW;wBAChC,GAAG,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC;4BAChC,CAAC,CAAC,EAAE,WAAW,EAAE,mBAAmB,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE;4BACtE,CAAC,CAAC,EAAE,CAAC;qBACR,CAAC;oBACF,MAAM;gBACR,CAAC;YACH,CAAC;YAED,oFAAoF;YACpF,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACvB,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC;gBACzB,QAAQ,EAAE,CAAC;YACb,CAAC;YACD,MAAM;QACR,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM;QAEnC,wCAAwC;QACxC,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACpF,SAAS,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,KAAK,CAAC;YACtD,UAAU,CAAC,GAAG,EAAE,CAAC;QACnB,CAAC;QAED,iCAAiC;QACjC,iEAAiE;QACjE,IAAI,OAAO,GAAG,QAAQ,CAAC;QACvB,OAAO,OAAO,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,CAAE,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACpE,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,UAAU,GAAG,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC;QAE5C,yCAAyC;QACzC,MAAM,QAAQ,GAAqB,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACxD,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAE,MAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;YAC/C,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;YAC9B,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,SAAS;YACzB,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,SAAS;YAC7B,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtD,CAAC,CAAC,CAAC;QAEJ,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1E,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAErE,MAAM,mBAAmB,GAAG,0BAA0B,CACpD,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,UAAU,CACX,CAAC;QAEF,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,iBAAiB,CAAC,UAAU,EAAE,CAAC,EAAE,YAAY,EAAE,YAAY,CAAC;YAClE,QAAQ,EAAE,CAAC,GAAG,YAAY,GAAG,GAAG;YAChC,UAAU,EAAE,cAAc;YAC1B,QAAQ;YACR,UAAU;YACV,GAAG,CAAC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtE,CAAC,CAAC;QAEH,CAAC,IAAI,YAAY,CAAC;QAClB,SAAS,EAAE,CAAC;IACd,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { VDTLine } from '../vdt';
|
|
2
|
+
import type { TextAlign } from '../types';
|
|
3
|
+
export interface MeasuredBlock {
|
|
4
|
+
lines: VDTLine[];
|
|
5
|
+
totalHeight: number;
|
|
6
|
+
}
|
|
7
|
+
export interface MeasurementCache {
|
|
8
|
+
_blocks: Map<string, MeasuredBlock>;
|
|
9
|
+
}
|
|
10
|
+
export interface MeasureBlockOptions {
|
|
11
|
+
textAlign?: TextAlign;
|
|
12
|
+
hyphenate?: boolean;
|
|
13
|
+
firstLineIndentPx?: number;
|
|
14
|
+
hangingIndent?: boolean;
|
|
15
|
+
/** Use Knuth-Plass optimal line breaking instead of greedy. */
|
|
16
|
+
optimal?: boolean;
|
|
17
|
+
/** Max space stretch ratio (for K-P glue model). Default 1.5. */
|
|
18
|
+
maxStretchRatio?: number;
|
|
19
|
+
/** Min space shrink ratio (for K-P glue model). Default 0.8. */
|
|
20
|
+
minShrinkRatio?: number;
|
|
21
|
+
/** Demerit for a too-short final line (runt). 0 disables. */
|
|
22
|
+
runtPenalty?: number;
|
|
23
|
+
/** Approximate minimum characters on the final line before runt penalty
|
|
24
|
+
* applies. Converted internally to a pixel threshold via normal space width. */
|
|
25
|
+
runtMinCharacters?: number;
|
|
26
|
+
}
|
|
27
|
+
export declare const SOFT_HYPHEN = "\u00AD";
|
|
28
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/measure/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;qFACiF;IACjF,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,WAAW,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/measure/types.ts"],"names":[],"mappings":"AA8BA,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Block-level markdown tokenizer. Splits the source into `ContentBlock`s
|
|
3
|
+
* (headings, paragraphs, blockquotes, list items, math display blocks) and
|
|
4
|
+
* attaches per-character `sourceMap` arrays so higher layers can map cursor
|
|
5
|
+
* positions back into the original markdown.
|
|
6
|
+
*/
|
|
7
|
+
import type { ContentBlock, ParseIssue } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Memoized wrapper around parseMarkdown: returns the cached result when the
|
|
10
|
+
* input string is byte-for-byte identical to the previous call. This avoids
|
|
11
|
+
* reparsing the whole document on each keystroke when upstream recomputes
|
|
12
|
+
* only because a sibling state changed.
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseMarkdownMemo(markdown: string): ContentBlock[];
|
|
15
|
+
export declare function parseMarkdownWithIssuesMemo(markdown: string): {
|
|
16
|
+
blocks: ContentBlock[];
|
|
17
|
+
issues: ParseIssue[];
|
|
18
|
+
};
|
|
19
|
+
export declare function parseMarkdown(markdown: string): ContentBlock[];
|
|
20
|
+
/**
|
|
21
|
+
* Merge consecutive blockquote lines into a single block, and consecutive
|
|
22
|
+
* non-blank, non-special lines into paragraphs.
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseMarkdownWithIssues(markdown: string): {
|
|
25
|
+
blocks: ContentBlock[];
|
|
26
|
+
issues: ParseIssue[];
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=blockParser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blockParser.d.ts","sourceRoot":"","sources":["../../src/parse/blockParser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAY,UAAU,EAAE,MAAM,SAAS,CAAC;AAoBlE;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAQlE;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAAC,MAAM,EAAE,UAAU,EAAE,CAAA;CAAE,CAQ9G;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAE9D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAAC,MAAM,EAAE,UAAU,EAAE,CAAA;CAAE,CA2Q1G"}
|