mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Touch up docs
This commit is contained in:
parent
59957746e9
commit
3680c854a2
@ -29,6 +29,7 @@ flate2 = "1"
|
||||
fontdb = "0.9"
|
||||
if_chain = "1"
|
||||
image = { version = "0.24", default-features = false, features = ["png", "jpeg", "gif"] }
|
||||
indexmap = "1.9.3"
|
||||
log = "0.4"
|
||||
miniz_oxide = "0.7"
|
||||
once_cell = "1"
|
||||
@ -43,6 +44,7 @@ siphasher = "0.3"
|
||||
subsetter = "0.1.1"
|
||||
svg2pdf = "0.4"
|
||||
tiny-skia = "0.6.6"
|
||||
tracing = "0.1.37"
|
||||
ttf-parser = "0.18.1"
|
||||
unicode-math-class = "0.1"
|
||||
unicode-segmentation = "1"
|
||||
@ -50,8 +52,6 @@ unicode-xid = "0.2"
|
||||
unscanny = "0.1"
|
||||
usvg = { version = "0.22", default-features = false, features = ["text"] }
|
||||
xmp-writer = "0.1"
|
||||
tracing = "0.1.37"
|
||||
indexmap = "1.9.3"
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
stacker = "0.1.15"
|
||||
|
3
assets/files/details.toml
Normal file
3
assets/files/details.toml
Normal file
@ -0,0 +1,3 @@
|
||||
title = "Secret project"
|
||||
version = 2
|
||||
authors = ["Mr Robert", "Miss Enola"]
|
@ -1,11 +0,0 @@
|
||||
authors = ["Mr Robert", "Miss Enola", "Mr Jonathan"]
|
||||
version = "1.0.3"
|
||||
|
||||
series = [
|
||||
{ name = "attack on titan", fans = 500},
|
||||
{ name = "demon slayer", fans = 10}
|
||||
]
|
||||
|
||||
[informations]
|
||||
location = "room A204"
|
||||
pages = 47
|
@ -8,4 +8,4 @@ inline_table = { first = "amazing", second = "greater" }
|
||||
|
||||
[table]
|
||||
element = 5
|
||||
others = [false, "indeed", 7]
|
||||
others = [false, "indeed", 7]
|
@ -22,24 +22,24 @@ doc = false
|
||||
typst = { path = ".." }
|
||||
typst-library = { path = "../library" }
|
||||
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
|
||||
clap = { version = "4.2.4", features = ["derive", "env"] }
|
||||
codespan-reporting = "0.11"
|
||||
comemo = "0.2.2"
|
||||
dirs = "5"
|
||||
elsa = "1.8"
|
||||
inferno = "0.11.15"
|
||||
memmap2 = "0.5"
|
||||
notify = "5"
|
||||
once_cell = "1"
|
||||
open = "4.0.2"
|
||||
same-file = "1"
|
||||
siphasher = "0.3"
|
||||
walkdir = "2"
|
||||
clap = { version = "4.2.4", features = ["derive", "env"] }
|
||||
open = "4.0.2"
|
||||
tracing = "0.1.37"
|
||||
tracing-subscriber = "0.3.17"
|
||||
tracing-flame = "0.2.0"
|
||||
tracing-error = "0.2"
|
||||
inferno = "0.11.15"
|
||||
tempfile = "3.5.0"
|
||||
tracing = "0.1.37"
|
||||
tracing-error = "0.2"
|
||||
tracing-flame = "0.2.0"
|
||||
tracing-subscriber = "0.3.17"
|
||||
walkdir = "2"
|
||||
|
||||
[build-dependencies]
|
||||
clap = { version = "4.2.4", features = ["derive", "string"] }
|
||||
|
@ -12,14 +12,14 @@ bench = false
|
||||
[dependencies]
|
||||
typst = { path = ".." }
|
||||
typst-library = { path = "../library" }
|
||||
unscanny = "0.1"
|
||||
include_dir = "0.7"
|
||||
pulldown-cmark = "0.9"
|
||||
comemo = "0.2.2"
|
||||
heck = "0.4"
|
||||
include_dir = "0.7"
|
||||
once_cell = "1"
|
||||
pulldown-cmark = "0.9"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_yaml = "0.8"
|
||||
heck = "0.4"
|
||||
yaml-front-matter = "0.1"
|
||||
unicode_names2 = "0.6.0"
|
||||
once_cell = "1"
|
||||
unscanny = "0.1"
|
||||
ureq = { version = "2.6", features = ["json"] }
|
||||
yaml-front-matter = "0.1"
|
||||
|
@ -300,7 +300,7 @@ pub struct FuncModel {
|
||||
pub name: &'static str,
|
||||
pub display: &'static str,
|
||||
pub oneliner: &'static str,
|
||||
pub showable: bool,
|
||||
pub element: bool,
|
||||
pub details: Html,
|
||||
pub params: Vec<ParamModel>,
|
||||
pub returns: Vec<&'static str>,
|
||||
@ -340,7 +340,7 @@ fn func_model(resolver: &dyn Resolver, func: &Func, info: &FuncInfo) -> FuncMode
|
||||
name: info.name,
|
||||
display: info.display,
|
||||
oneliner: oneliner(docs),
|
||||
showable: func.element().is_some(),
|
||||
element: func.element().is_some(),
|
||||
details: Html::markdown(resolver, docs),
|
||||
params: info.params.iter().map(|param| param_model(resolver, param)).collect(),
|
||||
returns: info.returns.clone(),
|
||||
|
@ -64,7 +64,7 @@ Content and code blocks can be nested arbitrarily. In the example below,
|
||||
}
|
||||
```
|
||||
|
||||
## Let bindings { #bindings }
|
||||
## 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.
|
||||
The assignment of a value is optional, if no value is assigned, the variable
|
||||
@ -82,7 +82,10 @@ Sum is #add(2, 3).
|
||||
```
|
||||
|
||||
Let bindings can also be used to destructure [arrays]($type/array) and
|
||||
[dictionaries]($type/dictionary).
|
||||
[dictionaries]($type/dictionary). In this case, the left-hand side of the
|
||||
assignment should mirror an array or dictionary. The `..` operator can be used
|
||||
once in the pattern to collect the remainder of the array's or dictionary's
|
||||
items.
|
||||
|
||||
```example
|
||||
#let (x, y) = (1, 2)
|
||||
@ -117,6 +120,28 @@ You can use the underscore to discard elements in a destructuring pattern:
|
||||
The y coordinate is #y.
|
||||
```
|
||||
|
||||
Destructuring also work in argument lists of functions ...
|
||||
|
||||
```example
|
||||
#let left = (2, 4, 5)
|
||||
#let right = (3, 2, 6)
|
||||
#left.zip(right).map(
|
||||
((a,b)) => a + b
|
||||
)
|
||||
```
|
||||
|
||||
... and on the left-hand side of normal assignments. This can be useful to
|
||||
swap variables among other things.
|
||||
|
||||
```example
|
||||
#{
|
||||
let a = 1
|
||||
let b = 2
|
||||
(a, b) = (b, a)
|
||||
[a = #a, b = #b]
|
||||
}
|
||||
```
|
||||
|
||||
## Conditionals { #conditionals }
|
||||
With a conditional, you can display or compute different things depending on
|
||||
whether some condition is fulfilled. Typst supports `{if}`, `{else if}` and
|
||||
@ -206,12 +231,19 @@ can be either:
|
||||
- a [dictionary]($type/dictionary) that has the specified key,
|
||||
- a [symbol]($type/symbol) that has the specified modifier,
|
||||
- a [module]($type/module) containing the specified definition,
|
||||
- [content]($type/content) that has the specified field.
|
||||
- [content]($type/content) consisting of an element that has the specified
|
||||
field. The available fields match the arguments of the
|
||||
[element function]($type/function/#element-functions) that were given when
|
||||
the element was constructed.
|
||||
|
||||
```example
|
||||
#let dict = (greet: "Hello")
|
||||
#dict.greet \
|
||||
#emoji.face
|
||||
|
||||
#let it = [= Heading]
|
||||
#it.body \
|
||||
#it.level
|
||||
```
|
||||
|
||||
## Methods { #methods }
|
||||
|
@ -12,11 +12,12 @@ of elements.
|
||||
|
||||
## Set rules { #set-rules }
|
||||
With set rules, you can customize the appearance of elements. They are written
|
||||
as a [function call]($type/function) to the respective function 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]($func/text.family) and
|
||||
as a [function call]($type/function) to an
|
||||
[element function]($type/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]($func/text.family) and
|
||||
[heading numbering]($func/heading.numbering).
|
||||
|
||||
```example
|
||||
@ -62,9 +63,10 @@ a _set-if_ rule.
|
||||
## 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 function name, a colon and then a set rule. 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.
|
||||
`{show}` keyword followed by a [selector]($type/selector), a colon and then a set rule. The most basic form of selector is an
|
||||
[element function]($type/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)
|
||||
@ -78,7 +80,7 @@ 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 behind the colon with an arbitrary
|
||||
[function]($type/function). This functions receives the element in question and
|
||||
[function]($type/function). This function receives the element in question and
|
||||
can return arbitrary content. Different
|
||||
[fields]($scripting/#fields) are available on the element passed
|
||||
to the function. Below, we define a show rule that formats headings for a
|
||||
|
@ -644,14 +644,14 @@ Folds all items into a single value using an accumulator function.
|
||||
Sums all items (works for any types that can be added).
|
||||
|
||||
- default: any (named)
|
||||
If set and the array is empty, sum will return this.
|
||||
What to return if the array is empty. Must be set if the array can be empty.
|
||||
- returns: any
|
||||
|
||||
### product()
|
||||
Calculates the product all items (works for any types that can be multiplied)
|
||||
|
||||
- default: any (named)
|
||||
If set and the array is empty, sum will return this.
|
||||
What to return if the array is empty. Must be set if the array can be empty.
|
||||
- returns: any
|
||||
|
||||
### any()
|
||||
@ -814,6 +814,13 @@ documentation about [set]($styling/#set-rules) and
|
||||
[show]($styling/#show-rules) rules to learn about additional ways
|
||||
you can work with functions in Typst.
|
||||
|
||||
### Element functions { #element-functions }
|
||||
Some functions are associated with _elements_ like [headings]($func/heading) or
|
||||
[tables]($func/table). When called, these create an element of their respective
|
||||
kind. In contrast to normal functions, they can further be used in
|
||||
[set rules]($styling/#set-rules), [show rules]($styling/#show-rules), and
|
||||
[selectors]($type/selector).
|
||||
|
||||
### Defining functions { #definitions }
|
||||
You can define your own function with a
|
||||
[let binding]($scripting/#bindings) that has a parameter list after
|
||||
@ -916,30 +923,11 @@ Returns the captured named arguments as a dictionary.
|
||||
|
||||
- returns: dictionary
|
||||
|
||||
# Module
|
||||
An evaluated module, either built-in or resulting from a file.
|
||||
|
||||
You can access definitions from the module using
|
||||
[field access notation]($scripting/#fields) and interact with it using the
|
||||
[import and include syntaxes]($scripting/#modules).
|
||||
|
||||
## Example
|
||||
```example
|
||||
<<< #import "utils.typ"
|
||||
<<< #utils.add(2, 5)
|
||||
|
||||
<<< #import utils: sub
|
||||
<<< #sub(1, 4)
|
||||
>>> #7
|
||||
>>>
|
||||
>>> #(-3)
|
||||
```
|
||||
|
||||
# Selector
|
||||
A filter for selecting elements within the document.
|
||||
|
||||
You can construct a selector in the following ways:
|
||||
- you can use an element function
|
||||
- you can use an element [function]($type/function)
|
||||
- you can filter for an element function with
|
||||
[specific fields]($type/function.where)
|
||||
- you can use a [string]($type/string) or [regular expression]($func/regex)
|
||||
@ -948,13 +936,16 @@ You can construct a selector in the following ways:
|
||||
- call the [`selector`]($func/selector) function to convert any of the above
|
||||
types into a selector value and use the methods below to refine it
|
||||
|
||||
A selector is what you can use to query the document for certain types
|
||||
of elements. It can also be used to apply styling rules to element. You can
|
||||
combine multiple selectors using the methods shown below.
|
||||
Selectors are used to [apply styling rules]($styling/#show-rules) to elements.
|
||||
You can also use selectors to [query]($func/query) the document for certain
|
||||
types of elements.
|
||||
|
||||
Selectors can also be passed to several of Typst's built-in functions to
|
||||
Furthermore, you can pass a selector to several of Typst's built-in functions to
|
||||
configure their behaviour. One such example is the [outline]($func/outline)
|
||||
where it can be use to change which elements are listed within the outline.
|
||||
where it can be used to change which elements are listed within the outline.
|
||||
|
||||
Multiple selectors can be combined using the methods shown below. However, not
|
||||
all kinds of selectors are supported in all places, at the moment.
|
||||
|
||||
## Example
|
||||
```example
|
||||
@ -1004,3 +995,22 @@ first match of the selector argument.
|
||||
- inclusive: boolean (named)
|
||||
Whether `start` itself should match or not. This is only relevant if both
|
||||
selectors match the same type of element. Defaults to `{true}`.
|
||||
|
||||
# Module
|
||||
An evaluated module, either built-in or resulting from a file.
|
||||
|
||||
You can access definitions from the module using
|
||||
[field access notation]($scripting/#fields) and interact with it using the
|
||||
[import and include syntaxes]($scripting/#modules).
|
||||
|
||||
## Example
|
||||
```example
|
||||
<<< #import "utils.typ"
|
||||
<<< #utils.add(2, 5)
|
||||
|
||||
<<< #import utils: sub
|
||||
<<< #sub(1, 4)
|
||||
>>> #7
|
||||
>>>
|
||||
>>> #(-3)
|
||||
```
|
||||
|
@ -16,6 +16,7 @@ bench = false
|
||||
|
||||
[dependencies]
|
||||
typst = { path = ".." }
|
||||
chinese-number = { version = "0.7.2", default-features = false, features = ["number-to-chinese"] }
|
||||
comemo = "0.2.2"
|
||||
csv = "1"
|
||||
ecow = "0.1"
|
||||
@ -31,6 +32,8 @@ serde_json = "1"
|
||||
serde_yaml = "0.8"
|
||||
smallvec = "1.10"
|
||||
syntect = { version = "5", default-features = false, features = ["default-syntaxes", "regex-fancy"] }
|
||||
toml = { version = "0.7.3", default-features = false, features = ["parse"] }
|
||||
tracing = "0.1.37"
|
||||
ttf-parser = "0.18.1"
|
||||
typed-arena = "2"
|
||||
unicode-bidi = "0.3.13"
|
||||
@ -38,6 +41,3 @@ unicode-math-class = "0.1"
|
||||
unicode-script = "0.5"
|
||||
unicode-segmentation = "1"
|
||||
xi-unicode = "0.3"
|
||||
chinese-number = { version = "0.7.2", default-features = false, features = ["number-to-chinese"] }
|
||||
tracing = "0.1.37"
|
||||
toml = { version = "0.7.3", default-features = false, features = ["parse"]}
|
||||
|
@ -41,6 +41,7 @@ pub fn module() -> Module {
|
||||
scope.define("even", even);
|
||||
scope.define("odd", odd);
|
||||
scope.define("rem", rem);
|
||||
scope.define("mod", mod_);
|
||||
scope.define("quo", quo);
|
||||
scope.define("inf", Value::Float(f64::INFINITY));
|
||||
scope.define("nan", Value::Float(f64::NAN));
|
||||
@ -912,6 +913,27 @@ pub fn rem(
|
||||
dividend.apply2(divisor.v, Rem::rem, Rem::rem).value()
|
||||
}
|
||||
|
||||
/// Calculate the modulus of two numbers. (Deprecated)
|
||||
///
|
||||
/// **This function is deprecated in favor of `rem`. It will be removed in
|
||||
/// a future update.**
|
||||
///
|
||||
/// Display: Modulus
|
||||
/// Category: calculate
|
||||
/// Returns: integer or float
|
||||
#[func]
|
||||
pub fn mod_(
|
||||
/// The dividend of the remainder.
|
||||
dividend: Num,
|
||||
/// The divisor of the remainder.
|
||||
divisor: Spanned<Num>,
|
||||
) -> Value {
|
||||
if divisor.v.float() == 0.0 {
|
||||
bail!(divisor.span, "divisor must not be zero");
|
||||
}
|
||||
dividend.apply2(divisor.v, Rem::rem, Rem::rem).value()
|
||||
}
|
||||
|
||||
/// Calculate the quotient of two numbers.
|
||||
///
|
||||
/// ## Example
|
||||
|
@ -201,7 +201,6 @@ fn convert_json(value: serde_json::Value) -> Value {
|
||||
}
|
||||
|
||||
/// Format the user-facing JSON error message.
|
||||
#[track_caller]
|
||||
fn format_json_error(error: serde_json::Error) -> EcoString {
|
||||
assert!(error.is_syntax() || error.is_eof());
|
||||
eco_format!("failed to parse json file: syntax error in line {}", error.line())
|
||||
@ -209,30 +208,24 @@ fn format_json_error(error: serde_json::Error) -> EcoString {
|
||||
|
||||
/// Read structured data from a TOML file.
|
||||
///
|
||||
/// The file must contain a valid TOML table. Tables will be
|
||||
/// The file must contain a valid TOML table. TOML tables will be
|
||||
/// converted into Typst dictionaries, and TOML arrays will be converted into
|
||||
/// Typst arrays. Strings and booleans will be converted into the Typst
|
||||
/// equivalents, numbers will be converted to floats or integers depending on
|
||||
/// whether they are whole numbers. TOML DateTim will be converted to strings.
|
||||
/// equivalents and numbers will be converted to floats or integers depending on
|
||||
/// whether they are whole numbers. For the time being, datetimes will be
|
||||
/// converted to strings as Typst does not have a built-in datetime yet.
|
||||
///
|
||||
/// The function returns a dictionary.
|
||||
///
|
||||
/// The JSON files in the example contain objects with the keys `temperature`,
|
||||
/// `unit`, and `weather`.
|
||||
/// The TOML file in the example consists of a table with the keys `title`,
|
||||
/// `version`, and `authors`.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```example
|
||||
/// #let informations(content) = {
|
||||
/// [This work is made by #content.authors.join(", ", last: " and "). We are currently at version #content.version.
|
||||
/// The favorites series of the audience are ]
|
||||
/// for serie in content.series [
|
||||
/// - #serie.name with #serie.fans fans.
|
||||
/// ]
|
||||
/// [We need to submit our work in #content.informations.location, we currently have #content.informations.pages pages.]
|
||||
/// }
|
||||
/// #let details = toml("details.toml")
|
||||
///
|
||||
///
|
||||
/// #informations(toml("informations.toml"))
|
||||
/// Title: #details.title \
|
||||
/// Version: #details.version \
|
||||
/// Authors: #(details.authors
|
||||
/// .join(", ", last: " and "))
|
||||
/// ```
|
||||
///
|
||||
/// Display: TOML
|
||||
@ -268,23 +261,22 @@ fn convert_toml(value: toml::Value) -> Value {
|
||||
.map(|(key, value)| (key.into(), convert_toml(value)))
|
||||
.collect(),
|
||||
),
|
||||
// Todo: make it use native date/time object(s) once it is implemented.
|
||||
// TODO: Make it use native date/time object(s) once it is implemented.
|
||||
toml::Value::Datetime(v) => Value::Str(v.to_string().into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Format the user-facing TOML error message.
|
||||
#[track_caller]
|
||||
fn format_toml_error(error: toml::de::Error) -> String {
|
||||
fn format_toml_error(error: toml::de::Error) -> EcoString {
|
||||
if let Some(range) = error.span() {
|
||||
format!(
|
||||
"failed to parse toml file: {message}, index {start}-{end}",
|
||||
message = error.message(),
|
||||
start = range.start,
|
||||
end = range.end
|
||||
eco_format!(
|
||||
"failed to parse toml file: {}, index {}-{}",
|
||||
error.message(),
|
||||
range.start,
|
||||
range.end
|
||||
)
|
||||
} else {
|
||||
format!("failed to parse toml file: {message}", message = error.message())
|
||||
eco_format!("failed to parse toml file: {}", error.message())
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,7 +365,6 @@ fn convert_yaml_key(key: serde_yaml::Value) -> Option<Str> {
|
||||
}
|
||||
|
||||
/// Format the user-facing YAML error message.
|
||||
#[track_caller]
|
||||
fn format_yaml_error(error: serde_yaml::Error) -> EcoString {
|
||||
eco_format!("failed to parse yaml file: {}", error.to_string().trim())
|
||||
}
|
||||
|
@ -31,6 +31,9 @@ pub fn type_(
|
||||
/// in monospace with syntax-highlighting. The exceptions are `{none}`,
|
||||
/// integers, floats, strings, content, and functions.
|
||||
///
|
||||
/// **Note:** This function is for debugging purposes. Its output should not be
|
||||
/// considered stable and may change at any time!
|
||||
///
|
||||
/// ## Example
|
||||
/// ```example
|
||||
/// #none vs #repr(none) \
|
||||
|
@ -5,6 +5,9 @@ use crate::prelude::*;
|
||||
/// The `measure` function lets you determine the layouted size of content.
|
||||
/// Note that an infinite space is assumed, therefore the measured height/width
|
||||
/// may not necessarily match the final height/width of the measured content.
|
||||
/// If you want to measure in the current layout dimensions, you can combined
|
||||
/// `measure` and [`layout`]($func/layout).
|
||||
///
|
||||
/// The same content can have a different size depending on the styles that
|
||||
/// are active when it is layouted. For example, in the example below
|
||||
/// `[#content]` is of course bigger when we increase the font size.
|
||||
|
@ -8,10 +8,6 @@ use crate::prelude::*;
|
||||
/// descriptions span over multiple lines, they use hanging indent to
|
||||
/// communicate the visual hierarchy.
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This function also has dedicated syntax: Starting a line with a slash,
|
||||
/// followed by a term, a colon and a description creates a term list item.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```example
|
||||
/// / Ligature: A merged glyph.
|
||||
@ -19,6 +15,10 @@ use crate::prelude::*;
|
||||
/// between two adjacent letters.
|
||||
/// ```
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This function also has dedicated syntax: Starting a line with a slash,
|
||||
/// followed by a term, a colon and a description creates a term list item.
|
||||
///
|
||||
/// Display: Term List
|
||||
/// Category: layout
|
||||
#[element(Layout)]
|
||||
|
@ -228,25 +228,25 @@ fn items() -> LangItems {
|
||||
equation: |body, block| math::EquationElem::new(body).with_block(block).pack(),
|
||||
math_align_point: || math::AlignPointElem::new().pack(),
|
||||
math_delimited: |open, body, close| math::LrElem::new(open + body + close).pack(),
|
||||
math_attach: |base, top, bottom, topleft, bottomleft, topright, bottomright| {
|
||||
math_attach: |base, t, b, tl, bl, tr, br| {
|
||||
let mut elem = math::AttachElem::new(base);
|
||||
if let Some(top) = top {
|
||||
elem.push_t(Some(top));
|
||||
if let Some(t) = t {
|
||||
elem.push_t(Some(t));
|
||||
}
|
||||
if let Some(bottom) = bottom {
|
||||
elem.push_b(Some(bottom));
|
||||
if let Some(b) = b {
|
||||
elem.push_b(Some(b));
|
||||
}
|
||||
if let Some(topleft) = topleft {
|
||||
elem.push_tl(Some(topleft));
|
||||
if let Some(tl) = tl {
|
||||
elem.push_tl(Some(tl));
|
||||
}
|
||||
if let Some(bottomleft) = bottomleft {
|
||||
elem.push_bl(Some(bottomleft));
|
||||
if let Some(bl) = bl {
|
||||
elem.push_bl(Some(bl));
|
||||
}
|
||||
if let Some(topright) = topright {
|
||||
elem.push_tr(Some(topright));
|
||||
if let Some(tr) = tr {
|
||||
elem.push_tr(Some(tr));
|
||||
}
|
||||
if let Some(bottomright) = bottomright {
|
||||
elem.push_br(Some(bottomright));
|
||||
if let Some(br) = br {
|
||||
elem.push_br(Some(br));
|
||||
}
|
||||
elem.pack()
|
||||
},
|
||||
|
@ -2,16 +2,23 @@ use super::*;
|
||||
|
||||
/// A base with optional attachments.
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This function also has dedicated syntax for attachments after the base: Use the
|
||||
/// underscore (`_`) to indicate a subscript i.e. bottom attachment and the hat (`^`)
|
||||
/// to indicate a superscript i.e. top attachment.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```example
|
||||
/// // With syntax.
|
||||
/// $ sum_(i=0)^n a_i = 2^(1+i) $
|
||||
///
|
||||
/// // With function call.
|
||||
/// $ attach(
|
||||
/// Pi, t: alpha, b: beta,
|
||||
/// tl: 1, tr: 2, bl: 3, br: 4,
|
||||
/// ) $
|
||||
/// ```
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This function also has dedicated syntax for attachments after the base: Use
|
||||
/// the underscore (`_`) to indicate a subscript i.e. bottom attachment and the
|
||||
/// hat (`^`) to indicate a superscript i.e. top attachment.
|
||||
///
|
||||
/// Display: Attachment
|
||||
/// Category: math
|
||||
#[element(LayoutMath)]
|
||||
@ -21,41 +28,42 @@ pub struct AttachElem {
|
||||
pub base: Content,
|
||||
|
||||
/// The top attachment, smartly positioned at top-right or above the base.
|
||||
/// Use limits() or scripts() on the base to override the smart positioning.
|
||||
///
|
||||
/// You can wrap the base in `{limits()}` or `{scripts()}` to override the
|
||||
/// smart positioning.
|
||||
pub t: Option<Content>,
|
||||
|
||||
/// The bottom attachment, smartly positioned at the bottom-right or below the base.
|
||||
/// Use limits() or scripts() on the base to override the smart positioning.
|
||||
/// The bottom attachment, smartly positioned at the bottom-right or below
|
||||
/// the base. You can wrap the base in `{limits()}` or `{scripts()}` to
|
||||
/// override the smart positioning.
|
||||
pub b: Option<Content>,
|
||||
|
||||
/// The top-left attachment before the base.
|
||||
/// The top-left attachment (before the base).
|
||||
pub tl: Option<Content>,
|
||||
|
||||
/// The bottom-left attachment before base.
|
||||
/// The bottom-left attachment (before base).
|
||||
pub bl: Option<Content>,
|
||||
|
||||
/// The top-right attachment after the base.
|
||||
/// The top-right attachment (after the base).
|
||||
pub tr: Option<Content>,
|
||||
|
||||
/// The bottom-right attachment after the base.
|
||||
/// The bottom-right attachment (after the base).
|
||||
pub br: Option<Content>,
|
||||
}
|
||||
|
||||
type GetAttachmentContent =
|
||||
fn(&AttachElem, styles: ::typst::model::StyleChain) -> Option<Content>;
|
||||
|
||||
impl LayoutMath for AttachElem {
|
||||
#[tracing::instrument(skip(ctx))]
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
let base = ctx.layout_fragment(&self.base())?;
|
||||
|
||||
let getarg = |ctx: &mut MathContext, getter: GetAttachmentContent| {
|
||||
type GetAttachment = fn(&AttachElem, styles: StyleChain) -> Option<Content>;
|
||||
let getarg = |ctx: &mut MathContext, getter: GetAttachment| {
|
||||
getter(self, ctx.styles())
|
||||
.map(|elem| ctx.layout_fragment(&elem))
|
||||
.transpose()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let base = ctx.layout_fragment(&self.base())?;
|
||||
|
||||
ctx.style(ctx.style.for_superscript());
|
||||
let arg_tl = getarg(ctx, Self::tl);
|
||||
let arg_tr = getarg(ctx, Self::tr);
|
||||
|
@ -2,10 +2,14 @@ use super::*;
|
||||
|
||||
/// Displays a diagonal line over a part of an equation.
|
||||
///
|
||||
/// This is commonly used to show the eliminiation of a term.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```example
|
||||
/// >>> #set page(width: 140pt)
|
||||
/// Here, we can simplify:
|
||||
/// $ (a dot.c b dot.c cancel(x)) / cancel(x) $
|
||||
/// $ (a dot b dot cancel(x)) /
|
||||
/// cancel(x) $
|
||||
/// ```
|
||||
///
|
||||
/// Display: Cancel
|
||||
@ -23,18 +27,22 @@ pub struct CancelElem {
|
||||
/// Defaults to `{100% + 3pt}`.
|
||||
///
|
||||
/// ```example
|
||||
/// $ a + cancel(x, length: #200%) - b - cancel(x, length: #200%) $
|
||||
/// >>> #set page(width: 140pt)
|
||||
/// $ a + cancel(x, length: #200%)
|
||||
/// - cancel(x, length: #200%) $
|
||||
/// ```
|
||||
#[default(Rel::new(Ratio::one(), Abs::pt(3.0).into()))]
|
||||
pub length: Rel<Length>,
|
||||
|
||||
/// If the cancel line should be inverted (heading northwest instead of
|
||||
/// northeast).
|
||||
/// If the cancel line should be inverted (pointing to the top left instead
|
||||
/// of top right).
|
||||
///
|
||||
/// Defaults to `{false}`.
|
||||
///
|
||||
/// ```example
|
||||
/// $ (a cancel((b + c), inverted: #true)) / cancel(b + c, inverted: #true) $
|
||||
/// >>> #set page(width: 140pt)
|
||||
/// $ (a cancel((b + c), inverted: #true)) /
|
||||
/// cancel(b + c, inverted: #true) $
|
||||
/// ```
|
||||
#[default(false)]
|
||||
pub inverted: bool,
|
||||
@ -45,7 +53,8 @@ pub struct CancelElem {
|
||||
/// Defaults to `{false}`.
|
||||
///
|
||||
/// ```example
|
||||
/// $ cancel(x, cross: #true) $
|
||||
/// >>> #set page(width: 140pt)
|
||||
/// $ cancel(Pi, cross: #true) $
|
||||
/// ```
|
||||
#[default(false)]
|
||||
pub cross: bool,
|
||||
@ -54,7 +63,8 @@ pub struct CancelElem {
|
||||
/// [line's documentation]($func/line.angle) for more details.
|
||||
///
|
||||
/// ```example
|
||||
/// $ cancel(x, rotation: #30deg) $
|
||||
/// >>> #set page(width: 140pt)
|
||||
/// $ cancel(Pi, rotation: #30deg) $
|
||||
/// ```
|
||||
#[default(Angle::zero())]
|
||||
pub rotation: Angle,
|
||||
@ -63,7 +73,15 @@ pub struct CancelElem {
|
||||
/// [line's documentation]($func/line.stroke) for more details.
|
||||
///
|
||||
/// ```example
|
||||
/// $ cancel(x, stroke: #{red + 1.5pt}) $
|
||||
/// >>> #set page(width: 140pt)
|
||||
/// $ cancel(
|
||||
/// sum x,
|
||||
/// stroke: #(
|
||||
/// paint: red,
|
||||
/// thickness: 1.5pt,
|
||||
/// dash: "dashed",
|
||||
/// ),
|
||||
/// ) $
|
||||
/// ```
|
||||
#[resolve]
|
||||
#[fold]
|
||||
|
@ -19,7 +19,7 @@ use crate::text::TextElem;
|
||||
/// If you just want to link to a labelled element and not get an automatic
|
||||
/// textual reference, consider using the [`link`]($func/link) function instead.
|
||||
///
|
||||
/// # Example
|
||||
/// ## Example
|
||||
/// ```example
|
||||
/// #set heading(numbering: "1.")
|
||||
/// #set math.equation(numbering: "(1)")
|
||||
@ -51,6 +51,36 @@ use crate::text::TextElem;
|
||||
/// To customize the supplement, add content in square brackets after the
|
||||
/// reference: `[@intro[Chapter]]`.
|
||||
///
|
||||
/// ## Customization
|
||||
/// If you write a show rule for references, you can access the referenced
|
||||
/// element through the `element` field of the reference. The `element` may
|
||||
/// be `{none}` even if it exists if Typst hasn't discovered it yet, so you
|
||||
/// always need to handle that case in your code.
|
||||
///
|
||||
/// ```example
|
||||
/// #set heading(numbering: "1.")
|
||||
/// #set math.equation(numbering: "(1)")
|
||||
///
|
||||
/// #show ref: it => {
|
||||
/// let eq = math.equation
|
||||
/// let el = it.element
|
||||
/// if el != none and el.func() == eq {
|
||||
/// // Override equation references.
|
||||
/// numbering(
|
||||
/// el.numbering,
|
||||
/// ..counter(eq).at(el.location())
|
||||
/// )
|
||||
/// } else {
|
||||
/// // Other references as usual.
|
||||
/// it
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// = Beginnings <beginning>
|
||||
/// In @beginning we prove @pythagoras.
|
||||
/// $ a^2 + b^2 = c^2 $ <pythagoras>
|
||||
/// ```
|
||||
///
|
||||
/// Display: Reference
|
||||
/// Category: meta
|
||||
#[element(Synthesize, Locatable, Show)]
|
||||
@ -86,35 +116,7 @@ pub struct RefElem {
|
||||
#[synthesized]
|
||||
pub citation: Option<CiteElem>,
|
||||
|
||||
/// Content of the element, it should be referable.
|
||||
///
|
||||
/// ```example
|
||||
/// #set heading(numbering: (..nums) => {
|
||||
/// nums.pos().map(str).join(".")
|
||||
/// }, supplement: [Chapt])
|
||||
///
|
||||
/// #show ref: it => {
|
||||
/// if it.has("element") and it.element.func() == heading {
|
||||
/// let element = it.element
|
||||
/// "["
|
||||
/// element.supplement
|
||||
/// "-"
|
||||
/// numbering(element.numbering, ..counter(heading).at(element.location()))
|
||||
/// "]"
|
||||
/// } else {
|
||||
/// it
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// = Introduction <intro>
|
||||
/// = Summary <sum>
|
||||
/// == Subsection <sub>
|
||||
/// @intro
|
||||
///
|
||||
/// @sum
|
||||
///
|
||||
/// @sub
|
||||
/// ```
|
||||
/// The referenced element.
|
||||
#[synthesized]
|
||||
pub element: Option<Content>,
|
||||
}
|
||||
@ -123,22 +125,14 @@ impl Synthesize for RefElem {
|
||||
fn synthesize(&mut self, vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
|
||||
let citation = self.to_citation(vt, styles)?;
|
||||
self.push_citation(Some(citation));
|
||||
self.push_element(None);
|
||||
|
||||
if !vt.introspector.init() {
|
||||
self.push_element(None);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// find the element content
|
||||
let target = self.target();
|
||||
let elem = vt.introspector.query_label(&self.target());
|
||||
// not in bibliography, but in document, then push the element
|
||||
if let (false, Ok(elem)) =
|
||||
(BibliographyElem::has(vt, &target.0), elem.at(self.span()))
|
||||
{
|
||||
self.push_element(Some(elem));
|
||||
} else {
|
||||
self.push_element(None);
|
||||
if vt.introspector.init() && !BibliographyElem::has(vt, &target.0) {
|
||||
if let Ok(elem) = vt.introspector.query_label(&target) {
|
||||
self.push_element(Some(elem));
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -9,19 +9,11 @@ use crate::layout::BlockElem;
|
||||
use crate::meta::{Figurable, LocalName};
|
||||
use crate::prelude::*;
|
||||
|
||||
/// Raw text with optional syntax highlighting.
|
||||
/// Raw text with optionalw syntax highlighting.
|
||||
///
|
||||
/// Displays the text verbatim and in a monospace font. This is typically used
|
||||
/// to embed computer code into your document.
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This function also has dedicated syntax. You can enclose text in 1 or 3+
|
||||
/// backticks (`` ` ``) to make it raw. Two backticks produce empty raw text.
|
||||
/// When you use three or more backticks, you can additionally specify a
|
||||
/// language tag for syntax highlighting directly after the opening backticks.
|
||||
/// Within raw blocks, everything is rendered as is, in particular, there are no
|
||||
/// escape sequences.
|
||||
///
|
||||
/// ## Example
|
||||
/// ````example
|
||||
/// Adding `rbx` to `rcx` gives
|
||||
@ -34,6 +26,14 @@ use crate::prelude::*;
|
||||
/// ```
|
||||
/// ````
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This function also has dedicated syntax. You can enclose text in 1 or 3+
|
||||
/// backticks (`` ` ``) to make it raw. Two backticks produce empty raw text.
|
||||
/// When you use three or more backticks, you can additionally specify a
|
||||
/// language tag for syntax highlighting directly after the opening backticks.
|
||||
/// Within raw blocks, everything is rendered as is, in particular, there are no
|
||||
/// escape sequences.
|
||||
///
|
||||
/// Display: Raw Text / Code
|
||||
/// Category: text
|
||||
#[element(Synthesize, Show, Finalize, LocalName, Figurable)]
|
||||
|
@ -5,8 +5,13 @@ use crate::prelude::*;
|
||||
/// ## Example
|
||||
/// ```example
|
||||
/// #set page(height: 100pt)
|
||||
///
|
||||
/// #line(length: 100%)
|
||||
/// #line(end: (50%, 50%))
|
||||
/// #line(
|
||||
/// length: 4cm,
|
||||
/// stroke: 2pt + maroon,
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// Display: Line
|
||||
@ -41,30 +46,37 @@ pub struct LineElem {
|
||||
/// - A stroke combined from color and thickness using the `+` operator as
|
||||
/// in `{2pt + red}`.
|
||||
/// - A stroke described by a dictionary with any of the following keys:
|
||||
/// - `color`: the color to use for the stroke
|
||||
/// - `thickness`: the stroke's thickness
|
||||
/// - `cap`: one of `"butt"`, `"round"` or `"square"`, the line cap of the stroke
|
||||
/// - `join`: one of `"miter"`, `"round"` or `"bevel"`, the line join of the stroke
|
||||
/// - `miter-limit`: the miter limit to use if `join` is `"miter"`, defaults to 4.0
|
||||
/// - `dash`: the dash pattern to use. Can be any of the following:
|
||||
/// - One of the strings `"solid"`, `"dotted"`, `"densely-dotted"`, `"loosely-dotted"`,
|
||||
/// `"dashed"`, `"densely-dashed"`, `"loosely-dashed"`, `"dashdotted"`,
|
||||
/// `"densely-dashdotted"` or `"loosely-dashdotted"`
|
||||
/// - An array with elements that specify the lengths of dashes and gaps, alternating.
|
||||
/// Elements can also be the string `"dot"` for a length equal to the line thickness.
|
||||
/// - A dict with the keys `array`, same as the array above, and `phase`, the offset to
|
||||
/// the start of the first dash.
|
||||
///
|
||||
/// - `paint`: The [color]($type/color) to use for the stroke.
|
||||
/// - `thickness`: The stroke's thickness as a [length]($type/length).
|
||||
/// - `cap`: How the line terminates. One of `{"butt"}`, `{"round"}`, or
|
||||
/// `{"square"}`.
|
||||
/// - `join`: How sharp turns of a contour are rendered. One of
|
||||
/// `{"miter"}`, `{"round"}`, or `{"bevel"}`. Not applicable to lines
|
||||
/// but to [polygons]($func/polygon) or [paths]($func/path).
|
||||
/// - `miter-limit`: Number at which protruding sharp angles are rendered
|
||||
/// with a bevel instead. The higher the number, the sharper an angle
|
||||
/// can be before it is bevelled. Only applicable if `join` is
|
||||
/// `{"miter"}`. Defaults to `{4.0}`.
|
||||
/// - `dash`: The dash pattern to use. Can be any of the following:
|
||||
/// - One of the predefined patterns `{"solid"}`, `{"dotted"}`,
|
||||
/// `{"densely-dotted"}`, `{"loosely-dotted"}`, `{"dashed"}`,
|
||||
/// `{"densely-dashed"}`, `{"loosely-dashed"}`, `{"dash-dotted"}`,
|
||||
/// `{"densely-dash-dotted"}` or `{"loosely-dash-dotted"}`
|
||||
/// - An [array]($type/array) with alternating lengths for dashes and
|
||||
/// gaps. You can also use the string `{"dot"}` for a length equal to
|
||||
/// the line thickness.
|
||||
/// - A [dictionary]($type/dictionary) with the keys `array` (same as
|
||||
/// the array above), and `phase` (of type [length]($type/length)),
|
||||
/// which defines where in the pattern to start drawing.
|
||||
///
|
||||
/// ```example
|
||||
/// #set line(length: 100%)
|
||||
/// #stack(
|
||||
/// line(length: 100%, stroke: 2pt + red),
|
||||
/// v(1em),
|
||||
/// line(length: 100%, stroke: (color: blue, thickness: 4pt, cap: "round")),
|
||||
/// v(1em),
|
||||
/// line(length: 100%, stroke: (color: blue, thickness: 1pt, dash: "dashed")),
|
||||
/// v(1em),
|
||||
/// line(length: 100%, stroke: (color: blue, thickness: 1pt, dash: ("dot", 2pt, 4pt, 2pt))),
|
||||
/// spacing: 1em,
|
||||
/// line(stroke: 2pt + red),
|
||||
/// line(stroke: (paint: blue, thickness: 4pt, cap: "round")),
|
||||
/// line(stroke: (paint: blue, thickness: 1pt, dash: "dashed")),
|
||||
/// line(stroke: (paint: blue, thickness: 1pt, dash: ("dot", 2pt, 4pt, 2pt))),
|
||||
/// )
|
||||
/// ```
|
||||
#[resolve]
|
||||
|
@ -55,8 +55,8 @@ pub struct RectElem {
|
||||
/// - `miter-limit`: the miter limit to use if `join` is `"miter"`, defaults to 4.0
|
||||
/// - `dash`: the dash pattern to use. Can be any of the following:
|
||||
/// - One of the strings `"solid"`, `"dotted"`, `"densely-dotted"`, `"loosely-dotted"`,
|
||||
/// `"dashed"`, `"densely-dashed"`, `"loosely-dashed"`, `"dashdotted"`,
|
||||
/// `"densely-dashdotted"` or `"loosely-dashdotted"`
|
||||
/// `"dashed"`, `"densely-dashed"`, `"loosely-dashed"`, `"dash-dotted"`,
|
||||
/// `"densely-dash-dotted"` or `"loosely-dash-dotted"`
|
||||
/// - An array with elements that specify the lengths of dashes and gaps, alternating.
|
||||
/// Elements can also be the string `"dot"` for a length equal to the line thickness.
|
||||
/// - A dict with the keys `array`, same as the array above, and `phase`, the offset to
|
||||
|
@ -16,7 +16,7 @@ doctest = false
|
||||
bench = false
|
||||
|
||||
[dependencies]
|
||||
heck = "0.4"
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = { version = "1", features = ["full", "extra-traits"] }
|
||||
heck = "0.4"
|
||||
|
@ -91,13 +91,13 @@ pub struct LangItems {
|
||||
pub math_attach: fn(
|
||||
base: Content,
|
||||
// Positioned smartly.
|
||||
top: Option<Content>,
|
||||
bottom: Option<Content>,
|
||||
t: Option<Content>,
|
||||
b: Option<Content>,
|
||||
// Fixed positions.
|
||||
topleft: Option<Content>,
|
||||
bottomleft: Option<Content>,
|
||||
topright: Option<Content>,
|
||||
bottomright: Option<Content>,
|
||||
tl: Option<Content>,
|
||||
bl: Option<Content>,
|
||||
tr: Option<Content>,
|
||||
br: Option<Content>,
|
||||
) -> Content,
|
||||
/// A base with an accent: `arrow(x)`.
|
||||
pub math_accent: fn(base: Content, accent: char) -> Content,
|
||||
|
@ -48,8 +48,9 @@ use unicode_segmentation::UnicodeSegmentation;
|
||||
use crate::diag::{
|
||||
bail, error, At, SourceError, SourceResult, StrResult, Trace, Tracepoint,
|
||||
};
|
||||
use crate::model::ShowableSelector;
|
||||
use crate::model::{
|
||||
Content, Introspector, Label, Recipe, Selector, StabilityProvider, Styles, Transform,
|
||||
Content, Introspector, Label, Recipe, StabilityProvider, Styles, Transform,
|
||||
Unlabellable, Vt,
|
||||
};
|
||||
use crate::syntax::ast::AstNode;
|
||||
@ -1428,8 +1429,9 @@ impl Eval for ast::ShowRule {
|
||||
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
||||
let selector = self
|
||||
.selector()
|
||||
.map(|sel| sel.eval(vm)?.cast::<Selector>().at(sel.span()))
|
||||
.transpose()?;
|
||||
.map(|sel| sel.eval(vm)?.cast::<ShowableSelector>().at(sel.span()))
|
||||
.transpose()?
|
||||
.map(|selector| selector.0);
|
||||
|
||||
let transform = self.transform();
|
||||
let span = transform.span();
|
||||
|
@ -256,9 +256,9 @@ cast_from_value! {
|
||||
"dashed" => vec![Abs::pt(3.0).into(), Abs::pt(3.0).into()].into(),
|
||||
"densely-dashed" => vec![Abs::pt(3.0).into(), Abs::pt(2.0).into()].into(),
|
||||
"loosely-dashed" => vec![Abs::pt(3.0).into(), Abs::pt(6.0).into()].into(),
|
||||
"dashdotted" => vec![Abs::pt(3.0).into(), Abs::pt(2.0).into(), DashLength::LineWidth, Abs::pt(2.0).into()].into(),
|
||||
"densely-dashdotted" => vec![Abs::pt(3.0).into(), Abs::pt(1.0).into(), DashLength::LineWidth, Abs::pt(1.0).into()].into(),
|
||||
"loosely-dashdotted" => vec![Abs::pt(3.0).into(), Abs::pt(4.0).into(), DashLength::LineWidth, Abs::pt(4.0).into()].into(),
|
||||
"dash-dotted" => vec![Abs::pt(3.0).into(), Abs::pt(2.0).into(), DashLength::LineWidth, Abs::pt(2.0).into()].into(),
|
||||
"densely-dash-dotted" => vec![Abs::pt(3.0).into(), Abs::pt(1.0).into(), DashLength::LineWidth, Abs::pt(1.0).into()].into(),
|
||||
"loosely-dash-dotted" => vec![Abs::pt(3.0).into(), Abs::pt(4.0).into(), DashLength::LineWidth, Abs::pt(4.0).into()].into(),
|
||||
array: Vec<DashLength> => {
|
||||
Self {
|
||||
array,
|
||||
@ -314,14 +314,14 @@ cast_from_value! {
|
||||
.transpose()?.map(Smart::Custom).unwrap_or(Smart::Auto))
|
||||
}
|
||||
|
||||
let paint = take::<Paint>(&mut dict, "color")?;
|
||||
let paint = take::<Paint>(&mut dict, "paint")?;
|
||||
let thickness = take::<Length>(&mut dict, "thickness")?;
|
||||
let line_cap = take::<LineCap>(&mut dict, "cap")?;
|
||||
let line_join = take::<LineJoin>(&mut dict, "join")?;
|
||||
let dash_pattern = take::<Option<DashPattern>>(&mut dict, "dash")?;
|
||||
let miter_limit = take::<f64>(&mut dict, "miter-limit")?;
|
||||
|
||||
dict.finish(&["color", "thickness", "cap", "join", "dash", "miter-limit"])?;
|
||||
dict.finish(&["paint", "thickness", "cap", "join", "dash", "miter-limit"])?;
|
||||
|
||||
Self {
|
||||
paint,
|
||||
|
@ -584,7 +584,6 @@ impl Fold for Vec<Meta> {
|
||||
|
||||
/// The missing key access error message.
|
||||
#[cold]
|
||||
#[track_caller]
|
||||
fn missing_field(key: &str) -> EcoString {
|
||||
eco_format!("content does not contain field {:?}", Str::from(key))
|
||||
}
|
||||
|
@ -412,9 +412,7 @@ impl Selector {
|
||||
Self::Or(selectors) => selectors.iter().any(move |sel| sel.matches(target)),
|
||||
Self::And(selectors) => selectors.iter().all(move |sel| sel.matches(target)),
|
||||
Self::Location(location) => target.location() == Some(*location),
|
||||
Self::Before { .. } | Self::After { .. } => {
|
||||
panic!("Cannot match a `Selector::Before` or `Selector::After` selector")
|
||||
}
|
||||
Self::Before { .. } | Self::After { .. } => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -491,7 +489,7 @@ impl Cast for LocatableSelector {
|
||||
|
||||
fn cast(value: Value) -> StrResult<Self> {
|
||||
fn validate(selector: &Selector) -> StrResult<()> {
|
||||
match &selector {
|
||||
match selector {
|
||||
Selector::Elem(elem, _) => {
|
||||
if !elem.can::<dyn Locatable>() {
|
||||
Err(eco_format!("{} is not locatable", elem.name()))?
|
||||
@ -533,6 +531,56 @@ impl Cast for LocatableSelector {
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
/// A selector that can be used with show rules.
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
pub struct ShowableSelector(pub Selector);
|
||||
|
||||
impl Cast for ShowableSelector {
|
||||
fn is(value: &Value) -> bool {
|
||||
matches!(value, Value::Str(_) | Value::Label(_) | Value::Func(_))
|
||||
|| value.type_name() == "regular expression"
|
||||
|| value.type_name() == "selector"
|
||||
}
|
||||
|
||||
fn cast(value: Value) -> StrResult<Self> {
|
||||
fn validate(selector: &Selector) -> StrResult<()> {
|
||||
match selector {
|
||||
Selector::Elem(_, _) => {}
|
||||
Selector::Label(_) => {}
|
||||
Selector::Regex(_) => {}
|
||||
Selector::Or(_)
|
||||
| Selector::And(_)
|
||||
| Selector::Location(_)
|
||||
| Selector::Can(_)
|
||||
| Selector::Before { .. }
|
||||
| Selector::After { .. } => {
|
||||
Err("this selector cannot be used with show")?
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
if !Self::is(&value) {
|
||||
return <Self as Cast>::error(value);
|
||||
}
|
||||
|
||||
let selector = Selector::cast(value)?;
|
||||
validate(&selector)?;
|
||||
Ok(Self(selector))
|
||||
}
|
||||
|
||||
fn describe() -> CastInfo {
|
||||
CastInfo::Union(vec![
|
||||
CastInfo::Type("function"),
|
||||
CastInfo::Type("label"),
|
||||
CastInfo::Type("string"),
|
||||
CastInfo::Type("regular expression"),
|
||||
CastInfo::Type("selector"),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
/// A show rule transformation that can be applied to a match.
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
pub enum Transform {
|
||||
|
@ -850,12 +850,19 @@ fn item(p: &mut Parser, keyed: bool) -> SyntaxKind {
|
||||
return SyntaxKind::Spread;
|
||||
}
|
||||
|
||||
if !p.eat_if(SyntaxKind::Underscore) {
|
||||
code_expr_or_pattern(p);
|
||||
} else {
|
||||
return SyntaxKind::Underscore;
|
||||
if p.at(SyntaxKind::Underscore) {
|
||||
// This is a temporary workaround to fix `v.map(_ => {})`.
|
||||
let mut lexer = p.lexer.clone();
|
||||
let next =
|
||||
std::iter::from_fn(|| Some(lexer.next())).find(|kind| !kind.is_trivia());
|
||||
if next != Some(SyntaxKind::Arrow) {
|
||||
p.eat();
|
||||
return SyntaxKind::Underscore;
|
||||
}
|
||||
}
|
||||
|
||||
code_expr_or_pattern(p);
|
||||
|
||||
if !p.eat_if(SyntaxKind::Colon) {
|
||||
return SyntaxKind::Int;
|
||||
}
|
||||
|
5
tests/typ/bugs/args-underscore.typ
Normal file
5
tests/typ/bugs/args-underscore.typ
Normal file
@ -0,0 +1,5 @@
|
||||
// Test that lone underscore works.
|
||||
// Ref: false
|
||||
|
||||
---
|
||||
#test((1, 2, 3).map(_ => {}).len(), 3)
|
@ -96,7 +96,7 @@ Hey
|
||||
= Heading
|
||||
|
||||
---
|
||||
// Error: 7-10 expected function, label, string, regular expression, location, or selector, found color
|
||||
// Error: 7-10 expected function, label, string, regular expression, or selector, found color
|
||||
#show red: []
|
||||
|
||||
---
|
||||
|
@ -37,3 +37,7 @@ the ```rs &mut T``` reference.
|
||||
= Red
|
||||
== Blue
|
||||
=== Green
|
||||
|
||||
---
|
||||
// Error: 7-35 this selector cannot be used with show
|
||||
#show selector(heading).or(strong): none
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
---
|
||||
// Test reading TOML data.
|
||||
#let data = toml("/toml_types.toml")
|
||||
#let data = toml("/toml-types.toml")
|
||||
#test(data.string, "wonderful")
|
||||
#test(data.integer, 42)
|
||||
#test(data.float, 3.14)
|
||||
@ -60,7 +60,7 @@
|
||||
|
||||
---
|
||||
// Test reading YAML data
|
||||
#let data = yaml("/yamltypes.yaml")
|
||||
#let data = yaml("/yaml-types.yaml")
|
||||
#test(data.len(), 7)
|
||||
#test(data.null_key, (none, none))
|
||||
#test(data.string, "text")
|
||||
|
@ -23,10 +23,10 @@ $ mat(
|
||||
---
|
||||
// Test baseline alignment.
|
||||
$ mat(
|
||||
a, b^2;
|
||||
sum_(x \ y) x, a^(1/2);
|
||||
zeta, alpha;
|
||||
) $
|
||||
a, b^2;
|
||||
sum_(x \ y) x, a^(1/2);
|
||||
zeta, alpha;
|
||||
) $
|
||||
|
||||
---
|
||||
// Test alternative delimiter with set rule.
|
||||
|
@ -11,18 +11,18 @@
|
||||
|
||||
#set text(size: 12pt, weight: "regular")
|
||||
#outline(
|
||||
title: "Chapter outline",
|
||||
indent: true,
|
||||
target: heading
|
||||
.where(level: 1)
|
||||
.or(heading.where(level: 2))
|
||||
.after(it.location(), inclusive: true)
|
||||
.before(
|
||||
heading
|
||||
.where(level: 1, outlined: true)
|
||||
.after(it.location(), inclusive: false),
|
||||
inclusive: false,
|
||||
)
|
||||
title: "Chapter outline",
|
||||
indent: true,
|
||||
target: heading
|
||||
.where(level: 1)
|
||||
.or(heading.where(level: 2))
|
||||
.after(it.location(), inclusive: true)
|
||||
.before(
|
||||
heading
|
||||
.where(level: 1, outlined: true)
|
||||
.after(it.location(), inclusive: false),
|
||||
inclusive: false,
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
|
@ -2,22 +2,19 @@
|
||||
|
||||
---
|
||||
// Some simple test lines
|
||||
|
||||
#line(length: 60pt, stroke: red)
|
||||
#v(3pt)
|
||||
#line(length: 60pt, stroke: 2pt)
|
||||
#v(3pt)
|
||||
#line(length: 60pt, stroke: blue + 1.5pt)
|
||||
#v(3pt)
|
||||
#line(length: 60pt, stroke: (color: red, thickness: 1pt, dash: "dashed"))
|
||||
#line(length: 60pt, stroke: (paint: red, thickness: 1pt, dash: "dashed"))
|
||||
#v(3pt)
|
||||
#line(length: 60pt, stroke: (color: red, thickness: 4pt, cap: "round"))
|
||||
#line(length: 60pt, stroke: (paint: red, thickness: 4pt, cap: "round"))
|
||||
|
||||
---
|
||||
// Set rules with stroke
|
||||
|
||||
#set line(stroke: (color: red, thickness: 1pt, cap: "butt", dash: "dashdotted"))
|
||||
|
||||
#set line(stroke: (paint: red, thickness: 1pt, cap: "butt", dash: "dash-dotted"))
|
||||
#line(length: 60pt)
|
||||
#v(3pt)
|
||||
#line(length: 60pt, stroke: blue)
|
||||
@ -26,79 +23,78 @@
|
||||
|
||||
---
|
||||
// Rectangle strokes
|
||||
|
||||
#rect(width: 20pt, height: 20pt, stroke: red)
|
||||
#v(3pt)
|
||||
#rect(width: 20pt, height: 20pt, stroke: (rest: red, top: (color: blue, dash: "dashed")))
|
||||
#rect(width: 20pt, height: 20pt, stroke: (rest: red, top: (paint: blue, dash: "dashed")))
|
||||
#v(3pt)
|
||||
#rect(width: 20pt, height: 20pt, stroke: (thickness: 5pt, join: "round"))
|
||||
|
||||
---
|
||||
// Dashing
|
||||
#line(length: 60pt, stroke: (color: red, thickness: 1pt, dash: ("dot", 1pt)))
|
||||
#line(length: 60pt, stroke: (paint: red, thickness: 1pt, dash: ("dot", 1pt)))
|
||||
#v(3pt)
|
||||
#line(length: 60pt, stroke: (color: red, thickness: 1pt, dash: ("dot", 1pt, 4pt, 2pt)))
|
||||
#line(length: 60pt, stroke: (paint: red, thickness: 1pt, dash: ("dot", 1pt, 4pt, 2pt)))
|
||||
#v(3pt)
|
||||
#line(length: 60pt, stroke: (color: red, thickness: 1pt, dash: (array: ("dot", 1pt, 4pt, 2pt), phase: 5pt)))
|
||||
#line(length: 60pt, stroke: (paint: red, thickness: 1pt, dash: (array: ("dot", 1pt, 4pt, 2pt), phase: 5pt)))
|
||||
#v(3pt)
|
||||
#line(length: 60pt, stroke: (color: red, thickness: 1pt, dash: ()))
|
||||
#line(length: 60pt, stroke: (paint: red, thickness: 1pt, dash: ()))
|
||||
#v(3pt)
|
||||
#line(length: 60pt, stroke: (color: red, thickness: 1pt, dash: (1pt, 3pt, 9pt)))
|
||||
#line(length: 60pt, stroke: (paint: red, thickness: 1pt, dash: (1pt, 3pt, 9pt)))
|
||||
|
||||
---
|
||||
// Line joins
|
||||
#stack(dir: ltr,
|
||||
polygon(stroke: (thickness: 4pt, color: blue, join: "round"),
|
||||
#stack(
|
||||
dir: ltr,
|
||||
spacing: 1em,
|
||||
polygon(stroke: (thickness: 4pt, paint: blue, join: "round"),
|
||||
(0pt, 20pt), (15pt, 0pt), (0pt, 40pt), (15pt, 45pt)),
|
||||
h(1em),
|
||||
polygon(stroke: (thickness: 4pt, color: blue, join: "bevel"),
|
||||
polygon(stroke: (thickness: 4pt, paint: blue, join: "bevel"),
|
||||
(0pt, 20pt), (15pt, 0pt), (0pt, 40pt), (15pt, 45pt)),
|
||||
h(1em),
|
||||
polygon(stroke: (thickness: 4pt, color: blue, join: "miter"),
|
||||
polygon(stroke: (thickness: 4pt, paint: blue, join: "miter"),
|
||||
(0pt, 20pt), (15pt, 0pt), (0pt, 40pt), (15pt, 45pt)),
|
||||
h(1em),
|
||||
polygon(stroke: (thickness: 4pt, color: blue, join: "miter", miter-limit: 20.0),
|
||||
polygon(stroke: (thickness: 4pt, paint: blue, join: "miter", miter-limit: 20.0),
|
||||
(0pt, 20pt), (15pt, 0pt), (0pt, 40pt), (15pt, 45pt)),
|
||||
)
|
||||
---
|
||||
|
||||
// Error: 29-56 unexpected key "thicknes", valid keys are "color", "thickness", "cap", "join", "dash", and "miter-limit"
|
||||
#line(length: 60pt, stroke: (color: red, thicknes: 1pt))
|
||||
// Error: 29-56 unexpected key "thicknes", valid keys are "paint", "thickness", "cap", "join", "dash", and "miter-limit"
|
||||
#line(length: 60pt, stroke: (paint: red, thicknes: 1pt))
|
||||
|
||||
---
|
||||
|
||||
// Error: 29-55 expected "solid", "dotted", "densely-dotted", "loosely-dotted", "dashed", "densely-dashed", "loosely-dashed", "dashdotted", "densely-dashdotted", "loosely-dashdotted", array, dictionary, dash pattern, or none
|
||||
#line(length: 60pt, stroke: (color: red, dash: "dash"))
|
||||
// Error: 29-55 expected "solid", "dotted", "densely-dotted", "loosely-dotted", "dashed", "densely-dashed", "loosely-dashed", "dash-dotted", "densely-dash-dotted", "loosely-dash-dotted", array, dictionary, dash pattern, or none
|
||||
#line(length: 60pt, stroke: (paint: red, dash: "dash"))
|
||||
|
||||
---
|
||||
// 0pt strokes must function exactly like 'none' strokes and not draw anything
|
||||
|
||||
#rect(width: 10pt, height: 10pt, stroke: none)
|
||||
#rect(width: 10pt, height: 10pt, stroke: 0pt)
|
||||
|
||||
#rect(width: 10pt, height: 10pt, stroke: none, fill: blue)
|
||||
#rect(width: 10pt, height: 10pt, stroke: 0pt + red, fill: blue)
|
||||
|
||||
#line(length: 30pt, stroke: 0pt)
|
||||
#line(length: 30pt, stroke: (color: red, thickness: 0pt, dash: ("dot", 1pt)))
|
||||
#line(length: 30pt, stroke: (paint: red, thickness: 0pt, dash: ("dot", 1pt)))
|
||||
|
||||
#table(columns: 2, stroke: none)[A][B]
|
||||
#table(columns: 2, stroke: 0pt)[A][B]
|
||||
|
||||
#path(
|
||||
fill: red,
|
||||
stroke: none,
|
||||
closed: true,
|
||||
((0%, 0%), (4%, -4%)),
|
||||
((50%, 50%), (4%, -4%)),
|
||||
((0%, 50%), (4%, 4%)),
|
||||
((50%, 0%), (4%, 4%)),
|
||||
fill: red,
|
||||
stroke: none,
|
||||
closed: true,
|
||||
((0%, 0%), (4%, -4%)),
|
||||
((50%, 50%), (4%, -4%)),
|
||||
((0%, 50%), (4%, 4%)),
|
||||
((50%, 0%), (4%, 4%)),
|
||||
)
|
||||
|
||||
#path(
|
||||
fill: red,
|
||||
stroke: 0pt,
|
||||
closed: true,
|
||||
((0%, 0%), (4%, -4%)),
|
||||
((50%, 50%), (4%, -4%)),
|
||||
((0%, 50%), (4%, 4%)),
|
||||
((50%, 0%), (4%, 4%)),
|
||||
fill: red,
|
||||
stroke: 0pt,
|
||||
closed: true,
|
||||
((0%, 0%), (4%, -4%)),
|
||||
((50%, 50%), (4%, -4%)),
|
||||
((0%, 50%), (4%, 4%)),
|
||||
((50%, 0%), (4%, 4%)),
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user