API
renderToBuffer(element, options?): Promise<Uint8Array> // the PDF bytes
renderToFile(element, path, options?): Promise<void> // renders, then writes the file
renderToStream(element, options?): Promise<Readable> // the PDF as a Node stream
renderToStream returns a stream to pipe into an HTTP response:
(await renderToStream(<Invoice />)).pipe(res). The stream starts once the PDF is ready, and a
failed render rejects the promise.
All three take the same options:
| Option | Default | What it does |
|---|---|---|
images | none | Image bytes by id, for <Image src="logo">. An id wins over a path or URL with the same text. |
localImages | off | { root: '/srv/app/images' } or { root: [dirA, dirB] }: folders <Image src="./logo.png"> may read files from. A relative path is resolved against the first. maxBytes (20 MiB) limits each file. The INKOXIDE_LOCAL_IMAGES environment variable (folders separated by :, ; on Windows) sets it for every render. |
remoteImages | off | { allow: ['https://cdn.example.com/', '*.example.org'] }: hosts <Image src="https://…"> and <Image src={{ uri }}> may load from. A URL entry allows its origin (scheme, host and port), and, with a path, that path and the paths under it: https://cdn.example.com/img allows /img/logo.png, not /imgs/logo.png. A host entry allows https: at that host, or with *. at its subdomains. Ports must match: an entry without a port allows only its scheme's default port (443 for https:, 80 for http:), and cdn.example.com:8443 or https://cdn.example.com:8443 only port 8443. timeoutMs (10 000; Infinity for no limit) and maxBytes (20 MiB, 20 971 520 bytes) limit each image, and redirects are not followed. The INKOXIDE_REMOTE_IMAGES environment variable (comma-separated) sets it for every render. |
imageTimeoutMs | 10000 | How long a function or promise <Image src> may take to settle; Infinity waits without a limit |
pdfA | false | Write PDF/A, for archiving: true or '2b', '3b' or '1b' (see PDF/A). Wins over <Document conformance>. |
encryption | none | { userPassword, ownerPassword, permissions }: encrypt the PDF (see Passwords and permissions). Replaces the <Document> props of the same names. |
compress | true | Compress the page content |
subsetFonts | true | Embed only the glyphs the document uses |
creationDate | none | RFC 3339 timestamp written to the PDF. Without it, the same input gives byte-identical output. |
threads | all cores | How many cores one render spreads its pages over: an integer from 1 to 256 |
validate | outside production | Check the document tree first, for clearer errors |
A bad option fails the render with ENGINE_REJECTED at its path (options.threads,
options.remoteImages.timeoutMs): a creationDate that is not RFC 3339, a threads that is
not an integer from 1 to 256, or a timeout or maxBytes that is not a number from 0 (NaN, a
negative number, a string), or an option of the wrong type (threads: '4', localImages
without root). A fractional timeout is rounded up to a whole millisecond.
Font.register({ family, src }) adds a font family, from a path, a URL or bytes. See
Fonts.
Font.registerHyphenationCallback(fn) splits words for hyphenation with your own function;
null removes it. See Text: hyphenation and direction.
StyleSheet.create(styles) returns the styles unchanged, with their types.
init() loads Tailwind's compiler (when @inkoxide/tailwind is installed), the engine and
the fonts. The first render does it anyway; call it at server startup so the first request does not wait (about 160 ms). It resolves
to the same status as engineStatus().
Health checks. version() returns { engine, schema, gitSha }: the engine's version, the
document schema version it reads and the commit it was built from. engineStatus() returns
undefined until the engine has started (the first init or render), then { version, fonts, hyphenation, warnings }: the font ids registered, which hyphenation languages loaded
({ en: true }), and start-up warnings such as a missing bundled font.
app.get('/health', (_req, res) => {
const status = engineStatus();
res.status(status ? 200 : 503).json(status ?? { starting: true });
});
countPages(pdf) is the page count of a PDF made by renderToBuffer. It reads the page
tree the engine writes, so it is not a general PDF parser.
Types. The props of a component are exported as a type named after it (DocumentProps,
TextProps, TextFieldProps, FieldProps, SvgProps, MarkerProps, TspanProps, CanvasProps and so on); PolyProps
serves Polyline and Polygon, GradientProps both gradients, SvgPresentation the
attributes every SVG shape takes, and SvgTextProps the props of a Text in an Svg. Also
exported:
- styles and values:
Style,StyleProp,AbsoluteLength,Length,LengthPercent,LengthAuto,PageSize,PagePreset,BreakProp,BookmarkProp,FontWeightName,Permissions(of<Document permissions>), andTextFormat, theformatof aTextField; renderprops and images:RenderProp,PageInfo,ImageSrc,ImageSrcValue,ImageRequest,Painter, the painter aCanvasdraws with,CanvasGradient, its gradients, andCanvasTextOptions, the options of itstext;- options and results:
RenderToBufferOptions,LocalImageOptions,RemoteImageOptions,FontRegistration,FontSource,FontSrc,EmojiSource,FontWeight,HyphenationCallback,EngineStatus,EngineVersion,RenderErrorCodeandDataIssue.
Concurrency. A render runs on Node's thread pool, so many can run at once. threads sets
how many cores one render uses; with threads: 1 each render stays on its own pool thread.
Node's UV_THREADPOOL_SIZE (default 4) caps how many renders run at the same time.
Synced from packages/render/GUIDE.md in the inkoxide repository.