Wit

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: &#39;fragment&#39; });
  } 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, &#39;report.wit&#39;, {
  meta:  { version: &#39;0.4.0&#39; },
  sales: [ { site: &#39;Dunmore&#39;, lit: &#39;yes&#39; } ],
});

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: &#39;/content/main.wit&#39;,
  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 a referencethrows E_MISSING_REFERENCE_FILE without it.
  • Using an async fileReader — it must be synchronous.
  • Catching only one error family — parse throws WitError, the runtime throws RuntimeError; catch both.
  • Rendering per request without caching.

See also

External data

· Resolve & expand · Rendering · CLI reference (the host wiring to contrast).