Об этом проекте
Pretext — это чистая библиотека JavaScript/TypeScript для измерения многострочного текста и вычисления разметки строк. Она избегает DOM-API измерения, таких как `getBoundingClientRect` и `offsetHeight`, которые вызывают принудительный reflow, и вместо этого выполняет собственное измерение, используя браузерный canvas `measureText` как эталон. Это делает её полезной для виртуализации, пользовательских движков разметки, рендеринга в canvas/SVG и проверок переполнения во время разработки.
## Установка
```sh
npm install @chenglou/pretext
```
## Основные сценарии использования
### 1. Измерение высоты абзаца без обращения к DOM
```ts
import { prepare, layout } from '@chenglou/pretext'
const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀', '16px Inter')
const { height, lineCount } = layout(prepared, 320, 20)
```
`prepare()` выполняет однократную работу: нормализацию пробелов, сегментацию текста, применение правил склейки и измерение на основе canvas. Затем `layout()` — это дешёвая чисто арифметическая операция над кэшированными ширинами, поэтому её можно повторно запускать при изменении размера без повторной подготовки.
Опции для `prepare()` включают `whiteSpace: 'pre-wrap'` для поведения, похожего на textarea, `wordBreak: 'keep-all'` для CSS-подобного `word-break: keep-all` и `letterSpacing` для CSS `letter-spacing`.
### 2. Ручная разметка строк
`prepareWithSegments()` возвращает более богатую структуру для пользовательской разметки. Доступны следующие API:
- `layoutWithLines()` — возвращает все строки при фиксированной максимальной ширине, включая текст и измеренные ширины.
- `walkLineRanges()` — вызывает callback для каждой строки с шириной и начальным/конечным курсорами, без построения строк.
- `measureLineStats()` — возвращает количество строк и ширину самой широкой строки без аллокаций.
- `measureNaturalWidth()` — возвращает ширину самой широкой принудительной строки, когда ширина не является причиной переноса.
- `layoutNextLine()` / `layoutNextLineRange()` — API в стиле итератора для разметки строк по одной с потенциально разными ширинами, полезные для обтекания текстом плавающих элементов или динамических контейнеров.
- `materializeLineRange()` — преобразует диапазон разметки обратно в полную строку.
Это позволяет выполнять рендеринг в Canvas, SVG, WebGL и в перспективе в серверных средах. Демо включены в репозиторий и доступны на chenglou.me/pretext.
## Помощник для rich inline
Отдельный помощник в `@chenglou/pretext/rich-inline` поддерживает базовый inline-поток rich-text со смешанными шрифтами, атомарными элементами (например, чипами и упоминаниями) и дополнительной шириной, задаваемой вызывающей стороной, для оформления pill-элементов. Он намеренно узкий: только inline, только `white-space: normal`, и это не универсальный движок форматирования CSS inline.
## Основные пункты глоссария API
- `PreparedText` — непрозрачный быстрый дескриптор; `PreparedTextWithSegments` — более богатый дескриптор для ручной разметки.
- `LayoutCursor` использует индексы сегментов/графем, а не смещения в исходной строке.
- `layout()` для пустой строки возвращает `{ lineCount: 0, height: 0 }`; браузеры задают пустым блокам размер в один `line-height`, поэтому вызывающей стороне может потребоваться ограничение.
- Мягкие переносы поддерживаются: они действуют как необязательные точки переноса и материализуются как завершающий `-`, когда выбираются.
- `clearCache()` очищает общие внутренние кэши; `setLocale()` задаёт локаль для будущих вызовов подготовки.
- Более богатый дескриптор включает приблизительные `segLevels` для пользовательского bidi-осведомлённого рендеринга, но Pretext не реализует полный Unicode Bidirectional Algorithm.
## Ограничения
Pretext не является полноценным движком рендеринга шрифтов. Он нацелен на распространённые конфигурации CSS-текста:
- `white-space: normal` и `pre-wrap`
- `word-break: normal` и `keep-all`
- `overflow-wrap: break-word`
- `line-break: auto`
- `letter-spacing` как числовое значение в пикселях
- Табы следуют значению по умолчанию `tab-size: 8`
Заметные ограничения:
- `system-ui` и `-apple-system` небезопасны на macOS для точности `layout()`; рекомендуется именованный шрифт.
- Эмодзи рядом с пунктуацией могут переноситься иначе, чем в браузере.
- Некоторые шрифты, например Shantell Sans, могут давать другие переносы строк в длинных словах.
- Во время выполнения требуются `Intl.Segmenter`, измерение текста через Canvas 2D и Unicode property escapes.
- Возможности CSS-шрифтов за пределами сокращённой записи `font` для canvas не моделируются отдельно.
В целом Pretext позиционируется как специализированная библиотека для измерения многострочного текста, дающая веб-разработчикам быструю и детерминированную альтернативу запросам к разметке браузера.
Comments
0 Rating appears after 10 ratings
Sign in to join the discussion.