Active Foundation

Search documentation

Search all pages, headings and text, in the current package or topic or in all documentation.

Export guarantees

What each export guarantees for international text, and which route to take where the grid does not.

@workspace/active-grid 11.0.0Status unknowncontent differs from the recorded release 11.0.0baseline ce081dc3

The package's own guide

This guide is the package's docs/guides/export-guarantees.md, included unchanged from the package as it is in Foundation. Links to the package's internal design documents keep their text.

What each export of @workspace/active-grid guarantees for international text, who owns that guarantee, and which route a consumer takes when the grid does not guarantee what it needs. Decided in ADR-055; the PDF fonts, the workbook direction and the error model are ADR-054; the formats are export.md. active-charts carries the same tiers in its own words for its own formats (its SVG and PNG exports have no grid counterpart).

The tiers#

TierOwnerFormatsScript guaranteeLimitation
L0packageCSV, clipboard TSV, JSON, XLSX valuesevery script, including supplementary-plane characters and ZWJ sequences: the logical Unicode text, no direction or isolation controls; XLSX numbers and dates stay typeddata only: no font. An XLSX also carries its sheet direction (Workbook.Views[0].RTL), never a font or a style
L1package + browserthe live gridwhat the browser shapes (joining, reordering, marks, bidi) with the fonts the page loadsa glyph no loaded font has is the browser's fallback
L2spreadsheet appthe XLSX viewan rtl grid's workbook opens right to lefthow the sheet looks (fonts, shaping) is the spreadsheet application's
L3apackagePDFLatin, Greek, Cyrillic, Armenian, Georgian, Han (BMP), Kana, Hangul (precomposed), each cell fully covered by one embedded TrueType family; WinAnsi without a setrefused with a code, never drawn broken: complex and right-to-left scripts, combining marks, joiners and selectors, emoji, supplementary-plane characters, uncovered cells
L3b-rasterhosta PDF the host builds with an image of the grideverything the host's browser shapesthe table is a picture: its text is not selectable or searchable
L3b-printhosta PDF the host's browser printseverything the host's browser shapes, as selectable texta host recipe, not a package route; valid only as far as the host has verified it with its own browser and fonts

No tier promises more than it says.

Known gap (ROADMAP R-64). In presentation mode (always for the clipboard, and CSV, JSON or XLSX with {mode: 'presentation'}), a number, percentage or amount formatted for some locales still carries the bidi marks Intl inserts (for example U+200F in a he-IL amount, U+061C in an ar-EG number). Data mode, the default, is L0 as stated.

Per script#

Script or dataLive (L1)CSV, TSV, JSON (L0)XLSX (L0 values, rtl view)PDF, no setPDF, host set that covers it
LatinbrowserpackagepackageHelvetica (WinAnsi)drawn (L3a)
Cyrillic, Greekbrowserpackagepackage'EXPORT_FONT_REQUIRED'drawn (L3a)
Han, Kana, Hangul (BMP)browserpackagepackage'EXPORT_FONT_REQUIRED'drawn (L3a)
Arabic, Hebrewbrowserpackagepackage'EXPORT_TEXT_UNSUPPORTED''EXPORT_TEXT_UNSUPPORTED'; host L3b
Devanagari and other Indicbrowserpackagepackage'EXPORT_TEXT_UNSUPPORTED''EXPORT_TEXT_UNSUPPORTED'; host L3b
Combining mark in the textbrowserpackagepackage'EXPORT_TEXT_UNSUPPORTED''EXPORT_TEXT_UNSUPPORTED' (normalizable says whether NFC would help)
Emoji, ZWJ sequencesbrowserpackagepackage'EXPORT_TEXT_UNSUPPORTED''EXPORT_TEXT_UNSUPPORTED'; host L3b
Supplementary planebrowserpackagepackage'EXPORT_TEXT_UNSUPPORTED''EXPORT_TEXT_UNSUPPORTED'; host L3b
A script no family coversbrowserpackagepackage'EXPORT_FONT_REQUIRED''EXPORT_GLYPH_COVERAGE'

One refused cell refuses the whole PDF: a table is one document. Thai, Lao, Khmer, Myanmar, Tibetan, Mongolian, Syriac, Thaana and N'Ko are refused like Arabic. A refusal names one code point and, for a script, its name; it never carries the cell text.

Which route#

The consumer needsRoute
the data, for a program or a spreadsheetCSV, TSV or JSON (L0); XLSX for typed cells and the sheet direction
a PDF with selectable text in a supported scriptPDF (L3a) with an export font set that covers every cell
a PDF with Arabic, Hebrew, Indic, emoji or other shaped texta host route: L3b-raster (image in a PDF) or L3b-print (browser print)

The grid never hands over to a host route by itself: it refuses, and the host decides. A host that knows its data is complex-script can leave PDF out of export.formats.

Errors#

A GridExportError code separates four kinds of failure; none carries the exported text (at most one code point and a script name, the host's family name, the detected font format, the missing module, the families tried).

KindCodesWhat the host does
a refusal of the text (L3a)'EXPORT_TEXT_UNSUPPORTED', 'EXPORT_FONT_REQUIRED', 'EXPORT_GLYPH_COVERAGE'supply or extend fonts, or take a host route
a font set the export cannot use'EXPORT_FONT_FACE_MISSING', 'EXPORT_FONT_SOURCE_INVALID', 'EXPORT_FONT_FORMAT_UNSUPPORTED'fix the configuration
a font that did not arrive'EXPORT_FONT_LOAD_FAILED' (the host loader's error is the cause)retry; the next export calls the loader again
the export itself could not run'EXPORT_DEPENDENCY_MISSING' (missingModule)install the module, or offer no such export

The codes and their meaning are active-charts' where the failure is the same; the charts add two of their own (a capture that failed, a CSV without rows).

Configuring export fonts in a host#

The host owns its fonts. A typical enterprise set is a corporate Latin family first and a CJK family as its fallback, with faces loaded only when a PDF needs them:

TSX
const load = (path: string) => () =>  fetch(path, {signal: AbortSignal.timeout(15_000)}).then((response) => {    if (!response.ok) throw new Error(`font ${response.status}`);    return response.arrayBuffer();  });
const fonts: GridExportFonts = {  families: [    {      family: 'Corporate Sans',      faces: [        {source: load('/fonts/corporate-sans-regular.ttf')},        {source: load('/fonts/corporate-sans-bold.ttf'), weight: 700},        {source: load('/fonts/corporate-sans-italic.ttf'), style: 'italic'},      ],    },    {      family: 'Example CJK Sans',      faces: [{source: load('/fonts/example-cjk-sans-regular.ttf')}],    },  ],};
<GridDefaults export={{fonts}}>{children}</GridDefaults>;
  • The PDF needs static TrueType (glyf) faces; WOFF, WOFF2, CFF-flavoured OpenType and variable fonts cannot be embedded.

  • The header row and group rows are bold: give a bold face, or they draw in the regular one.

  • Keep the object stable (a module constant): each face object is loaded once, and concurrent exports share the load.

  • The same object serves active-charts as its export font set.

Host routes (L3b)#

These are recipes for a host. The grid provides neither.

L3b-raster: a browser image in a PDF#

  1. Render the grid in a browser or headless browser that has the fonts the cells need.

  2. Wait for document.fonts.ready and for the rows to be loaded.

  3. Take a screenshot of the grid element at a scale for print (for example 2x device pixels).

  4. Place the image in the host's PDF.

The browser shapes every script it has fonts for. The cells are pixels: they cannot be selected, searched or read by assistive technology from the PDF, and a table longer than a page needs the host to paginate the capture.

L3b-print: the browser prints a PDF#

  1. Launch a browser the host controls (for example headless Chromium) with the fonts installed or loaded.

  2. Render a page with the table (the live grid, or a print layout the host builds from the same rows).

  3. Wait for document.fonts.ready.

  4. Print with the browser's PDF mechanism (in Chromium, page.pdf()).

  5. Verify before relying on it: extract the text from the PDF and render it back to an image, for each script the host serves.

The browser shapes the text and writes it as selectable text with a Unicode mapping. This was verified once in a research harness (Chromium 153 on Windows with the operating system's fonts): Arabic, Hebrew and Devanagari came back from the PDF in logical order, and the rendered PDF showed joined Arabic, right-to-left Hebrew and formed Devanagari conjuncts. That is evidence the recipe works, not a guarantee for another browser version, operating system or font set. A virtualised grid draws only its visible rows, so a print route renders a layout of all rows, not the scrolled viewport.

This page as Markdown