快速、精确,支持你甚至不知道存在的各种语言。绕过 DOM 测量,零回流。可渲染到 DOM、Canvas、SVG。
绕过 getBoundingClientRect 和 offsetHeight,以浏览器自身的字体引擎作为基准真值。
不依赖任何 DOM 测量 API。prepare() 一次预计算,layout() 纯算术复用——窗口大小变化时只需重新调用 layout(),无需重新 prepare。
中文、阿拉伯语、Emoji、混合双向文本……你能想到的所有语言和文字系统,并针对特定浏览器怪异行为做了处理。
渲染到 DOM、Canvas、SVG、WebGL,服务端渲染即将支持。手动排版每一行,自由控制输出方式。
无需估算和缓存的精确虚拟化/遮挡剔除。已知高度让你的滚动列表如丝般顺滑。
从简单的高度测量到逐行排版,从固定宽度到变宽排版(文字环绕浮动图片),从全量行信息到仅行宽回调——API 覆盖从简到繁的所有场景。
返回的高度信息让这些曾经棘手的问题变得简单。
无需估算行高、无需缓存,直接拿到精确高度用于虚拟滚动列表。
瀑布流、JS 驱动的类 flexbox 实现、无需 CSS hack 即可微调布局值。
AI 时代自动验证按钮文字不会溢出到下一行,无需打开浏览器。
新文本加载前即可知道高度,便于重新锚定滚动位置、消除 CLS。
从简单的段落高度测量,到完整的手动行排版。
import { prepare, layout } from '@chenglou/pretext' // 一次性预处理:规范化、分段、测量 const prepared = prepare( 'AGI 春天到了. بدأت الرحلة 🚀', '16px Inter' ) // 纯算术运算,无 DOM 布局和回流! const { height, lineCount } = layout(prepared, textWidth, 20) // pre-wrap 模式:保留空格、制表符和换行 const prepared2 = prepare( textareaValue, '16px Inter', { whiteSpace: 'pre-wrap' } ) const { height: h2 } = layout(prepared2, textareaWidth, 20)
import { prepareWithSegments, layoutWithLines } from '@chenglou/pretext' const prepared = prepareWithSegments( 'AGI 春天到了. بدأت الرحلة 🚀', '18px "Helvetica Neue"' ) // 获取所有行信息 const { lines } = layoutWithLines(prepared, 320, 26) // 渲染到 Canvas for (let i = 0; i < lines.length; i++) ctx.fillText(lines[i].text, 0, i * 26)
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 }
// Web 一直缺失的功能:多行"收缩包裹" let maxW = 0 walkLineRanges(prepared, 320, line => { if (line.width > maxW) maxW = line.width }) // maxW 就是最紧凑容器宽度 // 可通过二分搜索 + walkLineRanges 找到理想宽度
从简单测量到精细排版,覆盖所有场景。
一次性文本分析 + 测量。规范化空白字符、分段、应用粘连规则、测量分段宽度。返回不透明句柄。font 格式同 canvas context,如 16px Inter。options 支持 { whiteSpace: 'pre-wrap' }。
根据最大宽度和行高计算文本高度。纯算术运算,是低开销热路径。窗口 resize 时只需重新调用 layout()。
与 prepare() 相同,但返回更丰富的结构以满足手动行排版需求。
接受固定最大宽度,返回所有行信息(text, width, start, end)。
底层 API,每行调用回调传入行宽和游标,不构建文本字符串。适用于二分搜索理想宽度、收缩包裹、平衡排版等场景。
迭代器 API,每行可使用不同宽度。返回从 start 开始的一行,段落用尽返回 null。实现文字环绕等效果。
清除 Pretext 内部共享缓存。当应用循环使用大量不同字体或文本变体时可释放累积缓存。
为后续的 prepare() 和 prepareWithSegments() 设置语言环境。内部也会调用 clearCache()。不影响已有的预处理状态。
Pretext 并不试图成为完整的字体渲染引擎,目前针对常见文本设置优化。
white-space: normal、word-break: normal、overflow-wrap: break-word、line-break: auto{ whiteSpace: 'pre-wrap' } 后,普通空格、\t 制表符和 \n 硬换行将被保留。制表符遵循浏览器默认 tab-size: 8system-ui 对 layout() 精度不安全,请使用具名字体overflow-wrap: break-word)