PretextでDOMを触らずに複数行テキストを配置する
Pretext は、Canvas、DOM、OpenType データを使用して Web アプリケーション内の多言語テキストを測定してレイアウトし、予測可能な改行と寸法を生成します。
ひと目でわかる
- これは何?
- Canvasのフォント計測を基準に、文章の高さや行範囲を計算するTypeScriptライブラリのAPI、適用範囲、ブラウザ依存の注意点を見ます。
- 誰に向いている?
- 向いているのは、仮想化リスト、可変幅のCanvas描画、リサイズ時の再計算などで、DOMのレイアウト計測を減らしたいフロントエンド実装です。完全なCSS組版や自動ハイフネーションが必要な用途には足りません。
- 商用利用できる?
- できます。MIT は寛容なライセンスで、著作権表示とライセンス表示を残せば、使用・改変・販売が可能です。
- 今もメンテナンスされている?
- されています。直近 1 日以内に新しいコミットがあります。
- 何の言語で書かれている?
- 主に TypeScript です(GitHub の言語統計による)。
回答はプロジェクトの GitHub データ(最終同期:2026年9月15日)と当サイトの分析に基づくもので、法的助言ではありません。
オープンソース詳細解説
ブラウザの再レイアウトを避ける計測層
Pretextは複数行テキストの計測とレイアウトを行うJavaScriptまたはTypeScriptライブラリです。`getBoundingClientRect`や`offsetHeight`のようなDOM計測を使わず、ブラウザ自身のフォントエンジンをCanvasで参照し、セグメントごとの幅から行を組み立てます。READMEはDOM、Canvas、SVG、将来的なサーバーサイドへの描画を用途として挙げています。
狙いはフォントを再現することではなく、ブラウザの計測結果を使って高さや改行位置を先に得ることです。したがって、CSSのfont指定、文字間隔、利用可能な幅が実際の表示側とずれると結果もずれます。ライブラリ単独で全ブラウザの組版を置き換えるものだと解釈しない方がよいでしょう。
prepareを一度、layoutを何度も呼ぶ
基本APIは二段階です。`prepare(text, font, options)`が空白の正規化、セグメント化、結合規則の適用、Canvasによる幅の計測を行い、再利用する不透明な値を返します。`layout(prepared, maxWidth, lineHeight)`はキャッシュ済みの幅から高さと行数を算術的に計算します。同じテキストと設定で`prepare`を繰り返すと事前計算の効果が失われるため、リサイズ時は`layout`だけを呼び直します。
`whiteSpace: 'pre-wrap'`なら通常の空白、タブ、改行を残せます。`wordBreak: 'keep-all'`と数値の`letterSpacing`も指定できます。空文字列は行数0、高さ0になる一方、ブラウザの空ブロックはline-height分の高さになる場合があるため、UIの仕様に応じて呼び出し側で扱いをそろえます。
高さの計算が効くUIの箇所
READMEは、推測値や固定キャッシュに頼らない仮想化とオクルージョン、masonryやJavaScript駆動のflexbox風配置、ボタンなどの文字が次の行へあふれない開発時検証、新しい文章の読み込みによるレイアウトシフトの抑制を用途として説明しています。
たとえば記事カードを仮想化する場合、表示前に本文の高さを得てスクロール領域を予約できます。リサイズ時の計算はキャッシュを再利用できるため、DOMの高さを読み取ってから書き換える往復を減らせます。ただし、フォントが未ロードの状態やOS固有のフォント差は残ります。実際のフォントロード後にも境界幅のサンプルを使って誤差を測る必要があります。
行文字列を自分で描画する低レベルAPI
`prepareWithSegments`と`layoutWithLines`を使うと、固定幅で分割された各行を受け取れます。`measureLineStats`は行数と最大幅、`walkLineRanges`は文字列を新しく作らずに行範囲と幅を扱うAPIです。`layoutNextLineRange`は行ごとに幅を変えられるため、画像の横だけ狭い本文やCanvas上の独自レイアウトに向きます。必要なら`materializeLineRange`で範囲を文字列に戻します。
`@chenglou/pretext/rich-inline`は、異なるフォントの断片、メンション、チップ、装飾用の`extraWidth`、分割禁止の`break: 'never'`を扱います。対象は通常のインラインテキストで、white-space: normalに限定されています。ネストしたマークアップツリーや一般的なCSSインラインエンジンを実装するAPIではありません。
対応範囲をCSSの名前で確認する
READMEで説明されている範囲は、white-spaceのnormalとpre-wrap、word-breakのnormalとkeep-all、overflow-wrapのbreak-word、line-breakのauto、ピクセル値のletter-spacingです。タブ幅はブラウザ既定のtab-size: 8として扱われ、ソフトハイフンは選ばれた改行位置でだけ可視化されます。自動ハイフネーションは内蔵されていません。
実行時には`Intl.Segmenter`とCanvas 2Dのテキスト計測が必要で、Intl.Segmenterのない環境はサポートされません。READMEはmacOSの`system-ui`を`layout()`の精度にとって安全でないフォントとして扱い、プラットフォームのバグ台帳を案内しています。採用前に対象ブラウザ、フォント、混在言語、絵文字、タブを含む実データで行数と最大幅を比較するのが先です。
npm導入とMITライセンス
パッケージは`npm install @chenglou/pretext`で導入できます。デモを動かす場合はリポジトリをクローンし、`bun install`、`bun start`を実行して`/demos/index`を開きます。Windowsでは`bun run start:windows`がREADMEに記載されています。ライブデモと別のデモ群へのリンクも提供されています。
ライセンスはMITで、ソフトウェアは現状のまま提供され保証はありません。READMEにはバージョン番号、性能ベンチマーク、本番結果、セキュリティ体制の確約は見当たりません。導入の評価記録には、実行したパッケージ版、使用フォント、ブラウザ、`lineCount`と表示結果の差を残すと、DOM計測を置き換える判断を具体化できます。
リサイズと多言語入力を小さなケースで測る
Pretextを組み込む前に、同じ文字列へ`prepare`を一度だけ適用し、幅320、240、160の順で`layout`を呼びます。高さと`lineCount`がCSSの実表示と一致するか、フォントロード前後で差が出るかを記録します。日本語、英語、アラビア語、絵文字、タブ、ソフトハイフンを一つのテストセットに含めます。
Canvas描画では`prepareWithSegments`と`layoutWithLines`を使い、最も幅の広い行を`measureLineStats`で確認します。浮動画像のケースでは`layoutNextLineRange`の幅を上下で変え、行文字列を`materializeLineRange`で描画します。Pretextが扱わない自動ハイフネーションやネストしたCSSを期待していないことも、テスト結果と一緒に残します。
編集部の結論
向いているのは、仮想化リスト、可変幅のCanvas描画、リサイズ時の再計算などで、DOMのレイアウト計測を減らしたいフロントエンド実装です。完全なCSS組版や自動ハイフネーションが必要な用途には足りません。最初に対象ブラウザで`prepare`と`layout`の結果を実測し、フォント、letterSpacing、Canvasの幅をCSSと一致させてから導入してください。
コミュニティノート