| name | pretext-docs |
| description | API reference for @chenglou/pretext — a pure JS/TS library for measuring and laying out multiline text without DOM reflows. Use when you need to look up a pretext function signature, understand the two-phase prepare/layout model, find the right function for a use case (height-only vs line content vs variable-width), check PrepareOptions or LayoutCursor types, or orient yourself before writing code that uses pretext. Also use when user says "pretext API", "pretext docs", "pretext types", "how does pretext work", "pretext functions", or "what does prepare/layout/layoutWithLines/walkLineRanges do". |
| user-invocable | true |
pretext docs
What it is
@chenglou/pretext is a pure JavaScript/TypeScript library that measures and lays out multiline text without touching the DOM. It eliminates expensive browser layout reflows (getBoundingClientRect, offsetHeight) from text-sizing code. Works in browser and Node.js (requires Canvas API).
npm install @chenglou/pretext
import { prepare, layout } from '@chenglou/pretext'
Two-phase model
The library separates work into two phases — understand this before writing any code:
| Phase | Function | What it does | Cost |
|---|
| Prepare | prepare() | Tokenizes text, measures segments with Canvas font engine, caches results | ~19 ms / 500 texts |
| Layout | layout() | Pure arithmetic line-breaking using cached widths — zero DOM | ~0.09 ms / text |
Rule: Call prepare() once per unique (text, font) pair and store the result. Call layout() as many times as needed (different widths, on resize, in render loops). Never call prepare() inside a render loop.
Core API
| Function | Signature | Returns | When to use |
|---|
prepare | (text, font, options?) | PreparedText | One-time measurement. Use when you only need height/count afterward. |
prepareWithSegments | (text, font, options?) | PreparedTextWithSegments | Use when you need layoutWithLines, layoutNextLine, or walkLineRanges. |
layout | (prepared, maxWidth, lineHeight) | LayoutResult | Fast height + line count. Requires only PreparedText. |
layoutWithLines | (prepared, maxWidth, lineHeight) | LayoutLinesResult | Returns each line's text, width, and cursor positions. Requires PreparedTextWithSegments. |
layoutNextLine | (prepared, cursor, maxWidth) | LayoutLine | null | Iterator-style: one line at a time, optionally with a different maxWidth per call. Requires PreparedTextWithSegments. |
walkLineRanges | (prepared, maxWidth, onLine) | number (line count) | Geometry pass — invokes onLine per line without materializing text strings. Fastest option when you only need widths/positions. Requires PreparedTextWithSegments. |
profilePrepare | (text, font, options?) | PrepareProfile | Diagnostic timing breakdown. Use when debugging slow prepare() calls. |
clearCache | () | void | Clears the global Canvas measurement cache. Call only when fonts change at runtime. |
setLocale | (locale?) | void | Sets locale for Intl.Segmenter word-break rules. Affects all subsequent prepare() calls globally. |
Type reference
type PreparedText = { }
type PreparedTextWithSegments = PreparedText & { segments: string[] }
type LayoutResult = {
lineCount: number
height: number
}
type LayoutLinesResult = LayoutResult & {
lines: LayoutLine[]
}
type LayoutLine = {
text: string
width: number
start: LayoutCursor
end: LayoutCursor
}
type LayoutLineRange = {
width: number
start: LayoutCursor
end: LayoutCursor
}
type LayoutCursor = {
segmentIndex: number
graphemeIndex: number
}
type PrepareOptions = {
whiteSpace?: 'normal' | 'pre-wrap'
}
type PrepareProfile = {
analysisMs: number
measureMs: number
totalMs: number
analysisSegments: number
preparedSegments: number
breakableSegments: number
}
Font string format
The font argument is a CSS font shorthand string — the same value you pass to ctx.font on a Canvas 2D context.
"16px Arial"
"bold 14px sans-serif"
"italic 600 18px/1.5 'Helvetica Neue', sans-serif"
──────────────────────────────────────────────────
style weight size/line-height family
The font family must match exactly what the browser has loaded. A mismatch silently falls back to the system default, producing wrong measurements. Always wait for fonts to be ready before calling prepare().
Function selection matrix
| Goal | Recommended function |
|---|
| Paragraph height or line count only | prepare() + layout() |
| Line text + widths (for Canvas rendering) | prepareWithSegments() + layoutWithLines() |
Variable maxWidth per line (shaped containers) | prepareWithSegments() + layoutNextLine() loop |
| Line geometry without building strings (perf-critical) | prepareWithSegments() + walkLineRanges() |
Diagnose slow prepare() | profilePrepare() |
Global caveats
clearCache() — clears the Canvas measurement cache shared across all calls. Only needed if fonts change after initial load (e.g., a font is swapped at runtime). Do not call it in hot paths.
setLocale(locale?) — sets the locale for Intl.Segmenter. Affects word-break and line-break behavior globally. Call once at app startup if your content uses a non-default locale. Pass no argument to reset to the runtime default.
- Canvas requirement —
prepare() uses the Canvas 2D API to measure font metrics. In Node.js, install and register a Canvas shim (e.g., node-canvas) before importing pretext.
- SSR — pretext can run server-side with
node-canvas. Measurements are font-renderer-dependent, so results may differ slightly between Node and browser if font rendering engines differ.