effect-text
v0.2.0
Published
Effect-native text preparation, measurement, and greedy multiline layout
Readme
effect-text
Effect-native text preparation and greedy multiline layout.
Text.prepare owns segmentation, measurement, and caching. Text.layout*
stays pure, so prepared text can be reprojected on resize, animation, or
obstacle changes without re-entering services.
Install · Quick Start · Surface · Support Envelope · Examples · Proof
Install
npm install effect-text effectUse the equivalent pnpm add or bun add command if that is your package
manager. effect is a required peer dependency.
Quick Start
import { Effect } from "effect"
import { Text } from "effect-text"
const program = Effect.gen(function* () {
const prepared = yield* Text.prepareWithSegments({
text: "Prepare once, layout many times.",
font: { family: "Mono", size: 16 },
whiteSpace: "normal"
})
return {
summary: Text.layout(prepared, { maxWidth: 120, lineHeight: 20 }),
lines: Text.layoutLines(prepared, { maxWidth: 120, lineHeight: 20 })
}
}).pipe(Effect.provide(Text.TextLayoutLive))
Effect.runPromise(program)Use Text.prepare when you only need summary projections such as layout or
measureNaturalWidth. Use Text.prepareWithSegments when you need materialized
lines, cursor stepping, streaming projection, or variable-width layout.
Surface
| Surface | What it owns |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| Text | Effectful preparation and pure layout: prepare, prepareWithSegments, layout, layoutLines, layoutLinesWith, layoutNextLine, streamLines |
| Contracts | Explicit runtime seams: WordSegmenter, TextMeasurer, MeasurementCache, EngineProfile, HyphenationDictionary |
| Browser | Browser measurer layers, cache freshness, support data, parity harness helpers |
| React | Prepare-identity helpers and pure prepared-layout projection helpers |
| Errors | MeasurementFailed, TextLayoutDecodeError, PrepareError |
| Experimental.Calibration | Additive effect-search studies with internal effect-math scoring adapters |
Ownership boundaries are deliberate:
effect-text/browserowns support data, browser measurement, font-readiness revision helpers, and parity artifacts.effect-text/reactstays framework-thin: prepare identity plus pure prepared-layout projection only.Experimental.Calibrationis additive and does not make layout effectful.
Support Envelope
Shipped behavior is explicit and bounded.
- Browser profiles:
canvas-monospaceandcanvas-system-ui - Hyphenation locales:
en-us,en-gb,de,fr,es - Locale fallback: exact match, then shipped base language, then deterministic non-dictionary fallback
- Overflow precedence:
hard-break -> soft-hyphen -> dictionary-hyphen -> explicit-break -> grapheme-fallback - Tab policy:
tabWidth: 4, CSS-style column stops - Browser freshness: support-profile identity + full font identity + font-readiness revision
Stability lanes are also explicit:
| Module | Stability |
| -------------- | ----------- |
| Contracts | Stable |
| Errors | Stable |
| Text | Provisional |
| Browser | Provisional |
| React | Provisional |
| Experimental | Unstable |
Current non-goals:
- No claim of full CSS layout parity.
- No claim of full shaping-engine parity across arbitrary font stacks.
- Browser claims are limited to the shipped support manifest and checked-in parity artifacts.
- Explicit Unicode bidi control handling remains outside the released surface.
The checked-in support authority lives at
src/contracts/supportManifest.ts.
Examples
Runnable examples live in examples/:
| Example | What it proves |
| ---------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| 01-quick-start | Deterministic prepare/layout flow |
| 02-cursor-and-stream | Cursor stepping and Stream projection |
| 03-explicit-services-and-caching | Custom service wiring and shared caching |
| 04-canvas-measurement | Official browser-layer composition |
| 05-experimental-calibration-search | Seeded effect-search optimization over calibration corpora |
| 06-live-browser-parity | Shipped browser support envelope and parity artifacts |
| 07-dictionary-hyphenation | Dictionary hyphenation and deterministic fallback |
Run one directly with Bun:
bun run packages/effect-text/examples/01-quick-start.tsProof
Run the package proof surface from packages/effect-text/:
bun run check
bun run check:tests
bun run lint
bun run test
bun run bench
bun run verify:browser-parity
bun run verify:calibration
bun run verify:support-manifest
bun run build
bun run docgenRefresh checked-in artifacts only when intentional runtime changes land:
bun run verify:browser-parity --write
bun run verify:calibration --write
bun run bench
bun run verify:support-manifestAcknowledgments
The prepare/layout split is inspired by
pretext. Experimental.Calibration
builds on the local effect-search package for
seeded studies and uses effect-math behind
internal adapters for loss aggregation and summary statistics.
License
MIT — Copyright © 2026 Scene Systems
