Manual
The document
OverviewGrammarDocument headerSyntax cheatsheet Scene Step
Content
Text blocks
Paragraph Heading 1 Heading 2 Heading 3 Heading 4 List
Maths
Equation Maths
Tables & images
Table Image
Formatting
Bold Italics Inline Code Highlight
Text colours
Links & references
Link Footnote Icon Internote Reference
ValueWhere inline content works
Narrative only
Note Definition Example Task Divider
Graph pane
Graph
Curves & areas
Curve Integral
Data marks
Scatter Histogram
Fits
Fit Residuals
Surfaces
Contour Heatmap
Marks
Line Segment Vector Point Polygon Text
Shapes
Circle Square Rectangle Triangle Star Diamond Hexagon
Axis furniture
Axis label Axis Brace
Expressions
Code pane
Code Lines
Animation & interaction
Cues that wrap content
Cue Draw cue Trace cue Highlight cue Spotlight cue Type cue
Cues on a value
Value cue Zoom cue
Anchors & timing Parameter
Advanced features
Data Let Define Preset Include If For Ignore
Reference
All constructs A–ZAttribute types
Concepts
IdentifiersBody & detailDerived attributes
Guidance
The narrative contractWhat earns a place on the canvasParameter or cueHonest numbersCode demonstrates, never computesAuthor-attached data only
?
  1. The document
  2. Syntax cheatsheet

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: @let(…), @data#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 declares

Those 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 thing

Order 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, @include: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: @if(audience: teacher){…} and @for(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
On this page
SigilsNames, ids & shorthandBracketsAttributesProseValuesCuesDirectives
PrivacyTermsContact Support
Syntax cheatsheet · Internote