25. August 2026 · Von YasKad
chenglou/pretext

Pretext: mehrzeiligen Text messen und verteilen, ohne das DOM zu berühren

chenglou/pretext · 50.570★ · 2.739 forks

Alles Wissenswerte über chenglou/pretext: eine JavaScript/TypeScript-Bibliothek, die die Höhe, den Zeilenumbruch und die Bereiche eines Absatzes berechnet, indem sie die Typografie-Engine des Browsers als Referenz nutzt — ohne DOM-Knoten auf dem heißen Pfad einzufügen oder zu messen.

Desambiguierung: Dieser Bericht dokumentiert chenglou/pretext (Textmessungs-Bibliothek, npm-Paket @chenglou/pretext, erstellt im März 2026). Nicht zu verwechseln mit PreTeXtBook/pretext (459 Sterne), einem Autoren- und Veröffentlichungssystem für akademische Dokumente, oder mit pretext-project/pretext-project.github.io, einer Sammlung von Social-Engineering-Vorwänden.


Was Pretext ist

Pretext ist eine JavaScript/TypeScript-Bibliothek zum Messen und Verteilen mehrzeiliger Absätze. Sie löst eine Operation, die klein erscheint, aber viele Oberflächen prägt: zu wissen, wie viele Zeilen ein Text bei einer gegebenen Breite einnehmen und wie hoch er sein wird, ohne ihn im DOM zu rendern und getBoundingClientRect() oder offsetHeight abzufragen — Lesevorgänge, die eine Neuberechnung des Layouts (Reflow) erzwingen, eine der teuersten Operationen im Browser.

Das Projekt trennt zwei Operationen. prepare() erledigt die Arbeit, die vom Text und der Schriftart abhängt — Leerzeichen normalisieren, mit Intl.Segmenter segmentieren, „Klebe”-Regeln anwenden (NBSP, ZWSP, weiche Trennstriche, harte Umbrüche) und die Segmente mit Canvas messen — und liefert ein wiederverwendbares opakes Handle. layout() nimmt dieses Ergebnis, eine maximale Breite und eine Zeilenhöhe entgegen und berechnet height und lineCount durch Arithmetik über zwischengespeicherte Breiten. Bei einer Größenänderung oder in einem Virtualisierungsdurchlauf läuft nur der zweite Teil erneut, nicht die gesamte Analyse.

Pretext versucht nicht, die CSS-Layout-Engine zu ersetzen oder zu einer vollständigen Schriftrendering-Engine zu werden. Es ist ein spezialisiertes Werkzeug für den Fall, dass man einen Textfluss aus JavaScript heraus vorhersagen oder kontrollieren muss: Virtualisierung, Canvas, SVG, WebGL, dynamisches redaktionelles Design, Animation, Etikettenvalidierung während der Entwicklung und (laut README demnächst) serverseitiges Rendering.

Der Ursprung

Das Repository wurde am 7. März 2026 von Cheng Lou (chenglou) erstellt, der laut Simon Willisons Blog zuvor React-Core-Entwickler und der ursprüngliche Schöpfer der Animationsbibliothek react-motion (21.914 Sterne) war. Das Paket @chenglou/pretext wurde erstmals am 27. März 2026 auf npm veröffentlicht (Version 0.0.0); das GitHub-Repository stammt von etwa zwanzig Tagen zuvor, was auf eine private Entwicklung vor dem öffentlichen Launch hindeutet.

Das README erkennt explizit das Projekt text-layout von Sebastian Markbåge als Vorläufer an (ein Fork bleibt erhalten, chenglou/text-layout, mit 34 Sternen) sowie dessen Architektur: measureText von Canvas für das Shaping, bidi-Daten basierend auf pdf.js und Streaming-Zeilenumbrüche. Das README beschreibt zudem eine besondere Entwicklungsmethode: Die Engine wurde „sehr KI-freundlich” iteriert, indem Coding-Agenten wie Claude Code und Codex die Ground Truth des Browsers gezeigt und sie über Wochen hinweg dazu gebracht wurden, bei jeder relevanten Containerbreite dagegen zu messen und zu iterieren.

Die Verifizierung ist ein charakteristisches Merkmal des Ursprungs: Tests renderten eine vollständige Kopie von Der große Gatsby in mehreren Browsern, um zu bestätigen, dass die geschätzten Messungen korrekt waren, und später kam der Ordner corpora/ mit derselben Methode über lange gemeinfreie Dokumente auf Thai, Chinesisch, Koreanisch, Japanisch, Arabisch und anderen hinzu.

Visuell reichhaltige mehrsprachige Textlayout-Szene: abstrakte Glyphen-Cluster, die Koreanisch, arabisches RTL, Chinesisch, Thai, Japanisch und Emoji-Zeichen darstellen, fließen über eine dunkle Cyberpunk-Leinwand, bidirektionale Textsegmente krümmen sich umeinander mit neonfarbenen Richtungspfeilen, Zeilenumbruch-Entscheidungen werden als leuchtende Nähte zwischen Graphemen gezeigt, ein schwaches offenes Buch im Hintergrund verweist auf lange gemeinfreie Validierungsdokumente, die Komposition vermittelt Genauigkeit über Sprachen, komplexe Schriftsysteme, gemischten RTL/LTR-Inhalt und plattformspezifisches Emoji-Rendering hinweg, ultra-detailliert, 8K-Auflösung, Dark Mode, Cyberpunk-/Tech-Ästhetik, Neon-Akzente, kein lesbarer Text.

Philosophie und Prinzipien

Ihr Kernprinzip ist es, das Teure vom Wiederholbaren zu trennen: einmal analysieren und messen, und Zeilenumbrüche bei vielen Breiten mit zwischengespeicherten Daten neu berechnen. Das README warnt wörtlich: „Führe prepare() nicht erneut für denselben Text und dieselbe Konfiguration aus; das würde seine Vorberechnung zerstören.” Das ist der Leistungsvertrag: prepare() ist teuer, aber einmalig; layout() ist der heiße Pfad — sub-millisekundenschnell, ohne DOM-Lesevorgänge, ohne Canvas-Aufrufe und ohne String-Arbeit.

Konzeptionelles Cyberpunk-Diagramm zur Leistungsphilosophie: eine teure Vorbereitungsphase wird als dichte leuchtende Schmiede dargestellt, die Text einmal analysiert, während sich viele billige Layoutphasen in wiederholte Neon-Zeilenberechnungen über wechselnde Breiten hinweg auffächern, ein geisterhafter Browser-Layoutbaum wird vollständig umgangen, Reflow und Layout-Thrashing werden als vermiedene defekte rote Schaltkreise dargestellt, das Bild betont die Trennung von kostspieliger Analyse und wiederholbarer Verteilung, die Referenz auf die Browser-Font-Engine und einen bewusst engen, CSS-kompatiblen Umfang, ultra-detailliert, 8K-Auflösung, Dark Mode, Cyberpunk-/Tech-Ästhetik, Neon-Akzente, kein lesbarer Text.

Ein weiteres Prinzip, sichtbar im Code und in der internen Dokumentation, ist die Nutzung der Font-Engine des Browsers als Referenz, statt ganz CSS neu zu erfinden. Pretext modelliert CSS-Eigenschaften, die außerhalb der canvas.font-Abkürzung liegen (wie font-optical-sizing oder font-feature-settings), nicht separat und beschränkt sein Ziel auf gängige Textkonfigurationen: white-space: normal und pre-wrap, word-break: normal und keep-all, overflow-wrap: break-word, line-break: auto und letter-spacing als numerischer Pixelwert. Diese bewusste Enge erklärt sowohl seine relative Präzision als auch seine Grenzen.

Der Ansatz zur Korrektur plattformspezifischer Eigenheiten — ein Bug-„Kontobuch” (PLATFORM_BUGS.md) mit Links zu Chromium, Mozilla und WebKit, Reproduktionen und per Fähigkeitserkennung ausgelösten Korrekturen — spiegelt eine Philosophie der Ehrlichkeit wider: Statt universelle Genauigkeit zu versprechen, dokumentiert es, wo es von jedem Browser abweicht und wie das gemildert wird.

Cyberpunk-Buchhaltungsvisualisierung für die Verfolgung von Plattform-Bugs: ein leuchtendes holografisches Kontobuch öffnet sich, um Einträge für Chromium-, Mozilla- und WebKit-Eigenheiten zu offenbaren, jeder Bug erscheint als kleiner Neon-Chip mit Reproduktions-Icons, Milderungs-Schilden und Fähigkeitserkennungs-Markern, schwache Browser-Engine-Logos werden als Wireframe-Schaltkreismuster abstrahiert, die Gesamtstimmung ist ehrlich, präzise und systemorientiert und betont dokumentierte Abweichung von echten Browsern statt universeller Perfektion, ultra-detailliert, 8K-Auflösung, Dark Mode, Cyberpunk-/Tech-Ästhetik, Neon-Akzente, kein lesbarer Text.

Wie es funktioniert

Der Browser berechnet die endgültige Größe eines Elements innerhalb eines Baums aus Stilen, Schriftarten, Containern und Flussregeln. Das Abfragen von Geometrie nach DOM-Änderungen kann ihn zwingen, diese Arbeit zu synchronisieren. Für eine Handvoll statischer Etiketten ist das irrelevant; bei großen Listen, in Streaming eintreffenden Nachrichten, Animationen oder vielen Höhenkorrekturen erzeugt das Abwechseln von Schreib- und Lesevorgängen Layout-Thrashing und sichtbare Sprünge.

Pretext umgeht den Layoutbaum für die Schätzung. Es nutzt CanvasRenderingContext2D.measureText(), das Textmetriken gemäß der aktiven Schriftart zurückgibt, als Messreferenz; danach setzt es die Zeilen im Nutzercode zusammen. Der Vorteil ist nicht, dass Canvas magisch schneller als CSS insgesamt ist, sondern dass der heiße Pfad von layout() weder ein temporäres Element einfügen noch Geometrie vom DOM erfragen muss.

Detaillierte Cyberpunk-Visualisierung der Vorbereitungsphase einer Textmessungs-Bibliothek: ein Strom abstrakter glyphenartiger Zeichen tritt in eine leuchtende Pipeline ein, durchläuft einen segmentierten Graphem-Splitter, Leerzeichen-Normalisierungsknoten und Canvas-Messsonden, winzige Neon-Marker stellen geschützte Leerzeichen, Nullbreiten-Leerzeichen, weiche Trennstriche und harte Zeilenumbrüche dar, ein wiederverwendbares opakes Handle entsteht als kompaktes leuchtendes Token, der Hintergrund ist gefüllt mit schwachen Schriftmetriken, UTF-16-Codeeinheiten und Intl.Segmenter-ähnlichen Gittermustern, ultra-detailliert, 8K-Auflösung, Dark Mode, Cyberpunk-/Tech-Ästhetik, Neon-Akzente, kein lesbarer Text.

Der Kern folgt dieser Sequenz:

  1. Vorbereitung. prepare(text, font, options) nimmt den Text und einen Font-Wert im von Canvas akzeptierten Format entgegen (zum Beispiel 16px Inter). Es segmentiert den Inhalt, misst die Abschnitte einmal und liefert ein opakes Handle. Optionen: { whiteSpace: 'pre-wrap' }, um Leerzeichen, Tabulatoren und harte Umbrüche zu erhalten; { wordBreak: 'keep-all' } für word-break: keep-all (CJK/Hangul); { letterSpacing: n } in CSS-Pixeln.
  2. Verteilung. layout(prepared, maxWidth, lineHeight) löst auf, wie viele Zeilen passen, und liefert { height, lineCount }. Es ist der Schritt, der wiederholt werden soll, wenn sich die Breite ändert.

High-Tech-Illustration eines sub-millisekundenschnellen Layout-Hotpaths: ein vorbereitetes Text-Handle sitzt links, ein heller Neon-Strahl tritt in eine Layout-Engine ein, und die Ausgabe ist ein Stapel leuchtender Zeilenboxen mit abstrakten Höhen- und Zeilenzahl-Indikatoren, mehrere Breitenschieberegler zeigen denselben Text, der sofort über verschiedene Containerbreiten hinweg neu umbricht, zwischengespeicherte Breitenbalken leuchten im Hintergrund, es sind keine DOM-Knoten, keine Canvas-Aufrufe und keine String-Manipulation sichtbar, stattdessen betont die Szene Geschwindigkeit, Wiederholung und null Layout-Thrashing, ultra-detailliert, 8K-Auflösung, Dark Mode, Cyberpunk-/Tech-Ästhetik, Neon-Akzente, kein lesbarer Text.

  1. Manuelle Kontrolle, falls nötig. prepareWithSegments() und layoutWithLines() liefern die Zeilen; walkLineRanges(), measureLineStats(), layoutNextLineRange() und materializeLineRange() erlauben es, sie Zeile für Zeile zu durchlaufen, ohne den gesamten Text zu materialisieren. Damit lässt sich in Canvas, SVG oder um ein Hindernis herum zeichnen, dessen Breite sich pro Zeile ändert (das README enthält ein Beispiel, das Text um ein schwebendes Bild herum fließen lässt).

Dunkle futuristische Szene, die manuelle Zeilenbereichskontrolle für Textrendering zeigt: ein Absatz aus abstrakten Glyphenzeilen fließt um ein schwebendes holografisches Bildhindernis herum, jede Zeile ist eine leuchtende Box, die einzeln durchlaufen, gemessen und materialisiert werden kann, Seitenpanels zeigen Zeilenbereiche, Statistiken pro Zeile und Berechnungen der nächsten Zeile, die Komposition legt Canvas-, SVG-, WebGL- und benutzerdefinierte Rendering-Anwendungsfälle nahe, mit präziser typografischer Geometrie und ohne Abhängigkeit vom vollständigen Seiten-DOM, ultra-detailliert, 8K-Auflösung, Dark Mode, Cyberpunk-/Tech-Ästhetik, Neon-Akzente, kein lesbarer Text.

Das Design stützt sich auf Browser-APIs, nicht auf eigene typografische Tabellen: Canvas liefert die Breite der Segmente, und Intl.Segmenter hilft, Wörter und Grapheme für Sprachen, Emojis und Schriftsysteme ohne Leerzeichen zu unterteilen. Das ist wichtig, weil das Zerschneiden eines Strings nach UTF-16-Indizes nicht dem Zerschneiden sichtbarer Zeichen entspricht.

Offizieller und halboffizieller Status

Die offizielle Oberfläche ist das README (die öffentliche Wahrheitsquelle für Beispiele und Grenzen), die Entwicklungsdokumentation (DEVELOPMENT.md), das Plattform-Bug-Register (PLATFORM_BUGS.md), das CHANGELOG.md, die Demos unter chenglou.me/pretext und das npm-Paket @chenglou/pretext. Es ist Teil keines Marketplace und keines formalen Standards; es gibt keine Organisation, die es im Sinne einer Zertifizierung „unterstützt”.

Seine Halboffizialität besteht in der Praxis in der Übernahme durch TanStack Virtual: Die offizielle TanStack-Website widmet eine Dokumentationsseite („Text Measurement with Pretext”) seiner Nutzung als Höhenschätzer für textdominierte Zeilen in Chats, Streams, Feeds, Kommentaren, Changelogs und Benachrichtigungen, wobei TanStack die Kontrolle über Scroll, sichtbaren Bereich und Position behält. Keines dieser Signale stellt ein Vendor-Endorsement der Methodik oder ihrer Ergebnisse dar; es sind Integrationen und technische Referenzen, keine Standardbezeichnung.

Cyberpunk-Visualisierung von Textvirtualisierung und Streaming-Oberflächen: ein hoch scrollender Feed aus chatähnlichen Zeilen, Kommentaren, Benachrichtigungen und Changelog-Einträgen, gerendert als leuchtende abstrakte Textblöcke, ein virtuelles Viewport hebt nur die sichtbaren Zeilen hervor, während Zeilen außerhalb des Bildschirms zu Wireframes mit niedriger Opazität verblassen, ein Neon-Scroll-Indikator verfolgt die Position, schwebende Messchips sagen Zeilenhöhen vor dem Rendern voraus, die Szene legt flüssige Leistung in langen Listen, Nachrichtenströmen, Feeds und Echtzeit-UIs nahe, ultra-detailliert, 8K-Auflösung, Dark Mode, Cyberpunk-/Tech-Ästhetik, Neon-Akzente, kein lesbarer Text.

Das Ökosystem

Pretext wurde schnell zu einer Referenzplattform für eine Welle von Ports, Adaptern und Experimenten.

Repositories des Autors: chenglou/pretext (die Hauptbibliothek), chenglou/text-layout (34 Sterne, Markbåges früheres Projekt, als Vorläufer erhalten), chenglou/react-motion (21.914 Sterne, die Animationsbibliothek, deren ursprünglicher Schöpfer Lou war) und chenglou/freerange (594 Sterne, statische @fit-Prüfungen für TypeScript-Layoutcode).

Ports zu anderen Sprachen und Plattformen: tornikegomareli/swift-pretextkit (183 Sterne, ein Swift-Port für Apple-Plattformen, veröffentlicht drei Tage nach dem Original), wieslawsoltes/PretextSharp (27 Sterne, Textvorbereitung und Zeilenlayout für SkiaSharp), craigm26/pretext_dart (8 Sterne) und nathankim0/pretext_flutter (7 Sterne, Dart/Flutter-Ports), waleed-qamar/flutter_pretext (35 Sterne, ein weiterer Flutter-Port), hyj1230/pretext-py (4 Sterne, eine Python-Neuimplementierung), mjshin82/UnityPretext (46 Sterne, ein Unity-Adapter) und fifteen42/pretext-video (90 Sterne, verwandelt die Webcam in lebendige Typografie durch Kombination von Pretext mit MediaPipe).

Cyberpunk-Ökosystemkarte einer Textlayout-Bibliothek, die sich über Programmiersprachen und Plattformen ausbreitet: ein zentraler leuchtender Kern verbindet sich mit Satellitenknoten für Swift, C#, Dart, Flutter, Python, Unity, React Native, Vite, Yoga-basiertes DOM-loses Layout und Webcam-Typografie-Experimente, jeder Knoten hat einen eigenen Neon-Farbton und ein abstraktes Plattform-Icon, Datenströme pulsieren zwischen ihnen, die Szene vermittelt schnelle Adoption, Ports, Adapter und Community-Expansion, ohne lesbare Beschriftungen zu zeigen, ultra-detailliert, 8K-Auflösung, Dark Mode, Cyberpunk-/Tech-Ästhetik, Neon-Akzente, kein lesbarer Text.

Adapter für Frameworks und Tooling: JubaKitiashvili/expo-pretext (259 Sterne, sagt React-Native-Texthöhen vor dem Rendern voraus), Agent-Pattern-Labs/textura (154 Sterne, „Pretext x Yoga = Textura”, eine DOM-lose Layout-Engine), BaselAshraf81/layout-sans (67 Sterne, eine reine TypeScript-2D-Flex-/Grid-Layout-Engine, angetrieben von Pretext), LucasBassetti/react-pretext (2 Sterne, ein Headless-React-Adapter), BALOTIAS/vite-pretext (4 Sterne, ein konfigurationsfreies Vite-Plugin zur Beseitigung textbedingter CLS), nikilok/virtual-text-layout (4 Sterne, ein React-Hook, der measureElement von TanStack Virtual ersetzt) und lucascrespo23/pinch-type (112 Sterne, „zoome mit Pinch-Geste den Text, nicht die Seite”).

Kuratierte Listen und benachbarte Projekte: bluedusk/awesome-pretext (35 Sterne, eine kuratierte Liste von Demos und Tutorials), AsharibAli/pretext-skills (12 Sterne) und yaniv-golan/pretext-skill (15 Sterne), „Skills” für KI-Agenten. Als direkter Vergleich veröffentlichte leeoniya uWrap.js (erwähnt in HN 43583478), eine ~2 KB große Bibliothek zur Schätzung der ASCII-Zeilenhöhe, die er selbst im Haupt-Thread Pretext gegenüberstellte.

Das allgemeine Muster des Ökosystems: ein sehr kleiner Kern, den viele auf Sprachen (Swift, C#, Dart, Python), Frameworks (React, React Native, Flutter, Vue, Vite, Unity) und Nischenanwendungsfälle (PDF, Video, 3D) erweitern, plus eine Schicht von „Skills” für KI-Agenten.

Zahlen zum Repository

Messung: 22. August 2026, GitHub-API und npm-Registry.

MetrikWert
Sterne49.966
Forks2.729
Echte Abonnenten147
Commits (main-Branch)410
Offene Issues + PRs90
HauptspracheTypeScript
LizenzMIT
Erstellung7. März 2026
Neueste npm-Version0.0.8 (12. Juni 2026)
npm-Downloads (Woche 14.–20. Aug. 2026)905.501
npm-Downloads (Monat 22. Jul.–20. Aug. 2026)4.127.107

watchers_count spiegelt die Sternezahl, weshalb subscribers_count als tatsächliche Abonnentenzahl gemeldet wird. open_issues_count umfasst offene Änderungsanfragen. Die Releases-API lieferte eine leere Liste: Pretext veröffentlicht keine formalen GitHub-Releases, hat aber Git-Tags (v0.0.4…v0.0.8) und npm-Versionen mit einem CHANGELOG.md pro Version; die Referenzversion ist die von npm (0.0.8).

Die wichtigsten Mitwirkenden nach Beitragszahl sind chenglou (403), bg-l2norm (2) und, mit je einem Beitrag, brandonmcconnell, cxa, threepointone, bytaesu und somnai-dreams. Die Konzentration von 403 der 410 Beiträge bei einem einzigen Autor bestätigt, dass es sich um ein Projekt mit einem einzigen Hauptverantwortlichen handelt.

Schnelleinstieg

Installation und erster Start

npm install @chenglou/pretext

Anforderungen: eine Browserumgebung (oder Runtime) mit verfügbarem Intl.Segmenter und Canvas 2D. Reines Node ohne diese APIs wird derzeit nicht unterstützt; serverseitiges Rendering ist als zukünftige Arbeit aufgeführt. Es ist ausschließlich ESM; es gibt keine direkte Unterstützung für CommonJS-require().

Erster Start im Browser:

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

const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀', '16px Inter')
const { height, lineCount } = layout(prepared, 320, 20)
// height und lineCount: reine Arithmetik, ohne DOM-Layout oder Reflow

Gängige Arbeitsabläufe

  1. Die Höhe eines Absatzes vor dem Rendern vorhersagen. prepare(text, '16px Inter') einmal; layout(prepared, breite, 20) so oft wie sich die Breite ändert. Das Ergebnis liefert { height, lineCount }, um den Scroll zu verankern, eine virtualisierte Zeile zu dimensionieren oder zu prüfen, dass ein Etikett in eine Schaltfläche passt.
  2. Text um ein Bild herum fließen lassen (redaktionelles Layout). Mit prepareWithSegments plus einem LayoutCursor pro Zeile layoutNextLineRange() aufrufen mit einer Breite, die schrumpft, während die Zeile neben dem Bild liegt, und materializeLineRange(), um den Text dieser Zeile zu erhalten.
  3. Mehrzeiliges Shrinkwrap (die Mindestbreite, die den Text enthält). measureLineStats(prepared, breite) liefert { lineCount, maxLineWidth }; walkLineRanges() durchläuft die Zeilen, ohne Strings zu erstellen — nützlich für eine binäre Suche nach einer „schönen” Breite.
  4. Chat-Virtualisierung mit TanStack Virtual. prepare() pro Text und Stil zwischenspeichern, layout() für die aktuelle Breite ausführen und, wenn sich Breite/Schriftart/Zeilenhöhe ändern, die Messungen von Virtual zurücksetzen, um Offsets neu zu berechnen.

Wesentliche Konfiguration

Die 4–5 „Einstellungen”, auf die ein neuer Nutzer zuerst stößt, sind die Optionen von prepare() und die Parameter von layout(): font (ein Canvas-Schriftstring, z. B. 16px Inter, der mit dem effektiven CSS des gemessenen Texts übereinstimmen muss — eine benannte Schriftart verwenden, nicht system-ui), lineHeight (ein layout()-Parameter, der mit dem CSS line-height übereinstimmen muss), { whiteSpace: 'pre-wrap' } (für textarea-ähnlichen Text), { wordBreak: 'keep-all' } (für CJK/Hangul) und { letterSpacing: n } (ein Wert in CSS-Pixeln).

Zudem gibt es zwei globale Helfer: setLocale(locale?), um das Gebietsschema des Wortsegmentierers festzulegen (und Caches zu leeren), und clearCache(), um den gemeinsamen Metrik-Cache freizugeben, wenn die App durch viele Schriftarten zirkuliert.

Häufige Fallstricke und Lösungen

  • system-ui ist unter macOS unsicher. Canvas und DOM können unterschiedliche Schriftarten auflösen. Lösung: eine benannte Schriftart verwenden. PLATFORM_BUGS.md verlinkt die Bugs Chromium #489579956 und Mozilla #2020917.
  • Apple-Color-Emoji werden in Canvas bei kleinen Größen größer gemessen als im DOM (macOS, Chrome und Firefox). Die Korrektur wird einmal pro Schriftart per Fähigkeitserkennung erkannt und pro Emoji-Graphem abgezogen; ihre Deaktivierung senkt den Genauigkeits-Sweep von 7680/7680 auf ~7652–7660/7680.
  • Warten, bis die Schriftart geladen ist, bevor vorbereitet wird. Ist die Schriftart nicht verfügbar, weichen Canvas-Messungen von dem ab, was der Browser später anwendet.
  • layout() mit leerem String liefert { lineCount: 0, height: 0 }. Wird ein anderes Verhalten benötigt, mit Math.max(1, lineCount) * lineHeight klemmen.
  • prepare() nicht ohne Änderungen erneut aufrufen. Das zerstört den Hauptvorteil der Vorberechnung; bei einer Größenänderung wird nur layout() erneut ausgeführt.
  • Safari benötigt eine Zeilenumbruch-Toleranz von 1/64 px (Chromium/Gecko nutzen 0,005 px). Und Safari 26.4 scheitert noch an word-break-keep-all-006 von WPT; die Korrektur breakKeepAllAfterPunctuation bleibt bestehen, bis WebKit es upstream behebt.
  • Headless mit devicePixelRatio = 1 verschleiert die Emoji- und macOS-system-ui-Bugs. In einem Browser mit Kopf auf einem Retina-Display erneut testen.
  • Automatische Silbentrennung ist nicht eingebaut. Weiche Trennstriche vor prepare() einfügen.
  • CSS außerhalb der canvas.font-Abkürzung (font-optical-sizing, font-feature-settings, font-variation-settings) wird nicht separat modelliert.

Integrationen und Migration

  • TanStack Virtual: offiziell dokumentierte Integration als Höhenschätzer für textdominierte Zeilen. TanStack behält weiterhin Scroll, Bereich und Positionierung; Pretext liefert nur die Schätzung.
  • Migration von DOM-Messungen: Das Migrationsmuster ist, getBoundingClientRect()/offsetHeight auf dem heißen Pfad durch prepare()+layout() zu ersetzen, während der echte Text im DOM für die Barrierefreiheit erhalten bleibt.
  • Migration von uWrap.js (leeoniya): uWrap ist ~2 KB groß, nur ASCII/Latein, nur white-space: pre-line, ohne weiche Trennstriche oder Emoji; Pretext deckt normal und pre-wrap, weiche Trennstriche, Emoji und vollständige Mehrzeiligkeit ab. Es ist eine Umfangsänderung, keine API-Änderung.
  • Integration mit MCP/CI/Editoren: eine Entwicklungszeit-Nutzung (prüfen, dass ein Etikett ohne Browser passt) und CI-Fälle (Geometrie als Unit-Test), SSR (vorberechnete Höhen bei der Hydration) und 3D/WebGL (Zeilenpositionen als Koordinaten). Es ist kein offizieller Pretext-MCP-Server dokumentiert.

Wie man beiträgt

Der Entwicklungsprozess ist in DEVELOPMENT.md und AGENTS.md dokumentiert: einmalige Installation mit bun install (das Projekt nutzt Bun, nicht npm, für die Entwicklung); tägliche Entwicklung mit bun start (bedient die lokale Demo-Website unter http://localhost:3000); Verifizierung mit bun run check (Typprüfung mit tsc, Linting mit oxlint, Dead-Code-Scan mit knip) und bun test; Pretext-spezifische Genauigkeit und Benchmark (bun run accuracy-check, accuracy-snapshot, benchmark-check, corpus-check/corpus-sweep); Paketierung mit bun run build:package.

Dokumentierte Regeln: das README als öffentliche Wahrheitsquelle pflegen; kein Monkey-Patching (die Grundursache beheben, nicht das Symptom); das Changelog trägt nur nutzerorientierte Notizen; Diffs, die die heiße Engine ändern, müssen die Genauigkeits- und Benchmark-Snapshots neu generieren.

Wie die Community reagierte

Die zurückgewonnene Evidenz zeigt starke Begeisterung, aber auch konkrete Kritik an der Leistung und daran, worauf die Leute achten.

Der Haupt-Hacker-News-Thread (397 Punkte, 69 Kommentare, veröffentlicht am 28. März 2026) sammelte bemerkenswerte Meinungen. simonw: „Dieses Ding ist sehr beeindruckend. Das Problem, das es löst, ist die effiziente Berechnung der Höhe von umbrochenem Text auf einer Webseite, ohne diesen Text zuerst zu rendern (sehr teuer). Es tut dies, indem es die Breite/Höhe einzelner Segmente — man denke an Wörter — vorberechnet und zwischenspeichert…” rattray: „Unabhängig vom Thema sind die Ankündigungs-Tweets dazu eine meisterhafte Demonstration dafür, warum eine architektonische/Plattform-Verbesserung hohe Wirkung haben kann.”

leeoniya (Autor von uWrap.js) löste den technischsten Austausch aus: „Ich habe vor einem Jahr etwas Ähnliches für diesen Zweck geschrieben, aber viel einfacher und 2 KB, keine KI: uWrap.js… Bei ASCII-Text ist meins in 80 ms fertig, während Pretext 2200 ms braucht.” simonw antwortete, dass uWrap nur Latein handhabe und keine weichen Trennstriche/Emoji, und nur pre-line. liuliu (ein Projektmitarbeiter) entgegnete, dass prepare measureText in einer Schleife nutze und dass „diese Bibliothek dafür gedacht ist, prepare einmal und layout viele Male auszuführen. layout-Aufrufe sollten unter 1 ms liegen.” leeoniya probierte, 100.000 Sätze mit Zeilenumbrüchen zu verketten: „nicht viel schneller, ~1880 ms.”

lewisjoe: „Kurze Zusammenfassung von pretext: Wenn man Text im Web layouten will, muss man die canvas.measureText-API nutzen und Umbruch/Segmentierung/RTL selbst implementieren. Pretext macht das einfacher.” rikroots: „Textlayout-Engines sind absurd schwierig. Man beginnt zu denken, ‘es ist eine schwere Aufgabe, aber ich schaffe das’ und findet sich drei Monate später in einer Ecke wieder, schreiend ‘warum, Chinesisch?’” tadfisher (von Mozilla): „Ich würde es begrüßen, wenn das Offenlegen des Textlayout-Messers des Browsers eines Tages zu einer Web-API würde.”

In einem sekundären Thread (16 Punkte) wandte sublinear ein: „So cool das ist, fällt es mir schwer, das auf einer Produktions-Webseite zu sehen. Wenn es eine JS-Abhängigkeit für das Styling gibt, muss der Entwickler trotzdem ein CSS-Fallback schreiben.” In einem anderen Thread (14 Punkte, 5 Kommentare) korrigierte lewisjoe einen Artikel über Pretext: „Pretext befreit das Browser-Textlayout nicht vollständig (zumindest noch nicht). Es nutzt weiterhin canvas.measureText, das die kritische Schwerarbeit erledigt”; der Autor des Artikels, cyrusradfar, stimmte zu und aktualisierte den Beitrag.

Simon Willisons Blog (29. März 2026) präsentiert es als „eine aufregende neue Browser-Bibliothek” und hebt die Verifizierungsmethode mit Der große Gatsby und die mehrsprachigen Korpora hervor. Den Odells Blog (30. März 2026, Dev.to) argumentiert, dass „die Community drei Tage damit verbracht hat, Drachen zu bauen [Canvas-Demos]. Sie sollte Chat-Oberflächen bauen” — das eigentliche Merkmal sei, seiner Ansicht nach, die Höhe vorherzusagen, ohne aus dem DOM zu lesen.

Ehrliche Zusammenfassung: Die Begeisterung ist breit und auf hohem Niveau (397 Punkte im Haupt-Thread). Die eigentliche Kritik kommt von leeoniya (Leistung von prepare in einer Schleife) und sublinear (Schwierigkeit der Produktionsadoption wegen der JS-Abhängigkeit für Styling). cyrusradfar selbst räumt ein, dass die SSR-Einschränkung noch von Canvas abhängt.

Pretext im Vergleich zu anderen Ansätzen

AnsatzÜberprüfbare ÜberschneidungÜberprüfbarer Unterschied
leeoniya / uWrap.jsSchätzt Zeilenhöhe für Virtualisierung mit Canvas’ measureText.uWrap ist ~2 KB groß, nur Latein/ASCII, nur white-space: pre-line, ohne weiche Trennstriche oder Emoji; Pretext deckt normal und pre-wrap, weiche Trennstriche, Emoji und vollständige Mehrzeiligkeit ab.
Skia-wasm (auf HN erwähnt)Rendert Text, ohne vom Browser-DOM abhängig zu sein.Skia ist eine vollständige Rendering-Engine, die „die ganze Welt mitbringt”; Pretext misst und verteilt nur, delegiert das finale Rendering an den Browser.
DOM-Messungen (getBoundingClientRect, offsetHeight)Liefern die reale, endgültige Geometrie.Erzwingen synchronisierten Reflow; bei großen Listen erzeugen sie Layout-Thrashing. Pretext vermeidet diesen Lesevorgang auf dem heißen Pfad.
CSS text-wrap: balance/pretty (auf HN erwähnt)Passt die Anzahl der Wörter pro Zeile an.Eliminiert nicht den leeren Raum am rechten Rand und liefert keine Höhe vor dem Rendern; es ist eine Ergänzung, kein Ersatz.

Der nützlichste Vergleich erfolgt nicht nach Popularität: Pretext sticht hervor, wenn wiederholte Messung auf dem kritischen Pfad liegt oder wenn die App die Zeilenumbrüche explizit besitzen muss. Für eine gewöhnliche Website mit stabilem Inhalt bleiben CSS, ResizeObserver und semantische Struktur einfacher und angemessener.

Anwendungsfälle und wem dieses Repository helfen kann

  • Teams, die textdichte Listen virtualisieren (Chats, Feeds, Kommentare, Benachrichtigungen, Zeitleisten) können prepare()+layout() mit TanStack Virtual nutzen, um die Höhe jeder Zeile vorherzusagen und den Scroll ohne sichtbare Korrekturen zu verankern.
  • Ersteller von Rich-Text-Editoren oder streamendem KI-Chat können Höhen neu berechnen, während Tokens eintreffen, ohne dass eine sich verändernde Blase den Bildlauf ständig korrigiert.
  • Canvas-, SVG-, WebGL- oder 3D-Engine-Entwickler können Zeilen und Bereiche erhalten, um Text in einem DOM-losen Renderer zu zeichnen, oder Zeilenpositionen als Koordinaten und Texturgröße berechnen, bevor GPU-Speicher zugewiesen wird.
  • SSR-/Hydration-Teams können Höhen während des serverseitigen Renderns vorberechnen, um den Client vom ersten Frame an mit korrekten Dimensionen zu hydrieren und CLS zu vermeiden.
  • Wer Oberflächenvalidierung während der Entwicklung durchführt, kann prüfen, dass ein Etikett in eine Schaltfläche passt oder ein 50-Zeichen-Text auf eine Karte passt, ohne den Browser zu öffnen.
  • Plattformübergreifende Teams können vom Kern ausgehen und verifizierte Ports nutzen: Swift, React Native, Flutter, C#/SkiaSharp oder Python.
  • Für eine gewöhnliche Website mit stabilem Inhalt bleiben CSS + ResizeObserver + semantische Struktur einfacher und angemessener.

Ressourcen


Hinweis: Dieser Artikel kombiniert das README, DEVELOPMENT.md, PLATFORM_BUGS.md, das CHANGELOG.md, die npm-Registry @chenglou/pretext, die GitHub-API und Artikel von Simon Willison, Den Odell und Cyrus Radfar, alle konsultiert am 22. August 2026. Stern-, Download- und Beitragszahlen ändern sich mit der Zeit.

Kommentare