3/29/2026 at 7:15:23 PM
This thing is very impressive.The problem it solves is efficiently calculating the height of some wrapped text on a web page, without actually rendering that text to the page first (very expensive).
It does that by pre-calculating the width/height of individual segments - think words - and caching those. Then it implements the full algorithm for how browsers construct text strings by line-wrapping those segments using custom code.
This is absurdly hard because of the many different types of wrapping and characters (hyphenation, emoji, Chinese, etc) that need to be taken into account - plus the fact that different browsers (in particular Safari) have slight differences in their rendering algorithms.
It tests the resulting library against real browsers using a wide variety of long text documents, see https://github.com/chenglou/pretext/tree/main/corpora and https://github.com/chenglou/pretext/blob/main/pages/accuracy...
by simonw
3/30/2026 at 12:10:50 AM
i wrote something similar for this purpose, but much simpler and in 2kb, without AI, about a year ago.uWrap.js: https://news.ycombinator.com/item?id=43583478. it did not reach 11k stars overnight, tho :D
for ASCII text, mine finishes in 80ms, while pretext takes 2200ms. i haven't yet checked pretext for accuracy (how closely it matches the browser), but will test tonight - i expect it will do well.
let's see how close pretext can get to 80ms (or better) without adopting the same tricks.
https://github.com/chenglou/pretext/issues/18
there are already significant perf improvement PRs open right now, including one done using autoresearch.
by leeoniya
3/30/2026 at 12:36:11 AM
Looks like uWrap only handles latin characters and doesn't deal with things like soft hyphens or emoji correction, plus uWrap only handles white-space: pre-line while Pretext doesn't handle pre-line but does handle both normal and pre-wrap.by simonw
3/30/2026 at 12:39:10 AM
correct, it was meant for estimating row height for virtualizing a 100k row table with a latin-ish LTR charset (no emoji handling, etc). its scope is much narrower. still, the difference in perf is significant, which i have found to be true in general of AI-generated geenfield code.by leeoniya
3/30/2026 at 4:02:41 AM
I've worked with text and in my experience all of these things (soft hyphens, emoji correction, non-latin languages, etc) are not exceptions you can easily incorporate later, but rather the rules that end up foundational parts of the codebase.That is to say, I wouldn't be so quick to call a library that only handles latin characters comparable to one that handles all this breath of things, and I also wouldn't be so quick to blame the performance delta on the assumption of greenfield AI-generated code.
by aylmao
3/30/2026 at 9:27:00 AM
no disagreement. i never claimed uWrap did anything more than it does. it was not meant for typography/text-layout but for line count estimation. it never needed to be perfect, and i did not claim equivalence to pretext. however, for the use case of virtualization of data tables -- a use case pretext is also targeted at -- and in the common case of latin alphabets, right now pretext is significantly slower. i hope that it can become faster despite its much more thorough support for "rest of the owl".by leeoniya
3/30/2026 at 4:19:54 AM
uWrap demo has text extending beyond text boxes all other the place on Safari, is that the price of simplicity?by eviks
3/30/2026 at 9:17:52 AM
i don't have a mac to test this with currently, so hopefully it's not the price but a matter of adding a Safari-specific adjustement :)internally it still uses the Canvas measureText() API, so there's nothing fundamentally that should differ unless Safari has broken measureText, which tbh, would not be out of character for that browser.
by leeoniya
3/30/2026 at 9:20:44 AM
Chrome is no different, for example, "RobertDowneyjr" is out of the box, so does "enthusiastic" in a couple of places.by eviks
3/30/2026 at 9:32:02 AM
ack, see my reply to sibling comment: https://news.ycombinator.com/item?id=47572206by leeoniya
3/30/2026 at 12:36:48 AM
prepare uses measure text, if it is in a for loop, it won't be fast. This library is meant to do prepare once and then layout many times. layout calls should be sub-1 ms.by liuliu
3/30/2026 at 12:41:16 AM
it is not clear from the API/docs how i would use prepare() once on one text and then use layout() for completely different text.i think the intended purpose is that your text is maybe large but static and your layout just changes quickly. this is not the case for figuring out the height of 100k rows of different texts in a table, for example.
by leeoniya
3/30/2026 at 1:52:21 AM
I think for that to use pretext is to join each row with hard line break and then do prepare once, then walk each line. At least that will put the single layout performance into the best light.I am skeptical getting row height of many items only once is the intended behavior though. It is probably the intended behavior to get row height of many items and enables you to resizing width many time later (which is pretty useful on desktop).
by liuliu
3/30/2026 at 2:59:48 AM
tried just doing a concat of the 100k sentences with line breaks, it wasnt much faster, ~1880ms.by leeoniya
3/30/2026 at 1:49:45 AM
There's a handful of perf related PRs open already so maybe it will be faster soon. I'm sure with enough focus on it we could have a hyper optimized version in a few hours.by contrahax
3/29/2026 at 7:33:45 PM
> This thing is very impressive.Agreed! Text layout engines are stupidly hard. You start out thinking "It's a hard task, but I can do it" and then 3 months later you find yourself in a corner screaming "Why, Chinese? Why do you need to rotate your punctuation differently when you render in columns??"
This effort feeds back to the DOM, making it far more useful than my efforts which are confined to rendering multiline text on a canvas - for example: https://scrawl-v8.rikweb.org.uk/demo/canvas-206.html
by rikroots
3/30/2026 at 4:25:11 AM
Why do you bring up Chinese cornes if the basic Latin text in the Pretext demo is deficient?(by the way, in your cool demo the wheel template can have some letter parts like the top of L or d extend beyond the wheel)
by eviks
3/30/2026 at 7:12:09 AM
> the wheel template can have some letter parts like the top of L or d extend beyond the wheelYeah - I use the template (in that case, a circle) to calculate line lengths, then I run 2d text along the 1d lines. Even if I tried to keep all of the glyphs inside the wheel I'd fail - because some fonts lie about how tall they are. Fonts are, basically, criminals.
by rikroots
3/30/2026 at 7:01:32 AM
> It does that by pre-calculating the width/height of individual segments - think words - and caching those.From the description, it doesn’t calculate it, but instead renders the segments in canvas and measures them. That’s still relatively slow compared to what native rendered-text-width APIs will do, and you have to hope that the browser’s rendering will use the identical logic in non-canvas contexts.
by layer8
3/30/2026 at 7:42:06 AM
I recently battled this and reverted to using DOM measurements. In my case the measurement would be off by around a pixel, which caused layout issues if I tried rendering the text in DOM. This was only happening on some Linux and Android setupsby spoiler
3/30/2026 at 11:16:01 AM
I count using an off-screen canvas as a form of "calculating" here.by simonw
3/29/2026 at 7:20:19 PM
I had struggled so much to measure text and number of lines when creating dynamic subtitles for remotion videos, not sure if it was my incompetence or a complexity with the DOM itself. I feel hopeful this will make it much easier :-)by jimkleiber
3/30/2026 at 7:29:22 AM
I mentioned this elsewhere, but it's not actually doing any of what you describe. It's rendering the text to a canvas and then measuring that. I don't see any benchmarks that indicate it's faster than just sticking it in a <p> tag, and not any clear indication that it would be. It's certainly not implementing the full algorithm for text rendering in a browser.It certainly seems to provide an API for analysing text layouts, but all of the computation still goes through the browser's native layout system.
by slopinthebag
3/30/2026 at 11:18:59 AM
How would you explain what it's doing here and why the author bothered to create the library?by simonw
3/30/2026 at 6:17:04 PM
Even when it is rendered... I have my text/zoom level pretty close to maxed out on Android as my issues are mostly retinal, not correctable with glasses... and so many apps will completely scroll my long inputs off screen while I'm trying to input... or otherwise make it impossible to see/edit after I've entered a handful of lines. It's infuriating to say the least.by tracker1
3/29/2026 at 10:43:55 PM
> The problem it solves is efficiently calculating the height of some wrapped text on a web page, without actually rendering that text to the page first (very expensive).But in the end, in a browser, the actual text rendering is still done by the browser?
It's a library that allows to "do stuff" before the browser renders the actual text, but by still having the browser render, eventually, the actual text?
Or is this thing actually doing the final rendering of the text too?
by TacticalCoder
3/29/2026 at 10:48:07 PM
Yes the browser still renders the text at the end - but you can now do fancy calculations in advance to decide where you're going to ask the browser to draw it.by simonw
3/29/2026 at 11:45:28 PM
I suspect exposing the browser's text layout measurer is going to become a Web API in the future, much like exposing the HTML parser via setHTML().by tadfisher