Literal & raw nodes; custom CSS
A raw node embeds content verbatim — code, foreign markup, a
themed stylesheet. Doubling the marker to @@name freezes Wit
syntax inside the body; tripling it to @@@name freezes even the {{…}} interpolation holes. The freeze level is how you choose how
much processing the body receives.
A literal body
Inside @@name … name@@, every Wit construct is inert — an @, #, _, *, or ::hole:: is just text:
@@code let x = @not_a_node; code@@
let x = @not_a_node;That renders the line literally, @not_a_node and all.
Block or inline
A raw node is a block when a newline directly follows the opening @@name, and inline otherwise. The first literal name@@ closes it; if none appears, that is E_UNCLOSED_RAW_NODE. One whitespace character at each boundary is
trimmed.
Names map to elements
A raw node named after a known HTML tag emits that element — @@@code becomes <code>, @@pre becomes <pre>. A custom name becomes a <div> carrying class="wit-node" and a data-wit-name attribute. Bodies
are HTML-escaped, except for @@style and @@script, which are emitted as raw text (with a break-out guard
against a stray closing tag).
The three freeze levels
- One marker —
@name— is an ordinary node: live Wit, and no interpolation (prose is not an interpolation context). - Two markers —
@@name— freezes Wit but keeps{{…}}live. - Three markers —
@@@name— freezes both.
This is why {{path}} is live only inside a raw node
body — it is the one place interpolation resolves.
Themed CSS with interpolation
The flagship use: drive a stylesheet from a data definition.
#theme: { accent - green } @@style .badge { color: {{theme.accent}}; } style@@
That renders .badge { color: green; } — the {{theme.accent}} resolves because @@style is a
two-marker raw node. Triple it and the hole stays literal:
@@@code {{x}} code@@@ ~ renders the literal text {{x}}
{{x}} ~ renders the literal text {{x}}
Not shipped: component defs
You may see ##name … name## raw-component definitions in older
notes. They are roadmap, not shipped — there is no ## token today. Do not rely on them.
Common mistakes
- Expecting
{{…}}to be live in prose — it is live only inside a raw node body. - Freezing a table you want resolved from data.
- Documenting
##component defs as if they shipped.