@weasel-js/text 1.7.0 → 1.7.2

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runs.ts","../src/runs/textTransform.ts","../src/runs/resolveRuns.ts","../src/measure/verticalAlign.ts","../src/layout/textPoseLayout.ts","../src/measure/measureText.ts","../src/measure/measureTextBounds.ts","../src/measure/lineBoxes.ts","../src/markdownText.ts"],"names":["resolveScreenLength"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Canonical inline-styling primitive for text nodes. A node's text is\n * either a plain `string` (treated as a single-run, default-styled fragment)\n * or `StyledRun[]` for rich content. `toRuns` is the funnel that normalizes\n * either form into the array shape used by the renderer.\n *\n * Every field except `text` is optional; missing fields fall back to the\n * node-level `TextStyle`. `bold`/`italic` are toggles; richer weight axes\n * (300/500/900) are out of scope for slice 1.\n */\n\nimport type { FillStyle, ScreenLength, Stroke } from '@weasel-js/paint';\nimport type { TextTransform } from './runs/textTransform';\n\n/** A span of text with its own styling, as authored. Fields left absent\n * inherit from the node's text style — this is the difference between a run\n * and a fully resolved one. */\nexport interface StyledRun {\n text: string;\n bold?: boolean;\n italic?: boolean;\n fontFamily?: string;\n /** World units, or `{ px }` for screen pixels — resolved against the view\n * scale `resolveRuns` is given, like `TextStyle.fontSize`. */\n fontSize?: ScreenLength;\n fill?: FillStyle;\n /** Outline over this run's glyphs. Overrides the node's own `data.stroke`;\n * absent inherits it. Only painted on the outline tier. */\n stroke?: Stroke;\n /** World units, or `{ px }` for screen pixels. */\n letterSpacing?: ScreenLength;\n underline?: boolean;\n strikethrough?: boolean;\n /** Draw a rule above this run's ascent. Additive over the node style. */\n overline?: boolean;\n /**\n * Set this run as a superscript or subscript — a raised or lowered baseline\n * and a smaller size together, which is the pair `<sup>` and `<sub>` imply.\n *\n * A preset over the two primitives below, not a third mechanism: it supplies\n * a `baselineShift` and a `fontScale`, and naming either of those directly\n * overrides that half while leaving the other alone. The numbers are in\n * {@link SCRIPT_METRICS}.\n */\n script?: 'super' | 'sub';\n /**\n * Raise (positive) or lower (negative) this run off the line's shared\n * baseline, in ems of the *inherited* font size — so a run's rise does not\n * shrink along with the run when `fontScale` also applies.\n */\n baselineShift?: number;\n /**\n * Multiplier on the inherited font size. The relative counterpart to\n * `fontSize`, which pins an absolute size and wins over this when both are\n * present.\n */\n fontScale?: number;\n /**\n * CSS `text-transform` for this run's display. The run's `text` stays as\n * authored — carets, selections and edits address it — and only what is\n * drawn changes. Overrides the node's own; `'none'` turns an inherited one\n * off.\n */\n textTransform?: TextTransform;\n}\n\n/** Normalize the two accepted spellings of text content — a plain string or\n * an array of runs — to runs. Throws on a run with no string `text`. */\nexport function toRuns(input: string | StyledRun[]): StyledRun[] {\n if (typeof input === 'string') {\n return input.length === 0 ? [] : [{ text: input }];\n }\n for (let i = 0; i < input.length; i++) {\n const r = input[i];\n if (typeof r?.text !== 'string') {\n throw new Error(`toRuns: run at index ${i} is missing string \\`text\\``);\n }\n }\n return input;\n}\n\n/** Concatenate runs, dropping all styling. */\nexport function runsToPlainText(runs: readonly StyledRun[]): string {\n let out = '';\n for (const r of runs) out += r.text;\n return out;\n}\n\n/** A run flag an inline marker can toggle. The additive style toggles on\n * `StyledRun`; the valued fields (family, size, paint, `script`) have no\n * inline spelling and are not addressable this way. */\nexport type RunFlag = 'bold' | 'italic' | 'underline' | 'strikethrough' | 'overline';\n\n/** One inline marker: a delimiter repeated `repeat` times, and the flags it\n * turns on between its opening and closing occurrence. */\nexport interface RunMarker {\n delimiter: string;\n repeat: number;\n flags: readonly RunFlag[];\n}\n\n/**\n * The inline grammar `runsToMarkdown` writes and `markdownToRuns` reads.\n *\n * Markers sharing a delimiter are matched longest-first, which is what lets\n * `***` mean something other than `**` followed by `*`. A backslash escapes\n * any delimiter character and itself, in both directions.\n */\nexport interface RunGrammar {\n markers: readonly RunMarker[];\n}\n\n/**\n * The markdown subset the kit reads and writes: `**bold**`, `*italic*`,\n * `***both***`.\n *\n * Deliberately not the whole of markdown, and deliberately silent on\n * `underline` / `strikethrough` — the two run flags with no entry here are\n * dropped by `runsToMarkdown`, as they always have been. A grammar that wants\n * `~~struck~~` adds one marker; nothing else has to change.\n */\nexport const MARKDOWN_RUN_GRAMMAR: RunGrammar = {\n markers: [\n { delimiter: '*', repeat: 3, flags: ['bold', 'italic'] },\n { delimiter: '*', repeat: 2, flags: ['bold'] },\n { delimiter: '*', repeat: 1, flags: ['italic'] },\n ],\n};\n\n/** Delimiter characters of a grammar, plus the backslash that escapes them. */\nfunction escapees(grammar: RunGrammar): Set<string> {\n const out = new Set<string>(['\\\\']);\n for (const m of grammar.markers) out.add(m.delimiter);\n return out;\n}\n\nfunction escapeFor(text: string, chars: ReadonlySet<string>): string {\n let out = '';\n for (const ch of text) out += chars.has(ch) ? `\\\\${ch}` : ch;\n return out;\n}\n\n/** The flags a run turns on, in the grammar's own marker order so two runs\n * with the same flags always serialize identically. */\nfunction flagsOf(run: StyledRun, grammar: RunGrammar): Set<RunFlag> {\n const on = new Set<RunFlag>();\n for (const m of grammar.markers) {\n for (const f of m.flags) if (run[f]) on.add(f);\n }\n return on;\n}\n\nfunction sameFlags(a: ReadonlySet<RunFlag>, b: readonly RunFlag[]): boolean {\n return a.size === b.length && b.every((f) => a.has(f));\n}\n\n/**\n * Render runs in `grammar`, defaulting to the markdown subset. The flavor\n * written to the clipboard alongside the plain-text one.\n *\n * A run whose flags exactly match one marker takes it; otherwise the markers\n * that cover them nest. Flags no marker spells are dropped — the text still\n * round-trips, without that styling.\n */\nexport function runsToMarkdown(\n runs: readonly StyledRun[],\n grammar: RunGrammar = MARKDOWN_RUN_GRAMMAR,\n): string {\n const chars = escapees(grammar);\n let out = '';\n for (const r of runs) {\n const escaped = escapeFor(r.text, chars);\n const on = flagsOf(r, grammar);\n if (on.size === 0) { out += escaped; continue; }\n\n const exact = grammar.markers.find((m) => sameFlags(on, m.flags));\n if (exact) {\n const d = exact.delimiter.repeat(exact.repeat);\n out += `${d}${escaped}${d}`;\n continue;\n }\n // No single marker says all of it: nest the ones that each say part.\n const covering = grammar.markers.filter(\n (m) => m.flags.length === 1 && on.has(m.flags[0]),\n );\n const open = covering.map((m) => m.delimiter.repeat(m.repeat)).join('');\n const close = [...covering].reverse().map((m) => m.delimiter.repeat(m.repeat)).join('');\n out += `${open}${escaped}${close}`;\n }\n return out;\n}\n\n/**\n * Parse `input` in `grammar`, defaulting to the markdown subset, into styled\n * runs. Newlines are preserved as literal characters inside a run — they are\n * not run-boundary markers in this format.\n */\nexport function markdownToRuns(\n input: string,\n grammar: RunGrammar = MARKDOWN_RUN_GRAMMAR,\n): StyledRun[] {\n const chars = escapees(grammar);\n // Longest-first per delimiter, so `***` is tried before `**` before `*`.\n const byDelimiter = new Map<string, RunMarker[]>();\n for (const m of grammar.markers) {\n const list = byDelimiter.get(m.delimiter) ?? [];\n list.push(m);\n byDelimiter.set(m.delimiter, list);\n }\n for (const list of byDelimiter.values()) list.sort((a, b) => b.repeat - a.repeat);\n\n const runs: StyledRun[] = [];\n const active = new Set<RunFlag>();\n let buf = '';\n let i = 0;\n\n function flush(): void {\n if (buf.length === 0) return;\n const run: StyledRun = { text: buf };\n for (const f of active) run[f] = true;\n runs.push(run);\n buf = '';\n }\n\n while (i < input.length) {\n const ch = input[i];\n\n if (ch === '\\\\' && i + 1 < input.length && chars.has(input[i + 1])) {\n buf += input[i + 1];\n i += 2;\n continue;\n }\n\n const markers = byDelimiter.get(ch);\n if (markers) {\n let count = 0;\n while (i + count < input.length && input[i + count] === ch) count++;\n // The longest marker the delimiter run can pay for. A run shorter than\n // every marker still matches the shortest, which is how a lone `*`\n // toggles italic where `***` toggles both.\n const marker = markers.find((m) => m.repeat <= count) ?? markers[markers.length - 1];\n flush();\n for (const f of marker.flags) {\n if (active.has(f)) active.delete(f);\n else active.add(f);\n }\n i += marker.repeat;\n continue;\n }\n\n buf += ch;\n i++;\n }\n\n flush();\n return runs;\n}\n","/**\n * CSS `text-transform` over styled runs: `uppercase`, `lowercase` and\n * `capitalize`, with the source offsets each transformed character came from.\n *\n * Case mapping is not length-preserving — `'ß'.toUpperCase()` is `'SS'` — and\n * every caret, selection and hit-test in the kit addresses the *source* text.\n * So a transform that changes a code point's length reports a\n * {@link RunSourceMap} alongside the text, and layout reads each cell's source\n * span off it instead of counting the characters it drew.\n */\n\n/** The CSS `text-transform` keywords the run model carries. `none` is an\n * explicit override: a run can turn off a transform it would inherit. */\nexport type TextTransform = 'none' | 'uppercase' | 'lowercase' | 'capitalize';\n\n/**\n * Where each UTF-16 unit of a transformed run's text came from in its source,\n * as run-relative offsets. `starts[i]` / `ends[i]` bound the source code point\n * that produced output unit `i`, so the two units `ß` uppercases to share one\n * span. `length` is the source run's own length.\n */\nexport interface RunSourceMap {\n length: number;\n starts: readonly number[];\n ends: readonly number[];\n}\n\n/** A run's text after its transform. `srcMap` is present only when some code\n * point changed length — otherwise output offsets are source offsets. */\nexport interface TransformedRunText {\n text: string;\n srcMap?: RunSourceMap;\n}\n\n/** Title-case mappings that differ from the uppercase one (UnicodeData and\n * SpecialCasing). Everything absent titlecases as it uppercases. */\nconst TITLE: ReadonlyMap<number, string> = new Map<number, string>([\n [0x00df, 'Ss'],\n [0x01c4, 'Dž'], [0x01c5, 'Dž'], [0x01c6, 'Dž'],\n [0x01c7, 'Lj'], [0x01c8, 'Lj'], [0x01c9, 'Lj'],\n [0x01ca, 'Nj'], [0x01cb, 'Nj'], [0x01cc, 'Nj'],\n [0x01f1, 'Dz'], [0x01f2, 'Dz'], [0x01f3, 'Dz'],\n [0x0587, 'Եւ'],\n [0xfb00, 'Ff'], [0xfb01, 'Fi'], [0xfb02, 'Fl'], [0xfb03, 'Ffi'], [0xfb04, 'Ffl'],\n [0xfb05, 'St'], [0xfb06, 'St'],\n [0xfb13, 'Մն'], [0xfb14, 'Մե'], [0xfb15, 'Մի'],\n [0xfb16, 'Վն'], [0xfb17, 'Մխ'],\n [0x1fb3, 'ᾼ'], [0x1fbc, 'ᾼ'],\n [0x1fc3, 'ῌ'], [0x1fcc, 'ῌ'],\n [0x1ff3, 'ῼ'], [0x1ffc, 'ῼ'],\n [0x1fb2, 'Ὰͅ'], [0x1fb4, 'Άͅ'], [0x1fb7, 'ᾼ͂'],\n [0x1fc2, 'Ὴͅ'], [0x1fc4, 'Ήͅ'], [0x1fc7, 'ῌ͂'],\n [0x1ff2, 'Ὼͅ'], [0x1ff4, 'Ώͅ'], [0x1ff7, 'ῼ͂'],\n]);\n\nfunction titlecase(ch: string): string {\n const cp = ch.codePointAt(0)!;\n // Greek with ypogegrammeni: the titlecase form keeps the iota subscript,\n // where uppercase spells it out as a capital iota.\n if (cp >= 0x1f80 && cp <= 0x1faf) return String.fromCodePoint(cp | 0x8);\n return TITLE.get(cp) ?? ch.toUpperCase();\n}\n\nconst WORD_FALLBACK = /[\\p{L}\\p{N}][\\p{L}\\p{N}\\p{M}\\p{Pc}'’]*/gu;\n\n/** Source offsets at which a word begins, by the same UAX #29 word boundaries\n * browsers use for `capitalize`. */\nfunction wordStarts(text: string): Set<number> {\n const out = new Set<number>();\n if (typeof Intl !== 'undefined' && 'Segmenter' in Intl) {\n const seg = new Intl.Segmenter(undefined, { granularity: 'word' });\n for (const s of seg.segment(text)) if (s.isWordLike) out.add(s.index);\n return out;\n }\n for (const m of text.matchAll(WORD_FALLBACK)) out.add(m.index!);\n return out;\n}\n\n/** Whether mapping `full` per code point, run by run, produces exactly the\n * units `whole` does — true unless a mapping spans a run boundary. */\nfunction alignsPerCodePoint(\n texts: readonly string[], whole: string, map: (ch: string) => string,\n): boolean {\n let n = 0;\n for (const t of texts) for (const ch of t) n += map(ch).length;\n return n === whole.length;\n}\n\nconst upper = (ch: string): string => ch.toUpperCase();\nconst lower = (ch: string): string => ch.toLowerCase();\n\n/**\n * Apply each run's transform to its text. `texts[i]` is transformed by\n * `transforms[i]`; the runs are read as one paragraph, so final sigma and\n * `capitalize`'s word starts see across run boundaries — a word split by\n * styling still gets one capital.\n *\n * Mappings are the locale-independent ones JavaScript's `toUpperCase` /\n * `toLowerCase` implement, which include `ß` → `SS` and final sigma.\n * `capitalize` titlecases the first code point of each word when it has a\n * case to change, and leaves every other character as it was.\n */\nexport function transformRunTexts(\n texts: readonly string[],\n transforms: readonly TextTransform[],\n): TransformedRunText[] {\n if (transforms.every((t) => t === 'none')) return texts.map((text) => ({ text }));\n\n const full = texts.join('');\n // Lowercasing is contextual (final sigma), so the per-code-point pieces are\n // read out of the whole paragraph's mapping wherever the two align.\n const wholeUpper = transforms.includes('uppercase') ? full.toUpperCase() : '';\n const wholeLower = transforms.includes('lowercase') ? full.toLowerCase() : '';\n const upperAligned = wholeUpper !== '' && alignsPerCodePoint(texts, wholeUpper, upper);\n const lowerAligned = wholeLower !== '' && alignsPerCodePoint(texts, wholeLower, lower);\n const starts = transforms.includes('capitalize') ? wordStarts(full) : null;\n\n const out: TransformedRunText[] = [];\n let base = 0;\n let upOff = 0;\n let lowOff = 0;\n for (let i = 0; i < texts.length; i++) {\n const source = texts[i];\n const t = transforms[i] ?? 'none';\n let text = '';\n const srcStarts: number[] = [];\n const srcEnds: number[] = [];\n let resized = false;\n let local = 0;\n for (const ch of source) {\n const up = upper(ch);\n const lo = lower(ch);\n let piece = ch;\n if (t === 'uppercase') {\n piece = upperAligned ? wholeUpper.slice(upOff, upOff + up.length) : up;\n } else if (t === 'lowercase') {\n piece = lowerAligned ? wholeLower.slice(lowOff, lowOff + lo.length) : lo;\n } else if (t === 'capitalize' && starts!.has(base + local) && up !== ch) {\n piece = titlecase(ch);\n }\n upOff += up.length;\n lowOff += lo.length;\n if (piece.length !== ch.length) resized = true;\n text += piece;\n for (let k = 0; k < piece.length; k++) {\n srcStarts.push(local);\n srcEnds.push(local + ch.length);\n }\n local += ch.length;\n }\n out.push(resized\n ? { text, srcMap: { length: source.length, starts: srcStarts, ends: srcEnds } }\n : { text });\n base += source.length;\n }\n return out;\n}\n","/**\n * Apply node-level `ResolvedTextStyle` defaults to each `StyledRun`,\n * producing a fully-resolved run with every styling field set. Downstream\n * layout and draw never re-resolve defaults — `ResolvedRun` is the\n * canonical shape the renderer consumes.\n *\n * `bold`/`italic` toggles on a run are folded into `fontWeight`/`fontStyle`:\n * `bold: true` → fontWeight 700, `italic: true` → fontStyle 'italic'.\n * Explicit `fontFamily` / `fontSize` / `fill` / `letterSpacing` on the run\n * override the node-level value (`letterSpacing: 0` on a run is an override,\n * not an absence — it zeroes inherited tracking).\n *\n * `underline` / `strikethrough` / `overline` are *additive*, like\n * `bold`/`italic`: a run can turn a decoration on but never off, so they\n * resolve as `run.x || style.x` and not `run.x ?? style.x`. See the header of\n * `runs/rangeStyle.ts` for why the model collapses the tri-state.\n *\n * `script` is folded the same way the toggles are, into the two primitives it\n * is a preset over: `baselineShift` and `fontScale`. Both come out as one\n * world-unit `baselineShift` and a final `fontSize`, so layout never learns\n * that superscripts exist — it places a run against a baseline and an offset.\n *\n * `textTransform` is applied here too, so `text` is what gets drawn. When a\n * transform changes a length, `srcMap` says which source characters each\n * drawn one came from; see `textTransform.ts`.\n */\n\nimport type { FillStyle, Stroke } from '@weasel-js/paint';\nimport { resolveScreenLength } from '@weasel-js/paint';\nimport type { StyledRun } from '../runs';\nimport type { ResolvedTextStyle } from '../textStyle';\nimport { transformRunTexts, type RunSourceMap } from './textTransform';\n\n/** A run with every style resolved against the node's text style — no\n * optional inheritance left. This is what layout and painting consume. */\nexport interface ResolvedRun {\n /** The text as drawn — after `textTransform`, so not necessarily the\n * run's source text. */\n text: string;\n /** Present when `text` differs in length from the source it was\n * transformed from: where each of its UTF-16 units came from. Absent\n * means `text`'s offsets are the source's. */\n srcMap?: RunSourceMap;\n fontFamily: string;\n fontSize: number;\n fontWeight: number;\n fontStyle: 'normal' | 'italic';\n /** `null` is an explicit no-fill: the glyphs are painted by `stroke` alone,\n * which only the outline tier can do. Nothing is emitted for a run with\n * neither. */\n fill: FillStyle | null;\n /** Outline over this run's glyphs, or absent for none. Painted only on the\n * outline tier — a distance field has no geometry to stroke. */\n stroke?: Stroke;\n /** Extra advance added after each glyph of this run, in world units. */\n letterSpacing: number;\n /** Draw a rule below this run's baseline. Additive over the node style. */\n underline: boolean;\n /** Draw a rule through this run's x-height. Additive over the node style. */\n strikethrough: boolean;\n /** Draw a rule above this run's ascent. Additive over the node style. */\n overline: boolean;\n /**\n * How far this run sits off the line's shared baseline, in world units;\n * positive raises. 0 for ordinary text.\n *\n * Already multiplied out against the inherited font size, and already\n * carrying whatever `script` asked for — layout adds it to a baseline and\n * asks nothing about where it came from.\n */\n baselineShift: number;\n /**\n * The size this run holds its line open at, when a relative size shrank it\n * below the size it inherited — so a superscript alone on its line keeps the\n * line's height and baseline instead of collapsing them. Absent means\n * `fontSize`.\n */\n strutSize?: number;\n}\n\n/**\n * What `script: 'super'` and `script: 'sub'` expand to, as fractions of the\n * inherited font size: `size` scales it, `shift` raises (positive) or lowers\n * (negative) the baseline.\n *\n * These are Adobe's defaults — InDesign and Illustrator ship 58.3% size and\n * 33.3% position for both — chosen because a drawing tool's users have those\n * numbers in their fingers already. They are not read from the font: the\n * `OS/2` table carries real `ySuperscript*` / `ySubscript*` metrics, but the\n * baked atlas tier has no slot for them (see `layoutRuns`'s note on the\n * decoration constants, which are derived for the same reason), and metrics\n * that applied on one glyph tier and not the other would reflow text as it\n * crossed the size threshold.\n *\n * Exported so a consumer building a character panel can show the percentages\n * it is about to apply. Override either half per run with `baselineShift` /\n * `fontScale`.\n */\nexport const SCRIPT_METRICS: Readonly<\n Record<'super' | 'sub', Readonly<{ size: number; shift: number }>>\n> = Object.freeze({\n super: Object.freeze({ size: 0.583, shift: 0.333 }),\n sub: Object.freeze({ size: 0.583, shift: -0.333 }),\n});\n\nfunction numericWeight(w: number | string): number {\n if (typeof w === 'number') return w;\n if (w === 'bold') return 700;\n if (w === 'normal') return 400;\n const parsed = Number(w);\n return Number.isFinite(parsed) ? parsed : 400;\n}\n\n/** Resolve each run's styling against the node's text style, filling in\n * everything the run left inherited. `viewScale` resolves a run's own\n * `{ px }` size or spacing; the inherited ones arrived already resolved on\n * `style`. */\nexport function resolveRuns(\n runs: readonly StyledRun[],\n style: ResolvedTextStyle,\n viewScale = 1,\n): ResolvedRun[] {\n const out: ResolvedRun[] = [];\n const baseWeight = numericWeight(style.fontWeight);\n const shown = transformRunTexts(\n runs.map((r) => r.text),\n runs.map((r) => r.textTransform ?? style.textTransform),\n );\n for (let i = 0; i < runs.length; i++) {\n const run = runs[i];\n const { text, srcMap } = shown[i];\n const scriptKey = run.script ?? style.script;\n const script = scriptKey ? SCRIPT_METRICS[scriptKey] : undefined;\n // Against the inherited size, not the run's own: a superscript that also\n // shrank its rise would climb less the smaller it got.\n const shiftEm = run.baselineShift ?? script?.shift ?? 0;\n const scale = run.fontScale ?? script?.size ?? 1;\n const relative = run.fontSize === undefined && scale !== 1;\n out.push({\n text,\n ...(srcMap ? { srcMap } : {}),\n fontFamily: run.fontFamily ?? style.fontFamily,\n // An absolute size wins over a relative one; naming both is a consumer\n // saying \"this size exactly\", which a multiplier cannot improve on.\n fontSize: run.fontSize !== undefined\n ? resolveScreenLength(run.fontSize, viewScale)\n : style.fontSize * scale,\n fontWeight: run.bold ? 700 : baseWeight,\n fontStyle: run.italic ? 'italic' : style.fontStyle,\n fill: run.fill ?? style.fill,\n // Unlike the decorations below, a run's stroke *replaces* the node's\n // rather than adding to it — there is only one outline to paint.\n ...((run.stroke ?? style.stroke) !== undefined\n ? { stroke: run.stroke ?? style.stroke }\n : {}),\n letterSpacing: run.letterSpacing !== undefined\n ? resolveScreenLength(run.letterSpacing, viewScale)\n : style.letterSpacing,\n // `||`, not `??`: run-level decorations are additive over the node style.\n underline: run.underline || style.underline,\n strikethrough: run.strikethrough || style.strikethrough,\n overline: run.overline || style.overline,\n baselineShift: shiftEm * style.fontSize,\n ...(relative ? { strutSize: style.fontSize } : {}),\n });\n }\n return out;\n}\n","/**\n * Box vertical alignment for text draw commands. Given the command's box\n * `height` and the laid-out text block's height, returns the Y offset to\n * apply to every quad. `'top'` (or an undefined `align`, or a missing box\n * `height`) is the legacy behavior: offset 0.\n */\nexport type TextVerticalAlign = 'top' | 'center' | 'bottom';\n\n/** How far to shift laid-out text down inside a box of `boxHeight` to satisfy\n * a vertical alignment. Zero when the box height is unknown or alignment is\n * top. */\nexport function verticalAlignOffset(\n align: TextVerticalAlign | undefined,\n boxHeight: number | undefined,\n textHeight: number,\n): number {\n if (align === undefined || align === 'top' || boxHeight === undefined) return 0;\n const slack = boxHeight - textHeight;\n return align === 'center' ? slack / 2 : slack;\n}\n","/**\n * How a text pose lays out — the one decision every consumer of a text node\n * reads: the painters (`kit:text`, `createTextLayer`), picking\n * (`textLineBoxes`), the caret (`caretIndexAt`), fitting (`fitTextPose`) and\n * the DOM edit overlay.\n *\n * The pose width is always the box `align` resolves within. It is the wrap\n * width only when the style declares `wrap`; otherwise a line runs as long as\n * its text, whichever of them is asking.\n */\nimport type { LaidOutRuns, LayoutRunsOpts } from './layoutRuns';\nimport { cachedLayoutRuns } from './layoutCache';\nimport { resolveAlign, resolveTextStyle, type ResolvedTextStyle } from '../textStyle';\nimport { resolveRuns, type ResolvedRun } from '../runs/resolveRuns';\nimport { toRuns } from '../runs';\nimport { verticalAlignOffset } from '../measure/verticalAlign';\nimport type { TextPose } from '../pose';\n\n/** What {@link layoutTextPose} hands `cachedLayoutRuns`. */\nexport interface TextPoseLayoutInput {\n style: ResolvedTextStyle;\n runs: ResolvedRun[];\n opts: LayoutRunsOpts & { align: 'left' | 'center' | 'right' };\n}\n\n/**\n * The resolved runs and layout options for `pose`. A text draw command built\n * from these lays out, in the renderer, into exactly the lines\n * {@link layoutTextPose} reports.\n *\n * `scale` is the view scale a `{ px }` `fontSize` or `letterSpacing` resolves\n * against. Everything past this point is world units, so a caller that\n * measures, hit-tests or paints one pose has to pass the same scale to each\n * or they disagree.\n */\nexport function textPoseLayoutInput(pose: TextPose, scale = 1): TextPoseLayoutInput {\n const style = resolveTextStyle(pose.style, { fill: pose.fill, stroke: pose.stroke }, scale);\n // Empty runs are not a styling, so they fall back to the plain string\n // rather than lay out nothing.\n const source = pose.runs && pose.runs.length > 0 ? pose.runs : pose.text;\n return {\n style,\n runs: resolveRuns(toRuns(source), style, scale),\n opts: {\n maxWidth: style.wrap ? pose.width : Infinity,\n alignWidth: pose.width,\n lineHeight: style.lineHeight,\n align: resolveAlign(style.align, style.direction),\n },\n };\n}\n\n/** A text pose laid out. */\nexport interface TextPoseLayout {\n /** Origin-relative, shared with the layout cache — treat as immutable. */\n laid: LaidOutRuns;\n /** World position of the layout's origin: `pose.x`, and `pose.y` shifted by\n * `verticalAlign` within the pose height. */\n x: number;\n y: number;\n}\n\n/** The lines `pose` lays out into, and where they sit in world space. */\nexport function layoutTextPose(pose: TextPose, scale = 1): TextPoseLayout {\n const { runs, opts } = textPoseLayoutInput(pose, scale);\n const laid = cachedLayoutRuns(runs, opts);\n return {\n laid,\n x: pose.x,\n y: pose.y + verticalAlignOffset(pose.verticalAlign, pose.height, laid.bounds.height),\n };\n}\n","/**\n * Wrap-aware text measurement. Greedy word-wrap against `maxWidth` using\n * `ctx.measureText`. Lines explicitly broken by `\\n` are preserved; long\n * single words that exceed `maxWidth` are emitted on their own line without\n * mid-word breaking (caller can decide to clip).\n *\n * Returns the laid-out lines, the total block height in world units\n * (`lines.length * fontSize * lineHeight`), and per-line `lineStarts` —\n * the offset of each line's first character in the original `text`. The\n * starts are used by `caretIndexAt` to map a clicked (x, y) back to a\n * character offset in the source string. Trailing whitespace consumed by\n * the wrap is not included in `lines[i]` but is implicit in the gap\n * between `lineStarts[i] + lines[i].length` and `lineStarts[i + 1]`.\n *\n * The caller owns the `ctx.font` setup — pass a context whose `font`\n * already matches `style` (use `fontString(style)`).\n */\n\nimport type { ResolvedTextStyle } from '../textStyle';\n\n/**\n * Advance width of `text` in world units, tracking included.\n *\n * `letter-spacing` is not part of the CSS `font` shorthand, so a context\n * whose `font` was set from `fontString(style)` measures glyphs only. The\n * GL path (`layoutRuns`) adds `letterSpacing` after **every** code point\n * including the last, matching CSS, so this does too — and every 2D-side\n * width has to go through here or the two paths disagree about where a line\n * breaks.\n */\nexport function measuredWidth(\n ctx: CanvasRenderingContext2D,\n text: string,\n style: ResolvedTextStyle,\n): number {\n return ctx.measureText(text).width + text.length * style.letterSpacing;\n}\n\n/** Result of `measureText`: wrapped lines, per-line source offsets, and total block height. */\nexport interface MeasuredText {\n lines: string[];\n lineStarts: number[];\n height: number;\n}\n\n/** Greedy word-wrap text measurement against `maxWidth`; preserves explicit `\\n` breaks. */\nexport function measureText(\n ctx: CanvasRenderingContext2D,\n text: string,\n maxWidth: number,\n style: ResolvedTextStyle,\n): MeasuredText {\n const lines: string[] = [];\n const lineStarts: number[] = [];\n const paragraphs = text.split('\\n');\n\n let pos = 0;\n for (let pi = 0; pi < paragraphs.length; pi++) {\n if (pi > 0) pos += 1; // step past the '\\n' between paragraphs\n const paragraph = paragraphs[pi];\n if (paragraph === '') {\n lines.push('');\n lineStarts.push(pos);\n continue;\n }\n const words = paragraph.split(/(\\s+)/).filter((w) => w.length > 0);\n let current = '';\n let currentStart = pos;\n let consumed = 0; // chars of `paragraph` we've already accounted for\n for (const word of words) {\n if (current === '') currentStart = pos + consumed;\n const candidate = current + word;\n if (current === '' || measuredWidth(ctx, candidate, style) <= maxWidth) {\n current = candidate;\n } else {\n lines.push(current.trimEnd());\n lineStarts.push(currentStart);\n if (/^\\s+$/.test(word)) {\n current = '';\n } else {\n current = word;\n currentStart = pos + consumed;\n }\n }\n consumed += word.length;\n }\n lines.push(current.trimEnd());\n lineStarts.push(currentStart);\n pos += paragraph.length;\n }\n\n const height = lines.length * style.fontSize * style.lineHeight;\n return { lines, lineStarts, height };\n}\n","import type { TextStyle } from '../textStyle';\nimport { resolveTextStyle } from '../textStyle';\nimport { resolveRuns } from '../runs/resolveRuns';\nimport { cachedLayoutRuns } from '../layout/layoutCache';\n\n/** Options for `measureTextBounds`. */\nexport interface MeasureTextBoundsOpts {\n /** Wrap width; words exceeding it start a new line. Default `Infinity` (no wrap). */\n maxWidth?: number;\n /** Overrides `style`'s `lineHeight` multiplier for this measurement. */\n lineHeight?: number;\n /** View scale any `{ px }` size in `style` resolves against. Default 1,\n * which measures a `{ px }` size as that many world units. */\n scale?: number;\n}\n\n/**\n * Measure how the GL/MSDF renderer will lay out a single plain-text string,\n * using the registered font atlas metrics. Mirrors {@link textCommand} exactly\n * (`resolveTextStyle` → `resolveRuns` → `cachedLayoutRuns`), so the returned\n * bounds match what actually gets drawn — use it to size backgrounds/pills, place\n * labels, or test overlap without guessing widths.\n *\n * Pass `opts.maxWidth` to measure word-wrapped height (e.g. for a fixed-width\n * text box); omitting it measures the unwrapped single-line width. `opts.lineHeight`\n * overrides the style's multiplier without changing `style` itself.\n *\n * Returns `{ width, height }` in the same units as `style.fontSize`. The font\n * must already be registered via `registerFont`; an unregistered family falls\n * back to the atlas fallback glyph (and warns), so register fonts at app boot\n * before measuring.\n */\nexport function measureTextBounds(\n text: string,\n style?: TextStyle,\n opts?: MeasureTextBoundsOpts,\n): { width: number; height: number } {\n const resolved = resolveTextStyle(style, undefined, opts?.scale);\n const runs = resolveRuns([{ text }], resolved, opts?.scale);\n const { bounds } = cachedLayoutRuns(runs, {\n maxWidth: opts?.maxWidth ?? Infinity,\n lineHeight: opts?.lineHeight ?? resolved.lineHeight,\n align: resolved.align,\n });\n // Copied: the layout behind it is shared, and handing a caller a mutable\n // reference into a cache entry is how one measurement corrupts the next.\n return { width: bounds.width, height: bounds.height };\n}\n","/**\n * Where a text node's lines actually sit inside its pose box.\n *\n * A text pose is a layout box, not a bounding box: `\"Away\"` in a 309-unit-wide\n * box leaves most of the box empty, and anything that treats the pose as the\n * node's extent — picking, lasso, clipping, SVG export — claims that empty\n * space. `textLineBoxes` returns the per-line rectangles instead.\n *\n * The numbers come from `layoutTextPose`, the layout every painter of a text\n * pose draws, so the boxes cannot drift from what is painted — they wrap only\n * where the style declares `wrap`, and honor `align` and `verticalAlign`.\n *\n * These are line boxes, not ink boxes: each is `fontSize * lineHeight` tall\n * from the pen's line top. Ink can escape vertically at a `lineHeight` low\n * enough — see the `bounds` note at the end of `layoutRuns` — which is the\n * right trade for hit-testing, where a box that hugged the ink would make\n * an `x` harder to click than an `X`.\n */\n\nimport type { Rect } from '@weasel-js/geom';\nimport { layoutTextPose } from '../layout/textPoseLayout';\nimport type { TextPose } from '../pose';\n\n/** Options for {@link textLineBoxes}. */\nexport interface TextLineBoxesOpts {\n /** Grow every box by this much on all four sides (world units). Default 0.\n * Picking wants a little slack so a single hairline row of text is still\n * grabbable; clipping and export want none. */\n padding?: number;\n /** Keep boxes for blank lines (zero width). Default `false` — a blank line\n * covers no area, so for hit-testing and silhouettes it is noise. Pass\n * `true` when the indices have to line up with the laid-out lines. */\n includeEmpty?: boolean;\n}\n\n/** Per-line rectangles for a text pose, in world units, in layout order. */\nexport function textLineBoxes(pose: TextPose, opts: TextLineBoxesOpts = {}): Rect[] {\n const padding = opts.padding ?? 0;\n const { laid, x: dx, y: dy } = layoutTextPose(pose);\n\n const out: Rect[] = [];\n for (const line of laid.lines) {\n if (!opts.includeEmpty && line.x1 <= line.x0) continue;\n out.push({\n x: line.x0 + dx - padding,\n y: line.y0 + dy - padding,\n width: line.x1 - line.x0 + padding * 2,\n height: line.y1 - line.y0 + padding * 2,\n });\n }\n return out;\n}\n","import { resolveScreenLength } from '@weasel-js/paint';\nimport { markdownToRuns, type StyledRun } from './runs';\nimport { SCRIPT_METRICS } from './runs/resolveRuns';\nimport { DECORATION_KINDS, decorationRule, type DecorationKind } from './layout/decorationMetrics';\nimport { transformRunTexts } from './runs/textTransform';\n\nexport type { StyledRun };\n\n/** Width-measurement strategy for `layoutMarkdown`; canvas-backed default supplied by `createMarkdownRenderer`. */\nexport type MeasureFn = (text: string, fontSize: number, bold: boolean, italic: boolean) => number;\n\n/** A `StyledRun` with its resolved size and its position relative to the\n * start of its line: `x` along the line, `y` off its baseline. */\nexport interface PositionedRun extends StyledRun {\n x: number;\n /** Advance width, as the layout's `MeasureFn` measured it. */\n width: number;\n /** Baseline offset, positive down — a superscript's is negative. Add it to\n * the line's baseline when painting. */\n y: number;\n /** The run's font size in px, with `fontScale` and `script` already folded\n * in. Resolved once here so layout and paint cannot disagree about it. */\n size: number;\n}\n\n/**\n * A run's size and baseline offset, resolved the way `resolveRuns` resolves\n * them for the GL path: an absolute `fontSize` wins over a multiplier, and\n * the rise is measured against the *inherited* size so it does not shrink\n * along with the run.\n */\nfunction runMetrics(run: StyledRun, fontSize: number): { size: number; y: number } {\n const script = run.script ? SCRIPT_METRICS[run.script] : undefined;\n const scale = run.fontScale ?? script?.size ?? 1;\n const shiftEm = run.baselineShift ?? script?.shift ?? 0;\n return {\n size: run.fontSize !== undefined\n ? resolveScreenLength(run.fontSize, 1)\n : fontSize * scale,\n // Canvas y grows downward; a positive shift is a rise. Guarded so an\n // unshifted run reports 0 rather than -0.\n y: shiftEm === 0 ? 0 : -shiftEm * fontSize,\n };\n}\n\n/** A single laid-out line of text: its positioned runs, total width, and computed line height. */\nexport interface LayoutLine {\n runs: PositionedRun[];\n width: number;\n height: number;\n}\n\n/** Output of `layoutMarkdown`: per-line breakdown plus overall block dimensions. */\nexport interface LayoutResult {\n lines: LayoutLine[];\n width: number;\n height: number;\n}\n\n/** Word-wrap parsed runs into lines bounded by `maxWidth`; pass `Infinity` for single-line layout. */\nexport function layoutMarkdown(\n runs: StyledRun[],\n maxWidth: number,\n fontSize: number,\n measure: MeasureFn,\n lineHeightFactor: number = 1.3,\n): LayoutResult {\n if (runs.length === 0) return { lines: [], width: 0, height: 0 };\n // No caret reads this layout, so the transformed text simply replaces the source.\n const shown = transformRunTexts(runs.map((r) => r.text), runs.map((r) => r.textTransform ?? 'none'));\n runs = runs.map((r, i) => (shown[i].text === r.text ? r : { ...r, text: shown[i].text }));\n\n const lines: LayoutLine[] = [];\n let currentRuns: PositionedRun[] = [];\n let lineX = 0;\n let lineMaxSize = 0;\n\n function commitLine() {\n const effectiveFontSize = lineMaxSize > 0 ? lineMaxSize : fontSize;\n const lineHeight = effectiveFontSize * lineHeightFactor;\n lines.push({ runs: currentRuns, width: lineX, height: lineHeight });\n currentRuns = [];\n lineX = 0;\n lineMaxSize = 0;\n }\n\n function processSegment(segRun: StyledRun) {\n // Already a screen-pixel layout, so a run's `{ px }` size is its size.\n const { size: effectiveSize, y: runY } = runMetrics(segRun, fontSize);\n lineMaxSize = Math.max(lineMaxSize, effectiveSize);\n\n if (maxWidth === Infinity) {\n const w = measure(segRun.text, effectiveSize, segRun.bold ?? false, segRun.italic ?? false);\n currentRuns.push({ ...segRun, x: lineX, width: w, y: runY, size: effectiveSize });\n lineX += w;\n return;\n }\n\n // Word-wrap: split run text by spaces\n const words = segRun.text.split(/ /);\n let wordBuf = '';\n\n for (let wi = 0; wi < words.length; wi++) {\n const word = words[wi];\n const candidate = wordBuf.length > 0 ? wordBuf + ' ' + word : word;\n const candidateW = measure(candidate, effectiveSize, segRun.bold ?? false, segRun.italic ?? false);\n\n if (lineX + candidateW > maxWidth && (lineX > 0 || wordBuf.length > 0)) {\n // Flush current wordBuf as a run on the current line\n if (wordBuf.length > 0) {\n const w = measure(wordBuf, effectiveSize, segRun.bold ?? false, segRun.italic ?? false);\n currentRuns.push({ ...segRun, text: wordBuf, x: lineX, width: w, y: runY, size: effectiveSize });\n lineX += w;\n }\n commitLine();\n lineMaxSize = Math.max(lineMaxSize, effectiveSize);\n wordBuf = word;\n } else {\n // Either fits, or is an oversized single word starting a fresh line — accept it\n wordBuf = candidate;\n }\n }\n\n // Flush remaining wordBuf\n if (wordBuf.length > 0) {\n const w = measure(wordBuf, effectiveSize, segRun.bold ?? false, segRun.italic ?? false);\n currentRuns.push({ ...segRun, text: wordBuf, x: lineX, width: w, y: runY, size: effectiveSize });\n lineX += w;\n }\n }\n\n for (const run of runs) {\n // markdownToRuns embeds newlines inside runs; split on '\\n' so each\n // segment becomes its own line via commitLine().\n const segments = run.text.split('\\n');\n for (let si = 0; si < segments.length; si++) {\n if (si > 0) commitLine();\n const seg = segments[si];\n if (seg.length > 0) {\n processSegment({ ...run, text: seg });\n }\n }\n }\n\n // Commit final line\n if (currentRuns.length > 0) {\n commitLine();\n }\n\n const width = Math.max(...lines.map((l) => l.width));\n const height = lines.reduce((sum, l) => sum + l.height, 0);\n return { lines, width, height };\n}\n\n/** Pluggable text-painting strategy. The default fills white at `(x, y)`; markdown renderers replace this. */\nexport type TextRenderer = (\n ctx: CanvasRenderingContext2D,\n text: string,\n x: number,\n y: number,\n) => void;\n\n/** Font styling options threaded through `createMarkdownRenderer`. */\nexport interface MarkdownFontOptions {\n /** Font-family spec (e.g. `'\"Iowan Old Style\", Georgia, serif'`). Defaults to `sans-serif`. */\n family?: string;\n /** Numeric weight applied to non-bold runs. Bold runs always use `bold`. Default `normal`. */\n weight?: string | number;\n /** Override fill color. When set, used for all runs (italic and bold). */\n color?: string;\n /** Multiplier applied to font size for line height. Default 1.3. */\n lineHeight?: number;\n}\n\nfunction buildFont(\n fontSize: number,\n bold: boolean,\n italic: boolean,\n opts: MarkdownFontOptions = {},\n): string {\n const family = opts.family ?? 'sans-serif';\n const weight = bold ? 'bold' : (opts.weight !== undefined ? String(opts.weight) : 'normal');\n const parts: string[] = [];\n if (italic) parts.push('italic');\n parts.push(weight);\n parts.push(`${fontSize}px ${family}`);\n return parts.join(' ');\n}\n\nfunction canvasMeasure(ctx: CanvasRenderingContext2D, opts: MarkdownFontOptions = {}): MeasureFn {\n return (text, fontSize, bold, italic) => {\n ctx.font = buildFont(fontSize, bold, italic, opts);\n return ctx.measureText(text).width;\n };\n}\n\n/** Distance from the context's current `textBaseline` down to the alphabetic\n * baseline, for the font already set on it; 0 where the metric is missing. */\nfunction alphabeticBaselineBelow(ctx: CanvasRenderingContext2D): number {\n const current = ctx.textBaseline;\n if (current === 'alphabetic') return 0;\n const here = ctx.measureText('').fontBoundingBoxAscent;\n ctx.textBaseline = 'alphabetic';\n const alphabetic = ctx.measureText('').fontBoundingBoxAscent;\n ctx.textBaseline = current;\n const d = alphabetic - here;\n return Number.isFinite(d) ? d : 0;\n}\n\n/** Where a block `width` wide starts, given the x the context aligns it to. */\nfunction blockLeft(ctx: CanvasRenderingContext2D, x: number, width: number): number {\n const rtl = ctx.direction === 'rtl';\n switch (ctx.textAlign) {\n case 'center': return x - width / 2;\n case 'right': return x - width;\n case 'end': return rtl ? x : x - width;\n case 'start': return rtl ? x - width : x;\n default: return x;\n }\n}\n\n/**\n * Build a fill+stroke `TextRenderer` pair, laying the text out once.\n *\n * `text` is markdown, read by `markdownToRuns`, or runs already styled. The\n * block is placed by the context's `textAlign` and each run by its\n * `textBaseline`. The fill pass also paints underline, strikethrough and\n * overline in their run's fill, placed by the same metrics as the GL tier;\n * the stroke pass paints no rules, as on the GL tier.\n */\nexport function createMarkdownRenderer(\n ctx: CanvasRenderingContext2D,\n text: string | StyledRun[],\n fontSize: number,\n maxWidth: number = Infinity,\n fontOpts: MarkdownFontOptions = {},\n): { renderer: TextRenderer; strokeRenderer: TextRenderer; width: number; height: number } {\n const measure = canvasMeasure(ctx, fontOpts);\n const parsed = typeof text === 'string' ? markdownToRuns(text) : text;\n const layout = layoutMarkdown(parsed, maxWidth, fontSize, measure, fontOpts.lineHeight);\n\n /** Walk the layout, setting each run's font and handing over its\n * left-aligned paint position and the index of its line. */\n function walk(\n c: CanvasRenderingContext2D,\n x: number,\n y: number,\n drawRun: (run: PositionedRun, rx: number, ry: number, lineIndex: number) => void,\n ): void {\n const align = c.textAlign;\n const left = blockLeft(c, x, layout.width);\n c.textAlign = 'left';\n let lineY = y;\n layout.lines.forEach((line, li) => {\n const lineLeft = left + (layout.width - line.width) / 2;\n for (const run of line.runs) {\n c.font = buildFont(run.size, run.bold ?? false, run.italic ?? false, fontOpts);\n drawRun(run, lineLeft + run.x, lineY + run.y, li);\n }\n lineY += line.height;\n });\n c.textAlign = align;\n }\n\n const renderer: TextRenderer = (_ctx, _text, x, y) => {\n interface Span {\n flags: Record<DecorationKind, boolean>;\n fill: string;\n size: number;\n baselineY: number;\n line: number;\n x0: number;\n x1: number;\n }\n let span: Span | null = null;\n const flush = (): void => {\n const s = span;\n span = null;\n if (!s || s.x1 <= s.x0) return;\n _ctx.fillStyle = s.fill;\n for (const kind of DECORATION_KINDS) {\n if (!s.flags[kind]) continue;\n const { y0, y1 } = decorationRule(kind, s.baselineY, s.size);\n _ctx.fillRect(s.x0, y0, s.x1 - s.x0, y1 - y0);\n }\n };\n\n walk(_ctx, x, y, (run, rx, ry, line) => {\n const fill = fontOpts.color\n ?? (run.italic && !run.bold ? 'rgba(255, 255, 255, 0.7)' : '#FFFFFF');\n _ctx.fillStyle = fill;\n _ctx.fillText(run.text, rx, ry);\n\n if (!(run.underline || run.strikethrough || run.overline)) {\n flush();\n return;\n }\n const flags: Record<DecorationKind, boolean> = {\n underline: run.underline ?? false,\n strikethrough: run.strikethrough ?? false,\n overline: run.overline ?? false,\n };\n const baselineY = ry + alphabeticBaselineBelow(_ctx);\n const open = span;\n if (\n open !== null\n && open.line === line\n && open.x1 === rx\n && open.fill === fill\n && open.size === run.size\n && open.baselineY === baselineY\n && DECORATION_KINDS.every((k) => open.flags[k] === flags[k])\n ) {\n open.x1 = rx + run.width;\n } else {\n flush();\n span = { flags, fill, size: run.size, baselineY, line, x0: rx, x1: rx + run.width };\n }\n });\n flush();\n };\n\n const strokeRenderer: TextRenderer = (_ctx, _text, x, y) => {\n walk(_ctx, x, y, (run, rx, ry) => _ctx.strokeText(run.text, rx, ry));\n };\n\n return { renderer, strokeRenderer, width: layout.width, height: layout.height };\n}\n"]}
1
+ {"version":3,"sources":["../src/runs.ts","../src/runs/textTransform.ts","../src/runs/smallCaps.ts","../src/runs/resolveRuns.ts","../src/measure/verticalAlign.ts","../src/layout/textPoseLayout.ts","../src/measure/measureText.ts","../src/measure/measureTextBounds.ts","../src/measure/lineBoxes.ts","../src/markdownText.ts"],"names":["faceMetricsOf","resolveFontVariant","resolveScreenLength","width"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Canonical inline-styling primitive for text nodes. A node's text is\n * either a plain `string` (treated as a single-run, default-styled fragment)\n * or `StyledRun[]` for rich content. `toRuns` is the funnel that normalizes\n * either form into the array shape used by the renderer.\n *\n * Every field except `text` is optional; missing fields fall back to the\n * node-level `TextStyle`. `bold`/`italic` are toggles; `fontWeight` is the\n * numeric weight `bold` is a preset over.\n */\n\nimport type { FillStyle, ScreenLength, Stroke } from '@weasel-js/paint';\nimport type { TextTransform } from './runs/textTransform';\nimport type { FontVariantCaps } from './runs/smallCaps';\n\n/** A span of text with its own styling, as authored. Fields left absent\n * inherit from the node's text style — this is the difference between a run\n * and a fully resolved one. */\nexport interface StyledRun {\n text: string;\n /** Draw at weight 700. A preset over `fontWeight`, which wins when both\n * are present. */\n bold?: boolean;\n /** Numeric weight, 100–900. Overrides the node's weight and `bold`. */\n fontWeight?: number;\n italic?: boolean;\n fontFamily?: string;\n /** World units, or `{ px }` for screen pixels — resolved against the view\n * scale `resolveRuns` is given, like `TextStyle.fontSize`. */\n fontSize?: ScreenLength;\n fill?: FillStyle;\n /** Outline over this run's glyphs. Overrides the node's own `data.stroke`;\n * absent inherits it. Only painted on the outline tier. */\n stroke?: Stroke;\n /** World units, or `{ px }` for screen pixels. */\n letterSpacing?: ScreenLength;\n underline?: boolean;\n strikethrough?: boolean;\n /** Draw a rule above this run's ascent. Additive over the node style. */\n overline?: boolean;\n /**\n * Set this run as a superscript or subscript — a raised or lowered baseline\n * and a smaller size together, which is the pair `<sup>` and `<sub>` imply.\n *\n * A preset over the two primitives below, not a third mechanism: it supplies\n * a `baselineShift` and a `fontScale`, and naming either of those directly\n * overrides that half while leaving the other alone. The numbers are the\n * face's own `OS/2` script metrics, or {@link SCRIPT_METRICS} for a face\n * that states none — `scriptMetricsFor` answers which.\n */\n script?: 'super' | 'sub';\n /**\n * Raise (positive) or lower (negative) this run off the line's shared\n * baseline, in ems of the *inherited* font size — so a run's rise does not\n * shrink along with the run when `fontScale` also applies.\n */\n baselineShift?: number;\n /**\n * Multiplier on the inherited font size. The relative counterpart to\n * `fontSize`, which pins an absolute size and wins over this when both are\n * present.\n */\n fontScale?: number;\n /**\n * CSS `text-transform` for this run's display. The run's `text` stays as\n * authored — carets, selections and edits address it — and only what is\n * drawn changes. Overrides the node's own; `'none'` turns an inherited one\n * off.\n */\n textTransform?: TextTransform;\n /**\n * `'small-caps'` draws this run's lowercase letters as capitals at a\n * smaller size — synthesized, at the face's x-height over its cap height.\n * Like `textTransform`, only what is drawn changes. Overrides the node's\n * own; `'normal'` turns an inherited one off.\n */\n fontVariantCaps?: FontVariantCaps;\n}\n\n/** Normalize the two accepted spellings of text content — a plain string or\n * an array of runs — to runs. Throws on a run with no string `text`. */\nexport function toRuns(input: string | StyledRun[]): StyledRun[] {\n if (typeof input === 'string') {\n return input.length === 0 ? [] : [{ text: input }];\n }\n for (let i = 0; i < input.length; i++) {\n const r = input[i];\n if (typeof r?.text !== 'string') {\n throw new Error(`toRuns: run at index ${i} is missing string \\`text\\``);\n }\n }\n return input;\n}\n\n/** Concatenate runs, dropping all styling. */\nexport function runsToPlainText(runs: readonly StyledRun[]): string {\n let out = '';\n for (const r of runs) out += r.text;\n return out;\n}\n\n/** A run flag an inline marker can toggle. The additive style toggles on\n * `StyledRun`; the valued fields (family, size, paint, `script`) have no\n * inline spelling and are not addressable this way. */\nexport type RunFlag = 'bold' | 'italic' | 'underline' | 'strikethrough' | 'overline';\n\n/** One inline marker: a delimiter repeated `repeat` times, and the flags it\n * turns on between its opening and closing occurrence. */\nexport interface RunMarker {\n delimiter: string;\n repeat: number;\n flags: readonly RunFlag[];\n}\n\n/**\n * The inline grammar `runsToMarkdown` writes and `markdownToRuns` reads.\n *\n * Markers sharing a delimiter are matched longest-first, which is what lets\n * `***` mean something other than `**` followed by `*`. A backslash escapes\n * any delimiter character and itself, in both directions.\n */\nexport interface RunGrammar {\n markers: readonly RunMarker[];\n}\n\n/**\n * The markdown subset the kit reads and writes: `**bold**`, `*italic*`,\n * `***both***`.\n *\n * Deliberately not the whole of markdown, and deliberately silent on\n * `underline` / `strikethrough` — the two run flags with no entry here are\n * dropped by `runsToMarkdown`, as they always have been. A grammar that wants\n * `~~struck~~` adds one marker; nothing else has to change.\n */\nexport const MARKDOWN_RUN_GRAMMAR: RunGrammar = {\n markers: [\n { delimiter: '*', repeat: 3, flags: ['bold', 'italic'] },\n { delimiter: '*', repeat: 2, flags: ['bold'] },\n { delimiter: '*', repeat: 1, flags: ['italic'] },\n ],\n};\n\n/** Delimiter characters of a grammar, plus the backslash that escapes them. */\nfunction escapees(grammar: RunGrammar): Set<string> {\n const out = new Set<string>(['\\\\']);\n for (const m of grammar.markers) out.add(m.delimiter);\n return out;\n}\n\nfunction escapeFor(text: string, chars: ReadonlySet<string>): string {\n let out = '';\n for (const ch of text) out += chars.has(ch) ? `\\\\${ch}` : ch;\n return out;\n}\n\n/** The flags a run turns on, in the grammar's own marker order so two runs\n * with the same flags always serialize identically. */\nfunction flagsOf(run: StyledRun, grammar: RunGrammar): Set<RunFlag> {\n const on = new Set<RunFlag>();\n for (const m of grammar.markers) {\n for (const f of m.flags) if (run[f]) on.add(f);\n }\n return on;\n}\n\nfunction sameFlags(a: ReadonlySet<RunFlag>, b: readonly RunFlag[]): boolean {\n return a.size === b.length && b.every((f) => a.has(f));\n}\n\n/**\n * Render runs in `grammar`, defaulting to the markdown subset. The flavor\n * written to the clipboard alongside the plain-text one.\n *\n * A run whose flags exactly match one marker takes it; otherwise the markers\n * that cover them nest. Flags no marker spells are dropped — the text still\n * round-trips, without that styling.\n */\nexport function runsToMarkdown(\n runs: readonly StyledRun[],\n grammar: RunGrammar = MARKDOWN_RUN_GRAMMAR,\n): string {\n const chars = escapees(grammar);\n let out = '';\n for (const r of runs) {\n const escaped = escapeFor(r.text, chars);\n const on = flagsOf(r, grammar);\n if (on.size === 0) { out += escaped; continue; }\n\n const exact = grammar.markers.find((m) => sameFlags(on, m.flags));\n if (exact) {\n const d = exact.delimiter.repeat(exact.repeat);\n out += `${d}${escaped}${d}`;\n continue;\n }\n // No single marker says all of it: nest the ones that each say part.\n const covering = grammar.markers.filter(\n (m) => m.flags.length === 1 && on.has(m.flags[0]),\n );\n const open = covering.map((m) => m.delimiter.repeat(m.repeat)).join('');\n const close = [...covering].reverse().map((m) => m.delimiter.repeat(m.repeat)).join('');\n out += `${open}${escaped}${close}`;\n }\n return out;\n}\n\n/**\n * Parse `input` in `grammar`, defaulting to the markdown subset, into styled\n * runs. Newlines are preserved as literal characters inside a run — they are\n * not run-boundary markers in this format.\n */\nexport function markdownToRuns(\n input: string,\n grammar: RunGrammar = MARKDOWN_RUN_GRAMMAR,\n): StyledRun[] {\n const chars = escapees(grammar);\n // Longest-first per delimiter, so `***` is tried before `**` before `*`.\n const byDelimiter = new Map<string, RunMarker[]>();\n for (const m of grammar.markers) {\n const list = byDelimiter.get(m.delimiter) ?? [];\n list.push(m);\n byDelimiter.set(m.delimiter, list);\n }\n for (const list of byDelimiter.values()) list.sort((a, b) => b.repeat - a.repeat);\n\n const runs: StyledRun[] = [];\n const active = new Set<RunFlag>();\n let buf = '';\n let i = 0;\n\n function flush(): void {\n if (buf.length === 0) return;\n const run: StyledRun = { text: buf };\n for (const f of active) run[f] = true;\n runs.push(run);\n buf = '';\n }\n\n while (i < input.length) {\n const ch = input[i];\n\n if (ch === '\\\\' && i + 1 < input.length && chars.has(input[i + 1])) {\n buf += input[i + 1];\n i += 2;\n continue;\n }\n\n const markers = byDelimiter.get(ch);\n if (markers) {\n let count = 0;\n while (i + count < input.length && input[i + count] === ch) count++;\n // The longest marker the delimiter run can pay for. A run shorter than\n // every marker still matches the shortest, which is how a lone `*`\n // toggles italic where `***` toggles both.\n const marker = markers.find((m) => m.repeat <= count) ?? markers[markers.length - 1];\n flush();\n for (const f of marker.flags) {\n if (active.has(f)) active.delete(f);\n else active.add(f);\n }\n i += marker.repeat;\n continue;\n }\n\n buf += ch;\n i++;\n }\n\n flush();\n return runs;\n}\n","/**\n * CSS `text-transform` over styled runs: `uppercase`, `lowercase` and\n * `capitalize`, with the source offsets each transformed character came from.\n *\n * Case mapping is not length-preserving — `'ß'.toUpperCase()` is `'SS'` — and\n * every caret, selection and hit-test in the kit addresses the *source* text.\n * So a transform that changes a code point's length reports a\n * {@link RunSourceMap} alongside the text, and layout reads each cell's source\n * span off it instead of counting the characters it drew.\n */\n\n/** The CSS `text-transform` keywords the run model carries. `none` is an\n * explicit override: a run can turn off a transform it would inherit. */\nexport type TextTransform = 'none' | 'uppercase' | 'lowercase' | 'capitalize';\n\n/**\n * Where each UTF-16 unit of a transformed run's text came from in its source,\n * as run-relative offsets. `starts[i]` / `ends[i]` bound the source code point\n * that produced output unit `i`, so the two units `ß` uppercases to share one\n * span. `length` is the source run's own length.\n */\nexport interface RunSourceMap {\n length: number;\n starts: readonly number[];\n ends: readonly number[];\n}\n\n/** A run's text after its transform. `srcMap` is present only when some code\n * point changed length — otherwise output offsets are source offsets. */\nexport interface TransformedRunText {\n text: string;\n srcMap?: RunSourceMap;\n}\n\n/** Title-case mappings that differ from the uppercase one (UnicodeData and\n * SpecialCasing). Everything absent titlecases as it uppercases. */\nconst TITLE: ReadonlyMap<number, string> = new Map<number, string>([\n [0x00df, 'Ss'],\n [0x01c4, 'Dž'], [0x01c5, 'Dž'], [0x01c6, 'Dž'],\n [0x01c7, 'Lj'], [0x01c8, 'Lj'], [0x01c9, 'Lj'],\n [0x01ca, 'Nj'], [0x01cb, 'Nj'], [0x01cc, 'Nj'],\n [0x01f1, 'Dz'], [0x01f2, 'Dz'], [0x01f3, 'Dz'],\n [0x0587, 'Եւ'],\n [0xfb00, 'Ff'], [0xfb01, 'Fi'], [0xfb02, 'Fl'], [0xfb03, 'Ffi'], [0xfb04, 'Ffl'],\n [0xfb05, 'St'], [0xfb06, 'St'],\n [0xfb13, 'Մն'], [0xfb14, 'Մե'], [0xfb15, 'Մի'],\n [0xfb16, 'Վն'], [0xfb17, 'Մխ'],\n [0x1fb3, 'ᾼ'], [0x1fbc, 'ᾼ'],\n [0x1fc3, 'ῌ'], [0x1fcc, 'ῌ'],\n [0x1ff3, 'ῼ'], [0x1ffc, 'ῼ'],\n [0x1fb2, 'Ὰͅ'], [0x1fb4, 'Άͅ'], [0x1fb7, 'ᾼ͂'],\n [0x1fc2, 'Ὴͅ'], [0x1fc4, 'Ήͅ'], [0x1fc7, 'ῌ͂'],\n [0x1ff2, 'Ὼͅ'], [0x1ff4, 'Ώͅ'], [0x1ff7, 'ῼ͂'],\n]);\n\nfunction titlecase(ch: string): string {\n const cp = ch.codePointAt(0)!;\n // Greek with ypogegrammeni: the titlecase form keeps the iota subscript,\n // where uppercase spells it out as a capital iota.\n if (cp >= 0x1f80 && cp <= 0x1faf) return String.fromCodePoint(cp | 0x8);\n return TITLE.get(cp) ?? ch.toUpperCase();\n}\n\nconst WORD_FALLBACK = /[\\p{L}\\p{N}][\\p{L}\\p{N}\\p{M}\\p{Pc}'’]*/gu;\n\n/** Source offsets at which a word begins, by the same UAX #29 word boundaries\n * browsers use for `capitalize`. */\nfunction wordStarts(text: string): Set<number> {\n const out = new Set<number>();\n if (typeof Intl !== 'undefined' && 'Segmenter' in Intl) {\n const seg = new Intl.Segmenter(undefined, { granularity: 'word' });\n for (const s of seg.segment(text)) if (s.isWordLike) out.add(s.index);\n return out;\n }\n for (const m of text.matchAll(WORD_FALLBACK)) out.add(m.index!);\n return out;\n}\n\n/** Whether mapping `full` per code point, run by run, produces exactly the\n * units `whole` does — true unless a mapping spans a run boundary. */\nfunction alignsPerCodePoint(\n texts: readonly string[], whole: string, map: (ch: string) => string,\n): boolean {\n let n = 0;\n for (const t of texts) for (const ch of t) n += map(ch).length;\n return n === whole.length;\n}\n\nconst upper = (ch: string): string => ch.toUpperCase();\nconst lower = (ch: string): string => ch.toLowerCase();\n\n/**\n * Apply each run's transform to its text. `texts[i]` is transformed by\n * `transforms[i]`; the runs are read as one paragraph, so final sigma and\n * `capitalize`'s word starts see across run boundaries — a word split by\n * styling still gets one capital.\n *\n * Mappings are the locale-independent ones JavaScript's `toUpperCase` /\n * `toLowerCase` implement, which include `ß` → `SS` and final sigma.\n * `capitalize` titlecases the first code point of each word when it has a\n * case to change, and leaves every other character as it was.\n */\nexport function transformRunTexts(\n texts: readonly string[],\n transforms: readonly TextTransform[],\n): TransformedRunText[] {\n if (transforms.every((t) => t === 'none')) return texts.map((text) => ({ text }));\n\n const full = texts.join('');\n // Lowercasing is contextual (final sigma), so the per-code-point pieces are\n // read out of the whole paragraph's mapping wherever the two align.\n const wholeUpper = transforms.includes('uppercase') ? full.toUpperCase() : '';\n const wholeLower = transforms.includes('lowercase') ? full.toLowerCase() : '';\n const upperAligned = wholeUpper !== '' && alignsPerCodePoint(texts, wholeUpper, upper);\n const lowerAligned = wholeLower !== '' && alignsPerCodePoint(texts, wholeLower, lower);\n const starts = transforms.includes('capitalize') ? wordStarts(full) : null;\n\n const out: TransformedRunText[] = [];\n let base = 0;\n let upOff = 0;\n let lowOff = 0;\n for (let i = 0; i < texts.length; i++) {\n const source = texts[i];\n const t = transforms[i] ?? 'none';\n let text = '';\n const srcStarts: number[] = [];\n const srcEnds: number[] = [];\n let resized = false;\n let local = 0;\n for (const ch of source) {\n const up = upper(ch);\n const lo = lower(ch);\n let piece = ch;\n if (t === 'uppercase') {\n piece = upperAligned ? wholeUpper.slice(upOff, upOff + up.length) : up;\n } else if (t === 'lowercase') {\n piece = lowerAligned ? wholeLower.slice(lowOff, lowOff + lo.length) : lo;\n } else if (t === 'capitalize' && starts!.has(base + local) && up !== ch) {\n piece = titlecase(ch);\n }\n upOff += up.length;\n lowOff += lo.length;\n if (piece.length !== ch.length) resized = true;\n text += piece;\n for (let k = 0; k < piece.length; k++) {\n srcStarts.push(local);\n srcEnds.push(local + ch.length);\n }\n local += ch.length;\n }\n out.push(resized\n ? { text, srcMap: { length: source.length, starts: srcStarts, ends: srcEnds } }\n : { text });\n base += source.length;\n }\n return out;\n}\n","/**\n * Synthetic small caps: lowercase drawn as capitals at a smaller size, the\n * way a browser synthesizes `font-variant: small-caps` for a face with no\n * `smcp` feature. It is the one run style that sizes characters within a run\n * differently, so it reports a per-unit size map beside the text.\n *\n * It reads the text *after* `textTransform`, as CSS does: `uppercase` leaves\n * nothing to shrink, and `lowercase` shrinks everything.\n */\n\nimport { faceMetricsOf, resolveFontVariant, type FaceMetrics, type FontStyle } from '@weasel-js/font';\nimport type { RunSourceMap } from './textTransform';\n\n/** The CSS `font-variant-caps` keywords the run model carries. `normal` is an\n * explicit override: a run can turn off small caps it would inherit. */\nexport type FontVariantCaps = 'normal' | 'small-caps';\n\n/**\n * The small-caps size, as a fraction of the run's, for a face that states no\n * x-height and cap height. 0.7 is the factor Chromium and WebKit synthesize\n * with.\n */\nexport const SMALL_CAPS_SCALE = 0.7;\n\n/** The small-caps size for a face: its x-height over its cap height, so a\n * small capital stands as tall as its lowercase letters do, or\n * {@link SMALL_CAPS_SCALE} where the face lacks either. */\nexport function smallCapsScale(face?: FaceMetrics): number {\n const x = face?.xHeight;\n const cap = face?.capHeight;\n if (x === undefined || cap === undefined || x >= cap) return SMALL_CAPS_SCALE;\n return x / cap;\n}\n\n/** The small-caps scale a run set in `(family, weight, style)` gets —\n * resolved through the font registry exactly as layout resolves the run. */\nexport function smallCapsScaleFor(family: string, weight: number, style: FontStyle): number {\n return smallCapsScale(faceMetricsOf(resolveFontVariant(family, weight, style)));\n}\n\n/** Whether small caps draws `ch` as a smaller capital: whether it has a\n * capital other than itself. */\nexport function isSmallCapsLetter(ch: string): boolean {\n return ch.toUpperCase() !== ch;\n}\n\n/** A run's drawn text under small caps. `small[i]` says whether UTF-16 unit\n * `i` of `text` draws at the small size; absent when none does. */\nexport interface SmallCapsText {\n text: string;\n srcMap?: RunSourceMap;\n small?: readonly boolean[];\n}\n\n/**\n * Apply small caps to a run's drawn text. `srcMap` is the map `textTransform`\n * already produced for it, if any; the result's map composes the two, so\n * each drawn unit still names the source character it came from.\n */\nexport function smallCapsText(text: string, srcMap?: RunSourceMap): SmallCapsText {\n let out = '';\n const small: boolean[] = [];\n const starts: number[] = [];\n const ends: number[] = [];\n let resized = false;\n let anySmall = false;\n let at = 0;\n for (const ch of text) {\n const shrink = isSmallCapsLetter(ch);\n const piece = shrink ? ch.toUpperCase() : ch;\n if (piece.length !== ch.length) resized = true;\n anySmall ||= shrink;\n const start = srcMap ? srcMap.starts[at] : at;\n const end = srcMap ? srcMap.ends[at] : at + ch.length;\n for (let k = 0; k < piece.length; k++) {\n small.push(shrink);\n starts.push(start);\n ends.push(end);\n }\n out += piece;\n at += ch.length;\n }\n if (!anySmall) return srcMap ? { text, srcMap } : { text };\n const map = resized\n ? { length: srcMap?.length ?? text.length, starts, ends }\n : srcMap;\n return { text: out, ...(map ? { srcMap: map } : {}), small };\n}\n","/**\n * Apply node-level `ResolvedTextStyle` defaults to each `StyledRun`,\n * producing a fully-resolved run with every styling field set. Downstream\n * layout and draw never re-resolve defaults — `ResolvedRun` is the\n * canonical shape the renderer consumes.\n *\n * `bold`/`italic` toggles on a run are folded into `fontWeight`/`fontStyle`:\n * `bold: true` → fontWeight 700, `italic: true` → fontStyle 'italic'. A run's\n * own numeric `fontWeight` is the primitive `bold` is a preset over, so it\n * wins over both the flag and the node weight.\n * Explicit `fontFamily` / `fontSize` / `fill` / `letterSpacing` on the run\n * override the node-level value (`letterSpacing: 0` on a run is an override,\n * not an absence — it zeroes inherited tracking).\n *\n * `underline` / `strikethrough` / `overline` are *additive*, like\n * `bold`/`italic`: a run can turn a decoration on but never off, so they\n * resolve as `run.x || style.x` and not `run.x ?? style.x`. See the header of\n * `runs/rangeStyle.ts` for why the model collapses the tri-state.\n *\n * `script` is folded the same way the toggles are, into the two primitives it\n * is a preset over: `baselineShift` and `fontScale`. Both come out as one\n * world-unit `baselineShift` and a final `fontSize`, so layout never learns\n * that superscripts exist — it places a run against a baseline and an offset.\n *\n * `textTransform` is applied here too, so `text` is what gets drawn. When a\n * transform changes a length, `srcMap` says which source characters each\n * drawn one came from; see `textTransform.ts`.\n *\n * `fontVariantCaps: 'small-caps'` is applied after it, over the transformed\n * text: lowercase becomes capitals, and `sizeMap` gives those their smaller\n * size. See `smallCaps.ts`.\n */\n\nimport type { FillStyle, Stroke } from '@weasel-js/paint';\nimport { resolveScreenLength } from '@weasel-js/paint';\nimport { faceMetricsOf, resolveFontVariant, type FaceMetrics, type FontStyle } from '@weasel-js/font';\nimport type { StyledRun } from '../runs';\nimport type { ResolvedTextStyle } from '../textStyle';\nimport { transformRunTexts, type RunSourceMap } from './textTransform';\nimport { smallCapsScaleFor, smallCapsText } from './smallCaps';\n\n/** A run with every style resolved against the node's text style — no\n * optional inheritance left. This is what layout and painting consume. */\nexport interface ResolvedRun {\n /** The text as drawn — after `textTransform`, so not necessarily the\n * run's source text. */\n text: string;\n /** Present when `text` differs in length from the source it was\n * transformed from: where each of its UTF-16 units came from. Absent\n * means `text`'s offsets are the source's. */\n srcMap?: RunSourceMap;\n fontFamily: string;\n /** The run's size — what its line and its rules are set at, and what\n * every glyph is drawn at unless `sizeMap` says otherwise. */\n fontSize: number;\n /** Present when not every glyph is drawn at `fontSize`: the size each\n * UTF-16 unit of `text` is drawn at. Small caps is what produces one. */\n sizeMap?: readonly number[];\n fontWeight: number;\n fontStyle: 'normal' | 'italic';\n /** `null` is an explicit no-fill: the glyphs are painted by `stroke` alone,\n * which only the outline tier can do. Nothing is emitted for a run with\n * neither. */\n fill: FillStyle | null;\n /** Outline over this run's glyphs, or absent for none. Painted only on the\n * outline tier — a distance field has no geometry to stroke. */\n stroke?: Stroke;\n /** Extra advance added after each glyph of this run, in world units. */\n letterSpacing: number;\n /** Draw a rule below this run's baseline. Additive over the node style. */\n underline: boolean;\n /** Draw a rule through this run's x-height. Additive over the node style. */\n strikethrough: boolean;\n /** Draw a rule above this run's ascent. Additive over the node style. */\n overline: boolean;\n /**\n * How far this run sits off the line's shared baseline, in world units;\n * positive raises. 0 for ordinary text.\n *\n * Already multiplied out against the inherited font size, and already\n * carrying whatever `script` asked for — layout adds it to a baseline and\n * asks nothing about where it came from.\n */\n baselineShift: number;\n /**\n * The size this run holds its line open at, when a relative size shrank it\n * below the size it inherited — so a superscript alone on its line keeps the\n * line's height and baseline instead of collapsing them. Absent means\n * `fontSize`.\n */\n strutSize?: number;\n}\n\n/** What one script preset expands to. */\nexport type ScriptPreset = Readonly<{ size: number; shift: number }>;\n\n/**\n * What `script: 'super'` and `script: 'sub'` expand to for a face that states\n * no script metrics of its own, as fractions of the inherited font size:\n * `size` scales it, `shift` raises (positive) or lowers (negative) the\n * baseline.\n *\n * These are Adobe's defaults — InDesign and Illustrator ship 58.3% size and\n * 33.3% position for both. A face that carries `OS/2` script metrics uses\n * those instead; {@link scriptMetricsFor} is what a run actually gets.\n */\nexport const SCRIPT_METRICS: Readonly<Record<'super' | 'sub', ScriptPreset>> = Object.freeze({\n super: Object.freeze({ size: 0.583, shift: 0.333 }),\n sub: Object.freeze({ size: 0.583, shift: -0.333 }),\n});\n\nconst resolvedScripts = new WeakMap<FaceMetrics, Readonly<Record<'super' | 'sub', ScriptPreset>>>();\n\n/** The script presets for a face: its own `OS/2` values where it states\n * them, {@link SCRIPT_METRICS} per half where it does not. */\nexport function scriptMetrics(face?: FaceMetrics): Readonly<Record<'super' | 'sub', ScriptPreset>> {\n if (!face || (!face.superscript && !face.subscript)) return SCRIPT_METRICS;\n let out = resolvedScripts.get(face);\n if (!out) {\n out = Object.freeze({\n super: face.superscript ?? SCRIPT_METRICS.super,\n sub: face.subscript ?? SCRIPT_METRICS.sub,\n });\n resolvedScripts.set(face, out);\n }\n return out;\n}\n\n/**\n * The script presets a run set in `(family, weight, style)` gets — resolved\n * through the font registry exactly as layout resolves the run, so a\n * character panel, an SVG export and the DOM edit overlay read the numbers\n * the canvas draws with. Override either half per run with `baselineShift` /\n * `fontScale`.\n */\nexport function scriptMetricsFor(\n family: string,\n weight: number,\n style: FontStyle,\n): Readonly<Record<'super' | 'sub', ScriptPreset>> {\n return scriptMetrics(faceMetricsOf(resolveFontVariant(family, weight, style)));\n}\n\n/** A `TextStyle.fontWeight` as a number: the CSS keywords `bold` and\n * `normal` read as 700 and 400, anything unparseable as 400. */\nexport function numericWeight(w: number | string): number {\n if (typeof w === 'number') return w;\n if (w === 'bold' || w === 'bolder') return 700;\n if (w === 'normal') return 400;\n const parsed = Number(w);\n return Number.isFinite(parsed) ? parsed : 400;\n}\n\n/** Whether a weight reads as bold — 600 and up, the same line the font\n * registry draws between its regular and bold buckets. */\nexport function isBoldWeight(w: number | string): boolean {\n return numericWeight(w) >= 600;\n}\n\n/** The face a run is set in — its family, weight and style, each falling\n * back to the node's. Reads no font registry, so asking loads nothing. */\nexport function resolveRunFace(\n run: StyledRun,\n style: Pick<ResolvedTextStyle, 'fontFamily' | 'fontWeight' | 'fontStyle'>,\n): { fontFamily: string; fontWeight: number; fontStyle: FontStyle } {\n return {\n fontFamily: run.fontFamily ?? style.fontFamily,\n fontWeight: run.fontWeight ?? (run.bold ? 700 : numericWeight(style.fontWeight)),\n fontStyle: run.italic ? 'italic' : style.fontStyle,\n };\n}\n\n/** Resolve each run's styling against the node's text style, filling in\n * everything the run left inherited. `viewScale` resolves a run's own\n * `{ px }` size or spacing; the inherited ones arrived already resolved on\n * `style`. */\nexport function resolveRuns(\n runs: readonly StyledRun[],\n style: ResolvedTextStyle,\n viewScale = 1,\n): ResolvedRun[] {\n const out: ResolvedRun[] = [];\n const shown = transformRunTexts(\n runs.map((r) => r.text),\n runs.map((r) => r.textTransform ?? style.textTransform),\n );\n for (let i = 0; i < runs.length; i++) {\n const run = runs[i];\n let { text, srcMap } = shown[i];\n const scriptKey = run.script ?? style.script;\n const { fontFamily, fontWeight, fontStyle } = resolveRunFace(run, style);\n const script = scriptKey ? scriptMetricsFor(fontFamily, fontWeight, fontStyle)[scriptKey] : undefined;\n // Against the inherited size, not the run's own: a superscript that also\n // shrank its rise would climb less the smaller it got.\n const shiftEm = run.baselineShift ?? script?.shift ?? 0;\n const scale = run.fontScale ?? script?.size ?? 1;\n const relative = run.fontSize === undefined && scale !== 1;\n // An absolute size wins over a relative one; naming both is a consumer\n // saying \"this size exactly\", which a multiplier cannot improve on.\n const fontSize = run.fontSize !== undefined\n ? resolveScreenLength(run.fontSize, viewScale)\n : style.fontSize * scale;\n let sizeMap: number[] | undefined;\n if ((run.fontVariantCaps ?? style.fontVariantCaps) === 'small-caps') {\n const caps = smallCapsText(text, srcMap);\n text = caps.text;\n srcMap = caps.srcMap;\n if (caps.small) {\n const small = fontSize * smallCapsScaleFor(fontFamily, fontWeight, fontStyle);\n sizeMap = caps.small.map((s) => (s ? small : fontSize));\n }\n }\n out.push({\n text,\n ...(srcMap ? { srcMap } : {}),\n fontFamily,\n fontSize,\n ...(sizeMap ? { sizeMap } : {}),\n fontWeight,\n fontStyle,\n fill: run.fill ?? style.fill,\n // Unlike the decorations below, a run's stroke *replaces* the node's\n // rather than adding to it — there is only one outline to paint.\n ...((run.stroke ?? style.stroke) !== undefined\n ? { stroke: run.stroke ?? style.stroke }\n : {}),\n letterSpacing: run.letterSpacing !== undefined\n ? resolveScreenLength(run.letterSpacing, viewScale)\n : style.letterSpacing,\n // `||`, not `??`: run-level decorations are additive over the node style.\n underline: run.underline || style.underline,\n strikethrough: run.strikethrough || style.strikethrough,\n overline: run.overline || style.overline,\n baselineShift: shiftEm * style.fontSize,\n ...(relative ? { strutSize: style.fontSize } : {}),\n });\n }\n return out;\n}\n","/**\n * Box vertical alignment for text draw commands. Given the command's box\n * `height` and the laid-out text block's height, returns the Y offset to\n * apply to every quad. `'top'` (or an undefined `align`, or a missing box\n * `height`) is the legacy behavior: offset 0.\n */\nexport type TextVerticalAlign = 'top' | 'center' | 'bottom';\n\n/** How far to shift laid-out text down inside a box of `boxHeight` to satisfy\n * a vertical alignment. Zero when the box height is unknown or alignment is\n * top. */\nexport function verticalAlignOffset(\n align: TextVerticalAlign | undefined,\n boxHeight: number | undefined,\n textHeight: number,\n): number {\n if (align === undefined || align === 'top' || boxHeight === undefined) return 0;\n const slack = boxHeight - textHeight;\n return align === 'center' ? slack / 2 : slack;\n}\n","/**\n * How a text pose lays out — the one decision every consumer of a text node\n * reads: the painters (`kit:text`, `createTextLayer`), picking\n * (`textLineBoxes`), the caret (`caretIndexAt`), fitting (`fitTextPose`) and\n * the DOM edit overlay.\n *\n * The pose width is always the box `align` resolves within. It is the wrap\n * width only when the style declares `wrap`; otherwise a line runs as long as\n * its text, whichever of them is asking.\n */\nimport type { LaidOutRuns, LayoutRunsOpts } from './layoutRuns';\nimport { cachedLayoutRuns } from './layoutCache';\nimport { resolveAlign, resolveTextStyle, type ResolvedTextStyle } from '../textStyle';\nimport { resolveRuns, type ResolvedRun } from '../runs/resolveRuns';\nimport { toRuns } from '../runs';\nimport { verticalAlignOffset } from '../measure/verticalAlign';\nimport type { TextPose } from '../pose';\n\n/** What {@link layoutTextPose} hands `cachedLayoutRuns`. */\nexport interface TextPoseLayoutInput {\n style: ResolvedTextStyle;\n runs: ResolvedRun[];\n opts: LayoutRunsOpts & { align: 'left' | 'center' | 'right'; justify: boolean };\n}\n\n/**\n * The resolved runs and layout options for `pose`. A text draw command built\n * from these lays out, in the renderer, into exactly the lines\n * {@link layoutTextPose} reports.\n *\n * `scale` is the view scale a `{ px }` `fontSize` or `letterSpacing` resolves\n * against. Everything past this point is world units, so a caller that\n * measures, hit-tests or paints one pose has to pass the same scale to each\n * or they disagree.\n */\nexport function textPoseLayoutInput(pose: TextPose, scale = 1): TextPoseLayoutInput {\n const style = resolveTextStyle(pose.style, { fill: pose.fill, stroke: pose.stroke }, scale);\n // Empty runs are not a styling, so they fall back to the plain string\n // rather than lay out nothing.\n const source = pose.runs && pose.runs.length > 0 ? pose.runs : pose.text;\n return {\n style,\n runs: resolveRuns(toRuns(source), style, scale),\n opts: {\n maxWidth: style.wrap ? pose.width : Infinity,\n alignWidth: pose.width,\n lineHeight: style.lineHeight,\n align: resolveAlign(style.align, style.direction),\n justify: style.align === 'justify',\n },\n };\n}\n\n/** A text pose laid out. */\nexport interface TextPoseLayout {\n /** Origin-relative, shared with the layout cache — treat as immutable. */\n laid: LaidOutRuns;\n /** World position of the layout's origin: `pose.x`, and `pose.y` shifted by\n * `verticalAlign` within the pose height. */\n x: number;\n y: number;\n}\n\n/** The lines `pose` lays out into, and where they sit in world space. */\nexport function layoutTextPose(pose: TextPose, scale = 1): TextPoseLayout {\n const { runs, opts } = textPoseLayoutInput(pose, scale);\n const laid = cachedLayoutRuns(runs, opts);\n return {\n laid,\n x: pose.x,\n y: pose.y + verticalAlignOffset(pose.verticalAlign, pose.height, laid.bounds.height),\n };\n}\n","/**\n * Wrap-aware text measurement for a 2D context. Lines end where `layoutRuns`\n * ends them — at UAX #14 break opportunities when a word would overflow\n * `maxWidth`, and at every hard break — through the same `wrapLines`, with\n * widths from `ctx.measureText` plus tracking. A word wider than `maxWidth`\n * is emitted on its own line unbroken (caller can decide to clip).\n *\n * Returns the laid-out lines, the total block height in world units\n * (`lines.length * fontSize * lineHeight`), and per-line `lineStarts` —\n * the UTF-16 offset of each line's first character in `text`, which\n * `caretIndexAt` uses to map a clicked (x, y) back to a source offset.\n * Trailing spaces hang and are not included in `lines[i]`; neither is the\n * hard break that closed it.\n *\n * The caller owns the `ctx.font` setup — pass a context whose `font`\n * already matches `style` (use `fontString(style)`).\n */\n\nimport type { ResolvedTextStyle } from '../textStyle';\nimport { graphemeCount } from './graphemes';\nimport { wrapLines } from '../layout/lineBreak/wrapLines';\n\n/**\n * Advance width of `text` in world units, tracking included.\n *\n * `letter-spacing` is not part of the CSS `font` shorthand, so a context\n * whose `font` was set from `fontString(style)` measures glyphs only. The\n * GL path (`layoutRuns`) adds `letterSpacing` after every grapheme cluster\n * including the last, matching CSS, so this does too — and every 2D-side\n * width has to go through here or the two paths disagree about where a line\n * breaks.\n */\nexport function measuredWidth(\n ctx: CanvasRenderingContext2D,\n text: string,\n style: ResolvedTextStyle,\n): number {\n return ctx.measureText(text).width\n + (style.letterSpacing === 0 ? 0 : graphemeCount(text) * style.letterSpacing);\n}\n\n/** Result of `measureText`: wrapped lines, per-line source offsets, and total block height. */\nexport interface MeasuredText {\n lines: string[];\n lineStarts: number[];\n height: number;\n}\n\n/**\n * Wrap `text` against `maxWidth` at the break opportunities `layoutRuns`\n * wraps at, measuring with `ctx`.\n */\nexport function measureText(\n ctx: CanvasRenderingContext2D,\n text: string,\n maxWidth: number,\n style: ResolvedTextStyle,\n): MeasuredText {\n const cps: number[] = [];\n /** UTF-16 offset of each code point, then `text.length`. */\n const at: number[] = [];\n let u = 0;\n for (const ch of text) {\n cps.push(ch.codePointAt(0)!);\n at.push(u);\n u += ch.length;\n }\n at.push(u);\n\n const wrapped = wrapLines(cps, maxWidth, (start, end) => measuredWidth(ctx, text.slice(at[start], at[end]), style));\n const lines = wrapped.map((l) => text.slice(at[l.start], at[l.end]).replace(/ +$/, ''));\n const lineStarts = wrapped.map((l) => at[l.start]);\n const height = lines.length * style.fontSize * style.lineHeight;\n return { lines, lineStarts, height };\n}\n","import type { TextStyle } from '../textStyle';\nimport { resolveTextStyle } from '../textStyle';\nimport { resolveRuns } from '../runs/resolveRuns';\nimport { cachedLayoutRuns } from '../layout/layoutCache';\n\n/** Options for `measureTextBounds`. */\nexport interface MeasureTextBoundsOpts {\n /** Wrap width; words exceeding it start a new line. Default `Infinity` (no wrap). */\n maxWidth?: number;\n /** Overrides `style`'s `lineHeight` multiplier for this measurement. */\n lineHeight?: number;\n /** View scale any `{ px }` size in `style` resolves against. Default 1,\n * which measures a `{ px }` size as that many world units. */\n scale?: number;\n}\n\n/**\n * Measure how the GL/MSDF renderer will lay out a single plain-text string,\n * using the registered font atlas metrics. Mirrors {@link textCommand} exactly\n * (`resolveTextStyle` → `resolveRuns` → `cachedLayoutRuns`), so the returned\n * bounds match what actually gets drawn — use it to size backgrounds/pills, place\n * labels, or test overlap without guessing widths.\n *\n * Pass `opts.maxWidth` to measure word-wrapped height (e.g. for a fixed-width\n * text box); omitting it measures the unwrapped single-line width. `opts.lineHeight`\n * overrides the style's multiplier without changing `style` itself.\n *\n * Returns `{ width, height }` in the same units as `style.fontSize`. The font\n * must already be registered via `registerFont`; an unregistered family falls\n * back to the atlas fallback glyph (and warns), so register fonts at app boot\n * before measuring.\n */\nexport function measureTextBounds(\n text: string,\n style?: TextStyle,\n opts?: MeasureTextBoundsOpts,\n): { width: number; height: number } {\n const resolved = resolveTextStyle(style, undefined, opts?.scale);\n const runs = resolveRuns([{ text }], resolved, opts?.scale);\n const { bounds } = cachedLayoutRuns(runs, {\n maxWidth: opts?.maxWidth ?? Infinity,\n lineHeight: opts?.lineHeight ?? resolved.lineHeight,\n align: resolved.align,\n });\n // Copied: the layout behind it is shared, and handing a caller a mutable\n // reference into a cache entry is how one measurement corrupts the next.\n return { width: bounds.width, height: bounds.height };\n}\n","/**\n * Where a text node's lines actually sit inside its pose box.\n *\n * A text pose is a layout box, not a bounding box: `\"Away\"` in a 309-unit-wide\n * box leaves most of the box empty, and anything that treats the pose as the\n * node's extent — picking, lasso, clipping, SVG export — claims that empty\n * space. `textLineBoxes` returns the per-line rectangles instead.\n *\n * The numbers come from `layoutTextPose`, the layout every painter of a text\n * pose draws, so the boxes cannot drift from what is painted — they wrap only\n * where the style declares `wrap`, and honor `align` and `verticalAlign`.\n *\n * These are line boxes, not ink boxes: each is `fontSize * lineHeight` tall\n * from the pen's line top. Ink can escape vertically at a `lineHeight` low\n * enough — see the `bounds` note at the end of `layoutRuns` — which is the\n * right trade for hit-testing, where a box that hugged the ink would make\n * an `x` harder to click than an `X`.\n */\n\nimport type { Rect } from '@weasel-js/geom';\nimport { layoutTextPose } from '../layout/textPoseLayout';\nimport type { TextPose } from '../pose';\n\n/** Options for {@link textLineBoxes}. */\nexport interface TextLineBoxesOpts {\n /** Grow every box by this much on all four sides (world units). Default 0.\n * Picking wants a little slack so a single hairline row of text is still\n * grabbable; clipping and export want none. */\n padding?: number;\n /** Keep boxes for blank lines (zero width). Default `false` — a blank line\n * covers no area, so for hit-testing and silhouettes it is noise. Pass\n * `true` when the indices have to line up with the laid-out lines. */\n includeEmpty?: boolean;\n}\n\n/** Per-line rectangles for a text pose, in world units, in layout order. */\nexport function textLineBoxes(pose: TextPose, opts: TextLineBoxesOpts = {}): Rect[] {\n const padding = opts.padding ?? 0;\n const { laid, x: dx, y: dy } = layoutTextPose(pose);\n\n const out: Rect[] = [];\n for (const line of laid.lines) {\n if (!opts.includeEmpty && line.x1 <= line.x0) continue;\n out.push({\n x: line.x0 + dx - padding,\n y: line.y0 + dy - padding,\n width: line.x1 - line.x0 + padding * 2,\n height: line.y1 - line.y0 + padding * 2,\n });\n }\n return out;\n}\n","import { resolveScreenLength } from '@weasel-js/paint';\nimport { markdownToRuns, type StyledRun } from './runs';\nimport { faceMetricsFor, type FaceMetrics } from '@weasel-js/font';\nimport { numericWeight, scriptMetrics } from './runs/resolveRuns';\nimport { DECORATION_KINDS, decorationRule, type DecorationKind } from './layout/decorationMetrics';\nimport { transformRunTexts } from './runs/textTransform';\nimport { smallCapsScale, smallCapsText } from './runs/smallCaps';\nimport { wrapLines } from './layout/lineBreak/wrapLines';\n\nexport type { StyledRun };\n\n/** Width-measurement strategy for `layoutMarkdown`; canvas-backed default supplied by `createMarkdownRenderer`. */\nexport type MeasureFn = (text: string, fontSize: number, bold: boolean, italic: boolean) => number;\n\n/** The face a run's rules and script presets come from, for `layoutMarkdown`.\n * `createMarkdownRenderer` supplies one that looks the family up in the font\n * registry, so a registered face places them as it does on the GL tier. */\nexport type FaceMetricsFn = (bold: boolean, italic: boolean) => FaceMetrics | undefined;\n\n/** A `StyledRun` with its resolved size and its position relative to the\n * start of its line: `x` along the line, `y` off its baseline. */\nexport interface PositionedRun extends StyledRun {\n x: number;\n /** Advance width, as the layout's `MeasureFn` measured it. */\n width: number;\n /** Baseline offset, positive down — a superscript's is negative. Add it to\n * the line's baseline when painting. */\n y: number;\n /** The run's font size in px, with `fontScale` and `script` already folded\n * in. Resolved once here so layout and paint cannot disagree about it. */\n size: number;\n /** The face that placed the run's script and places its rules. */\n face?: FaceMetrics;\n}\n\n/**\n * A run's size and baseline offset, resolved the way `resolveRuns` resolves\n * them for the GL path: an absolute `fontSize` wins over a multiplier, and\n * the rise is measured against the *inherited* size so it does not shrink\n * along with the run.\n */\nfunction runMetrics(run: StyledRun, fontSize: number, face: FaceMetrics | undefined): { size: number; y: number } {\n const script = run.script ? scriptMetrics(face)[run.script] : undefined;\n const scale = run.fontScale ?? script?.size ?? 1;\n const shiftEm = run.baselineShift ?? script?.shift ?? 0;\n return {\n size: run.fontSize !== undefined\n ? resolveScreenLength(run.fontSize, 1)\n : fontSize * scale,\n // Canvas y grows downward; a positive shift is a rise. Guarded so an\n // unshifted run reports 0 rather than -0.\n y: shiftEm === 0 ? 0 : -shiftEm * fontSize,\n };\n}\n\n/** A run as `layoutMarkdown` walks it: small caps has split it where its\n * size changes, and marked the pieces drawn at the small size. */\ntype Segment = StyledRun & { smallCaps?: true; source?: StyledRun };\n\n/** A single laid-out line of text: its positioned runs, total width, and computed line height. */\nexport interface LayoutLine {\n runs: PositionedRun[];\n width: number;\n height: number;\n}\n\n/** Output of `layoutMarkdown`: per-line breakdown plus overall block dimensions. */\nexport interface LayoutResult {\n lines: LayoutLine[];\n width: number;\n height: number;\n}\n\n/**\n * Word-wrap parsed runs into lines bounded by `maxWidth`, breaking at the\n * UAX #14 opportunities `layoutRuns` breaks at; pass `Infinity` for\n * single-line layout.\n */\nexport function layoutMarkdown(\n runs: StyledRun[],\n maxWidth: number,\n fontSize: number,\n measure: MeasureFn,\n lineHeightFactor: number = 1.3,\n faceOf?: FaceMetricsFn,\n): LayoutResult {\n if (runs.length === 0) return { lines: [], width: 0, height: 0 };\n // No caret reads this layout, so the transformed text simply replaces the source.\n const shown = transformRunTexts(runs.map((r) => r.text), runs.map((r) => r.textTransform ?? 'none'));\n // Small caps splits a run where its size changes, marking the small pieces.\n const segs: Segment[] = [];\n runs.forEach((r, i) => {\n const text = shown[i].text;\n if (r.fontVariantCaps !== 'small-caps') { segs.push(text === r.text ? r : { ...r, text }); return; }\n const caps = smallCapsText(text);\n if (!caps.small) { segs.push({ ...r, text: caps.text }); return; }\n let at = 0;\n for (const piece of caps.text) {\n const small = caps.small[at];\n at += piece.length;\n const prev = segs[segs.length - 1];\n if (prev?.source === r && (prev.smallCaps === true) === small) prev.text += piece;\n else segs.push({ ...r, text: piece, source: r, ...(small ? { smallCaps: true as const } : {}) });\n }\n });\n\n // One sequence across every run, so a break opportunity that depends on a\n // neighbor in the next run is found the way `layoutRuns` finds it.\n const cps: number[] = [];\n /** Per code point: its run, and its UTF-16 span in that run's text. */\n const runOf: number[] = [];\n const startOf: number[] = [];\n const endOf: number[] = [];\n segs.forEach((r, ri) => {\n let at = 0;\n for (const ch of r.text) {\n cps.push(ch.codePointAt(0)!);\n runOf.push(ri);\n startOf.push(at);\n at += ch.length;\n endOf.push(at);\n }\n });\n // Already a screen-pixel layout, so a run's `{ px }` size is its size.\n const placed = segs.map(({ smallCaps, source: _source, ...run }) => {\n const face = faceOf?.(run.bold ?? false, run.italic ?? false);\n const { size: runSize, y } = runMetrics(run, fontSize, face);\n // The run's size holds the line, as on the GL tier, however small its capitals.\n return { run, face, y, runSize, size: smallCaps ? runSize * smallCapsScale(face) : runSize };\n });\n const pieceWidth = (p: Piece): number => {\n const { run, size } = placed[p.run];\n return measure(run.text.slice(p.start, p.end), size, run.bold ?? false, run.italic ?? false);\n };\n\n /** A UTF-16 span of one run's text, set on the current line. */\n interface Piece { run: number; start: number; end: number }\n\n /** Code points `[from, to)` as spans of their runs' texts. */\n function piecesOf(from: number, to: number): Piece[] {\n const out: Piece[] = [];\n for (let k = from; k < to; k++) {\n const last = out[out.length - 1];\n if (last && last.run === runOf[k] && last.end === startOf[k]) {\n out[out.length - 1] = { ...last, end: endOf[k] };\n } else {\n out.push({ run: runOf[k], start: startOf[k], end: endOf[k] });\n }\n }\n return out;\n }\n\n const lines: LayoutLine[] = [];\n\n function commitLine(line: Piece[]) {\n let x = 0;\n let maxSize = 0;\n const positioned: PositionedRun[] = [];\n for (const p of line) {\n const { run, face, size, y, runSize } = placed[p.run];\n const width = pieceWidth(p);\n positioned.push({ ...run, text: run.text.slice(p.start, p.end), x, width, y, size, ...(face ? { face } : {}) });\n x += width;\n maxSize = Math.max(maxSize, runSize);\n }\n lines.push({ runs: positioned, width: x, height: (maxSize > 0 ? maxSize : fontSize) * lineHeightFactor });\n }\n\n const widthOf = (start: number, end: number): number =>\n piecesOf(start, end).reduce((w, p) => w + pieceWidth(p), 0);\n for (const line of wrapLines(cps, maxWidth, widthOf)) {\n let end = line.end;\n // A wrapped line's trailing spaces hang past the edge, as they do in `layoutRuns`.\n if (line.wrapped) while (end > line.start && cps[end - 1] === 32) end--;\n commitLine(piecesOf(line.start, end));\n }\n\n const width = Math.max(...lines.map((l) => l.width));\n const height = lines.reduce((sum, l) => sum + l.height, 0);\n return { lines, width, height };\n}\n\n/** Pluggable text-painting strategy. The default fills white at `(x, y)`; markdown renderers replace this. */\nexport type TextRenderer = (\n ctx: CanvasRenderingContext2D,\n text: string,\n x: number,\n y: number,\n) => void;\n\n/** Font styling options threaded through `createMarkdownRenderer`. */\nexport interface MarkdownFontOptions {\n /** Font-family spec (e.g. `'\"Iowan Old Style\", Georgia, serif'`). Defaults to `sans-serif`. */\n family?: string;\n /** Numeric weight applied to non-bold runs. Bold runs always use `bold`. Default `normal`. */\n weight?: string | number;\n /** Override fill color. When set, used for all runs (italic and bold). */\n color?: string;\n /** Multiplier applied to font size for line height. Default 1.3. */\n lineHeight?: number;\n}\n\nfunction buildFont(\n fontSize: number,\n bold: boolean,\n italic: boolean,\n opts: MarkdownFontOptions = {},\n): string {\n const family = opts.family ?? 'sans-serif';\n const weight = bold ? 'bold' : (opts.weight !== undefined ? String(opts.weight) : 'normal');\n const parts: string[] = [];\n if (italic) parts.push('italic');\n parts.push(weight);\n parts.push(`${fontSize}px ${family}`);\n return parts.join(' ');\n}\n\nfunction canvasMeasure(ctx: CanvasRenderingContext2D, opts: MarkdownFontOptions = {}): MeasureFn {\n return (text, fontSize, bold, italic) => {\n ctx.font = buildFont(fontSize, bold, italic, opts);\n return ctx.measureText(text).width;\n };\n}\n\n/** Distance from the context's current `textBaseline` down to the alphabetic\n * baseline, for the font already set on it; 0 where the metric is missing. */\nfunction alphabeticBaselineBelow(ctx: CanvasRenderingContext2D): number {\n const current = ctx.textBaseline;\n if (current === 'alphabetic') return 0;\n const here = ctx.measureText('').fontBoundingBoxAscent;\n ctx.textBaseline = 'alphabetic';\n const alphabetic = ctx.measureText('').fontBoundingBoxAscent;\n ctx.textBaseline = current;\n const d = alphabetic - here;\n return Number.isFinite(d) ? d : 0;\n}\n\n/** Where a block `width` wide starts, given the x the context aligns it to. */\nfunction blockLeft(ctx: CanvasRenderingContext2D, x: number, width: number): number {\n const rtl = ctx.direction === 'rtl';\n switch (ctx.textAlign) {\n case 'center': return x - width / 2;\n case 'right': return x - width;\n case 'end': return rtl ? x : x - width;\n case 'start': return rtl ? x - width : x;\n default: return x;\n }\n}\n\n/**\n * Build a fill+stroke `TextRenderer` pair, laying the text out once.\n *\n * `text` is markdown, read by `markdownToRuns`, or runs already styled. The\n * block is placed by the context's `textAlign` and each run by its\n * `textBaseline`. The fill pass also paints underline, strikethrough and\n * overline in their run's fill, placed by the same metrics as the GL tier;\n * the stroke pass paints no rules, as on the GL tier.\n */\nexport function createMarkdownRenderer(\n ctx: CanvasRenderingContext2D,\n text: string | StyledRun[],\n fontSize: number,\n maxWidth: number = Infinity,\n fontOpts: MarkdownFontOptions = {},\n): { renderer: TextRenderer; strokeRenderer: TextRenderer; width: number; height: number } {\n const measure = canvasMeasure(ctx, fontOpts);\n const parsed = typeof text === 'string' ? markdownToRuns(text) : text;\n const family = fontOpts.family ?? 'sans-serif';\n const weight = numericWeight(fontOpts.weight ?? 400);\n const faceOf: FaceMetricsFn = (bold, italic) =>\n faceMetricsFor(family, bold ? 700 : weight, italic ? 'italic' : 'normal');\n const layout = layoutMarkdown(parsed, maxWidth, fontSize, measure, fontOpts.lineHeight, faceOf);\n\n /** Walk the layout, setting each run's font and handing over its\n * left-aligned paint position and the index of its line. */\n function walk(\n c: CanvasRenderingContext2D,\n x: number,\n y: number,\n drawRun: (run: PositionedRun, rx: number, ry: number, lineIndex: number) => void,\n ): void {\n const align = c.textAlign;\n const left = blockLeft(c, x, layout.width);\n c.textAlign = 'left';\n let lineY = y;\n layout.lines.forEach((line, li) => {\n const lineLeft = left + (layout.width - line.width) / 2;\n for (const run of line.runs) {\n c.font = buildFont(run.size, run.bold ?? false, run.italic ?? false, fontOpts);\n drawRun(run, lineLeft + run.x, lineY + run.y, li);\n }\n lineY += line.height;\n });\n c.textAlign = align;\n }\n\n const renderer: TextRenderer = (_ctx, _text, x, y) => {\n interface Span {\n flags: Record<DecorationKind, boolean>;\n fill: string;\n size: number;\n face: FaceMetrics | undefined;\n baselineY: number;\n line: number;\n x0: number;\n x1: number;\n }\n let span: Span | null = null;\n const flush = (): void => {\n const s = span;\n span = null;\n if (!s || s.x1 <= s.x0) return;\n _ctx.fillStyle = s.fill;\n for (const kind of DECORATION_KINDS) {\n if (!s.flags[kind]) continue;\n const { y0, y1 } = decorationRule(kind, s.baselineY, s.size, s.face);\n _ctx.fillRect(s.x0, y0, s.x1 - s.x0, y1 - y0);\n }\n };\n\n walk(_ctx, x, y, (run, rx, ry, line) => {\n const fill = fontOpts.color\n ?? (run.italic && !run.bold ? 'rgba(255, 255, 255, 0.7)' : '#FFFFFF');\n _ctx.fillStyle = fill;\n _ctx.fillText(run.text, rx, ry);\n\n if (!(run.underline || run.strikethrough || run.overline)) {\n flush();\n return;\n }\n const flags: Record<DecorationKind, boolean> = {\n underline: run.underline ?? false,\n strikethrough: run.strikethrough ?? false,\n overline: run.overline ?? false,\n };\n const baselineY = ry + alphabeticBaselineBelow(_ctx);\n const open = span;\n if (\n open !== null\n && open.line === line\n && open.x1 === rx\n && open.fill === fill\n && open.size === run.size\n && open.face === run.face\n && open.baselineY === baselineY\n && DECORATION_KINDS.every((k) => open.flags[k] === flags[k])\n ) {\n open.x1 = rx + run.width;\n } else {\n flush();\n span = { flags, fill, size: run.size, face: run.face, baselineY, line, x0: rx, x1: rx + run.width };\n }\n });\n flush();\n };\n\n const strokeRenderer: TextRenderer = (_ctx, _text, x, y) => {\n walk(_ctx, x, y, (run, rx, ry) => _ctx.strokeText(run.text, rx, ry));\n };\n\n return { renderer, strokeRenderer, width: layout.width, height: layout.height };\n}\n"]}