4 points par GN⁺ 2026-03-30 | Aucun commentaire pour le moment. | Partager sur WhatsApp
  • Pretext est une bibliothèque JavaScript/TypeScript pure qui calcule la hauteur et la répartition sur les lignes d’un texte multiligne sans accès au DOM, avec prise en charge des environnements navigateur et serveur
  • Comme elle n’utilise pas d’API de mesure du DOM telles que getBoundingClientRect, elle élimine le coût de reflow de mise en page et garantit la précision grâce à une logique de mesure interne basée sur le moteur de polices
  • Via les API prepare() / layout(), elle prétraite le texte puis effectue un calcul rapide de la hauteur par opérations arithmétiques pures en s’appuyant sur des données de largeur mises en cache
  • Elle prend en charge les emoji, le texte bidirectionnel mixte (bidi) et diverses langues, tout en fournissant les mêmes résultats avec Canvas, SVG, WebGL et le rendu côté serveur
  • Il s’agit d’un moteur de texte haute performance utilisable pour implémenter des mises en page UI précises comme le scroll virtualisé, la validation du débordement de texte et le placement de texte flottant

Vue d’ensemble

  • Pretext est une bibliothèque JavaScript/TypeScript pure dédiée à la mesure et à la mise en page de texte multiligne, compatible avec le DOM, Canvas, SVG et même le rendu côté serveur
  • Elle n’utilise pas les API de mesure du DOM (getBoundingClientRect, offsetHeight, etc.), ce qui supprime le coût de reflow de mise en page
  • Elle offre précision et rapidité grâce à une logique de mesure interne fondée sur le moteur de polices du navigateur
  • Elle prend en charge toutes les langues, les emoji et le texte bidirectionnel mixte (bidi), tout en gérant les différences entre navigateurs

Installation et démos

Fonctionnalités principales

  • Pretext propose deux grands modes d’utilisation
  • 1. Mesure de la hauteur d’un paragraphe sans accès au DOM

    • prepare() prétraite le texte, normalise les espaces, sépare les segments, applique les règles de glue et effectue une mesure basée sur canvas pour renvoyer un handle opaque
    • layout() utilise les largeurs mises en cache pour calculer la hauteur et le nombre de lignes par opérations arithmétiques pures
    • Pour un même texte et une même configuration, il n’est pas nécessaire de rappeler prepare() ; lors d’un redimensionnement, seul layout() doit être relancé
    • L’option { whiteSpace: 'pre-wrap' } permet de conserver tels quels les espaces, tabulations (\t) et retours à la ligne (\n)
    • Résultats de benchmark : prepare() environ 19 ms (sur 500 textes), layout() environ 0,09 ms
    • La hauteur renvoyée peut être utilisée pour des fonctionnalités UI telles que :
      • calcul précis des hauteurs dans la virtualisation et la gestion d’occlusion
      • systèmes de mise en page pilotés en JS (par ex. masonry ou structures de type flexbox)
      • validation du débordement de texte basée sur l’IA
      • maintien de la position de défilement lors du chargement du texte
  • 2. Construction manuelle de la mise en page d’un paragraphe

    • prepareWithSegments() génère des données au niveau des segments
    • layoutWithLines() renvoie, pour une largeur fixe, le texte de chaque ligne ainsi que ses informations de largeur
    • walkLineRanges() parcourt la largeur et la plage de curseurs de chaque ligne sans construire la chaîne de texte
      • Exemple : il est possible de faire un ajustement de mise en page par recherche binaire en testant plusieurs largeurs afin de trouver un nombre de lignes et une hauteur appropriés
    • layoutNextLine() effectue la mise en page ligne par ligne lorsque la largeur varie d’une ligne à l’autre
      • Exemple : placement de texte flottant pour faire couler le texte autour d’une image
    • Cette approche s’applique de la même manière à Canvas, SVG, WebGL et au rendu côté serveur

Résumé de l’API

  • API de mesure de base

    • prepare(text, font, options?) : analyse et mesure le texte, puis renvoie un handle à transmettre à layout()
    • layout(prepared, maxWidth, lineHeight) : calcule la hauteur du texte et le nombre de lignes selon la largeur et la hauteur de ligne données
  • API de mise en page manuelle

    • prepareWithSegments(text, font, options?) : renvoie des données au niveau des segments
    • layoutWithLines(prepared, maxWidth, lineHeight) : inclut le texte, la largeur et les informations de curseur pour chaque ligne
    • walkLineRanges(prepared, maxWidth, onLine) : transmet via callback la largeur et la plage de curseurs de chaque ligne
    • layoutNextLine(prepared, start, maxWidth) : effectue la mise en page sous forme d’itérateur ligne par ligne
    • Inclut les définitions de types LayoutLine, LayoutLineRange, LayoutCursor
  • Autres utilitaires

    • clearCache() : réinitialise le cache interne
    • setLocale(locale?) : définit la locale et réinitialise le cache (sans effet sur l’état existant)

Limitations et points d’attention

  • Pretext n’est pas un moteur de rendu de polices complet
  • Propriétés CSS ciblées par défaut :
    • white-space: normal
    • word-break: normal
    • overflow-wrap: break-word
    • line-break: auto
  • Avec { whiteSpace: 'pre-wrap' }, les espaces, tabulations et retours à la ligne sont conservés, avec application de tab-size: 8
  • Sur macOS, la police system-ui n’est pas adaptée à la précision de layout() ; il est donc recommandé d’utiliser un nom de police explicite
  • En raison de overflow-wrap: break-word, un retour à la ligne à l’intérieur d’un mot est possible sur des largeurs très étroites, mais la coupure se fait uniquement au niveau des graphèmes

Développement

  • Pour l’environnement de développement et les commandes, voir DEVELOPMENT.md

Contribution et contexte

  • Reprend les idées du projet text-layout de Sebastian Markbage
  • L’architecture a été développée à partir du shaping basé sur canvas measureText, du traitement bidi de pdf.js et d’une conception de retour à la ligne en streaming

Aucun commentaire pour le moment.

Aucun commentaire pour le moment.