mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Merge 8176cc9656265daabbb64c06a91ced0fa7e8625c into 9b09146a6b5e936966ed7ee73bce9dd2df3810ae
This commit is contained in:
commit
960347f723
@ -10,44 +10,157 @@ might not be a built-in property for everything you wish to do. For this reason,
|
|||||||
Typst further supports _show rules_ that can completely redefine the appearance
|
Typst further supports _show rules_ that can completely redefine the appearance
|
||||||
of elements.
|
of elements.
|
||||||
|
|
||||||
## Set rules
|
## The computational model behind typst
|
||||||
With set rules, you can customize the appearance of elements. They are written
|
|
||||||
as a [function call]($function) to an [element
|
Typesetting is controlled by hundreds of parameters, from page margins to font
|
||||||
function]($function/#element-functions) preceded by the `{set}` keyword (or
|
sizes to numbering conventions. Managing this mess is a major focus of every
|
||||||
`[#set]` in markup). Only optional parameters of that function can be provided
|
typesetting system. The first step is to arrange these properties into related
|
||||||
to the set rule. Refer to each function's documentation to see which parameters
|
groups. In typst, these groups are called _element functions_ (EFs), for
|
||||||
are optional. In the example below, we use two set rules to change the
|
example `text` for font properties (typeface, size, color etc.), `par` for
|
||||||
[font family]($text.font) and [heading numbering]($heading.numbering).
|
paragraphs (line spacing, alignment, indentation etc.), and `figure`
|
||||||
|
(placement rules, captioning, and numbering of tables and figures). A complete
|
||||||
|
list of the available element functions is **where??**. The term _functions_
|
||||||
|
indicates that these entities do not merely act as passive property
|
||||||
|
containers, but can actively process content (provided in the function's
|
||||||
|
positional argument `body`) according to the present parameter settings.
|
||||||
|
|
||||||
|
Since different parts of the document need different settings for the same
|
||||||
|
parameters (e.g. the font size in headings, plain text, and footnotes), an
|
||||||
|
element function type usually exists in multiple instances. On the other hand,
|
||||||
|
different EF types must interact to typeset a particular piece of content. You
|
||||||
|
can imagine this as an _ensemble_ of EMs playing together to create the
|
||||||
|
desired output. For example, math rendering requires the `math.equation` EF
|
||||||
|
for equation-specific information, but also `text` for the font, `par` for
|
||||||
|
line spacing, and `block` to control potential page breaks.
|
||||||
|
|
||||||
|
The set of active EFs changes frequently during the processing of your
|
||||||
|
document. To provide consistent access to precisely the members of the active
|
||||||
|
ensemble at a given point, typst uses the concept of a _context_ (see section
|
||||||
|
[Context]($context) for detailed information). By default, context expressions
|
||||||
|
refer to the context "here" (i.e. to the moment when processing reaches the
|
||||||
|
current document location), but you can specify and access many other
|
||||||
|
processing stages as well, e.g. "whenever an equation will be rendered in the
|
||||||
|
future" or "upon creation of the table-of-contents". Contexts guarantee that
|
||||||
|
parameters are accessed in a coordinated way and from the appropriate EF
|
||||||
|
instances.
|
||||||
|
|
||||||
|
There are three fundamental methods to modify parameters:
|
||||||
|
- function calls, e.g. `#text(size: 25pt, [Hello]))` Use 25pt font to typeset
|
||||||
|
just the given content, here 'Hello'.
|
||||||
|
- set rules, e.g. `#set text(size: 25pt)` Instruct the `text` EF to use 25pt
|
||||||
|
font until further notice.
|
||||||
|
- show rules, e.g. `#show math.equation: set text(size: 25pt)` Typeset
|
||||||
|
subsequent equations with 25pt font.
|
||||||
|
|
||||||
|
Show rules are the most powerful (and most complicated), because they give you
|
||||||
|
access to the interacting ensemble of EFs
|
||||||
|
in a precisely specified situation (here: equation rendering due to
|
||||||
|
`math.equation`). Consistency in a show rule is guaranteed because a show rule
|
||||||
|
always defines a context automatically, without the need to type the `context`
|
||||||
|
keyword explicitly.
|
||||||
|
|
||||||
|
Parameter modifications like the ones above have generally a _limited
|
||||||
|
lifetime_: A modification passed as a function argument expires when the
|
||||||
|
function completes, and the previous parameter value is restored at this
|
||||||
|
point. Set and show rules are active until the end of the enclosing scope,
|
||||||
|
i.e. until the next closing bracket or brace:
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#set heading(numbering: "I.")
|
#set text(size: 11pt) // #1
|
||||||
#set text(
|
this is 11pt \
|
||||||
font: "New Computer Modern"
|
#[ // open a new scope
|
||||||
)
|
still 11pt \
|
||||||
|
#set text(size: 25pt) // #2
|
||||||
|
now 25pt \
|
||||||
|
] // end of scope, #2 expires
|
||||||
|
// #1 reactivated
|
||||||
|
again 11pt
|
||||||
|
```
|
||||||
|
|
||||||
|
When several rules refering to the same parameter occur in the same scope,
|
||||||
|
each one overrides the previous specification. Modifications applied outside
|
||||||
|
of any scope, i.e. at the top level of the document, remain active during the
|
||||||
|
entire typesetting process unless they are explicitly overridden. These global
|
||||||
|
settings are usually provided by a [style template]($tutorial/making-a-template).
|
||||||
|
|
||||||
|
Now, let's delve into the details of set and show rules.
|
||||||
|
|
||||||
|
## Set rules
|
||||||
|
|
||||||
|
Set rules offer the easiest way to customize the appearance of subsequent
|
||||||
|
elements.
|
||||||
|
Their basic syntax resembles a [function call]($function) to an [element
|
||||||
|
function]($function/#element-functions) preceded by the `[#set]` keyword (or
|
||||||
|
`{set}` in script mode)
|
||||||
|
|
||||||
|
```typ
|
||||||
|
#set element-function(parameter-spec) // in markup mode
|
||||||
|
#{
|
||||||
|
set element-function(parameter-spec) // in script mode
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`element-function` specifies the EF you want to modify. The `parameter-spec`
|
||||||
|
is a sequence of named
|
||||||
|
parameters with their new values, as in an ordinary function call. The
|
||||||
|
supported parameter
|
||||||
|
names are the same as in the constructor of the respective EF, as described in
|
||||||
|
the
|
||||||
|
function's documentation. In the following example, we use two set rules to
|
||||||
|
change the heading's
|
||||||
|
[numbering style]($heading.numbering) and the text's [font
|
||||||
|
family]($text.font).
|
||||||
|
|
||||||
|
```example
|
||||||
|
#set heading(numbering: "I.1")
|
||||||
|
#set text(font: "New Computer Modern")
|
||||||
|
|
||||||
= Introduction
|
= Introduction
|
||||||
With set rules, you can style
|
With set rules, you can style
|
||||||
your document.
|
your document.
|
||||||
```
|
```
|
||||||
|
|
||||||
A top level set rule stays in effect until the end of the file. When nested
|
Note that you cannot pass positional arguments in a set rule – a set rule
|
||||||
inside of a block, it is only in effect until the end of that block. With a
|
is not really a function call, it just uses the same syntax for convenience.
|
||||||
block, you can thus restrict the effect of a rule to a particular segment of
|
|
||||||
your document. Below, we use a content block to scope the list styling to one
|
A set rule refers to all instances of the given EF type and stays in effect
|
||||||
particular list.
|
until the end of the present scope. In particular, a top level set rule
|
||||||
|
stays in effect until the end of the file unless explicitly overridden by
|
||||||
|
another set rule. To restrict a set rule's lifetime, you can enclose it in
|
||||||
|
a code block, i.e. in brackets or braces. Then, the rule expires at the end
|
||||||
|
of the block, and the previous behavior is restored. Below, we use a content
|
||||||
|
block to apply the modified list styling only to the list in brackets:
|
||||||
|
|
||||||
```example
|
```example
|
||||||
This list is affected: #[
|
This list is affected: #[
|
||||||
#set list(marker: [--])
|
#set list(marker: [--])
|
||||||
- Dash
|
- Dash
|
||||||
]
|
] // end of block, set rule expires
|
||||||
|
|
||||||
This one is not:
|
This one is not:
|
||||||
- Bullet
|
- Bullet
|
||||||
```
|
```
|
||||||
|
|
||||||
Sometimes, you'll want to apply a set rule conditionally. For this, you can use
|
The lifetime restriction to the current scope is especially powerful when set
|
||||||
a _set-if_ rule.
|
rules are used inside show rules (see next section): Since a show rule
|
||||||
|
implicitly defines a block, any set rule embedded there is only active within
|
||||||
|
the show rule's context and does not influence typesetting in other situations.
|
||||||
|
|
||||||
|
On the other hand, the lifetime restriction causes a common pitfall when you
|
||||||
|
want to apply a set rule conditionally. `set text(red)` in the following code
|
||||||
|
has no effect, because it expires before it can influence anything:
|
||||||
|
|
||||||
|
```typ
|
||||||
|
#let task(body, critical: false) = {
|
||||||
|
if critical {
|
||||||
|
set text(red)
|
||||||
|
} // end of block, set rule expires
|
||||||
|
// original behavior restored
|
||||||
|
[- #body]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To avoid this, you must write the condition in postfix notation via a _set-if_ rule:
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#let task(body, critical: false) = {
|
#let task(body, critical: false) = {
|
||||||
@ -59,30 +172,116 @@ a _set-if_ rule.
|
|||||||
#task(critical: false)[Work deadline]
|
#task(critical: false)[Work deadline]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Show rules
|
## Show rules
|
||||||
With show rules, you can deeply customize the look of a type of element. The
|
|
||||||
most basic form of show rule is a _show-set rule._ Such a rule is written as the
|
|
||||||
`{show}` keyword followed by a [selector], a colon and then a set rule. The most
|
|
||||||
basic form of selector is an [element function]($function/#element-functions).
|
|
||||||
This lets the set rule only apply to the selected element. In the example below,
|
|
||||||
headings become dark blue while all other text stays black.
|
|
||||||
|
|
||||||
```example
|
With show rules, you can deeply customize the typesetting process for
|
||||||
#show heading: set text(navy)
|
a given type of element. There are two variants of show rules: You
|
||||||
|
can specify the desired modifications by a set rule, which is simple
|
||||||
|
but of limited expressivity, or by a function, which is more involved
|
||||||
|
but unleashes the full range of customization options:
|
||||||
|
|
||||||
= This is navy-blue
|
```typ
|
||||||
But this stays black.
|
// in markup mode
|
||||||
|
#show selector-pattern: set-rule // set-rule variant
|
||||||
|
#show selector-pattern: function // function variant
|
||||||
|
|
||||||
|
#{ // likewise in script mode
|
||||||
|
show selector-pattern: set-rule // set-rule variant
|
||||||
|
show selector-pattern: function // function variant
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
With show-set rules you can mix and match properties from different functions to
|
The [selector]-pattern specifies the situation where the desired
|
||||||
achieve many different effects. But they still limit you to what is predefined
|
modifications shall apply.
|
||||||
in Typst. For maximum flexibility, you can instead write a show rule that
|
The most common form of `selector-pattern` is an [element
|
||||||
defines how to format an element from scratch. To write such a show rule,
|
function]($function/#element-functions) identifier. This means that the
|
||||||
replace the set rule after the colon with an arbitrary [function]. This function
|
right-hand side code (the set rule or function) is executed in the context of
|
||||||
receives the element in question and can return arbitrary content. The available
|
the selected EF, and all modifications expire after completion of this code
|
||||||
[fields]($scripting/#fields) on the element passed to the function again match
|
– modifications in a show rule cannot influence other typesetting
|
||||||
the parameters of the respective element function. Below, we define a show rule
|
situations. In the example below, the selector pattern refers
|
||||||
that formats headings for a fantasy encyclopedia.
|
to `heading`, so headings are printed red, while all other text stays black:
|
||||||
|
|
||||||
|
```example
|
||||||
|
#show heading: set text(red)
|
||||||
|
|
||||||
|
= First-level headings are red
|
||||||
|
== Second-level headings are also red
|
||||||
|
But plain text stays black.
|
||||||
|
```
|
||||||
|
|
||||||
|
You can refine the `selector-pattern` by means of the [where]($function.where)
|
||||||
|
function. The arguments of `where` are named parameters with values, and the
|
||||||
|
supported parameter names are the same as in the element function's constructor.
|
||||||
|
The selector pattern then restricts the show rule's scope to the EF instances
|
||||||
|
conforming to the given parameter settings. The following example changes
|
||||||
|
the color only for the first-level headings and leaves everything else unchanged:
|
||||||
|
|
||||||
|
```example
|
||||||
|
#show heading.where(level: 1): set text(red)
|
||||||
|
|
||||||
|
= First-level headings are red
|
||||||
|
== Second-level headings remain black
|
||||||
|
Plain text stays black as well.
|
||||||
|
```
|
||||||
|
|
||||||
|
A complete list of supported selector patterns is provided below.
|
||||||
|
|
||||||
|
To overcome the limitations of set rules on the right-hand side, you use the
|
||||||
|
`function` variant of the show rule. In this variant, the right-hand side is
|
||||||
|
the name of an arbitrary [function] that accepts exactly one positional
|
||||||
|
argument (it can have additional named arguments) and returns arbitrary
|
||||||
|
content:
|
||||||
|
|
||||||
|
```example
|
||||||
|
#let always-say-thank-you(it) = {
|
||||||
|
it
|
||||||
|
set text(green)
|
||||||
|
[thank you]
|
||||||
|
}
|
||||||
|
|
||||||
|
#show heading: always-say-thank-you
|
||||||
|
= This heading is boring
|
||||||
|
```
|
||||||
|
|
||||||
|
The function's argument (conventionally called `it`) is the EF that matched
|
||||||
|
the left-hand side of the show rule. The function implements the desired
|
||||||
|
modifications (via embedded set and show rules or any other code) and then
|
||||||
|
forwards the content for further processing, returns entirely new content, or
|
||||||
|
a combination thereof.
|
||||||
|
|
||||||
|
To support advanced customization, you can query the current values of the
|
||||||
|
parameter fields of the function's argument (`it.depth` in the example below).
|
||||||
|
Likewise, you can query the parameter values of other element functions in the
|
||||||
|
show rule's scope, for example the current `text.size`. This is possible
|
||||||
|
because a show rule implicitly defines a [Context]($context) to expose this
|
||||||
|
information to the user – outside of a context, these fields are not
|
||||||
|
accessible.
|
||||||
|
|
||||||
|
```example
|
||||||
|
#let always-say-thank-you(it) = {
|
||||||
|
it
|
||||||
|
if it.depth == 1 {
|
||||||
|
set text(red,
|
||||||
|
size: text.size * 150%)
|
||||||
|
[I don't care]
|
||||||
|
} else {
|
||||||
|
set text(green)
|
||||||
|
[thank you]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#set heading(numbering: "1.1 ")
|
||||||
|
#show heading: always-say-thank-you
|
||||||
|
= This heading is boring
|
||||||
|
== This one is better
|
||||||
|
```
|
||||||
|
|
||||||
|
In practice, the function is usually implemented in-place as an unnamed function
|
||||||
|
(aka. "lambda expression") with the syntax `it => { implementation }` for an
|
||||||
|
implementation in script mode or `it => [ implementation ]` for an
|
||||||
|
implementation in markup mode. In this more involved example, we define a
|
||||||
|
show rule that formats headings for a fantasy encyclopedia:
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#set heading(numbering: "(I)")
|
#set heading(numbering: "(I)")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user