[Girhub发现]Pretext – 不碰 DOM 的纯 JS 多行文本测量库

Github发现2026-04-02发布 WarpEdit
8 0 0

做前端开发的都知道,多行文本的高度测量一直是个头疼的问题。传统做法要么用 getBoundingClientRect,要么靠 offsetHeight,这些都会触发浏览器的重排(layout reflow),性能开销相当大。

今天要介绍的 Pretext 这个开源库,就是来解决这个痛点的——它能精确测量多行文本的高度和布局,而且完全不碰 DOM,纯靠 Canvas 和数学计算搞定。

Pretext GitHub 仓库截图

Pretext 的核心原理很有意思:它借用浏览器自己的字体引擎作为”ground truth”,通过 Canvas 的 measureText 来做文本测量,然后用纯数学方式计算行数和高度。这样既能保证测量精度,又能避免 DOM 操作带来的性能损耗。

31.8k 的 Stars 摆在这儿,说明确实有两把刷子。

相关链接

Pretext 是什么

Pretext 是一个纯 JavaScript/TypeScript 编写的多行文本测量与布局库。它的核心价值在于:在不触碰 DOM 的情况下,精确计算出多行文本的高度、行数,甚至每一行的具体内容。

作者是 chenglou,MIT 协议开源,目前已经斩获了 31,872 Stars1,649 Forks,妥妥的明星项目。

这个库的设计思路受到了 Sebastian Markbage 十年前的项目 text-layout 启发,在此基础上发展出了更完善的架构。

核心功能

Pretext 提供了两套 API,满足不同的使用场景:

1. 快速测量文本高度(不碰 DOM)

这是最常用的场景。你只需要调用 prepare() 做一次预处理,然后反复调用 layout() 获取高度:

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

const prepared = prepare("AGI 春天到了. 시작했다 journey 🚀", "16px Inter")
const { height, lineCount } = layout(prepared, textWidth, 20)

性能数据:

  • prepare() 单次处理 500 条文本约 19ms
  • layout() 热路径每次仅需 0.09ms

如果你需要支持 Textarea 风格的文本(保留空格、Tab、换行),可以传入 { whiteSpace: "pre-wrap" } 选项:

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

2. 手动控制每一行的布局

换用 prepareWithSegments API,你可以逐行获取文本内容,甚至动态改变每行的宽度:

import { prepareWithSegments, layoutWithLines } from "@chenglou/pretext"

const prepared = prepareWithSegments("AGI 春天到了. 시작했다 journey 🚀", "18px \"Helvetica Neue\"")
const { lines } = layoutWithLines(prepared, 320, 26)

for (let i = 0; i < lines.length; i++) {
  ctx.fillText(lines[i].text, 0, i * 26)
}

更高级的玩法是 walkLineRanges(),它只返回每行的宽度和光标位置,不构建完整的文本字符串,非常适合做二进制搜索宽度、shrink-wrap 布局等高级操作。

还有 layoutNextLine(),支持动态宽度——这在文字环绕浮动元素(如图片)的场景下特别有用:

let cursor = { segmentIndex: 0, graphemeIndex: 0 }
let y = 0

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
}

应用场景

Pretext 的价值在于解锁了一些以前很难实现的 Web UI 能力:

  • 虚拟滚动/可视区域渲染:不用再靠估算或缓存来预测列表项高度,可以精确计算
  • 瀑布流/Masonry 布局:纯 JS 实现的灵活布局,不再依赖 CSS
  • 防止布局抖动(CLS):文字加载前就能预留精确高度,滚动位置不会跳
  • 无浏览器环境的文本验证:特别是现在 AI 代码生成场景,可以验证按钮标签会不会溢出
  • Canvas/SVG/WebGL 渲染:手动控制每一行的绘制,适配各种自定义渲染需求

快速部署

安装

npm install @chenglou/pretext
# 或者
bun add @chenglou/pretext

运行 Demo

git clone https://github.com/chenglou/pretext.git
cd pretext
bun install
bun start
# 然后打开 /demos(注意不要加末尾斜杠)

注意事项

Pretext 并非要做一个完整的字体渲染引擎,它目前针对的是常见的文本场景:

  • white-space: normal
  • word-break: normal
  • overflow-wrap: break-word
  • line-break: auto

另外,system-ui 字体在 macOS 上可能导致 layout() 精度问题,建议使用具体的字体名称。

适用人群

  • 前端开发:需要精确文本测量来优化性能的工程师
  • UI 库开发者:正在构建虚拟列表、瀑布流等复杂布局的开发者
  • Canvas/WebGL 开发者:需要在画布上渲染文本的工程师
  • AI 代码生成场景:需要无浏览器环境验证文本布局的开发者

总结

Pretext 解决的是一个看似小但实际很关键的问题——多行文本的精确测量。通过预计算 + 纯数学热路径的思路,它实现了又快又准的文本布局能力。

31.8k Stars、1.6k Forks 的数据说明社区对这类工具确实有强需求。如果你也在被文本高度计算折磨,不妨试试 Pretext,说不定就打开新世界了。

© 版权声明

相关文章

暂无评论

none
暂无评论...