Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ Other helpers:
```ts
clearCache(): void // clears Pretext's shared internal caches used by prepare() and prepareWithSegments(). Useful if your app cycles through many different fonts or text variants and you want to release the accumulated cache
setLocale(locale?: string): void // optional (by default we use the current locale). Sets locale for future prepare() and prepareWithSegments(). Internally, it also calls clearCache(). Setting a new locale doesn't affect existing prepare() and prepareWithSegments() states (no mutations to them)
setMeasureContext(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | any): void // allows setting a custom canvas context for text measurement. Particularly useful in SSR environments (like NextJS or Node.js) where DOM and OffscreenCanvas are not available.
```

Notes:
Expand All @@ -222,6 +223,24 @@ Notes:
- `measureNaturalWidth()` returns the widest forced line. Hard breaks still count.
- `prepare()` and `prepareWithSegments()` do horizontal-only work. `lineHeight` stays a layout-time input.

## Server-Side Rendering (SSR)

To use Pretext in a server-side environment (like Node.js or NextJS), you'll need to provide a canvas implementation, as `document` and `OffscreenCanvas` are not globally available.

You can use the `canvas` package from npm and `setMeasureContext` to initialize the measurement context before calling `prepare()` or `prepareWithSegments()`:

```ts
import { setMeasureContext } from '@chenglou/pretext'
import { createCanvas } from 'canvas'

// Initialize the measurement context once, ideally at module scope
const canvas = createCanvas(1, 1)
const ctx = canvas.getContext('2d')
setMeasureContext(ctx)

// Now you can use prepare() and layout() as normal
```

## Caveats

Pretext doesn't try to be a full font rendering engine (yet?). It currently targets the common text setup:
Expand Down
3 changes: 3 additions & 0 deletions src/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {
import {
type BreakableFitMode,
clearMeasurementCaches,
setMeasureContext,
getCorrectedSegmentWidth,
getSegmentBreakableFitAdvances,
getEngineProfile,
Expand Down Expand Up @@ -785,3 +786,5 @@ export function setLocale(locale?: string): void {
setAnalysisLocale(locale)
clearCache()
}

export { setMeasureContext }
4 changes: 4 additions & 0 deletions src/measurement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ const maybeEmojiRe = /[\p{Emoji_Presentation}\p{Extended_Pictographic}\p{Regiona
let sharedGraphemeSegmenter: Intl.Segmenter | null = null
const emojiCorrectionCache = new Map<string, number>()

export function setMeasureContext(ctx: any): void {
measureContext = ctx
}

export function getMeasureContext(): CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D {
if (measureContext !== null) return measureContext

Expand Down