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 @include: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.

A bare name sets 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.

Warning
Outside a group a space ends the name, so a reference or an expression writes the hyphen: {{#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).

Last updated