Attributes
Writing the attribute group, the implicit :value and bare booleans, how names and aliases match, how a value is parsed by its type, and defaults set for several constructs at once.
#Writing the group
A construct's attributes are written in parentheses after its body and detail. Each entry is a name, a colon and a value, and entries are separated by a semicolon or a line break. The two separators can be mixed.
point(x: 1; y: 2; colour: orange)
graph{
curve(expression: x^2)
}(
x domain: [-3, 3]
y domain: [0, 9]
title: A parabola
)The name is everything before the first colon, and the value everything after it, trimmed. A semicolon or line break inside ( ), [ ] or { } belongs to the value, so a bracketed value can hold either. Anywhere else, \; is a literal semicolon: table(title: Yield at 300 K\; 1 atm) sets one title, where without the backslash the group would hold a second entry named 1 atm. A line in the group starting with // is a comment.
An entry with no colon is a boolean set to true, and ! before it sets it false (Bare and negated booleans). An attribute written twice takes the later value.
#:value, the implicit attribute
Most constructs mark one attribute as implicit, and its value can be written in the head after a colon. Each pair below compiles to the same thing:
image:photo.jpg(caption: The apparatus)
image(source: photo.jpg; caption: The apparatus)
curve:x^2(colour: blue)
curve(expression: x^2; colour: blue)
!truncate:8{…}
!truncate(length: 8){…}A reference page marks the implicit attribute in its attribute table. A construct that marks none has no : form, and writing one is an error that names the alternative:
option:correct{Paris}[parse]node `option` declares no implicit attribute — write `option(correct: …)` (D37)
The value is a single token. It starts after the colon and ends at the first bracket, space or line end, so a value with spaces in it is written in the group. Inside the token # and . are ordinary characters, which is how !cite:#fs1969() passes a reference and :overview.part.chalk a file name. Because the #id comes before the colon, curve#c:x^2() names the curve, and curve:x^2#c() reads x^2#c as the expression. An empty value before a bracket, curve:(), is an error, and so is a {{…}} expression in the token: write it in the group, curve(expression: {{…}}).
#Bare and negated booleans
A boolean attribute written as its bare name is true, and with ! before the name it is false:
graph{
curve(expression: x^2; dashed)
curve(expression: x^3; !endpoints)
}(
!show-grid
)dashed is dashed: true, and !endpoints is endpoints: false. The negated form is how an attribute that defaults to true is turned off: show-grid, show-axes, show-ticks and show-background on a graph, endpoints on a curve, fill on the shape marks.
Written out, a boolean is true or false, in any case. 1 and 0 are refused. yes and no are read outside canvas environments, and refused by an environment and its marks.
true whatever the attribute's type, so curve(colour) is refused because true is not a colour. And ! at the start of an entry negates; inside a value it opens a micronode. hidden: true !cue.to{false}(at: 1) is hidden until the cue at step 1 sets it to false.#Attribute names and aliases
A name is matched in any case, and each run of spaces inside it reads as one hyphen: x-domain, x domain and X Domain set the same attribute. A name the construct does not declare is an error — weight: 3 on a point: node `point`: attribute `weight` is not declared.
Many attributes also answer to aliases, which each construct declares for itself: color for colour, from and to for segment's start and end, and exp, f, func and function for curve's expression. A construct's reference page lists its aliases beside each attribute.
{{#c.text-size}}, never {{#c.text size}}.#Values parsed by type
A value is text until the attribute it is written in parses it with the attribute's type. Text the type cannot read is a compile error; nothing is coerced, and nothing falls back to the default: dashed: maybe on a curve is refused with curve.dashed: 'maybe' is not a boolean.
A type may be narrowed for one attribute: a number to whole values or to a range, a list to a length, text to a pattern. A value outside the narrowing is refused with an error that names it: !truncate:0{…} is refused because `0` is below the minimum of 1. The value types page lists what each type accepts, and a construct's reference page gives each attribute's type and default. An attribute left out takes its default; a required one left out is an error.
#Defaults for several constructs
A group written after a bare { }, with no name before it, sets defaults for everything inside the braces. The constructs compile in place, as if the braces were not there.
graph{
{
curve(expression: x^2)
curve(expression: x^3; colour: blue)
point(x: 1; y: 1)
}(
colour: red
dashed
)
}Both curves are dashed. The first curve and the point are red; the second curve keeps its own colour: blue. The point declares no dashed, so that default passes it by. Each default is parsed by the type of the attribute it lands on. The braces take no detail.
#Values from elsewhere
A value can also be read from another construct, with #id (Identifiers & references), or computed, with {{…}} (Expressions). Some constructs publish attributes that are computed while they render and can only be read (Derived attributes).