Design principles
The rules behind Wit's decisions. Read them before proposing a change or building on the AST.
Prose unless marked
Nothing typed means anything special by accident. A sentence is a sentence; a
character that only looks like markup — an email, C#, (see figure 2), a closing !! — stays prose.
Structure is opt-in and visible.
Never lose text silently
If Wit cannot use something, it stays prose or it is an error with a code and a location. Dropping a writer's words without saying so is a bug.
One way to do each thing
Parameters go in glued parens, keys end with :, and \ escapes. 0.3 removed the other forms rather than keep
several spellings of one idea; wit migrate carries old files
across.
Content in bodies, metadata in parameters
A node's content goes in its body; whatever describes the node — a link's address, an image's size — goes in its parameters. A body is always content and is never scanned for parameters.
Name the meaning
@finding reads as "this is a finding". Wit ships a small core
vocabulary that mirrors HTML's semantic shapes; everything else is a writer's
own definition, or the opaque @node, which carries its
parameters straight to the renderer.
#highlight @node(type: highlight) ::body:: node@ highlight# @highlight Some text highlight@
Some text
If a definition can express something, it does not become a core name.
One source, many outputs
The writer states intent; the renderer supplies meaning. A document parses into a plain, serialisable tree that HTML, Markdown, PDF or your own renderer consume.
Cost scales with rarity
Sentences cost nothing; common structure is one light mark; rare power — data, logic, scripts — costs a little more syntax.
Not Turing-complete
Logic is declarative: conditions, loops, data access. The script bridge, <% … %>, is the one explicit escape hatch for general
computation, which keeps documents analysable and output deterministic.
A file format, not a system
Wit is not a CMS, an editor or a general templating engine. It is a way to write
a document many programs can read. Data reaches prose through @name.field, not template holes.
Engineering
Zero runtime dependencies, deterministic output, source locations through every stage, small files and functions. The spec is executable: a behaviour is real when a case in the spec pins it, and the case is written first.
Common contributor mistakes
- Reaching for a new core name. If a definition would do, add a definition.
- Adding a second spelling. A new form for something Wit can already say breaks "one way".
- Turning prose into structure. Any new marker must leave ordinary sentences untouched; add prose-safety cases first.