返回项目

Pretext

如遇到长文本渲染卡顿或 resize 掉帧,可以采用这个仓库。

Pretext 是一个纯 TypeScript / JavaScript 的多行文本测量与排版库,作者是 chenglou(程嘉楼,前 Facebook React 核心成员,ReScript 作者之一)。目标是在完全不触碰 DOM 的前提下,准确计算一段文本在给定字体、宽度和换行规则下的高度、行数和换行位置。渲染目标覆盖 DOM、Canvas、SVG,服务端渲染在路线图上。

作者在 README 开头写的一句自述是:「Fast, accurate & supports all the languages you didn't even know about.」

为什么放在 Vibe Coding 分类

作者在 API 介绍里写了一句备注:「very AI-friendly iteration method」。这一点放到 Vibe Coding 场景里特别有意义。对 AI 辅助编码来说,纯算术的文本测量 API 有两个好处:

  • 不依赖浏览器运行时行为,LLM 可以完全在静态代码层面推理输出
  • prepare() / layout() 两阶段 API 的语义干净,AI 生成调用代码时出错率低

Vibe Coding 场景下经常要写自定义 editor、虚拟列表、富文本组件。这类项目里文本测量通常是最容易出问题的环节。传统做法依赖 getBoundingClientRectoffsetHeight 等 API,会触发 layout reflow,测量本身很慢,而且难以让 AI 生成可稳定复现的代码。Pretext 把这一层拆成纯函数计算,适合 AI 辅助开发的节奏。

两阶段 API

Pretext 把测量过程切成两个阶段:

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

// 阶段 1:一次性预计算
const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀', '16px Inter')

// 阶段 2:廉价热路径,resize 时反复调用
const { height, lineCount } = layout(prepared, textWidth, 20)

prepare() 做一次性重活:规范化空白、分段、应用 glue 规则、用 canvas 测量每个段,返回一个不透明句柄。之后在容器宽度变化或窗口 resize 时,反复调用 layout(),它是纯算术运算,不再碰 DOM。

这种切分的价值在于:高频重复发生的操作(滚动、resize、虚拟列表可见区域计算)走廉价路径,昂贵的测量只发生一次。同一个 prepared 句柄在不同宽度下可以无限次复用。

常用选项

需要保留空格、tab 和换行可见的 textarea 风格文本:

ts
const prepared = prepare(value, '16px Inter', { whiteSpace: 'pre-wrap' })

需要 CSS 的 word-break: keep-all 行为:

ts
const prepared = prepare(text, '16px Inter', { wordBreak: 'keep-all' })

多语言支持覆盖 CJK、阿拉伯语等 RTL 语言、emoji 等,作者的设计目标是「覆盖所有你没听过的语言」。

适用场景

  • 自定义富文本编辑器、代码编辑器、Markdown 编辑器
  • 虚拟列表或无限滚动中变长条目的高度预测
  • Canvas / SVG 图形应用中的文本布局
  • 需要在服务端预计算文本布局的 SSR 场景(路线图)
  • AI 辅助开发的 UI 组件,希望换行行为可被静态推理并可稳定复现

不适用场景

  • 只做单行文本显示,CSS 本身就够了
  • 只做一次性测量,getBoundingClientRect 一次调用足够
  • 需要极复杂的富文本样式(复杂混排、行内交互元素、表格等),这类需求仍然依赖 DOM

安装与示例

bash
npm install @chenglou/pretext

本地跑 demo:

bash
git clone https://github.com/chenglou/pretext.git
cd pretext
bun install
bun start
# 浏览器打开 /demos/index

作者也提供了在线演示:https://chenglou.me/pretext/

当前状态

当前版本号 0.0.5,属于早期阶段,API 仍可能变动。已经可用于生产环境的能力包括:DOM / Canvas / SVG 三种渲染目标、CJK 与 RTL 与 emoji 的多语言支持、pre-wrapkeep-all 等常见选项。服务端渲染在路线图上,尚未发布。License 为 MIT。

语言

TypeScript

分类

Vibe Coding

许可证

MIT

更新时间

4/11/2026

标签

text-layouttext-measurementtypographyline-breakingcanvassvgunicodedom-lessai-friendlyrtl
~/安装方式

# source

$npm install @chenglou/pretext
$git clone https://github.com/chenglou/pretext.git && cd pretext && bun install
$bun start

# usage

$import { prepare, layout } from '@chenglou/pretext'
$const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀', '16px Inter')
$const { height, lineCount } = layout(prepared, textWidth, 20)