Skip to content

<notatio-out>

What TreeForm can know about a head, from the page's resolveHead. */ export interface HeadInfo { /** Where the head is documented. */ href?: string; /** Its defining expression, over _-prefixed wildcards, if it has a reference one. */ definition?: MathJsonExpression; /** The wildcards, in parameter order. Defaults to first appearance in definition. */ params?: readonly string[]; /** Why it does not reduce further, when it sits on the primitive frontier. */ primitive?: string; }

/** The _-prefixed wildcards of expr, in order of first appearance. */ function wildcardsOf(expr: unknown): string[] { const found: string[] = []; const walk = (node: unknown): void => { if (typeof node === "string") { if (node.startsWith("_") && !found.includes(node)) found.push(node); } else if (Array.isArray(node)) node.forEach(walk); }; walk(expr); return found; }

/** expr with each wildcard replaced by its binding. Structural; nothing is evaluated. */ function substitute(expr: unknown, bindings: ReadonlyMap<string, unknown>): unknown { if (typeof expr === "string") return bindings.has(expr) ? bindings.get(expr) : expr; if (Array.isArray(expr)) return expr.map((node) => substitute(node, bindings)); return expr; }

/** The subtree of tree at path, or the tree itself for the empty path. */ function nodeAt(tree: unknown, path: string): unknown { if (!path) return tree; return path.split(".").reduce<unknown>((node, i) => { const fn = Array.isArray(node) ? node : (node as { fn?: unknown[] } | null)?.fn; return Array.isArray(fn) ? fn[Number(i) + 1] : undefined; }, tree); }

/** tree with the subtree at path replaced, copying only the spine. */ function replaceAt(tree: unknown, path: string, replacement: unknown): unknown { if (!path) return replacement; const [i, ...rest] = path.split("."); const fn = Array.isArray(tree) ? tree : (tree as { fn?: unknown[] } | null)?.fn; if (!Array.isArray(fn)) return tree; const next = [...fn]; next[Number(i) + 1] = replaceAt(fn[Number(i) + 1], rest.join("."), replacement); return Array.isArray(tree) ? next : { ...(tree as object), fn: next }; }

// Code forms whose source comes from a compute-engine compilation TARGET (via // target.compileToSource). The map is form -> target export name; held as a // value so the classes aren't tree-shaken out of the bundle. JavaScript is a // code form too but uses the free compile().code path (see #codeSources). const CODE_TARGETS = { python: "PythonTarget", glsl: "GLSLTarget", wgsl: "WGSLTarget", } as const; type CodeForm = keyof typeof CODE_TARGETS | "javascript" | "gpushader"; const CODE_FORMS = new Set<Form>([ ...(Object.keys(CODE_TARGETS) as Form[]), "javascript", "gpushader", ]);

// The display forms offered by the In/Out menu. const FORMS: readonly Form[] = [ "standard", "traditional", "input", "matrix", "tree", "full", "tex", "asciimath", "mathml", "wolfram", "python", "javascript", "glsl", "wgsl", "gpushader", ]; const FORM_LABEL: Record<Form, string> = { standard: "StandardForm", traditional: "TraditionalForm", input: "InputForm", matrix: "MatrixForm", tree: "TreeForm", full: "MathJSON", tex: "TeXForm", asciimath: "AsciiMathForm", mathml: "MathMLForm", wolfram: "WolframFullForm", python: "PythonForm", javascript: "JavaScriptForm", glsl: "GLSLForm", wgsl: "WGSLForm", gpushader: "GPUShaderForm", }; // The language tag for the forms that render as source in a <notatio-code> box. const FORM_LANG: Partial<Record<Form, string>> = { input: "notatio", full: "json", tex: "latex", asciimath: "asciimath", mathml: "xml", wolfram: "wolfram", python: "python", javascript: "javascript", glsl: "glsl", wgsl: "wgsl", gpushader: "wgsl", };

/** <notatio-out> -- read-only typeset rendering of a compute-engine expression. Accepts LaTeX (the default: it renders an encoding it is handed, and the cell hands it the editor's LaTeX), MathJSON or notatio; optionally evaluates first. Renders in light DOM so the host page's MathLive static stylesheet applies. compute-engine is loaded only when the input is MathJSON or notatio, or evaluation or an assertion is requested.

Set expect to a JSON MathJSON value to turn the element into a live snapshot assertion: the evaluated result is compared to expect and any mismatch or error diagnostic is shown inline.

Stories in the playground·packages/notatio-lit/src/notatio-out.ts· in Vue: <Out>

Attributes

AttributeTypeDefaultNotes
valuestring""The expression to render, in the encoding format names.
formatFormat"latex"How to read value: latex, mathjson or notatio.
inlinebooleanfalseSit inline in a sentence: the rendering alone, no label, no menu, no status.reflects
displaybooleanfalseSet as a centred display equation (\displaystyle), for $$…$$.reflects
evaluatebooleanfalseEvaluate before rendering, rather than rendering the input as given.
boxbooleanfalseBox without evaluating, so the source and AST forms populate.
rawbooleanfalseBox without canonicalising, so the expression shows as authored -- a - b stays a Subtract, a > b is not flipped into a Less. For a definition, whose spelling is the point. Ignored when evaluate is set.
expectstring""A MathJSON value to assert the result against; a mismatch is reported inline.
plannedbooleanfalseMark an expect mismatch as a known gap — shown as a note rather than a failure.
formForm"standard"The representation to show, e.g. standard, traditional, fullform, numpy.reflects
labelstring""Row label, e.g. In or Out.reflects
resolve-head
property resolveHead
((head: string) => HeadInfo | undefined) | undefinedProperty only (set it from script, not markup): what TreeForm knows about a head. A resolver from a head name to its HeadInfo -- a link to its page, the defining expression it can be unfolded into, the reason it sits on the primitive frontier. A reference page supplies one built from its entries.