- bidi 方向
。值注緩存估算值、得关它把文本從“渲染後才知道”變成“生成前就知道”,文本因為它就是排版數組索引 + 加減法 。卻能實時拖拽窗口自適應。引擎接著對每段用 Canvas.measureText 測寬度,值注現在同一份 prepared 數據
,得关行高也要對齊
,文本預先把文本拆成最小可測量單元,排版就加選項:
const prepared = prepare(textareaValue,引擎 '16px Inter', { whiteSpace: 'pre-wrap' })性能數據(官方基準):prepare 對 500 條混合文本批次大概 19ms,實際項目裏 ,值注
以前用 DOM 測量 + requestAnimationFrame 節流 ,得关
我特別欣賞它對 whiteSpace 的文本處理 。Firefox 各自的排版換行 quirks 。
不止性能
虛擬化列表。引擎自己對齊瀏覽器 quirks),
當然,它剛剛發布 ,讓智能界麵真正智能起來。你都得問瀏覽器“這個文本在多寬容器裏到底占多少高”。測量結果可預測。字重、還特別處理了 Safari 、實時流式輸出時 ,絕大多數業務場景夠用 :
import { prepare, layout } from '@chenglou/pretext'const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀', '16px Inter')const { height, lineCount } = layout(prepared, 300, 24) // 寬度 300px,我強烈建議用 AI 玩一玩 demos 。自己算換行、實際是瀏覽器字體引擎 + Unicode 規範 + 各家實現差異的超級複雜組合,包括 CJK、
不是取代 CSS
很多人問 :這不就是把 CSS 活搶了嗎 ?比如 CSS Shapes,以前 CSS 隻能給你最終渲染結果,全都可編程 。它不是萬能藥 。性能直接雪崩。另一套給“手動控製每一行”的高級玩法。文本不再是瓶頸,
高級 API 更狠,標點禁則 、適合頻繁切換字體的大應用。SVG 、就是證明。scroll position 直接算。輸入最大寬度和行高,聊天氣泡自動 shrinkwrap、emoji 、傾斜閱讀 、適合二分搜索最優容器寬度(比如聊天氣泡 shrinkwrap) 。Flex、卻能完美匹配瀏覽器字體引擎在各種語言、layoutWithLines 直接給你每行完整文本和寬度 。你在組件 mount 時 prepare 一次 ,作者設計時就考慮了 AI 友好 :API 極簡,卻依然用同一套測量引擎 。用 Canvas 測量每段寬度 、想怎麽玩就怎麽玩。核心思路是用瀏覽器自己的 Canvas 作為真理源頭,resize 或寬度變化時隻跑 layout,作者 Cheng Lou 之前在 React、
對比以前手寫 Canvas 文本布局的痛苦(自己測寬度 、walkLineRanges 更底層 ,又在 Midjourney 幹過視覺生成 ,硬換行可見,複雜排版規則如 full justification 的高級微調還在社區擴展中 。normal 模式下自動合並空白、不碰 DOM,緩存結果,它是聲明式 、作者用 AI 迭代對齊瀏覽器行為,虛擬列表、這就是為什麽它能跨瀏覽器精確:不是自己造輪子,混合 bidi ,
參考資料
- github.com/chenglou/pretext
- Pretext Demos
- 試試這個小遊戲
let cursor = { segmentIndex: 0, graphemeIndex: 0 }let y = 0while (true) { const width = (y < imageBottom) ? columnWidth - imageWidth : columnWidth const line = layoutNextLine(prepared, cursor, width) if (!line) break // 渲染 line.text cursor = line.end y += lineHeight}這些 API 把文本從“黑盒”變成“可編程對象” 。你隻需要專注業務邏輯。最優寬度二分搜索、

先說清楚它解決什麽痛點。一套給“隻需要高度”的場景 ,歡迎 PR 。
我覺得這是過去十年裏最值得關注的文本引擎之一。還跨瀏覽器一致 。多次 prepare 相同文本和字體直接複用 。行高 24px
prepare 做一次性重活:規範化空白 、希伯來文、虛擬化邏輯簡化成線性遍曆高度緩存 ,它讓你寫更絲滑的列表、對著瀏覽器真實渲染結果反複比對 ,不拚接字符串,
布局偏移(CLS)徹底消失