@apertura/render
Shared Apertura rendering primitives: measurement units, colours, DOM helpers, base view class
79 exported symbols · 27 declared here · 52 re-exported
Classes
Base implementation of {@link DocumentView}. Handles what every renderer needs identically: the root element, the resize subscription, zoom, and correct resource cleanup. Subclasses only implement {@link renderContent}.
Accumulates CSS rules and installs them as a single stylesheet. Renderers must emit shared CSS classes rather than inline `style` attributes. The difference is not cosmetic: a document with 50 000 runs produces 50 000 inline style attributes, each of which the browser parses separately and none of which can be shared. Routing the same formatting through a handful of generated classes cuts both the DOM size and the style recalculation cost by an order of magnitude. The builder also deduplicates: identical declaration blocks collapse onto one class, which is exactly what happens in real documents where a few dozen distinct formatting combinations cover the entire text.
Text measurement backed by a canvas, with aggressive caching. The pagination engine needs to know how wide a run is before it exists in the DOM, and doing that by inserting elements and reading `offsetWidth` forces a synchronous layout per measurement — the classic reason document viewers stall on large files. A 2D canvas context measures text without touching layout at all. Two caches sit on top of it: one for font metrics (per font, computed once) and one for measured strings (per font + string). Documents repeat the same words in the same formatting constantly, so the hit rate is high and the measurement cost effectively disappears after the first page.
A format registry that also knows how to draw. Parsers are registered in `@apertura/core`, which knows nothing about the browser; renderers are registered here. Subclassing rather than composing keeps the fluent chain a caller expects — `registerParser` returns `this`, so a registry can be built in one expression — while leaving the parser half usable on a server that has no DOM at all.
Functions
Removes every child of a node.
Excel column width in "characters" converted to pixels. Excel measures width in multiples of the width of the "0" glyph of the Normal style font and adds 5 pixels of cell padding (MS-OI29500, Column Width): `px = trunc(width * mdw) + 5`, where `mdw` is the digit width in pixels (7 for the default Calibri 11pt). This is where Excel's well-known default comes from: 8.43 characters is exactly 64 pixels.
Picks a readable text colour for a given background. Needed wherever a format specifies only a fill: a table header with a dark shade and default black text would be unreadable. The 0.5 threshold is on WCAG relative luminance.
Creates an SVG element; needed for VML shapes and drawing fallbacks.
Builds a complete CSS rule from a selector and a style map.
Eighths of a point: the unit of `w:sz` on border elements.
Escapes a string so it can be used as a CSS class name. Word style identifiers may contain spaces, dots and non-ASCII characters; all of them have to be neutralised before they become part of a selector.
Escapes a string for safe insertion into HTML markup.
`a:gray`: the colour rendered in shades of grey, by perceived brightness.
Half-points: the unit Word uses for font sizes (`w:sz w:val="24"` is 12pt).
Adds a stylesheet to the document exactly once. A page may host several viewers while the renderer stylesheet is shared; the key prevents a duplicate `<style>` on every mount.
`a:inv`: every channel inverted.
Converts a {@link Length} to a CSS string, or `undefined` when it is `auto`.
Converts a {@link Length} to pixels; percentages need a reference size.
Applies the `hueMod`/`hueOff` hue rotation of DrawingML; both wrap.
Applies the `lumMod`/`lumOff` luminance modulation used by DrawingML themes. Word writes theme colour variations this way, e.g. "Accent 1, lighter 40%" becomes `lumMod 60000` + `lumOff 40000` (values are thousandths of a percent).
Applies the `satMod`/`satOff` saturation modulation of DrawingML. The other half of the pair Office writes for a theme variation. Every theme Word ships states its fills as a scheme colour with both a luminance and a saturation modifier on it — a heading colour is `accent1` at 110% saturation and 75% luminance — and applying only the first paints a colour that is the right lightness and visibly the wrong intensity.
Subscribes to container size changes. Returns an unsubscribe function. When `ResizeObserver` is unavailable (older environments, server rendering) no subscription is created and the caller is responsible for triggering re-layout itself.
Parses `ST_HexColor`: six or eight hex digits, with or without a leading hash. The special value `auto` means "the application picks the colour", so it returns `undefined` and lets the caller apply its own contextual rule (usually black text on a light background).
Inverse of {@link columnWidthToPixels}.
Builds the outline of a preset shape.
Formats a value as a CSS point string, rounded to two decimals.
Formats a value as a CSS pixel string, rounded to two decimals.
An axis-aligned rectangle path, the fallback for an unknown preset.
WCAG 2.1 relative luminance, 0..1.
Re-scales a frame already in the document. The whole reason the model is worth having: changing the zoom is two style writes and no layout at all. Under the multiply-everything arrangement it was a full re-render — for Word, a re-pagination of the entire document on every step of the zoom control.
Excel row heights are expressed in points.
A box that draws at natural size and occupies the scaled one.
Darkening (`shade`): mixes towards black.
Serialises a style map into a CSS rule body. Used by the stylesheet generator, which emits real CSS rules instead of inline styles: one rule shared by ten thousand paragraphs is dramatically cheaper for the browser than ten thousand inline `style` attributes.
Lightening (`tint` in DrawingML): mixes towards white.
Interfaces
A live view of a document mounted into the DOM.
Thin DOM helpers. Renderers create thousands of elements per document, and calling `document.createElement` followed by one-by-one style assignment is the single biggest source of noise in that kind of code.
A font as far as measurement is concerned.
A length as stored in the file, together with the unit it was stored in. Keeping the unit lets the renderer decide how to emit it: some measurements are better expressed in `pt` so the browser can round them itself, others must be pixels because they take part in layout arithmetic.
Everything a preset needs to produce its path.
Colour handling for office formats. OOXML expresses colour in three different ways: a direct RGB value (`FF0000`), a reference to a theme colour (`accent1`), and modifiers applied on top of a theme colour (`lumMod`, `tint`, `shade`). This module holds the conversions that are common to every format; resolving theme references stays in the format packages, which are the ones with access to `theme1.xml`.
A renderer plugin: turns a parsed document into DOM.
Values
Shared registry for applications that do not need isolation.
Eighths of a point: the unit of border widths in WordprocessingML.
EMUs per centimetre.
English Metric Units: 914400 per inch. The base unit of DrawingML.
EMUs per point: 914400 / 72.
Named `ST_HighlightColor` values from WordprocessingML.
What a zoom is allowed to be. Beyond this the browser stops being useful.
CSS pixels per inch — 96, as is conventional on the web.
Twentieths of a point: 1440 per inch. The unit of WordprocessingML.