Skip to main content
1

Install the package

npm install @chenglou/pretext
2

Measure paragraph height

Use prepare() + layout() to get the height of a paragraph at a given container width — without reading from the DOM.
import { prepare, layout } from '@chenglou/pretext'

const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀', '16px Inter')
const { height, lineCount } = layout(prepared, textWidth, 20) // pure arithmetic. No DOM layout & reflow!
The font string passed to prepare() must match your CSS font declaration shorthand — including size, weight, style, and family. It follows the same format as canvasContext.font, for example '16px Inter' or 'bold 14px "Helvetica Neue"'.
Call prepare() once when the text first appears (for example, when a comment loads or a component mounts). Call layout() on every resize — it is pure arithmetic over cached widths and takes about 0.0002ms per text block.
3

Lay out lines manually

Switch to prepareWithSegments() + layoutWithLines() when you need the actual line strings and widths for rendering to canvas, SVG, or WebGL.
import { prepareWithSegments, layoutWithLines } from '@chenglou/pretext'

const prepared = prepareWithSegments('AGI 春天到了. بدأت الرحلة 🚀', '18px "Helvetica Neue"')
const { lines } = layoutWithLines(prepared, 320, 26) // 320px max width, 26px line height
for (let i = 0; i < lines.length; i++) ctx.fillText(lines[i].text, 0, i * 26)
Each entry in lines has a text string, a width number, and start/end cursors for further processing.
4

Flow text around a float with layoutNextLine

Use layoutNextLine() when the available width changes from line to line — for example, when text flows around a floated image.
let cursor = { segmentIndex: 0, graphemeIndex: 0 }
let y = 0

// Flow text around a floated image: lines beside the image are narrower
while (true) {
  const width = y < image.bottom ? columnWidth - image.width : columnWidth
  const line = layoutNextLine(prepared, cursor, width)
  if (line === null) break
  ctx.fillText(line.text, 0, y)
  cursor = line.end
  y += 26
}
layoutNextLine() is an iterator-style API. Pass the previous line’s end cursor as the next start. It returns null when the paragraph is exhausted.

Height prediction

Virtualization, masonry, and scroll anchoring with accurate heights.

Manual layout

Render lines yourself to canvas, SVG, or WebGL.

prepare() API

Full reference for prepare(), prepareWithSegments(), and options.

Build docs developers (and LLMs) love