How to parse in the browser¶
The parser itself needs nothing special: @idfkit/core has no I/O and no
node:* imports, so a bundler pulls in the parser and nothing else. The only
question is where the schema comes from.
Serve the bundle¶
Copy the data directory to a path your server serves:
Then point httpSource at it:
import { parseIdf, SchemaBundle, httpSource } from '@idfkit/core';
const bundle = new SchemaBundle(httpSource('/schemas/'));
const schema = await bundle.load('26.1.0');
const { document } = parseIdf(idfText, schema);
httpSource fetches the gzipped files and inflates them with
DecompressionStream, so the payload stays around 1 MB for all 17 versions and
does not depend on your server setting Content-Encoding.
Hold the SchemaBundle for the lifetime of the page. It caches by version,
shares one blob store across versions, and collapses concurrent loads of the
same version into a single fetch.
Do not put the bundle behind a bundler import¶
It is tempting to import schemas from '@idfkit/schemas/data/index.json' and let
the bundler inline it. Do not: the manifests and blob store are megabytes of
JSON, and inlining them puts all 17 versions into the initial bundle whether or
not the user opens a file.
If you would rather not serve static files at all, supply your own
BundleSource backed by dynamic import():
import { SchemaBundle, type BundleSource } from '@idfkit/core';
const source: BundleSource = {
async read(fileName) {
return (await import(`./schemas/${fileName}.json`)).default;
},
};
const bundle = new SchemaBundle(source);
That keeps each manifest in its own chunk, fetched on demand.
Reading a file the user picked¶
File.text() decodes as UTF-8, which is wrong for IDF often enough to matter:
real models carry single high bytes in degree signs and accented station names.
Decode as latin-1, the way loadIdf does on the server:
Reading it as UTF-8 turns those bytes into U+FFFD, and they will still be U+FFFD when you write the model back out.
Getting the version right¶
A file states its own version, and it usually states two components where the schema keys have three. Resolve rather than assume — see How to handle a version you do not know ahead of time.
Parsing off the main thread¶
Nothing here needs the DOM, so a worker works unchanged:
// worker.ts
import { parseIdf, writeIdf, SchemaBundle, httpSource } from '@idfkit/core';
const bundle = new SchemaBundle(httpSource('/schemas/'));
self.onmessage = async ({ data }) => {
const schema = await bundle.load(data.version);
const { document } = parseIdf(data.text, schema);
self.postMessage({ objects: document.size, idf: writeIdf(document) });
};
Documents themselves are not structured-cloneable — they hold prototypes and a live reference graph — so pass text across the boundary in both directions.