Syntax cheatsheet
The whole grammar on one page.
#Sigils
.— namespace and member access:canvas.graph,#islands.area#— assigns or refers to an identifier:curve#flight,path: #flight:— supplies the implicit attribute:image:photo.jpg!— a micronode:!teal{…},!value:#f.slope@— a directive:(…),#islands{{ }}— compile-time substitution:{{z-expected}}
#Names, ids & shorthand
name[#id][:value]
curve#flight #flight names this curve
image:photo.jpg :photo.jpg fills source — the first attribute image declaresThose two are all the shorthand carries. Every other attribute is written in the group like any other — the shorthand is not a place where attributes live:
image#hero:photo.jpg(width: 400)
image#hero(source: photo.jpg; width: 400) exactly the same thingOrder is fixed — # before : — and the : value is a simple token that ends at the first bracket, space, or end of line. Anything longer is written as a named attribute instead.
#Brackets
{ }— the body[ ]— the detail (a scene's canvas)( )— the attribute group
A node is recognised only by an opening bracket, which is why
Note: this is important stays prose. Micronodes and directives carry their own sigil and stand bare — !value:#f.slope, :overview.part.chalk.#Attributes
point(x: 1; y: 2; colour: orange) one line, semicolons
canvas.graph{
curve(expression: x^2)
}(
x-axis-label: x multiline, one per line
y-axis-label: y
)The group comes last, after the body and detail. The control-flow directives are the exception: (audience: teacher){…} and (n: 0..4){…} put theirs first.
#Prose
# Heading 1 through #### for Heading 4
**bold** *italic* `code`
!h:yellow{marked} highlight; ==marked== for the default
$x^2 + y^2 = r^2$ inline maths
!teal{tinted} one of nine colours
!link{Docs}(href: https://…)
--- divider
=== step (advances the scene)#Values
{{name}} an @let constant, spliced as text
{{#survey.area}} a dataset column, spliced as a comma list
#islands a binding — a reference, resolved live
#f.slope a derived value, read at render time
!value:#f.slope the same, in prose{{ }} for what is fixed at compile time; bindings for what moves — derived, animated and reader-set values cannot be substituted.
#Cues
cue{ … }(in: 1) fade in at step 1
cue.draw{ … }(in: 1) draw along the stroke
cue.trace{ … }(path: #flight; at: 2) ride a curve
cue.type{ … }(in: 1; speed: 30) type code in
x-domain: [0, 5] !cue.to{[0, 10]}(at: 2; over: 800ms)
x-domain: [0, 10] !cue.zoom{[2, 4]}(at: 2; draw: 400ms)
at: 2 a step index
at: 1500ms an absolute time
at: 2 + 500ms a step with an offset#Directives
@data#islands{ header | rows } inline dataset
@data#survey:file.csv attached dataset
@let(key: value) constants
@include:overview.part.chalk splice a partial
@define:card{ … }(param: default) declare a template
@preset#accent:text(size: 24) reusable attributes
@if(key: value){ … } conditional
@for(n: 0..4; as: i){ … } repetition
@ignore{ … } block comment