@apertura/core
Apertura core: byte sources, format detection, plugin registry, shared document model
114 exported symbols · 114 declared here · 0 re-exported
Classes
Base class for every error raised by Apertura. A common ancestor lets consumers distinguish "the file failed to open" from a genuine bug in their own code with a single `instanceof` check.
A source backed by a browser `Blob`/`File`, read lazily in chunks.
A synchronous cursor-based reader over a `Uint8Array`. Binary formats (ZIP headers, OLE2/CFB, PDF xref tables, TIFF IFDs) are read as sequences of fixed-width fields, and tracking the offset by hand in every parser is a reliable way to introduce bugs. The reader does it for us and bounds-checks every step.
The operation was aborted through an AbortSignal.
The file was identified, but its contents violate the format specification.
The document is encrypted and no usable password was supplied.
Registry of parsers. An instance rather than a global singleton: a single page may host several independently configured viewers, and tests must not see each other's registrations. {@link defaultRegistry} is available for simple cases. Renderers are registered in `ViewRegistry` from `@apertura/render`, which extends this class. The split is what lets a server open a document without the DOM appearing anywhere in the type graph.
A source backed by HTTP range requests. Lets a document be opened from a URL without downloading it in full: a few kilobytes of tail data are enough to list the contents of a 200 MB file. If the server does not support ranges, the source downloads the file once and serves subsequent reads from memory.
A source backed by a buffer already held in memory.
A format feature that has not been implemented yet. A dedicated type lets the viewer show "this part of the document is not supported yet" instead of a generic read failure.
A read ran past the end of the byte source.
The file format was not recognised, or no plugin is registered for it.
Markup the reader walked past that nothing has declared it may walk past. Only ever raised in strict mode, which no viewer turns on: a reader that stops at the first unknown attribute is useless against real files, where every generator writes something nobody has seen. What it is for is the opposite situation — a development run over a corpus, where an element the parser silently ignores is indistinguishable from one it handles, and a gap therefore survives for as long as nobody happens to look at the right page. Strict mode makes the ignoring explicit: everything the parser passes over must be named in the registry of markup we have decided draws nothing, with the reason. Anything else stops the parse and names itself.
Functions
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.
Orders two locators the way the document reads. Needed wherever a range has to be normalised — a user selects backwards about half the time — and wherever highlights are merged. Flows are ordered by their kind and index so that a body address always precedes a footnote's, which is arbitrary but stable, and stable is the property that matters.
Eight hex digits identifying the bytes a locator was made against. FNV-1a over the whole buffer, which is not a cryptographic hash and is not meant to be. The question it answers is "is this the same file as the one the address came from", where the alternative to a wrong answer is a wrong highlight, not a security breach. Sixty-four bits folded to thirty-two make an accidental collision a once-in-four-billion event between two files a user has open at the same moment, and a real hash would cost a megabyte of bookkeeping and a dependency for it.
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.
CP1251: Cyrillic text in legacy Microsoft Office files.
Latin-1 (ISO-8859-1): used for legacy ZIP entry names and PDF strings.
UTF-16LE: the native string encoding of OLE2/CFB and many Windows structures.
Decodes an XML part, honouring the byte order mark it may start with. Nearly every OOXML part is UTF-8, and this exists for the ones that are not: XML permits UTF-16, a writer occasionally uses it, and Excel opens such a file without comment. Decoding those bytes as UTF-8 yields a string of NULs with no root element — a whole workbook lost to two bytes at the front.
Determines the file format from its contents, name and MIME type. For ZIP containers the result is always `probable`: telling docx, xlsx, pptx and odt apart requires looking inside the archive, which is the job of `@apertura/ooxml`. The core deliberately avoids pulling in decompression just to detect a format.
Eighths of a point: the unit of `w:sz` on border elements.
Looks up a format by extension. Accepts `docx`, `.docx` or a whole file name.
Builds a locator string. The inverse of {@link parseLocator} for every input it accepts; the pair is covered by a round-trip test rather than by inspection, because the grammar is small enough to be exhaustively generated and too fiddly to eyeball.
`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).
`a:inv`: every channel inverted.
True when the string is shaped like a locator. Does not validate the path.
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.
The flow a locator addresses, without parsing the rest of it.
The path steps of a locator.
The same locator with a different character offset.
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.
Normalises text for quote matching and records where every character came from. The map back is the whole point, and the reason this is not three chained `replace` calls: a match found in normalised space has to become a range in the document, and every transformation that changes a length has to be accounted for as it happens. Unicode normalisation is applied per cluster rather than to the finished string. Running NFC over the assembled result would silently shorten the text out from under the offsets just recorded — the map would be right for every document without a diacritic and wrong for every document with one, which is the worst failure mode on offer. Per *character* would be no better in the other direction: NFC composes a base and its combining mark into one character, and a character examined alone has nothing to compose with, so decomposed text would stay decomposed and a quote stored precomposed would never match it. So a base character and the marks that follow it are normalised together, and every character that comes out is mapped to where the base came from.
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).
Parses a locator, or throws. Throwing rather than returning `undefined` because a malformed locator is a programming error on the caller's side — locators are produced by this library, not typed by hand — and a silent `undefined` here surfaces three layers away as a highlight that does not appear.
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.
Excel row heights are expressed in points.
Darkening (`shade`): mixes towards black.
Throws {@link CancelledError} if the signal has already been aborted.
Lightening (`tint` in DrawingML): mixes towards white.
Normalises any supported input into a {@link ByteSource}. Strings are URLs.
Strips the trailing NUL padding of a fixed-length string field.
Interfaces
An opened document: the contract shared by every parser. Deliberately narrow — it only carries what is meaningful for any format. Everything else (docx sections, xlsx sheets, pptx slides) lives in subtypes inside the format packages. The viewer works against this interface so that it can still show a title and a page count for a format whose renderer is not registered.
A random-access source of bytes. This is the central abstraction of the project: parsers never touch `File`, `Blob` or the network directly. That makes it possible to read a ZIP central directory at the end of a file, or a PDF xref table, without pulling the whole document into memory, and to run the same parser in a browser, in Node, or on top of HTTP range requests.
Result of format detection.
Metadata common to every format.
Format description: its name, how to open it, how to recognise it.
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.
Exact: a range between two locators. Valid while the file's bytes are.
One step down the tree. `kind` is a single letter so the whole path stays short — a locator is stored per chunk, and a corpus of a million chunks pays for every character. The letters are mnemonic rather than clever: `b` block, `t` table, `w` row (`r` was taken), `c` cell, `p` paragraph, `r` run, `s` shape, `i` inline object.
A resolved range in the document model.
Text prepared for matching, with a way back to the original offsets. Quote matching has to ignore differences no reader would call a difference: a non-breaking space against a space, a soft hyphen left over from justification, the zero-width joiners a copy-paste through a word processor leaves behind, and the two spellings Unicode allows for any accented letter. Normalising all of that changes the offsets, so the map back is built at the same time — without it a match in normalised space cannot be turned into a range in the document.
Options shared by every parser.
A parser plugin for one format. Parsers are registered explicitly rather than auto-discovered: an application that only needs to view spreadsheets should not ship a presentation parser in its bundle.
Everything a preset needs to produce its path.
A resolution, and how much to trust it. `resolvedBy` is not decoration. An application that watches it can see its documents drifting — the day the exact selectors stop matching and everything falls through to quotes is the day somebody started editing the corpus — and it can see that before a user reports a highlight in the wrong place.
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`.
Native: the address an Excel user already knows.
Native: a slide, and optionally one shape on it.
Portable: offsets into extracted text. For everyone who chunked the text with something else. LangChain and its cousins keep a start and an end and nothing else, and this is the selector that lets those chunks come back. `profile` is a hash of the extraction options that produced the offsets. Markdown with GFM tables and markdown with HTML tables are different strings, and without the profile the difference would show up as a highlight that is forty characters off rather than as an error.
Robust: the text with enough of its neighbours to be unambiguous. `prefix` and `suffix` are what separate the fourteenth "Total" in a workbook from the fifteenth. Thirty-two characters each is the figure the annotation community converged on: enough to disambiguate ordinary prose, short enough that storing it per chunk is free next to the chunk itself.
Type aliases
Everything Apertura can turn into a {@link ByteSource}.
Container kind: what can be determined from the first bytes of a file. This intermediate layer exists because many formats share one signature: docx, xlsx, pptx, odt and epub all start with `PK\x03\x04`. The core detector identifies the container, and the package that knows how to read that container narrows it down to a specific format.
Broad document category; determines which viewer applies.
Identifier of a concrete file format. A string literal union rather than an enum: the values are part of the public API, get serialised to JSON, and are used as registry keys.
The opaque wire form. Parse it with {@link parseLocator}.
The independent content streams of a document. A document is not one sequence of blocks. Headers, footers, footnotes, endnotes, comments and speaker notes are separate flows that interleave with the body only once it is laid out, and addressing them as if they were part of the body would make every address after the first footnote wrong.
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.
Catalogue of known formats. It also lists formats that have no parser yet: the catalogue answers "what is this file", not "can we open it". That lets the viewer say "this is a PowerPoint 97-2003 presentation, support is planned" instead of a bare "unknown format".
Named `ST_HighlightColor` values from WordprocessingML.
CSS pixels per inch — 96, as is conventional on the web.
Twentieths of a point: 1440 per inch. The unit of WordprocessingML.