mcpField
P
pretext

pretext

github.com/akillness设计与 UI53258 次安装今天更新
代码仓库

关于 pretext

pretext 是一个 JavaScript/TypeScript 库,使用缓存的字体度量来测量和排版多行文本,无需触发 DOM 重排。它适用于需要行布局与高度计算的渲染及服务端场景。

主要功能

  1. 01测量多行文本高度与行数
  2. 02按行布局并访问文本片段
  3. 03计算收缩包裹宽度
  4. 04设置空白、断词和字距选项
  5. 05输出到 DOM、Canvas、SVG 和 SSR

适用场景

  1. 01无需 DOM 测量即可计算段落高度
  2. 02排版环绕浮动图片的文本
  3. 03渲染多语言及表情符号文本
  4. 04在性能关键循环中避免重排

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/akillness/jeo-skills --skill pretext

安装后在 Claude Code 中输入/pretext确认已加载。

附带文件SKILL.toon

详细介绍

pretext — 快速多行文本测量与排版

不触发 DOM 回流。基于缓存字体度量进行纯算术计算。

pretext 是一个纯 JavaScript/TypeScript 库,可快速、准确、全面地测量和排版多行文本,且不会触发 getBoundingClientRect、offsetHeight 或任何其他 DOM 回流操作。

安装

插件(Claude Code)
claude plugin marketplace add chenglou/pretext
npm
npm install @chenglou/pretext
技能(任何平台)
npx skills add https://github.com/akillness/jeo-skills --skill pretext

适用场景

  • 无需在 DOM 中测量,即可计算段落高度和行数
  • 为环绕浮动图片或宽度可变的容器的文本构建手动换行布局
  • 处理包含 emoji、CJK 字符、RTL 文本和多语言混合内容的富文本
  • 使用准确的度量数据将测量后的文本渲染到 DOM、Canvas 或 SVG
  • 实现软连字符断词、字母间距或基于区域设置的断词
  • 避免在性能关键型渲染循环中触发布局回流
  • 服务端文本测量(适用于 SSR)

不适用场景

  • 需要完整的 CSS 文本引擎保真度 → 直接依赖 DOM 测量
  • 需要 OpenType 特性支持(连字、字距调整表)→ 使用专用字体整形库
  • 需要 PDF 文本排版 → 使用 PDF 生成库
  • 目标环境不支持 Intl.Segmenter 和 Canvas 2D

核心 API

用例 1:高度测量

通过纯算术计算段落高度和行数——调用 prepare() 后无需访问 DOM。

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

// One-time analysis + font measurement (cached)
const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀‎', '16px Inter')

// Pure arithmetic — no DOM interaction
const { height, lineCount } = layout(prepared, 320, 20)
// width: 320px container, lineHeight: 20px
用例 2:手动换行布局

访问每一行,以便进行自定义渲染(例如,让文本环绕浮动图片)。

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

const prepared = prepareWithSegments('Text here', '18px "Helvetica Neue"')
const { lines } = layoutWithLines(prepared, 320, 26)

for (const line of lines) {
  // line.text, line.y, line.width, line.segments
}
用例 3:收缩包裹宽度

查找可容纳文本且不会换行的最小容器宽度。

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

const prepared = prepare('Hello world', '14px system-ui')
const { width } = shrinkWrap(prepared, 26)

选项参考

选项类型值描述
whiteSpacestring'normal' | 'pre-wrap''pre-wrap' 会保留空白(textarea 样式)
wordBreakstring'normal' | 'keep-all''keep-all' 可防止 CJK 文本在词中间断行
letterSpacingnumber像素等效于 CSS 的字母间距
const prepared = prepare(text, font, {
  whiteSpace: 'pre-wrap',
  wordBreak: 'keep-all',
  letterSpacing: 1.5,
})

要求

  • Intl.Segmenter API(基于区域设置的词语/字素分段)
  • Canvas 2D 文本测量(CanvasRenderingContext2D.measureText)
  • 支持现代浏览器和 Node.js 16+(Node 中需安装 canvas 包)

输出目标

目标说明
DOM使用 lines + 绝对定位或 transform: translateY
Canvas使用 lines[i].y + ctx.fillText
SVG使用 lines[i].y + <text y=...> 元素
SSR在服务端计算高度;在客户端完成位置水合

操作规则

  1. 每组唯一的(文本、字体)组合只调用一次 prepare() / prepareWithSegments()——这是耗时步骤
  2. 在相同文本需要按不同宽度测量时,缓存 prepared 对象
  3. 可随时调用 layout() / layoutWithLines()——它们仅执行纯算术运算,没有副作用
  4. 在非浏览器环境中初始化前,务必检查 Intl.Segmenter 是否可用
  5. 先使用 shrinkWrap 查找最小宽度,再按固定容器宽度测量
  6. 需要逐行访问片段以进行富文本渲染时,优先使用 prepareWithSegments,而非 prepare

示例

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

// Basic height check
const p = prepare('Hello, 世界! 🌏', '16px sans-serif')
console.log(layout(p, 200, 20))  // { height: 20, lineCount: 1 }

// Variable-width layout (text around floated image)
const ps = prepareWithSegments('Long article text...', '16px Georgia')
const { lines } = layoutWithLines(ps, (lineIndex) => {
  return lineIndex < 5 ? 200 : 320  // narrower for first 5 lines
}, 24)

来源:chenglou/pretext — MIT 许可证

评论

支持 Markdown