chenglou/pretext

Public

Fast, accurate & comprehensive text measurement & layout

  • Stars51k+79 tuần này
  • Forks2.8k
  • Watchers134
  • Issues43
  • Ngày tạo08/03/2026
  • Cập nhật gần nhất16/10/2026
  • Ngôn ngữTypeScript
  • Giấy phép—
README.md45.2 KBRaw

Pretext

Pure JavaScript/TypeScript library for multiline text measurement & layout. Fast, accurate & supports all the languages you didn't even know about. Allows rendering to DOM, Canvas, SVG and soon, server-side.

Pretext side-steps the need for DOM measurements (e.g. getBoundingClientRect, offsetHeight), which trigger layout reflow, one of the most expensive operations in the browser. It implements its own text measurement logic, using the browsers' own font engine as ground truth (very AI-friendly iteration method).

Installation

npm install @chenglou/pretext

Demos

Clone the repo, run bun install, then bun start, and open http://localhost:3000/demos in your browser. On Windows, use bun run start:windows. Alternatively, see them live at chenglou.me/pretext. Some more at somnai-dreams.github.io/pretext-demos Building a chat or another long list? pages/demos/markdown-chat.md walks through the Markdown chat demo's patterns and when you can skip each.

API

Pretext serves 2 use cases:

1. Measure a paragraph's height without ever touching DOM

import { prepare, layout } from '@chenglou/pretext'

const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀‎', '16px Inter')
const { height, lineCount } = layout(prepared, 320, 20) // pure arithmetic. No DOM layout & reflow!

prepare() does the one-time work: normalize whitespace, segment the text at its break opportunities, measure the segments with canvas, and return an opaque handle. layout() is the cheap hot path after that: pure arithmetic over cached widths. Do not rerun prepare() for the same text and configs; that'd defeat its precomputation. For example, on resize, only rerun layout().

If you want textarea-like text where ordinary spaces, \t tabs, and \n hard breaks stay visible, pass { whiteSpace: 'pre-wrap' } to prepare():

const prepared = prepare(textareaValue, '16px Inter', { whiteSpace: 'pre-wrap' })
const { height } = layout(prepared, textareaWidth, 20)

// Long text edited live: prepare each paragraph apart, keeping its \n, and re-prepare only the one an edit touches

Nội dung README thuộc về chenglou và cộng đồng đóng góp, giấy phép Không có giấy phép. Nguồn: github.com/chenglou/pretext