Embed Wit in an app
Embedding Wit is the five-stage pipeline plus your own DataSource —
no CLI, no config file, no subprocess. This page is the copy-paste starting
point: wrap the stages in one function, catch the two error families, and choose
fragment or document output.
The worked helper
Verified end to end. Drop it into a server, a build step, or a static-site generator:
import { parse, WitError } from '@witlang/parser';
import { loadExternalData, resolve, expand, RuntimeError } from '@witlang/runtime';
import { renderHtml } from '@witlang/render-html';
export function compileWit(
src: string,
file: string,
data: Record<string, unknown> = {},
): string {
try {
const parsed = parse(src, file);
const loaded = loadExternalData(parsed, data); // dict DataSource
const resolved = resolve(loaded, { rootPath: file }); // rootPath for `reference`
const expanded = expand(resolved);
return renderHtml(expanded, { mode: 'fragment' });
} catch (err) {
if (err instanceof WitError || err instanceof RuntimeError) {
const { line, col } = err.loc;
throw new Error(`${file}:${line}:${col}: ${err.code}: ${err.message}`);
}
throw err;
}
}WitError covers parse; RuntimeError (and its subclasses ResolverError and ExpanderError) covers resolve and
expand. Both carry .code and .loc, so one branch formats
them all.
The embedded data path
The data argument is a DataSource: a plain dict for
static data, or a function for dynamic. No config file, no subprocess:
compileWit(src, 'report.wit', { meta: { version: '0.4.0' }, sales: [ { site: 'Dunmore', lit: 'yes' } ], });
Inside the document, @meta.version and (each @sales as s) then read that data exactly as if it had been
written inline.
Cross-file documents
If your documents use reference, pass rootPath and a
synchronous fileReader so the referenced files resolve against your
real or virtual filesystem:
resolve(loaded, {
rootPath: '/content/main.wit',
fileReader: (abs) => readFileFromCacheSync(abs), // must be synchronous
});Output choice
renderHtml(expanded, { mode: 'fragment' })— an<article>to inject into a page you already own.renderHtml(expanded, { mode: 'document' })— a standalone<!doctype html>file.renderMarkdown(expanded)— for a text or Markdown pipeline.
Common mistakes
- Forgetting
rootPath— a document with areferencethrowsE_MISSING_REFERENCE_FILEwithout it. - Using an
asyncfileReader— it must be synchronous. - Catching only one error family — parse throws
WitError, the runtime throwsRuntimeError; catch both. - Rendering per request without caching.
See also
External data· Resolve & expand · Rendering · CLI reference (the host wiring to contrast).