npm / @chenglou/pretext
@chenglou/pretext
What changed in @chenglou/pretext 1, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-27.
39 breaking8 new APIs and options3 performance4 behavior and defaults22 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli init@chenglou/pretext 176 changes
Breaking changes 39
An atomic rich-inline item's own leading or trailing whitespace no longer creates a gap; a whitespace-only atomic item is an empty box sized by
extraWidth.Unrecognized browser layout engines now use Chrome's rules throughout.
In jsdom and happy-dom, which lack a 2D canvas context, preparing text now throws the missing-Canvas error rather than a TypeError about null.
Chrome now applies text-spacing-trim widths to CJK punctuation pairs and line endings, including across rich-inline item boundaries.
The npm package no longer includes pages/demos and pages/assets; they remain in the repository.
Passing a font string that Canvas ignores, such as an empty one, now throws a RangeError.
Safari now measures generic font families using the fonts it draws for the page's language.
glueis removed; no-break spaces and word joiners aretext, andzero-width-glueandcontrolare added.The width argument now precedes the cursor, so callers must swap the second and third arguments.
The width now precedes the cursor, and the first line is returned without a cursor; swap the second and third arguments at existing calls.
When the first word exceeds the line width, a following space or zero-width space now ends the line instead of being moved by other content or letter spacing.
Preparing text now throws a
RangeErrorwhenletterSpacingis not finite.Chrome and Firefox no longer add letter spacing after joined-script letters; Safari continues to space each glyph it draws.
Chrome and Firefox now measure text with fi, fl or ffi ligatures as browsers draw it when letter spacing disables those ligatures; Safari remains narrower for this case.
Safari now counts spacing after each glyph it draws in complex text and combining-accent words; measuring glyphs requires additional Canvas calls.
Safari no longer adds letter spacing after U+0085 next-line characters, except next to complex text.
Chrome, Safari and Firefox line-break opportunities now come from ports of each browser's line breaker and data, changing breaks to match browsers in more cases.
Safari now ends lines at U+2028 and U+2029 in normal white space, pre-wrap and rich-inline items.
Negative maxWidth now behaves as zero in plain-text and rich-inline layout; rich-inline widths below 1px also follow the plain-text behavior.
Firefox no longer adds a space for newlines between East Asian characters other than Hangul, or next to East Asian punctuation on ja and zh pages.
Chrome and Firefox no longer add a space for a newline next to a zero-width space in normal white space.
Runs of no-break spaces between other break opportunities now break where they overflow a line, matching browsers.
Runtimes without navigator.userAgent now follow Chrome's rules; outside browsers, measurement uses a global OffscreenCanvas defined before the first prepare().
Handles now expose only segments, kinds and widths; callers must change reads of any other handle field.
Handles made by 0.0.9 must not be kept; prepare the text again.
prepareWithSegments() no longer returns approximate bidi levels per segment; render a paragraph as one DOM element with its direction set to get browser ordering.
A font string that Canvas ignores, such as an empty one, now throws a RangeError.
Rich-inline line and range cursors no longer index an item's text and are only for passing back to layout functions; use source offsets to find fragment text.
Rich-inline items are laid out as one paragraph: break opportunities come from their joined text, and each item is measured in its own font.
Rich inline accepts
{ width }boxes for images, emoji, formulas, badges and other inline objects; lines can break before and after a box.segLevels is gone; callers that read it must change.
The locale now controls language-sensitive line breaking and measurement instead of overriding
<html lang>; omitting it restores the page language, while an empty string means no page language.Firefox now collapses spaces on both sides of a soft hyphen into one space.
When a chosen soft-hyphen hyphen does not fit, layout now uses the latest earlier break that fits; Chrome's visible hyphen no longer receives letter spacing.
In pre-wrap text, tab stops now follow browser behavior, including browser-specific letter-spacing calculations and wrapping of tabs that do not fit.
Firefox treats lone carriage returns and form feeds as zero-width, including at rich-inline item boundaries; CRLF remains one space.
Safari treats a lone carriage return as zero-width in normal white space, with line-ending behavior depending on the text; CRLF remains one space.
A line containing only soft hyphens before a newline now counts as a line.
Wrapped lines no longer count trailing spaces in their width, and trailing spaces and tabs are measured and kept on lines as browsers lay them out.
New APIs and options 8
Rich-inline fragments identify which item owns the collapsed space measured by
gapBefore, or use -1 when no space precedes the fragment on its line.Now accepts a
prepare()handle, avoiding the need to retain every segment string when only line statistics are needed.Now accepts a
prepare()handle, avoiding the need to retain every segment string when measuring natural width.An options argument with
whiteSpace: 'pre-wrap'enables CSS pre-wrap behavior across styled runs, including preserved whitespace, line-ending newlines and line-start tab stops.An options argument with
wordBreak: 'keep-all'enables CSS keep-all line breaking for rich-inline paragraphs.Rich inline lays its items out as one paragraph, as a browser lays out a paragraph’s spans.
Read a fragment’s sourceStart and sourceEnd instead of reading rich-inline cursors as places in an item's text.
Now accepts a
prepare()handle, avoiding the need to retain every segment string when only line ranges are needed.
Performance 3
At a new width, layout is three to six times as fast as in 0.0.9.
Preparing text it has measured before is 1.1 to 13 times as fast as in 0.0.9.
Preparing and measuring rich-inline paragraphs is reported as faster for both new and previously measured paragraphs in the Markdown chat demo.
Behavior and default changes 4
Pretext now uses each browser's character rules instead of
Intl.Segmenter, which remains needed only for text in Southeast Asian scripts written without spaces.Pretext uses a port of each browser’s own line breaker and data to find line-break opportunities instead of its own rules.
Read a fragment’s sourceStart and sourceEnd instead of reading rich-inline cursors as places in an item's text.
Shared measured-text caches are bounded; after more than 262,144 segments, the next preparation empties them before measuring, while existing handles retain their widths.
Fixes and other changes 22
Firefox now breaks around bidi controls as if they were absent, including their effects on line width, spacing and adjacent accents.
Text using a web font split by unicode-range no longer retains a fallback font's space width after preparation without a character from the space's font subset.
Chrome and Firefox on macOS now measure text-font emoji and system-fallback emoji sequences more closely to their drawn widths at small sizes.
Chrome and Firefox on macOS no longer measure U+FE0F after a non-emoji character narrower than the browser draws it at small sizes.
Emoji widths no longer become permanently zero when first prepared while body is display:none, and page CSS no longer skews their measured width.
Chrome now uses fonts for a newly changed html lang value even when the font string is unchanged.
Chrome and Firefox now let ideographic spaces hang past the end of a line instead of wrapping them.
Chrome on macOS now accounts for kana kerning when measuring Japanese lines; name a Japanese font after a font list that Chrome Canvas does not shape as a whole.
Firefox now applies letter spacing in whole increments of 1/60px, matching its layout and preventing small line-wrap discrepancies.
Safari now retains a word's kerning with a following space, both with and without letter spacing.
Chrome line widths now account for kerning between spaces and neighboring words, preventing lines and widest-line-sized bubbles from exceeding Chrome's layout.
Reported line widths are clamped at zero instead of becoming negative, for example under strongly negative letter spacing.
Words wider than a line now account for kerning when choosing cuts, more closely matching Chrome and Firefox; measurements cost more when such a word is first prepared.
Ranges ending past their prepared text now materialize only text up to the range end instead of appending undefined or potentially iterating until memory runs out.
In Firefox, zero-width break: 'never' items and zero-width boxes that fall past a full line now land on the line Firefox uses.
Rich-inline line-start fragments now begin after spaces and soft hyphens skipped at line starts, including under negative letter spacing.
Rich-inline layout now keeps text or a break: 'never' item on a line when its overflow is within 0.005px, or 1/64px in Safari.
A line ending at a soft hyphen is measured with U+2010 HYPHEN when the font has one, while the line's text still ends with a hyphen-minus.
Browsers and in-app web views on iPhone, iPad and Mac now use Safari's WebKit wrapping rules; Safari worker preparation uses the same rules as page preparation.
Chrome and Firefox no longer lose text when a URL contains a second www. or scheme before its query.
Paragraphs made only of zero-width spaces now occupy one line instead of disappearing.
A zero-width space at paragraph or hard-line start no longer disappears when following text wraps.