From 95f9d90398d9dff48d32864ec4e1ca4e0a2a3dcc Mon Sep 17 00:00:00 2001 From: Himanshu Jain <210527591+Himaan1998Y@users.noreply.github.com> Date: Thu, 2 Apr 2026 00:03:18 +0530 Subject: [PATCH 1/4] docs: add quickstart guidance for new users --- README.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/README.md b/README.md index 88b598c..f780c35 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,79 @@ Pretext side-steps the need for DOM measurements (e.g. `getBoundingClientRect`, npm install @chenglou/pretext ``` +## Quick Start + +If you're coming from React, Vue, Angular, or plain DOM code, the core mental model is: + +1. `prepare()` once when the text or font changes +2. `layout()` whenever the available width changes +3. use the returned `height` / `lineCount` to drive your UI + +In other words: **prepare once, layout many times**. + +Start with the simplest question: + +- "I just need the paragraph height" -> use `prepare()` + `layout()` +- "I need the actual wrapped lines for custom rendering" -> use `prepareWithSegments()` + one of the rich line APIs + +### Common app pattern + +This is the most common integration shape for app UIs: + +```ts +import { prepare, layout } from '@chenglou/pretext' + +const prepared = prepare(text, font) +const { height, lineCount } = layout(prepared, width, lineHeight) +``` + +In a framework, the same rule applies: + +- recompute `prepare()` only when `text`, `font`, or whitespace mode changes +- recompute `layout()` when width or line height changes +- do **not** rerun `prepare()` on every resize + +React example: + +```ts +import { useMemo } from 'react' +import { prepare, layout } from '@chenglou/pretext' + +const prepared = useMemo( + () => prepare(text, font, whiteSpace ? { whiteSpace } : undefined), + [text, font, whiteSpace] +) + +const { height, lineCount } = useMemo( + () => layout(prepared, width, lineHeight), + [prepared, width, lineHeight] +) +``` + +The same idea applies outside React too: cache the `prepare()` result based on text/font inputs, then rerun `layout()` when width changes. + ## Demos Clone the repo, run `bun install`, then `bun start`, and open `/demos/index` in your browser. On Windows, use `bun run start:windows`. Alternatively, see them live at [chenglou.me/pretext](https://chenglou.me/pretext/). Some more at [somnai-dreams.github.io/pretext-demos](https://somnai-dreams.github.io/pretext-demos/) +Good first pages: + +- [chenglou.me/pretext/](https://chenglou.me/pretext/) — main demo page +- [chenglou.me/pretext/justification-comparison](https://chenglou.me/pretext/justification-comparison) — a stable example page in the main demo set +- [chenglou.me/pretext/accuracy](https://chenglou.me/pretext/accuracy) — browser-vs-library accuracy sweep +- [somnai-dreams.github.io/pretext-demos](https://somnai-dreams.github.io/pretext-demos/) — extra exploratory demos, including richer custom layouts + +## Which API should I start with? + +| If you need... | Start with... | +| --- | --- | +| height prediction for ordinary app text | `prepare()` + `layout()` | +| visible spaces / tabs / line breaks like a textarea | `prepare(..., { whiteSpace: 'pre-wrap' })` + `layout()` | +| custom line rendering to canvas / SVG / WebGL | `prepareWithSegments()` + `layoutWithLines()` | +| streaming or variable-width line routing | `prepareWithSegments()` + `layoutNextLine()` | +| shrink-wrap / widest-line geometry without building line strings | `prepareWithSegments()` + `walkLineRanges()` | + ## API Pretext serves 2 use cases: From e58fcfc352c1585394160f86f839e67e771e962b Mon Sep 17 00:00:00 2001 From: Himanshu Jain <210527591+Himaan1998Y@users.noreply.github.com> Date: Thu, 2 Apr 2026 00:27:58 +0530 Subject: [PATCH 2/4] docs: add Vue/Angular snippets and fix demo link --- README.md | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f780c35..45d019f 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,44 @@ const { height, lineCount } = useMemo( The same idea applies outside React too: cache the `prepare()` result based on text/font inputs, then rerun `layout()` when width changes. +Vue (Composition API) example: + +```ts +import { computed } from 'vue' +import { prepare, layout } from '@chenglou/pretext' + +const prepared = computed(() => + prepare(text.value, font.value, whiteSpace.value ? { whiteSpace: whiteSpace.value } : undefined) +) + +const measured = computed(() => + layout(prepared.value, width.value, lineHeight.value) +) + +const { height, lineCount } = measured.value +``` + +Angular (signals) example: + +```ts +import { computed, signal } from '@angular/core' +import { prepare, layout } from '@chenglou/pretext' + +const text = signal('Hello world') +const font = signal('16px Inter') +const whiteSpace = signal<'normal' | 'pre-wrap'>('normal') +const width = signal(320) +const lineHeight = signal(20) + +const prepared = computed(() => + prepare(text(), font(), whiteSpace() === 'normal' ? undefined : { whiteSpace: whiteSpace() }) +) + +const measured = computed(() => + layout(prepared(), width(), lineHeight()) +) +``` + ## Demos Clone the repo, run `bun install`, then `bun start`, and open `/demos/index` in your browser. On Windows, use `bun run start:windows`. @@ -70,7 +108,7 @@ Good first pages: - [chenglou.me/pretext/](https://chenglou.me/pretext/) — main demo page - [chenglou.me/pretext/justification-comparison](https://chenglou.me/pretext/justification-comparison) — a stable example page in the main demo set -- [chenglou.me/pretext/accuracy](https://chenglou.me/pretext/accuracy) — browser-vs-library accuracy sweep +- [chenglou.me/pretext/dynamic-layout](https://chenglou.me/pretext/dynamic-layout) — a practical multiline layout example - [somnai-dreams.github.io/pretext-demos](https://somnai-dreams.github.io/pretext-demos/) — extra exploratory demos, including richer custom layouts ## Which API should I start with? From a98c8eedcfbaa9c7c5a800edca67cd8eacee0803 Mon Sep 17 00:00:00 2001 From: Himanshu Jain <210527591+Himaan1998Y@users.noreply.github.com> Date: Thu, 2 Apr 2026 00:31:02 +0530 Subject: [PATCH 3/4] docs: make framework snippets reactive-safe --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 45d019f..aed6e68 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,8 @@ const measured = computed(() => layout(prepared.value, width.value, lineHeight.value) ) -const { height, lineCount } = measured.value +const height = computed(() => measured.value.height) +const lineCount = computed(() => measured.value.lineCount) ``` Angular (signals) example: @@ -97,6 +98,9 @@ const prepared = computed(() => const measured = computed(() => layout(prepared(), width(), lineHeight()) ) + +const height = computed(() => measured().height) +const lineCount = computed(() => measured().lineCount) ``` ## Demos From f3d1eafbd9eb0f7526580d31338fdc1c8a01fb8a Mon Sep 17 00:00:00 2001 From: Himanshu Jain <210527591+Himaan1998Y@users.noreply.github.com> Date: Thu, 9 Apr 2026 19:51:45 +0530 Subject: [PATCH 4/4] docs: trim quickstart to reduce overlap --- README.md | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/README.md b/README.md index aed6e68..a9d5e78 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,6 @@ const { height, lineCount } = useMemo( ) ``` -The same idea applies outside React too: cache the `prepare()` result based on text/font inputs, then rerun `layout()` when width changes. - Vue (Composition API) example: ```ts @@ -108,23 +106,6 @@ const lineCount = computed(() => measured().lineCount) Clone the repo, run `bun install`, then `bun start`, and open `/demos/index` in your browser. On Windows, use `bun run start:windows`. Alternatively, see them live at [chenglou.me/pretext](https://chenglou.me/pretext/). Some more at [somnai-dreams.github.io/pretext-demos](https://somnai-dreams.github.io/pretext-demos/) -Good first pages: - -- [chenglou.me/pretext/](https://chenglou.me/pretext/) — main demo page -- [chenglou.me/pretext/justification-comparison](https://chenglou.me/pretext/justification-comparison) — a stable example page in the main demo set -- [chenglou.me/pretext/dynamic-layout](https://chenglou.me/pretext/dynamic-layout) — a practical multiline layout example -- [somnai-dreams.github.io/pretext-demos](https://somnai-dreams.github.io/pretext-demos/) — extra exploratory demos, including richer custom layouts - -## Which API should I start with? - -| If you need... | Start with... | -| --- | --- | -| height prediction for ordinary app text | `prepare()` + `layout()` | -| visible spaces / tabs / line breaks like a textarea | `prepare(..., { whiteSpace: 'pre-wrap' })` + `layout()` | -| custom line rendering to canvas / SVG / WebGL | `prepareWithSegments()` + `layoutWithLines()` | -| streaming or variable-width line routing | `prepareWithSegments()` + `layoutNextLine()` | -| shrink-wrap / widest-line geometry without building line strings | `prepareWithSegments()` + `walkLineRanges()` | - ## API Pretext serves 2 use cases: