mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +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
|
||||
of elements.
|
||||
|
||||
## Set rules
|
||||
With set rules, you can customize the appearance of elements. They are written
|
||||
as a [function call]($function) to an [element
|
||||
function]($function/#element-functions) preceded by the `{set}` keyword (or
|
||||
`[#set]` in markup). Only optional parameters of that function can be provided
|
||||
to the set rule. Refer to each function's documentation to see which parameters
|
||||
are optional. In the example below, we use two set rules to change the
|
||||
[font family]($text.font) and [heading numbering]($heading.numbering).
|
||||
## The computational model behind typst
|
||||
|
||||
Typesetting is controlled by hundreds of parameters, from page margins to font
|
||||
sizes to numbering conventions. Managing this mess is a major focus of every
|
||||
typesetting system. The first step is to arrange these properties into related
|
||||
groups. In typst, these groups are called _element functions_ (EFs), for
|
||||
example `text` for font properties (typeface, size, color etc.), `par` for
|
||||
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
|
||||
#set heading(numbering: "I.")
|
||||
#set text(
|
||||
font: "New Computer Modern"
|
||||
)
|
||||
#set text(size: 11pt) // #1
|
||||
this is 11pt \
|
||||
#[ // 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
|
||||
With set rules, you can style
|
||||
your document.
|
||||
```
|
||||
|
||||
A top level set rule stays in effect until the end of the file. When nested
|
||||
inside of a block, it is only in effect until the end of that block. With a
|
||||
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
|
||||
particular list.
|
||||
Note that you cannot pass positional arguments in a set rule – a set rule
|
||||
is not really a function call, it just uses the same syntax for convenience.
|
||||
|
||||
A set rule refers to all instances of the given EF type and stays in effect
|
||||
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
|
||||
This list is affected: #[
|
||||
#set list(marker: [--])
|
||||
- Dash
|
||||
]
|
||||
] // end of block, set rule expires
|
||||
|
||||
This one is not:
|
||||
- Bullet
|
||||
```
|
||||
|
||||
Sometimes, you'll want to apply a set rule conditionally. For this, you can use
|
||||
a _set-if_ rule.
|
||||
The lifetime restriction to the current scope is especially powerful when set
|
||||
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
|
||||
#let task(body, critical: false) = {
|
||||
@ -59,30 +172,116 @@ a _set-if_ rule.
|
||||
#task(critical: false)[Work deadline]
|
||||
```
|
||||
|
||||
|
||||
## 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
|
||||
#show heading: set text(navy)
|
||||
With show rules, you can deeply customize the typesetting process for
|
||||
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
|
||||
But this stays black.
|
||||
```typ
|
||||
// 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
|
||||
achieve many different effects. But they still limit you to what is predefined
|
||||
in Typst. For maximum flexibility, you can instead write a show rule that
|
||||
defines how to format an element from scratch. To write such a show rule,
|
||||
replace the set rule after the colon with an arbitrary [function]. This function
|
||||
receives the element in question and can return arbitrary content. The available
|
||||
[fields]($scripting/#fields) on the element passed to the function again match
|
||||
the parameters of the respective element function. Below, we define a show rule
|
||||
that formats headings for a fantasy encyclopedia.
|
||||
The [selector]-pattern specifies the situation where the desired
|
||||
modifications shall apply.
|
||||
The most common form of `selector-pattern` is an [element
|
||||
function]($function/#element-functions) identifier. This means that the
|
||||
right-hand side code (the set rule or function) is executed in the context of
|
||||
the selected EF, and all modifications expire after completion of this code
|
||||
– modifications in a show rule cannot influence other typesetting
|
||||
situations. In the example below, the selector pattern refers
|
||||
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
|
||||
#set heading(numbering: "(I)")
|
||||
|
Loading…
x
Reference in New Issue
Block a user