mirror of
https://github.com/typst/typst
synced 2025-08-12 06:07:54 +08:00
Document escaping semicolon, valid identifiers, and state
tips (#6674)
Co-authored-by: Andrew Voynov <37143421+Andrew15-5@users.noreply.github.com> Co-authored-by: Yaksher <yaksher.git@gmail.com> Co-authored-by: Laurenz <laurmaedje@gmail.com>
This commit is contained in:
parent
3455ac7dd2
commit
0b639c7510
@ -75,7 +75,10 @@ impl Label {
|
||||
/// Creates a label from a string.
|
||||
#[func(constructor)]
|
||||
pub fn construct(
|
||||
/// The name of the label. Must not be empty.
|
||||
/// The name of the label.
|
||||
///
|
||||
/// Unlike the [dedicated syntax](#syntax), this constructor accepts
|
||||
/// any non-empty string, including names with special characters.
|
||||
name: Str,
|
||||
) -> StrResult<Label> {
|
||||
if name.is_empty() {
|
||||
|
@ -407,7 +407,7 @@ impl Counter {
|
||||
/// Create a new counter identified by a key.
|
||||
#[func(constructor)]
|
||||
pub fn construct(
|
||||
/// The key that identifies this counter.
|
||||
/// The key that identifies this counter globally.
|
||||
///
|
||||
/// - If it is a string, creates a custom counter that is only affected
|
||||
/// by manual updates,
|
||||
|
@ -273,8 +273,31 @@ impl State {
|
||||
#[func(constructor)]
|
||||
pub fn construct(
|
||||
/// The key that identifies this state.
|
||||
///
|
||||
/// Any [updates]($state.update) to the state will be identified with
|
||||
/// the string key. If you construct multiple states with the same
|
||||
/// `key`, then updating any one will affect all of them.
|
||||
key: Str,
|
||||
/// The initial value of the state.
|
||||
///
|
||||
/// If you construct multiple states with the same `key` but different
|
||||
/// `init` values, they will each use their own initial value but share
|
||||
/// updates. Specifically, the value of a state at some location in the
|
||||
/// document will be computed from that state's initial value and all
|
||||
/// preceding updates for the state's key.
|
||||
///
|
||||
/// ```example
|
||||
/// #let banana = state("key", "🍌")
|
||||
/// #let broccoli = state("key", "🥦")
|
||||
///
|
||||
/// #banana.update(it => it + "😋")
|
||||
///
|
||||
/// #context [
|
||||
/// - #state("key", "🍎").get()
|
||||
/// - #banana.get()
|
||||
/// - #broccoli.get()
|
||||
/// ]
|
||||
/// ```
|
||||
#[default]
|
||||
init: Value,
|
||||
) -> State {
|
||||
@ -328,7 +351,7 @@ impl State {
|
||||
Ok(sequence.last().unwrap().clone())
|
||||
}
|
||||
|
||||
/// Update the value of the state.
|
||||
/// Updates the value of the state.
|
||||
///
|
||||
/// The update will be in effect at the position where the returned content
|
||||
/// is inserted into the document. If you don't put the output into the
|
||||
@ -336,13 +359,44 @@ impl State {
|
||||
/// write `{let _ = state("key").update(7)}`. State updates are always
|
||||
/// applied in layout order and in that case, Typst wouldn't know when to
|
||||
/// update the state.
|
||||
///
|
||||
/// In contrast to [`get`]($state.get), [`at`]($state.at), and
|
||||
/// [`final`]($state.final), this function does not require [context].
|
||||
#[func]
|
||||
pub fn update(
|
||||
self,
|
||||
span: Span,
|
||||
/// If given a non function-value, sets the state to that value. If
|
||||
/// given a function, that function receives the previous state and has
|
||||
/// to return the new state.
|
||||
/// A value to update to or a function to update with.
|
||||
///
|
||||
/// - If given a non-function value, sets the state to that value.
|
||||
/// - If given a function, that function receives the state's previous
|
||||
/// value and has to return the state's new value.
|
||||
///
|
||||
/// When updating the state based on its previous value, you should
|
||||
/// prefer the function form instead of retrieving the previous value
|
||||
/// from the [context]($context). This allows the compiler to resolve
|
||||
/// the final state efficiently, minimizing the number of
|
||||
/// [layout iterations]($context/#compiler-iterations) required.
|
||||
///
|
||||
/// In the following example, `{fill.update(f => not f)}` will paint odd
|
||||
/// [items in the bullet list]($list.item) as expected. However, if it's
|
||||
/// replaced with `{context fill.update(not fill.get())}`, then layout
|
||||
/// will not converge within 5 attempts, as each update will take one
|
||||
/// additional iteration to propagate.
|
||||
///
|
||||
/// ```example
|
||||
/// #let fill = state("fill", false)
|
||||
///
|
||||
/// #show list.item: it => {
|
||||
/// fill.update(f => not f)
|
||||
/// context {
|
||||
/// set text(fill: fuchsia) if fill.get()
|
||||
/// it
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #lorem(5).split().map(list.item).join()
|
||||
/// ```
|
||||
update: StateUpdate,
|
||||
) -> Content {
|
||||
StateUpdateElem::new(self.key, update).pack().spanned(span)
|
||||
|
@ -14,7 +14,7 @@ provides compact syntax to embed a code expression into markup: An expression is
|
||||
introduced with a hash (`#`) and normal markup parsing resumes after the
|
||||
expression is finished. If a character would continue the expression but should
|
||||
be interpreted as text, the expression can forcibly be ended with a semicolon
|
||||
(`;`).
|
||||
(`;`). You can [escape a literal `#` or `;` with a backslash]($syntax/#escapes).
|
||||
|
||||
```example
|
||||
#emph[Hello] \
|
||||
@ -66,6 +66,7 @@ Content and code blocks can be nested arbitrarily. In the example below,
|
||||
## Bindings and Destructuring { #bindings }
|
||||
As already demonstrated above, variables can be defined with `{let}` bindings.
|
||||
The variable is assigned the value of the expression that follows the `=` sign.
|
||||
A [valid variable name](#identifiers) may contain `-`, but cannot start with `-`.
|
||||
The assignment of a value is optional, if no value is assigned, the variable
|
||||
will be initialized as `{none}`. The `{let}` keyword can also be used to create
|
||||
a [custom named function]($function/#defining-functions). Variables can be
|
||||
@ -77,8 +78,8 @@ is no containing block).
|
||||
This is #name's documentation.
|
||||
It explains #name.
|
||||
|
||||
#let add(x, y) = x + y
|
||||
Sum is #add(2, 3).
|
||||
#let my-add(x, y) = x + y
|
||||
Sum is #my-add(2, 3).
|
||||
```
|
||||
|
||||
Let bindings can also be used to destructure [arrays]($array) and
|
||||
|
@ -168,6 +168,34 @@ I got an ice cream for
|
||||
\$1.50! \u{1f600}
|
||||
```
|
||||
|
||||
## Identifiers
|
||||
Names of variables, functions, and so on (_identifiers_) can contain letters,
|
||||
numbers, hyphens (`-`), and underscores (`_`). They must start with a letter or
|
||||
an underscore.
|
||||
|
||||
More specifically, the identifier syntax in Typst is based on the
|
||||
[Unicode Standard Annex #31](https://www.unicode.org/reports/tr31/), with two
|
||||
extensions: Allowing `_` as a starting character, and allowing both `_` and `-`
|
||||
as continuing characters.
|
||||
|
||||
For multi-word identifiers, the recommended case convention is
|
||||
[Kebab case](https://en.wikipedia.org/wiki/Letter_case#Kebab_case). In Kebab
|
||||
case, words are written in lowercase and separated by hyphens (as in
|
||||
`top-edge`). This is especially relevant when developing modules and packages
|
||||
for others to use, as it keeps things predictable.
|
||||
|
||||
```example
|
||||
#let kebab-case = [Using hyphen]
|
||||
#let _schön = "😊"
|
||||
#let 始料不及 = "😱"
|
||||
#let π = calc.pi
|
||||
|
||||
#kebab-case
|
||||
#if -π < 0 { _schön } else { 始料不及 }
|
||||
// -π means -1 * π,
|
||||
// so it's not a valid identifier
|
||||
```
|
||||
|
||||
## Paths
|
||||
Typst has various features that require a file path to reference external
|
||||
resources such as images, Typst files, or data files. Paths are represented as
|
||||
|
Loading…
x
Reference in New Issue
Block a user