@reportwright/fonts
v1.0.0
Published
Fonts (Inter, JetBrains Mono, Noto), the HarfBuzz shaper and subsetter for @reportwright/engine.
Maintainers
Readme
@reportwright/fonts
The fonts, text shaper, PDF font subsetter and PDF/A colour profile that @reportwright/engine and @reportwright/viewer render with.
Live demo: mrarun005.github.io/reportwright-demo: every report in the live gallery is drawn with these fonts, loaded from a fontsUrl folder as described below.
Kept out of the engine so the engine stays small. It is a folder of files the engine finds by itself in Node, and that you serve as static files to the browser.
Its root import says where those files are, as URLs (no other code):
import { fontsUrl, subsetWasmUrl, iccUrl } from '@reportwright/fonts';
import { fileURLToPath } from 'node:url';
fileURLToPath(fontsUrl); // …/node_modules/@reportwright/fonts/public/fonts/The files themselves are the subpath @reportwright/fonts/public/* (e.g. @reportwright/fonts/public/harfbuzz-subset.wasm).
Install
npm i @reportwright/engine @reportwright/fontsQuick start (30 seconds)
Node: nothing to configure; defaultFontStore() finds the package.
import { render, defaultFontStore, exportPdf } from '@reportwright/engine';
const fonts = defaultFontStore(); // reads node_modules/@reportwright/fonts/public/fonts
const def = { $schema: 'reportwright/report@1', name: 'Hello', page: { size: 'A4', margins: [36, 36, 36, 36] },
sections: { body: { items: [{ type: 'textbox', name: 'Hi', x: 0, y: 0, w: 400, h: 24, value: 'नमस्ते · مرحبا · שלום · สวัสดี' }] } } };
const pdf = await exportPdf(await render(def, { fontStore: fonts }), { fonts }); // shaped, subset, no warningsBrowser (viewer, or the engine in a bundled app): copy the folder to your static files and pass its URL.
cp -r node_modules/@reportwright/fonts/public public/pw # → public/pw/fonts/, public/pw/harfbuzz-subset.wasm, public/pw/icc/mountViewer('#report', { definition, data, fontsUrl: '/pw/fonts/' }); // @reportwright/viewer
const fonts = defaultFontStore({ fontsUrl: '/pw/fonts/' }); // @reportwright/engine in a bundleBoth were verified against this version (Node 20; Vite 7 in Chromium).
Examples
Use the monospace face for codes and numbers: set the family in the item's style.
{ "type": "textbox", "name": "Code", "x": 0, "y": 30, "w": 400, "h": 24, "value": "INV-0042", "style": { "fontFamily": "JetBrains Mono" } }Cache the folder for a year. The files do not change within a package version:
Cache-Control: public, max-age=31536000, immutable on /pw/.
Your own fonts in Node: a FontStore over your files (new FontStore((key) => bytesOf(fontFile(key))), see the
engine), or upload them to the self-hosted server.
What is inside
| Path | What |
|---|---|
| public/fonts/Inter-*.ttf | Inter Regular, Italic, SemiBold, Bold, Bold Italic (the default family) |
| public/fonts/JetBrainsMono-*.ttf | JetBrains Mono Regular and Bold |
| public/fonts/NotoSans*-*.ttf | Noto Sans Arabic, Hebrew, Devanagari, Bengali, Gujarati, Kannada, Tamil, Telugu, Thai, Khmer, Lao, Myanmar (Regular and Bold) |
| public/fonts/harfbuzz.wasm | the HarfBuzz text shaper (complex scripts, ligatures, right-to-left) |
| public/harfbuzz-subset.wasm | the PDF font subsetter: a PDF embeds only the glyphs it uses |
| public/icc/sRGB-v2-magic.icc | the sRGB output intent exportPdf(model, { pdfa: true }) embeds |
5.3 MB unpacked. A face is loaded only when the layout first needs it. A font that cannot be loaded is an error
(there is no fallback font). Chinese, Japanese, Korean and emoji are in @reportwright/fonts-cjk
because they are large.
Related packages
@reportwright/engine (peer of this package), @reportwright/viewer, @reportwright/cli, @reportwright/fonts-cjk.
Fonts: SIL Open Font License 1.1 (the OFL-*.txt files); the rest MIT.
