Formats, detection, registry
A format is one object. Recognising one is data, not code — which is the only reason lazy loading works.
The format module
A format used to arrive in pieces: a parser plugin registered here, a view plugin registered somewhere else, an extraction adapter known only to whatever dispatched extraction. Three registrations for one thing, and the application had to know all three existed.
A module is the whole format — how to recognise it, how to open it, how to read it out as content, and, in the browser half, how to draw it.
import type { FormatModule } from '@genomdev/core';
export const docx: FormatModule<DocxDocument> = {
id: 'docx',
formats: ['docx', 'doc'],
detect: [
{ container: 'zip', contentType: WORD_MAIN },
{ container: 'ole2' }, // a candidate; canOpen decides
{ extension: ['docx', 'docm', 'dotx', 'doc'] },
],
async canOpen(source, detection) { … },
async open(source, options) { … },
walk: walkDocx,
};How a file is recognised
In two passes, and the order matters. The cheap pass reads the first bytes, the file name and the MIME type. For PDF that settles it. For a ZIP it does not — .docx, .xlsx and .pptx are the same archive with the same signature — so the second pass opens the archive and reads the content type of the main part from [Content_Types].xml.
Both passes happen in @genomdev/core, which is why neither needs a parser to be loaded. The rules a module declares are matched against what the passes found, and exactly one module is fetched.
| Rule | Strength | Example |
|---|---|---|
{ magic: [...] } | certain | %PDF- at offset 0 |
{ container: "zip", contentType } | certain | the main part of an OPC package |
{ container: "zip", entry } | certain | a file that must be in the archive |
{ container: "ole2" } | candidate | shortlists the module; canOpen decides |
{ extension: [...] } | probable | the weakest evidence there is |
{ mimeType: [...] } | probable | what the server said it was |
The registry
A registry is a list of entries, and an entry is either a module or a promise of one. It is an instance rather than a global: one page may host several independently configured viewers, and tests must not see each other’s registrations.
import { FormatRegistry } from '@genomdev/core';
import { docx } from '@genomdev/docx';
import { pdf } from '@genomdev/genom/lazy';
const registry = new FormatRegistry().register(docx, pdf);
registry.formats(); // ['docx', 'doc', 'pdf']
const found = await registry.resolve(source);
const document = await registry.open(source);A format of your own
The contract lives in a small package with no formats in it, so a third-party format plugs in exactly the way the built-in ones do. Implement FormatModule, add view if it draws, and pass it where the others go.
import type { ViewModule } from '@genomdev/core/dom';
export const markdown: ViewModule<MarkdownDocument> = {
id: 'md',
formats: ['md'],
detect: [{ extension: ['md', 'markdown'] }],
open: openMarkdown,
walk: walkMarkdown,
view: { mount: mountMarkdown },
};
// In an application:
<DocumentViewer file={file} formats={[docx, pdf, markdown]} />;