- Pretext एक शुद्ध JavaScript/TypeScript लाइब्रेरी है जो DOM access के बिना मल्टीलाइन टेक्स्ट की ऊंचाई और लाइन लेआउट की गणना करती है, और browser तथा server दोनों environments को support करती है
- यह getBoundingClientRect जैसे DOM measurement API का उपयोग नहीं करती, इसलिए layout reflow cost को हटाती है, और font engine-आधारित अपनी measurement logic से accuracy सुनिश्चित करती है
- prepare() / layout() API के जरिए टेक्स्ट को preprocess किया जाता है, और cached width data का उपयोग करके शुद्ध arithmetic operations से तेज height calculation किया जाता है
- यह emoji, mixed-direction text (bidi), और कई भाषाओं को support करती है, तथा Canvas·SVG·WebGL·server rendering में भी एक जैसे परिणाम देती है
- यह high-performance text engine है, जिसे virtualized scroll, text overflow validation, floating text placement जैसे सटीक UI layout implementations में उपयोग किया जा सकता है
अवलोकन
- Pretext मल्टीलाइन टेक्स्ट माप और लेआउट के लिए एक शुद्ध JavaScript/TypeScript लाइब्रेरी है, जो DOM, Canvas, SVG, और server-side rendering तक support करती है
- यह DOM measurement API (
getBoundingClientRect, offsetHeight आदि) का उपयोग नहीं करती, इसलिए layout reflow cost को हटाती है
- browser के font engine पर आधारित अपनी measurement logic के जरिए यह सटीक और तेज performance प्रदान करती है
- यह सभी भाषाओं, emoji, mixed-direction text (bidi) को support करती है, और browser के बीच के अंतर भी संभालती है
इंस्टॉलेशन और डेमो
मुख्य फीचर्स
- Pretext दो मुख्य usage patterns प्रदान करता है
-
1. DOM access के बिना paragraph height मापना
prepare() टेक्स्ट को preprocess करता है, whitespace normalization·segment separation·glue rules application·canvas-आधारित measurement करता है, और एक opaque handle लौटाता है
layout() cached width data का उपयोग करके शुद्ध arithmetic operations से height और line count की गणना करता है
- समान टेक्स्ट और settings में
prepare() को बार-बार call करने की जरूरत नहीं होती, और resize होने पर केवल layout() फिर से चलाना होता है
{ whiteSpace: 'pre-wrap' } option के साथ whitespace, tab(\t), line break(\n) को जस का तस रखा जा सकता है
- benchmark परिणाम:
prepare() लगभग 19ms (500 टेक्स्ट के आधार पर), layout() लगभग 0.09ms
- लौटाई गई height value का उपयोग निम्न UI फीचर्स में किया जा सकता है
- virtualization और occlusion handling में सटीक height calculation
- JS-आधारित layout systems (जैसे masonry, flexbox-जैसी संरचना)
- AI-आधारित text overflow validation
- text load होने पर scroll position बनाए रखना
-
2. मैन्युअल paragraph layout बनाना
prepareWithSegments() से segment-स्तर का data बनाया जाता है
layoutWithLines() fixed width पर हर line का text और width information लौटाता है
walkLineRanges() text string बनाए बिना हर line की width और cursor range पर iterate करता है
- उदाहरण: कई widths को test करके उपयुक्त line count और height खोजने के लिए binary-search शैली का layout adjustment संभव है
layoutNextLine() जब हर line की width अलग हो तब line-by-line क्रमिक layout करता है
- उदाहरण: image के आसपास text flow कराने के लिए floating text placement
- यह तरीका Canvas, SVG, WebGL, server-side rendering पर भी समान रूप से लागू होता है
API सारांश
-
बेसिक measurement API
prepare(text, font, options?): टेक्स्ट का analysis और measurement, layout() को देने के लिए handle लौटाता है
layout(prepared, maxWidth, lineHeight): दी गई width और line height के अनुसार text height और line count की गणना
-
मैन्युअल layout API
prepareWithSegments(text, font, options?): segment-स्तर का data लौटाता है
layoutWithLines(prepared, maxWidth, lineHeight): हर line के text, width, cursor information सहित
walkLineRanges(prepared, maxWidth, onLine): हर line की width और cursor range को callback के जरिए देता है
layoutNextLine(prepared, start, maxWidth): iterator के रूप में line-स्तर layout करता है
LayoutLine, LayoutLineRange, LayoutCursor type definitions शामिल हैं
-
अन्य utilities
clearCache(): internal cache initialize करता है
setLocale(locale?): locale सेट करता है और cache initialize करता है (मौजूदा state पर असर नहीं)
सीमाएँ और सावधानियाँ
- Pretext पूर्ण font rendering engine नहीं है
- डिफ़ॉल्ट target CSS properties
white-space: normal
word-break: normal
overflow-wrap: break-word
line-break: auto
{ whiteSpace: 'pre-wrap' } इस्तेमाल करने पर whitespace, tab, line break को बनाए रखता है और tab-size: 8 लागू करता है
- macOS पर
system-ui font, layout() accuracy के लिए उपयुक्त नहीं है, इसलिए explicit font name का उपयोग recommended है
overflow-wrap: break-word के कारण बहुत संकरी width पर शब्द के भीतर भी line break हो सकता है, लेकिन यह केवल grapheme unit के आधार पर ही विभाजित होता है
डेवलपमेंट से जुड़ी जानकारी
- development environment और commands के लिए
DEVELOPMENT.md देखें
योगदान और पृष्ठभूमि
- Sebastian Markbage के text-layout प्रोजेक्ट से विचार आगे बढ़ाए गए हैं
- canvas
measureText-आधारित shaping, pdf.js की bidi processing, और streaming line breaking डिज़ाइन को आगे विकसित किया गया है
1 टिप्पणियां
Hacker News की राय
यह प्रोजेक्ट सच में प्रभावशाली है
यह वेबपेज पर टेक्स्ट को वास्तव में render किए बिना line-break हुए टेक्स्ट की ऊंचाई को efficiently calculate करने की समस्या हल करता है
यह शब्द-आधारित segments की width और height को cache करता है, और browser के line-breaking algorithm को खुद implement करता है
hyphen, emoji, Chinese जैसी अलग-अलग character handling और browsers के बीच rendering differences (Safari सहित) की वजह से यह बहुत कठिन काम है
असली browser के साथ comparison testing के लिए corpora dataset और accuracy test page का उपयोग किया गया है
ASCII टेक्स्ट के आधार पर मेरा code 80ms लेता है, जबकि pretext 2200ms लेता है
accuracy अभी test नहीं की, लेकिन आज रात करने वाला हूँ
issue #18 में performance improvement PRs पहले से खुले हुए हैं
मैंने भी पहले canvas पर multiline text render करने की कोशिश में बहुत संघर्ष किया था
यह प्रोजेक्ट DOM से सीधे जुड़ा हुआ है, इसलिए कहीं ज्यादा उपयोगी है
उदाहरण: Scrawl demo
यह native API से धीमा हो सकता है, और इसकी गारंटी नहीं कि browser के non-canvas rendering जैसा ही logic इस्तेमाल करता हो
यह canvas पर render करके measure करता है, और बस text layout analysis के लिए API देने के स्तर पर है
यह सच में बहुत समय से इंतजार किया गया feature है
पहले responsive accordion जैसी चीजें ठीक से implement करना मुश्किल था
वेब का विकास पैटर्न हमेशा ① complex requirements का आना → ② JS/CSS hacks → ③ standardization रहा है
इस बार यह hack नहीं, बल्कि एक सही 2nd stage जैसा लगता है
RESEARCH.md देखें, तो इसमें browser-wise emoji measurement differences तक का बारीक अध्ययन किया गया है
maintenance मुश्किल होगा, लेकिन यह वेब विकास के लिए बड़ा turning point बन सकता है
इस बार यह भी रोचक है कि AI को development process में actively use किया गया। लगता है कि Cursor agent की मदद से इसका अधिकांश implementation हुआ
library author के अनुसार, Claude Code और Codex को browser का ground truth data सिखाकर कई हफ्तों तक iterative measurements कराए गए
संबंधित ट्वीट देखें
लगता है Autoresearch का भी कुछ हिस्सा उपयोग हुआ
shape-based reflow example मुझे खास तौर पर पसंद आया
इसे Ensō(enso.sonnet.io) में apply करना चाहता था, लेकिन simplicity बनाए रखने के लिए रुक गया
accordion example CSS के
interpolate-sizeसे भी implement किया जा सकता हैJosh Comeau का लेख देखें
text bubble example को
text-wrap: balance | prettyसे मिलते-जुलते तरीके से implement किया जा सकता हैbalanceयाprettyपूरी तरह समाधान नहीं हैंबहुत बार line lengths को बराबर बनाना वांछित नहीं होता
संबंधित CSSWG issue: #191
text-wrapहर line में शब्दों की संख्या संतुलित करने में मदद करता है, लेकिन right margin की समस्या फिर भी बनी रहती हैpretext canvas.measureText को सीधे इस्तेमाल नहीं करता, बल्कि अगर आप text और properties को JS API में दें तो यह अपने-आप layout calculate कर देता है
पहले measureText को सीधे इस्तेमाल करना पड़ता था या harfbuzz को browser में port करना पड़ता था
यह technical breakthrough कम, और मौजूदा elements के अच्छे संयोजन का परिणाम ज्यादा लगता है
फिर भी Skia-wasm / Canvaskit से इसका अंतर जानने की उत्सुकता है
pretext की अलग बात यह है कि AI की मदद से pure Typescript-based glyph rendering implement की गई है
यह कुछ वैसा फर्क लगता है जैसा ffmpeg को सीधे C में implement करने और Dart से call करने में होता है
इस तरह की कोशिश client-side FOSS की नई संभावनाएँ दिखाती है
पिछले साल मैंने HTML में print brochure typesetting system बनाया था, जहां line breaks और widow prevention के लिए Selection API से box boundaries को बार-बार calculate करना पड़ा
वह आज भी ठीक चलता है, लेकिन उसमें एक ऐसा off-by-one hack है जिसका कारण मुझे नहीं पता
pretext का iterative line generation feature सच में स्वागतयोग्य है
Fedora + Firefox environment में demo पूरी तरह टूटा हुआ दिख रहा है
उदाहरण: screenshot
ऐसी functionality वास्तव में browser standard API के रूप में उपलब्ध होनी चाहिए
W3C में feature request कैसे की जाए, या community voting जैसी कोई चीज संभव है या नहीं, यह जानने की जिज्ञासा है
लेकिन browser vendors इसे प्राथमिकता नहीं दे रहे
अभी Chrome AI-संबंधित APIs पर ज्यादा केंद्रित है
Sciter engine में पहले से Graphics.Text functionality है
यह canvas-based text rendering element है, जिस पर CSS styles सीधे apply किए जा सकते हैं
browser का text search (Ctrl+F) virtual scroll lists में सही तरह काम नहीं करता
इस तरह की समस्या हल करने के लिए शायद JS नहीं, बल्कि एक नई “Search” API चाहिए होगी
संबंधित प्रोजेक्ट: Display Locking, MDN दस्तावेज़
virtualized list के offscreen items DOM में नहीं होते, इसलिए उन्हें खोजा नहीं जा सकता
इसे हल करने के लिए selection, focus, scroll position, और match navigation तक को जोड़ने वाला नया browser contract चाहिए
लेकिन sites इसे consistently अपनाएँगी, इसकी संभावना कम है)