typst_library/math/
style.rs

1use codex::styling::MathVariant;
2
3use crate::foundations::{Cast, Content, func};
4use crate::math::EquationElem;
5
6/// Bold font style in math.
7///
8/// ```example
9/// $ bold(A) := B^+ $
10/// ```
11#[func(keywords = ["mathbf"])]
12pub fn bold(
13    /// The content to style.
14    body: Content,
15) -> Content {
16    body.set(EquationElem::bold, true)
17}
18
19/// Upright (non-italic) font style in math.
20///
21/// ```example
22/// $ upright(A) != A $
23/// ```
24#[func(keywords = ["mathup"])]
25pub fn upright(
26    /// The content to style.
27    body: Content,
28) -> Content {
29    body.set(EquationElem::italic, Some(false))
30}
31
32/// Italic font style in math.
33///
34/// For roman letters and greek lowercase letters, this is already the default.
35#[func(keywords = ["mathit"])]
36pub fn italic(
37    /// The content to style.
38    body: Content,
39) -> Content {
40    body.set(EquationElem::italic, Some(true))
41}
42
43/// Serif (roman) font style in math.
44///
45/// This is already the default.
46#[func(keywords = ["mathrm"])]
47pub fn serif(
48    /// The content to style.
49    body: Content,
50) -> Content {
51    body.set(EquationElem::variant, Some(MathVariant::Plain))
52}
53
54/// Sans-serif font style in math.
55///
56/// ```example
57/// $ sans(A B C) $
58/// ```
59#[func(title = "Sans Serif", keywords = ["mathsf"])]
60pub fn sans(
61    /// The content to style.
62    body: Content,
63) -> Content {
64    body.set(EquationElem::variant, Some(MathVariant::SansSerif))
65}
66
67/// Calligraphic (chancery) font style in math.
68///
69/// ```example
70/// Let $cal(P)$ be the set of ...
71/// ```
72///
73/// This is the default calligraphic/script style for most math fonts. See
74/// [`scr`]($math.scr) for more on how to get the other style (roundhand).
75#[func(title = "Calligraphic", keywords = ["mathcal", "chancery"])]
76pub fn cal(
77    /// The content to style.
78    body: Content,
79) -> Content {
80    body.set(EquationElem::variant, Some(MathVariant::Chancery))
81}
82
83/// Script (roundhand) font style in math.
84///
85/// ```example
86/// $ scr(S) $
87/// ```
88///
89/// There are two ways that fonts can support differentiating `cal` and `scr`.
90/// The first is using Unicode variation sequences. This works out of the box
91/// in Typst, however only a few math fonts currently support this.
92///
93/// The other way is using [font features]($text.features). For example, the
94/// roundhand style might be available in a font through the
95/// _[stylistic set]($text.stylistic-set) 1_ (`ss01`) feature. To use it in
96/// Typst, you could then define your own version of `scr` like this:
97///
98/// ```example
99/// #let scr(it) = text(
100///   stylistic-set: 1,
101///   $cal(it)$,
102/// )
103///
104/// We establish $cal(P) != scr(P)$.
105/// ```
106#[func(title = "Script Style", keywords = ["mathscr", "roundhand"])]
107pub fn scr(
108    /// The content to style.
109    body: Content,
110) -> Content {
111    body.set(EquationElem::variant, Some(MathVariant::Roundhand))
112}
113
114/// Fraktur font style in math.
115///
116/// ```example
117/// $ frak(P) $
118/// ```
119#[func(title = "Fraktur", keywords = ["mathfrak"])]
120pub fn frak(
121    /// The content to style.
122    body: Content,
123) -> Content {
124    body.set(EquationElem::variant, Some(MathVariant::Fraktur))
125}
126
127/// Monospace font style in math.
128///
129/// ```example
130/// $ mono(x + y = z) $
131/// ```
132#[func(title = "Monospace", keywords = ["mathtt"])]
133pub fn mono(
134    /// The content to style.
135    body: Content,
136) -> Content {
137    body.set(EquationElem::variant, Some(MathVariant::Monospace))
138}
139
140/// Blackboard bold (double-struck) font style in math.
141///
142/// For uppercase latin letters, blackboard bold is additionally available
143/// through [symbols]($category/symbols/sym) of the form `NN` and `RR`.
144///
145/// ```example
146/// $ bb(b) $
147/// $ bb(N) = NN $
148/// $ f: NN -> RR $
149/// ```
150#[func(title = "Blackboard Bold", keywords = ["mathbb"])]
151pub fn bb(
152    /// The content to style.
153    body: Content,
154) -> Content {
155    body.set(EquationElem::variant, Some(MathVariant::DoubleStruck))
156}
157
158/// Forced display style in math.
159///
160/// This is the normal size for block equations.
161///
162/// ```example
163/// $sum_i x_i/2 = display(sum_i x_i/2)$
164/// ```
165#[func(title = "Display Size", keywords = ["displaystyle"])]
166pub fn display(
167    /// The content to size.
168    body: Content,
169    /// Whether to impose a height restriction for exponents, like regular sub-
170    /// and superscripts do.
171    #[named]
172    #[default(false)]
173    cramped: bool,
174) -> Content {
175    body.set(EquationElem::size, MathSize::Display)
176        .set(EquationElem::cramped, cramped)
177}
178
179/// Forced inline (text) style in math.
180///
181/// This is the normal size for inline equations.
182///
183/// ```example
184/// $ sum_i x_i/2
185///     = inline(sum_i x_i/2) $
186/// ```
187#[func(title = "Inline Size", keywords = ["textstyle"])]
188pub fn inline(
189    /// The content to size.
190    body: Content,
191    /// Whether to impose a height restriction for exponents, like regular sub-
192    /// and superscripts do.
193    #[named]
194    #[default(false)]
195    cramped: bool,
196) -> Content {
197    body.set(EquationElem::size, MathSize::Text)
198        .set(EquationElem::cramped, cramped)
199}
200
201/// Forced script style in math.
202///
203/// This is the smaller size used in powers or sub- or superscripts.
204///
205/// ```example
206/// $sum_i x_i/2 = script(sum_i x_i/2)$
207/// ```
208#[func(title = "Script Size", keywords = ["scriptstyle"])]
209pub fn script(
210    /// The content to size.
211    body: Content,
212    /// Whether to impose a height restriction for exponents, like regular sub-
213    /// and superscripts do.
214    #[named]
215    #[default(true)]
216    cramped: bool,
217) -> Content {
218    body.set(EquationElem::size, MathSize::Script)
219        .set(EquationElem::cramped, cramped)
220}
221
222/// Forced second script style in math.
223///
224/// This is the smallest size, used in second-level sub- and superscripts
225/// (script of the script).
226///
227/// ```example
228/// $sum_i x_i/2 = sscript(sum_i x_i/2)$
229/// ```
230#[func(title = "Script-Script Size", keywords = ["scriptscriptstyle"])]
231pub fn sscript(
232    /// The content to size.
233    body: Content,
234    /// Whether to impose a height restriction for exponents, like regular sub-
235    /// and superscripts do.
236    #[named]
237    #[default(true)]
238    cramped: bool,
239) -> Content {
240    body.set(EquationElem::size, MathSize::ScriptScript)
241        .set(EquationElem::cramped, cramped)
242}
243
244/// The size of elements in an equation.
245///
246/// See the TeXbook p. 141.
247#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Cast)]
248pub enum MathSize {
249    /// Second-level sub- and superscripts.
250    ScriptScript,
251    /// Sub- and superscripts.
252    Script,
253    /// Math in text.
254    Text,
255    /// Math on its own line.
256    Display,
257}