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.
|
/// Creates a label from a string.
|
||||||
#[func(constructor)]
|
#[func(constructor)]
|
||||||
pub fn construct(
|
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,
|
name: Str,
|
||||||
) -> StrResult<Label> {
|
) -> StrResult<Label> {
|
||||||
if name.is_empty() {
|
if name.is_empty() {
|
||||||
|
@ -407,7 +407,7 @@ impl Counter {
|
|||||||
/// Create a new counter identified by a key.
|
/// Create a new counter identified by a key.
|
||||||
#[func(constructor)]
|
#[func(constructor)]
|
||||||
pub fn construct(
|
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
|
/// - If it is a string, creates a custom counter that is only affected
|
||||||
/// by manual updates,
|
/// by manual updates,
|
||||||
|
@ -273,8 +273,31 @@ impl State {
|
|||||||
#[func(constructor)]
|
#[func(constructor)]
|
||||||
pub fn construct(
|
pub fn construct(
|
||||||
/// The key that identifies this state.
|
/// 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,
|
key: Str,
|
||||||
/// The initial value of the state.
|
/// 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]
|
#[default]
|
||||||
init: Value,
|
init: Value,
|
||||||
) -> State {
|
) -> State {
|
||||||
@ -328,7 +351,7 @@ impl State {
|
|||||||
Ok(sequence.last().unwrap().clone())
|
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
|
/// 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
|
/// 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
|
/// write `{let _ = state("key").update(7)}`. State updates are always
|
||||||
/// applied in layout order and in that case, Typst wouldn't know when to
|
/// applied in layout order and in that case, Typst wouldn't know when to
|
||||||
/// update the state.
|
/// update the state.
|
||||||
|
///
|
||||||
|
/// In contrast to [`get`]($state.get), [`at`]($state.at), and
|
||||||
|
/// [`final`]($state.final), this function does not require [context].
|
||||||
#[func]
|
#[func]
|
||||||
pub fn update(
|
pub fn update(
|
||||||
self,
|
self,
|
||||||
span: Span,
|
span: Span,
|
||||||
/// If given a non function-value, sets the state to that value. If
|
/// A value to update to or a function to update with.
|
||||||
/// given a function, that function receives the previous state and has
|
///
|
||||||
/// to return the new state.
|
/// - 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,
|
update: StateUpdate,
|
||||||
) -> Content {
|
) -> Content {
|
||||||
StateUpdateElem::new(self.key, update).pack().spanned(span)
|
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
|
introduced with a hash (`#`) and normal markup parsing resumes after the
|
||||||
expression is finished. If a character would continue the expression but should
|
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
|
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
|
```example
|
||||||
#emph[Hello] \
|
#emph[Hello] \
|
||||||
@ -66,6 +66,7 @@ Content and code blocks can be nested arbitrarily. In the example below,
|
|||||||
## Bindings and Destructuring { #bindings }
|
## Bindings and Destructuring { #bindings }
|
||||||
As already demonstrated above, variables can be defined with `{let}` 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.
|
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
|
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
|
will be initialized as `{none}`. The `{let}` keyword can also be used to create
|
||||||
a [custom named function]($function/#defining-functions). Variables can be
|
a [custom named function]($function/#defining-functions). Variables can be
|
||||||
@ -77,8 +78,8 @@ is no containing block).
|
|||||||
This is #name's documentation.
|
This is #name's documentation.
|
||||||
It explains #name.
|
It explains #name.
|
||||||
|
|
||||||
#let add(x, y) = x + y
|
#let my-add(x, y) = x + y
|
||||||
Sum is #add(2, 3).
|
Sum is #my-add(2, 3).
|
||||||
```
|
```
|
||||||
|
|
||||||
Let bindings can also be used to destructure [arrays]($array) and
|
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}
|
\$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
|
## Paths
|
||||||
Typst has various features that require a file path to reference external
|
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
|
resources such as images, Typst files, or data files. Paths are represented as
|
||||||
|
Loading…
x
Reference in New Issue
Block a user