summaryrefslogtreecommitdiff
path: root/crates/typst-library/src/math
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-09-11 14:40:22 +0200
committerLaurenz <laurmaedje@gmail.com>2023-09-11 14:40:22 +0200
commitb471ac7d590abd2398ce25193b4e4df373bf2e9c (patch)
treeb5f7a6fdc807ee3340a4f42b0ad3cc563fe45429 /crates/typst-library/src/math
parent8f36fca68447a5d42a3d54b5fac7e5546ee244be (diff)
First-class types
Makes types first-class values.
Diffstat (limited to 'crates/typst-library/src/math')
-rw-r--r--crates/typst-library/src/math/accent.rs7
-rw-r--r--crates/typst-library/src/math/align.rs5
-rw-r--r--crates/typst-library/src/math/attach.rs35
-rw-r--r--crates/typst-library/src/math/cancel.rs26
-rw-r--r--crates/typst-library/src/math/class.rs7
-rw-r--r--crates/typst-library/src/math/frac.rs20
-rw-r--r--crates/typst-library/src/math/lr.rs (renamed from crates/typst-library/src/math/delimited.rs)32
-rw-r--r--crates/typst-library/src/math/matrix.rs47
-rw-r--r--crates/typst-library/src/math/mod.rs130
-rw-r--r--crates/typst-library/src/math/op.rs9
-rw-r--r--crates/typst-library/src/math/root.rs16
-rw-r--r--crates/typst-library/src/math/row.rs71
-rw-r--r--crates/typst-library/src/math/style.rs73
-rw-r--r--crates/typst-library/src/math/underover.rs44
14 files changed, 167 insertions, 355 deletions
diff --git a/crates/typst-library/src/math/accent.rs b/crates/typst-library/src/math/accent.rs
index d1bee198..c92f9585 100644
--- a/crates/typst-library/src/math/accent.rs
+++ b/crates/typst-library/src/math/accent.rs
@@ -5,16 +5,13 @@ const ACCENT_SHORT_FALL: Em = Em::new(0.5);
/// Attaches an accent to a base.
///
-/// ## Example { #example }
+/// # Example
/// ```example
/// $grave(a) = accent(a, `)$ \
/// $arrow(a) = accent(a, arrow)$ \
/// $tilde(a) = accent(a, \u{0303})$
/// ```
-///
-/// Display: Accent
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct AccentElem {
/// The base to which the accent is applied.
/// May consist of multiple letters.
diff --git a/crates/typst-library/src/math/align.rs b/crates/typst-library/src/math/align.rs
index aee89a89..bf81597c 100644
--- a/crates/typst-library/src/math/align.rs
+++ b/crates/typst-library/src/math/align.rs
@@ -1,10 +1,7 @@
use super::*;
/// A math alignment point: `&`, `&&`.
-///
-/// Display: Alignment Point
-/// Category: math
-#[element(LayoutMath)]
+#[elem(title = "Alignment Point", LayoutMath)]
pub struct AlignPointElem {}
impl LayoutMath for AlignPointElem {
diff --git a/crates/typst-library/src/math/attach.rs b/crates/typst-library/src/math/attach.rs
index d74beafe..c33b58e4 100644
--- a/crates/typst-library/src/math/attach.rs
+++ b/crates/typst-library/src/math/attach.rs
@@ -2,26 +2,13 @@ use super::*;
/// A base with optional attachments.
///
-/// ## Example { #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+3, bl: 4+5, br: 6,
/// ) $
/// ```
-///
-/// ## Syntax { #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)]
+#[elem(LayoutMath)]
pub struct AttachElem {
/// The base to which things are attached.
#[required]
@@ -86,19 +73,15 @@ impl LayoutMath for AttachElem {
/// Grouped primes.
///
-/// ## Example { #example }
/// ```example
/// $ a'''_b = a^'''_b $
/// ```
///
-/// ## Syntax
+/// # Syntax
/// This function has dedicated syntax: use apostrophes instead of primes. They
/// will automatically attach to the previous element, moving superscripts to
/// the next level.
-///
-/// Display: Attachment
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct PrimesElem {
/// The number of grouped primes.
#[required]
@@ -141,14 +124,10 @@ impl LayoutMath for PrimesElem {
/// Forces a base to display attachments as scripts.
///
-/// ## Example { #example }
/// ```example
/// $ scripts(sum)_1^2 != sum_1^2 $
/// ```
-///
-/// Display: Scripts
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct ScriptsElem {
/// The base to attach the scripts to.
#[required]
@@ -167,14 +146,10 @@ impl LayoutMath for ScriptsElem {
/// Forces a base to display attachments as limits.
///
-/// ## Example { #example }
/// ```example
/// $ limits(A)_1^2 != A_1^2 $
/// ```
-///
-/// Display: Limits
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct LimitsElem {
/// The base to attach the limits to.
#[required]
diff --git a/crates/typst-library/src/math/cancel.rs b/crates/typst-library/src/math/cancel.rs
index f576a727..d27031b9 100644
--- a/crates/typst-library/src/math/cancel.rs
+++ b/crates/typst-library/src/math/cancel.rs
@@ -4,17 +4,14 @@ use super::*;
///
/// This is commonly used to show the elimination of a term.
///
-/// ## Example { #example }
+/// # Example
/// ```example
/// >>> #set page(width: 140pt)
/// Here, we can simplify:
/// $ (a dot b dot cancel(x)) /
/// cancel(x) $
/// ```
-///
-/// Display: Cancel
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct CancelElem {
/// The content over which the line should be placed.
#[required]
@@ -53,8 +50,8 @@ pub struct CancelElem {
#[default(false)]
pub cross: bool,
- /// How to rotate the cancel line. See the [line's
- /// documentation]($func/line.angle) for more details.
+ /// How to rotate the cancel line. See the
+ /// [line's documentation]($line.angle) for more details.
///
/// ```example
/// >>> #set page(width: 140pt)
@@ -63,8 +60,7 @@ pub struct CancelElem {
#[default(Angle::zero())]
pub rotation: Angle,
- /// How to stroke the cancel line. See the
- /// [line's documentation]($func/line.stroke) for more details.
+ /// How to [stroke]($stroke) the cancel line.
///
/// ```example
/// >>> #set page(width: 140pt)
@@ -79,12 +75,12 @@ pub struct CancelElem {
/// ```
#[resolve]
#[fold]
- #[default(PartialStroke {
+ #[default(Stroke {
// Default stroke has 0.5pt for better visuals.
thickness: Smart::Custom(Abs::pt(0.5)),
..Default::default()
})]
- pub stroke: PartialStroke,
+ pub stroke: Stroke,
}
impl LayoutMath for CancelElem {
@@ -99,7 +95,7 @@ impl LayoutMath for CancelElem {
let span = self.span();
let length = self.length(styles).resolve(styles);
- let stroke = self.stroke(styles).unwrap_or(Stroke {
+ let stroke = self.stroke(styles).unwrap_or(FixedStroke {
paint: TextElem::fill_in(styles),
..Default::default()
});
@@ -139,7 +135,7 @@ impl LayoutMath for CancelElem {
/// Draws a cancel line.
fn draw_cancel_line(
length: Rel<Abs>,
- stroke: Stroke,
+ stroke: FixedStroke,
invert: bool,
angle: Angle,
body_size: Size,
@@ -172,8 +168,8 @@ fn draw_cancel_line(
// (-width / 2, height / 2) with length components (width, -height) (sign is
// inverted in the y-axis). After applying the scale, the line will have the
// correct length and orientation (inverted if needed).
- let start = Axes::new(-mid.x, mid.y).zip(scales).map(|(l, s)| l * s);
- let delta = Axes::new(width, -height).zip(scales).map(|(l, s)| l * s);
+ let start = Axes::new(-mid.x, mid.y).zip_map(scales, |l, s| l * s);
+ let delta = Axes::new(width, -height).zip_map(scales, |l, s| l * s);
let mut frame = Frame::new(body_size);
frame.push(
diff --git a/crates/typst-library/src/math/class.rs b/crates/typst-library/src/math/class.rs
index 69635c62..fc8a6c79 100644
--- a/crates/typst-library/src/math/class.rs
+++ b/crates/typst-library/src/math/class.rs
@@ -5,7 +5,7 @@ use super::*;
/// This is useful to treat certain symbols as if they were of a different
/// class, e.g. to make a symbol behave like a relation.
///
-/// ## Example { #example }
+/// # Example
/// ```example
/// #let loves = math.class(
/// "relation",
@@ -14,10 +14,7 @@ use super::*;
///
/// $x loves y and y loves 5$
/// ```
-///
-/// Display: Class
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct ClassElem {
/// The class to apply to the content.
#[required]
diff --git a/crates/typst-library/src/math/frac.rs b/crates/typst-library/src/math/frac.rs
index cf1d38e9..6a296203 100644
--- a/crates/typst-library/src/math/frac.rs
+++ b/crates/typst-library/src/math/frac.rs
@@ -4,21 +4,18 @@ const FRAC_AROUND: Em = Em::new(0.1);
/// A mathematical fraction.
///
-/// ## Example { #example }
+/// # Example
/// ```example
/// $ 1/2 < (x+1)/2 $
/// $ ((x+1)) / 2 = frac(a, b) $
/// ```
///
-/// ## Syntax { #syntax }
+/// # Syntax
/// This function also has dedicated syntax: Use a slash to turn neighbouring
/// expressions into a fraction. Multiple atoms can be grouped into a single
/// expression using round grouping parenthesis. Such parentheses are removed
/// from the output, but you can nest multiple to force them.
-///
-/// Display: Fraction
-/// Category: math
-#[element(LayoutMath)]
+#[elem(title = "Fraction", LayoutMath)]
pub struct FracElem {
/// The fraction's numerator.
#[required]
@@ -38,14 +35,11 @@ impl LayoutMath for FracElem {
/// A binomial expression.
///
-/// ## Example { #example }
+/// # Example
/// ```example
/// $ binom(n, k) $
/// ```
-///
-/// Display: Binomial
-/// Category: math
-#[element(LayoutMath)]
+#[elem(title = "Binomial", LayoutMath)]
pub struct BinomElem {
/// The binomial's upper index.
#[required]
@@ -135,10 +129,10 @@ fn layout(
frame.push(
line_pos,
FrameItem::Shape(
- Geometry::Line(Point::with_x(line_width)).stroked(Stroke {
+ Geometry::Line(Point::with_x(line_width)).stroked(FixedStroke {
paint: TextElem::fill_in(ctx.styles()),
thickness,
- ..Stroke::default()
+ ..FixedStroke::default()
}),
span,
),
diff --git a/crates/typst-library/src/math/delimited.rs b/crates/typst-library/src/math/lr.rs
index 25ecf623..0d3c855e 100644
--- a/crates/typst-library/src/math/delimited.rs
+++ b/crates/typst-library/src/math/lr.rs
@@ -7,16 +7,7 @@ pub(super) const DELIM_SHORT_FALL: Em = Em::new(0.1);
///
/// While matched delimiters scale by default, this can be used to scale
/// unmatched delimiters and to control the delimiter scaling more precisely.
-///
-/// ## Example { #example }
-/// ```example
-/// $ lr(]a, b/2]) $
-/// $ lr(]sum_(x=1)^n] x, size: #50%) $
-/// ```
-///
-/// Display: Left/Right
-/// Category: math
-#[element(LayoutMath)]
+#[elem(title = "Left/Right", LayoutMath)]
pub struct LrElem {
/// The size of the brackets, relative to the height of the wrapped content.
pub size: Smart<Rel<Length>>,
@@ -107,13 +98,9 @@ fn scale(
/// Floors an expression.
///
-/// ## Example { #example }
/// ```example
/// $ floor(x/2) $
/// ```
-///
-/// Display: Floor
-/// Category: math
#[func]
pub fn floor(
/// The expression to floor.
@@ -124,13 +111,9 @@ pub fn floor(
/// Ceils an expression.
///
-/// ## Example { #example }
/// ```example
/// $ ceil(x/2) $
/// ```
-///
-/// Display: Ceil
-/// Category: math
#[func]
pub fn ceil(
/// The expression to ceil.
@@ -141,13 +124,9 @@ pub fn ceil(
/// Rounds an expression.
///
-/// ## Example { #example }
/// ```example
/// $ round(x/2) $
/// ```
-///
-/// Display: Round
-/// Category: math
#[func]
pub fn round(
/// The expression to round.
@@ -158,14 +137,9 @@ pub fn round(
/// Takes the absolute value of an expression.
///
-/// ## Example { #example }
/// ```example
/// $ abs(x/2) $
/// ```
-///
-///
-/// Display: Abs
-/// Category: math
#[func]
pub fn abs(
/// The expression to take the absolute value of.
@@ -176,13 +150,9 @@ pub fn abs(
/// Takes the norm of an expression.
///
-/// ## Example { #example }
/// ```example
/// $ norm(x/2) $
/// ```
-///
-/// Display: Norm
-/// Category: math
#[func]
pub fn norm(
/// The expression to take the norm of.
diff --git a/crates/typst-library/src/math/matrix.rs b/crates/typst-library/src/math/matrix.rs
index c913592d..abb0da35 100644
--- a/crates/typst-library/src/math/matrix.rs
+++ b/crates/typst-library/src/math/matrix.rs
@@ -12,15 +12,12 @@ const DEFAULT_STROKE_THICKNESS: Em = Em::new(0.05);
///
/// Content in the vector's elements can be aligned with the `&` symbol.
///
-/// ## Example { #example }
+/// # Example
/// ```example
/// $ vec(a, b, c) dot vec(1, 2, 3)
/// = a + 2b + 3c $
/// ```
-///
-/// Display: Vector
-/// Category: math
-#[element(LayoutMath)]
+#[elem(title = "Vector", LayoutMath)]
pub struct VecElem {
/// The delimiter to use.
///
@@ -40,7 +37,7 @@ impl LayoutMath for VecElem {
#[tracing::instrument(skip(ctx))]
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
let delim = self.delim(ctx.styles());
- let frame = layout_vec_body(ctx, &self.children(), Align::Center)?;
+ let frame = layout_vec_body(ctx, &self.children(), FixedAlign::Center)?;
layout_delimiters(
ctx,
frame,
@@ -61,7 +58,7 @@ impl LayoutMath for VecElem {
///
/// Content in cells that are in the same row can be aligned with the `&` symbol.
///
-/// ## Example { #example }
+/// # Example
/// ```example
/// $ mat(
/// 1, 2, ..., 10;
@@ -70,10 +67,7 @@ impl LayoutMath for VecElem {
/// 10, 10, ..., 10;
/// ) $
/// ```
-///
-/// Display: Matrix
-/// Category: math
-#[element(LayoutMath)]
+#[elem(title = "Matrix", LayoutMath)]
pub struct MatElem {
/// The delimiter to use.
///
@@ -102,10 +96,8 @@ pub struct MatElem {
/// drawn after the second column of the matrix. Accepts either an
/// integer for a single line, or an array of integers
/// for multiple lines.
- /// - `stroke`: How to stroke the line. See the
- /// [line's documentation]($func/line.stroke)
- /// for more details. If set to `{auto}`, takes on a thickness of
- /// 0.05em and square line caps.
+ /// - `stroke`: How to [stroke]($stroke) the line. If set to `{auto}`,
+ /// takes on a thickness of 0.05em and square line caps.
///
/// ```example
/// $ mat(1, 0, 1; 0, 1, 2; augment: #2) $
@@ -204,7 +196,7 @@ impl LayoutMath for MatElem {
///
/// Content across different branches can be aligned with the `&` symbol.
///
-/// ## Example { #example }
+/// # Example
/// ```example
/// $ f(x, y) := cases(
/// 1 "if" (x dot y)/2 <= 0,
@@ -213,10 +205,7 @@ impl LayoutMath for MatElem {
/// 4 "else",
/// ) $
/// ```
-///
-/// Display: Cases
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct CasesElem {
/// The delimiter to use.
///
@@ -236,7 +225,7 @@ impl LayoutMath for CasesElem {
#[tracing::instrument(skip(ctx))]
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
let delim = self.delim(ctx.styles());
- let frame = layout_vec_body(ctx, &self.children(), Align::Left)?;
+ let frame = layout_vec_body(ctx, &self.children(), FixedAlign::Start)?;
layout_delimiters(ctx, frame, Some(delim.open()), None, self.span())
}
}
@@ -289,7 +278,7 @@ impl Delimiter {
fn layout_vec_body(
ctx: &mut MathContext,
column: &[Content],
- align: Align,
+ align: FixedAlign,
) -> SourceResult<Frame> {
let gap = ROW_GAP.scaled(ctx);
ctx.style(ctx.style.for_denominator());
@@ -319,7 +308,7 @@ fn layout_mat_body(
// look correct by default at all matrix sizes.
// The line cap is also set to square because it looks more "correct".
let default_stroke_thickness = DEFAULT_STROKE_THICKNESS.scaled(ctx);
- let default_stroke = Stroke {
+ let default_stroke = FixedStroke {
thickness: default_stroke_thickness,
line_cap: LineCap::Square,
..Default::default()
@@ -383,7 +372,7 @@ fn layout_mat_body(
let mut y = Abs::zero();
for (cell, &(ascent, descent)) in col.into_iter().zip(&heights) {
- let cell = cell.into_aligned_frame(ctx, &points, Align::Center);
+ let cell = cell.into_aligned_frame(ctx, &points, FixedAlign::Center);
let pos = Point::new(
if points.is_empty() { x + (rcol - cell.width()) / 2.0 } else { x },
y + ascent - cell.ascent(),
@@ -429,7 +418,7 @@ fn layout_mat_body(
Ok(frame)
}
-fn line_item(length: Abs, vertical: bool, stroke: Stroke, span: Span) -> FrameItem {
+fn line_item(length: Abs, vertical: bool, stroke: FixedStroke, span: Span) -> FrameItem {
let line_geom = if vertical {
Geometry::Line(Point::with_y(length))
} else {
@@ -482,14 +471,14 @@ fn layout_delimiters(
/// Parameters specifying how augmentation lines
/// should be drawn on a matrix.
#[derive(Default, Clone, Hash)]
-pub struct Augment<T = Length> {
+pub struct Augment<T: Numeric = Length> {
pub hline: Offsets,
pub vline: Offsets,
- pub stroke: Smart<PartialStroke<T>>,
+ pub stroke: Smart<Stroke<T>>,
}
impl Augment<Abs> {
- fn stroke_or(&self, fallback: Stroke) -> Stroke {
+ fn stroke_or(&self, fallback: FixedStroke) -> FixedStroke {
match &self.stroke {
Smart::Custom(v) => v.clone().unwrap_or(fallback),
_ => fallback,
@@ -543,7 +532,7 @@ cast! {
let vline = dict.take("vline").ok().map(Offsets::from_value)
.transpose().unwrap_or_default().unwrap_or_default();
- let stroke = dict.take("stroke").ok().map(PartialStroke::from_value)
+ let stroke = dict.take("stroke").ok().map(Stroke::from_value)
.transpose()?.map(Smart::Custom).unwrap_or(Smart::Auto);
Augment { hline, vline, stroke }
diff --git a/crates/typst-library/src/math/mod.rs b/crates/typst-library/src/math/mod.rs
index 5d32af64..578064ba 100644
--- a/crates/typst-library/src/math/mod.rs
+++ b/crates/typst-library/src/math/mod.rs
@@ -7,9 +7,9 @@ mod align;
mod attach;
mod cancel;
mod class;
-mod delimited;
mod frac;
mod fragment;
+mod lr;
mod matrix;
mod op;
mod root;
@@ -24,8 +24,8 @@ pub use self::align::*;
pub use self::attach::*;
pub use self::cancel::*;
pub use self::class::*;
-pub use self::delimited::*;
pub use self::frac::*;
+pub use self::lr::*;
pub use self::matrix::*;
pub use self::op::*;
pub use self::root::*;
@@ -57,79 +57,64 @@ use crate::text::{
/// Create a module with all math definitions.
pub fn module() -> Module {
let mut math = Scope::deduplicating();
- math.define("equation", EquationElem::func());
- math.define("text", TextElem::func());
-
- // Grouping.
- math.define("lr", LrElem::func());
- math.define("abs", abs_func());
- math.define("norm", norm_func());
- math.define("floor", floor_func());
- math.define("ceil", ceil_func());
- math.define("round", round_func());
-
- // Attachments and accents.
- math.define("attach", AttachElem::func());
- math.define("scripts", ScriptsElem::func());
- math.define("limits", LimitsElem::func());
- math.define("accent", AccentElem::func());
- math.define("underline", UnderlineElem::func());
- math.define("overline", OverlineElem::func());
- math.define("underbrace", UnderbraceElem::func());
- math.define("overbrace", OverbraceElem::func());
- math.define("underbracket", UnderbracketElem::func());
- math.define("overbracket", OverbracketElem::func());
- math.define("cancel", CancelElem::func());
-
- // Fractions and matrix-likes.
- math.define("frac", FracElem::func());
- math.define("binom", BinomElem::func());
- math.define("vec", VecElem::func());
- math.define("mat", MatElem::func());
- math.define("cases", CasesElem::func());
-
- // Roots.
- math.define("sqrt", sqrt_func());
- math.define("root", RootElem::func());
-
- // Styles.
- math.define("upright", upright_func());
- math.define("bold", bold_func());
- math.define("italic", italic_func());
- math.define("serif", serif_func());
- math.define("sans", sans_func());
- math.define("cal", cal_func());
- math.define("frak", frak_func());
- math.define("mono", mono_func());
- math.define("bb", bb_func());
-
- math.define("display", display_func());
- math.define("inline", inline_func());
- math.define("script", script_func());
- math.define("sscript", sscript_func());
-
- math.define("class", ClassElem::func());
-
- // Text operators.
- math.define("op", OpElem::func());
+ math.category("math");
+ math.define_elem::<EquationElem>();
+ math.define_elem::<TextElem>();
+ math.define_elem::<LrElem>();
+ math.define_elem::<AttachElem>();
+ math.define_elem::<ScriptsElem>();
+ math.define_elem::<LimitsElem>();
+ math.define_elem::<AccentElem>();
+ math.define_elem::<UnderlineElem>();
+ math.define_elem::<OverlineElem>();
+ math.define_elem::<UnderbraceElem>();
+ math.define_elem::<OverbraceElem>();
+ math.define_elem::<UnderbracketElem>();
+ math.define_elem::<OverbracketElem>();
+ math.define_elem::<CancelElem>();
+ math.define_elem::<FracElem>();
+ math.define_elem::<BinomElem>();
+ math.define_elem::<VecElem>();
+ math.define_elem::<MatElem>();
+ math.define_elem::<CasesElem>();
+ math.define_elem::<RootElem>();
+ math.define_elem::<ClassElem>();
+ math.define_elem::<OpElem>();
+ math.define_func::<abs>();
+ math.define_func::<norm>();
+ math.define_func::<floor>();
+ math.define_func::<ceil>();
+ math.define_func::<round>();
+ math.define_func::<sqrt>();
+ math.define_func::<upright>();
+ math.define_func::<bold>();
+ math.define_func::<italic>();
+ math.define_func::<serif>();
+ math.define_func::<sans>();
+ math.define_func::<cal>();
+ math.define_func::<frak>();
+ math.define_func::<mono>();
+ math.define_func::<bb>();
+ math.define_func::<display>();
+ math.define_func::<inline>();
+ math.define_func::<script>();
+ math.define_func::<sscript>();
+
+ // Text operators, spacings, and symbols.
op::define(&mut math);
-
- // Spacings.
spacing::define(&mut math);
-
- // Symbols.
for (name, symbol) in crate::symbols::SYM {
math.define(*name, symbol.clone());
}
- Module::new("math").with_scope(math)
+ Module::new("math", math)
}
/// A mathematical equation.
///
/// Can be displayed inline with text or as a separate block.
///
-/// ## Example { #example }
+/// # Example
/// ```example
/// #set text(font: "New Computer Modern")
///
@@ -142,16 +127,13 @@ pub fn module() -> Module {
/// $ sum_(k=1)^n k = (n(n+1)) / 2 $
/// ```
///
-/// ## Syntax { #syntax }
+/// # Syntax
/// This function also has dedicated syntax: Write mathematical markup within
/// dollar signs to create an equation. Starting and ending the equation with at
/// least one space lifts it into a separate block that is centered
/// horizontally. For more details about math syntax, see the
/// [main math page]($category/math).
-///
-/// Display: Equation
-/// Category: math
-#[element(
+#[elem(
Locatable, Synthesize, Show, Finalize, Layout, LayoutMath, Count, LocalName, Refable,
Outlinable
)]
@@ -160,7 +142,7 @@ pub struct EquationElem {
#[default(false)]
pub block: bool,
- /// How to [number]($func/numbering) block-level equations.
+ /// How to [number]($numbering) block-level equations.
///
/// ```example
/// #set math.equation(numbering: "(1)")
@@ -216,9 +198,9 @@ impl Synthesize for EquationElem {
impl Show for EquationElem {
#[tracing::instrument(name = "EquationElem::show", skip_all)]
fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- let mut realized = self.clone().pack().guarded(Guard::Base(Self::func()));
+ let mut realized = self.clone().pack().guarded(Guard::Base(Self::elem()));
if self.block(styles) {
- realized = realized.aligned(Axes::with_x(Some(Align::Center.into())))
+ realized = realized.aligned(Align::CENTER);
}
Ok(realized)
}
@@ -264,7 +246,7 @@ impl Layout for EquationElem {
if block {
if let Some(numbering) = self.numbering(styles) {
let pod = Regions::one(regions.base(), Axes::splat(false));
- let counter = Counter::of(Self::func())
+ let counter = Counter::of(Self::elem())
.display(Some(numbering), false)
.layout(vt, styles, pod)?
.into_frame();
@@ -277,7 +259,7 @@ impl Layout for EquationElem {
};
let height = frame.height().max(counter.height());
- frame.resize(Size::new(width, height), Align::CENTER_HORIZON);
+ frame.resize(Size::new(width, height), Axes::splat(FixedAlign::Center));
let x = if TextElem::dir_in(styles).is_positive() {
frame.width() - counter.width()
@@ -358,7 +340,7 @@ impl Refable for EquationElem {
}
fn counter(&self) -> Counter {
- Counter::of(Self::func())
+ Counter::of(Self::elem())
}
fn numbering(&self) -> Option<Numbering> {
diff --git a/crates/typst-library/src/math/op.rs b/crates/typst-library/src/math/op.rs
index 4016d24f..eed16465 100644
--- a/crates/typst-library/src/math/op.rs
+++ b/crates/typst-library/src/math/op.rs
@@ -4,23 +4,20 @@ use super::*;
/// A text operator in an equation.
///
-/// ## Example { #example }
+/// # Example
/// ```example
/// $ tan x = (sin x)/(cos x) $
/// $ op("custom",
/// limits: #true)_(n->oo) n $
/// ```
///
-/// ## Predefined Operators { #predefined }
+/// # Predefined Operators { #predefined }
/// Typst predefines the operators `arccos`, `arcsin`, `arctan`, `arg`, `cos`,
/// `cosh`, `cot`, `coth`, `csc`, `ctg`, `deg`, `det`, `dim`, `exp`, `gcd`,
/// `hom`, `id`, `im`, `inf`, `ker`, `lg`, `lim`, `liminf`, `limsup`, `ln`,
/// `log`, `max`, `min`, `mod`, `Pr`, `sec`, `sin`, `sinc`, `sinh`, `sup`,
/// `tan`, `tanh`, `tg` and `tr`.
-///
-/// Display: Text Operator
-/// Category: math
-#[element(LayoutMath)]
+#[elem(title = "Text Operator", LayoutMath)]
pub struct OpElem {
/// The operator's text.
#[required]
diff --git a/crates/typst-library/src/math/root.rs b/crates/typst-library/src/math/root.rs
index b889f1cb..03d0a212 100644
--- a/crates/typst-library/src/math/root.rs
+++ b/crates/typst-library/src/math/root.rs
@@ -2,14 +2,10 @@ use super::*;
/// A square root.
///
-/// ## Example { #example }
/// ```example
/// $ sqrt(3 - 2 sqrt(2)) = sqrt(2) - 1 $
/// ```
-///
-/// Display: Square Root
-/// Category: math
-#[func]
+#[func(title = "Square Root")]
pub fn sqrt(
/// The expression to take the square root of.
radicand: Content,
@@ -19,14 +15,10 @@ pub fn sqrt(
/// A general root.
///
-/// ## Example { #example }
/// ```example
/// $ root(3, x) $
/// ```
-///
-/// Display: Root
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct RootElem {
/// Which root of the radicand to take.
#[positional]
@@ -129,10 +121,10 @@ fn layout(
frame.push(
line_pos,
FrameItem::Shape(
- Geometry::Line(Point::with_x(radicand.width())).stroked(Stroke {
+ Geometry::Line(Point::with_x(radicand.width())).stroked(FixedStroke {
paint: TextElem::fill_in(ctx.styles()),
thickness,
- ..Stroke::default()
+ ..FixedStroke::default()
}),
span,
),
diff --git a/crates/typst-library/src/math/row.rs b/crates/typst-library/src/math/row.rs
index 687f82b8..cf3a8af2 100644
--- a/crates/typst-library/src/math/row.rs
+++ b/crates/typst-library/src/math/row.rs
@@ -121,7 +121,7 @@ impl MathRow {
pub fn into_frame(self, ctx: &MathContext) -> Frame {
let styles = ctx.styles();
- let align = AlignElem::alignment_in(styles).x.resolve(styles);
+ let align = AlignElem::alignment_in(styles).resolve(styles).x;
self.into_aligned_frame(ctx, &[], align)
}
@@ -137,53 +137,54 @@ impl MathRow {
self,
ctx: &MathContext,
points: &[Abs],
- align: Align,
+ align: FixedAlign,
) -> Frame {
- if self.iter().any(|frag| matches!(frag, MathFragment::Linebreak)) {
- let leading = if ctx.style.size >= MathSize::Text {
- ParElem::leading_in(ctx.styles())
- } else {
- TIGHT_LEADING.scaled(ctx)
- };
+ if !self.iter().any(|frag| matches!(frag, MathFragment::Linebreak)) {
+ return self.into_line_frame(points, align);
+ }
- let mut rows: Vec<_> = self.rows();
+ let leading = if ctx.style.size >= MathSize::Text {
+ ParElem::leading_in(ctx.styles())
+ } else {
+ TIGHT_LEADING.scaled(ctx)
+ };
- if matches!(rows.last(), Some(row) if row.0.is_empty()) {
- rows.pop();
- }
+ let mut rows: Vec<_> = self.rows();
- let AlignmentResult { points, width } = alignments(&rows);
- let mut frame = Frame::new(Size::zero());
+ if matches!(rows.last(), Some(row) if row.0.is_empty()) {
+ rows.pop();
+ }
- for (i, row) in rows.into_iter().enumerate() {
- let sub = row.into_line_frame(&points, align);
- let size = frame.size_mut();
- if i > 0 {
- size.y += leading;
- }
+ let AlignmentResult { points, width } = alignments(&rows);
+ let mut frame = Frame::new(Size::zero());
- let mut pos = Point::with_y(size.y);
- if points.is_empty() {
- pos.x = align.position(width - sub.width());
- }
- size.y += sub.height();
- size.x.set_max(sub.width());
- frame.push_frame(pos, sub);
+ for (i, row) in rows.into_iter().enumerate() {
+ let sub = row.into_line_frame(&points, align);
+ let size = frame.size_mut();
+ if i > 0 {
+ size.y += leading;
}
- frame
- } else {
- self.into_line_frame(points, align)
+
+ let mut pos = Point::with_y(size.y);
+ if points.is_empty() {
+ pos.x = align.position(width - sub.width());
+ }
+ size.y += sub.height();
+ size.x.set_max(sub.width());
+ frame.push_frame(pos, sub);
}
+
+ frame
}
- fn into_line_frame(self, points: &[Abs], align: Align) -> Frame {
+ fn into_line_frame(self, points: &[Abs], align: FixedAlign) -> Frame {
let ascent = self.ascent();
let mut frame = Frame::new(Size::new(Abs::zero(), ascent + self.descent()));
frame.set_baseline(ascent);
let mut next_x = {
let mut widths = Vec::new();
- if !points.is_empty() && align != Align::Left {
+ if !points.is_empty() && align != FixedAlign::Start {
let mut width = Abs::zero();
for fragment in self.iter() {
if matches!(fragment, MathFragment::Align) {
@@ -201,8 +202,10 @@ impl MathRow {
let mut point_widths = points.iter().copied().zip(widths);
let mut alternator = LeftRightAlternator::Right;
move || match align {
- Align::Left => prev_points.next(),
- Align::Right => point_widths.next().map(|(point, width)| point - width),
+ FixedAlign::Start => prev_points.next(),
+ FixedAlign::End => {
+ point_widths.next().map(|(point, width)| point - width)
+ }
_ => point_widths
.next()
.zip(prev_points.next())
diff --git a/crates/typst-library/src/math/style.rs b/crates/typst-library/src/math/style.rs
index 35a4cfdb..4d80a235 100644
--- a/crates/typst-library/src/math/style.rs
+++ b/crates/typst-library/src/math/style.rs
@@ -2,13 +2,9 @@ use super::*;
/// Bold font style in math.
///
-/// ## Example { #example }
/// ```example
/// $ bold(A) := B^+ $
/// ```
-///
-/// Display: Bold
-/// Category: math
#[func]
pub fn bold(
/// The content to style.
@@ -19,13 +15,9 @@ pub fn bold(
/// Upright (non-italic) font style in math.
///
-/// ## Example { #example }
/// ```example
/// $ upright(A) != A $
/// ```
-///
-/// Display: Upright
-/// Category: math
#[func]
pub fn upright(
/// The content to style.
@@ -37,9 +29,6 @@ pub fn upright(
/// Italic font style in math.
///
/// For roman letters and greek lowercase letters, this is already the default.
-///
-/// Display: Italic
-/// Category: math
#[func]
pub fn italic(
/// The content to style.
@@ -50,9 +39,6 @@ pub fn italic(
/// Serif (roman) font style in math.
///
/// This is already the default.
-///
-/// Display: Serif
-/// Category: math
#[func]
pub fn serif(
/// The content to style.
@@ -63,14 +49,10 @@ pub fn serif(
/// Sans-serif font style in math.
///
-/// ## Example { #example }
/// ```example
/// $ sans(A B C) $
/// ```
-///
-/// Display: Sans-serif
-/// Category: math
-#[func]
+#[func(title = "Sans Serif")]
pub fn sans(
/// The content to style.
body: Content,
@@ -80,14 +62,10 @@ pub fn sans(
/// Calligraphic font style in math.
///
-/// ## Example { #example }
/// ```example
/// Let $cal(P)$ be the set of ...
/// ```
-///
-/// Display: Calligraphic
-/// Category: math
-#[func]
+#[func(title = "Calligraphic")]
pub fn cal(
/// The content to style.
body: Content,
@@ -97,14 +75,10 @@ pub fn cal(
/// Fraktur font style in math.
///
-/// ## Example { #example }
/// ```example
/// $ frak(P) $
/// ```
-///
-/// Display: Fraktur
-/// Category: math
-#[func]
+#[func(title = "Fraktur")]
pub fn frak(
/// The content to style.
body: Content,
@@ -114,14 +88,10 @@ pub fn frak(
/// Monospace font style in math.
///
-/// ## Example { #example }
/// ```example
/// $ mono(x + y = z) $
/// ```
-///
-/// Display: Monospace
-/// Category: math
-#[func]
+#[func(title = "Monospace")]
pub fn mono(
/// The content to style.
body: Content,
@@ -134,16 +104,12 @@ pub fn mono(
/// For uppercase latin letters, blackboard bold is additionally available
/// through [symbols]($category/symbols/sym) of the form `NN` and `RR`.
///
-/// ## Example { #example }
/// ```example
/// $ bb(b) $
/// $ bb(N) = NN $
/// $ f: NN -> RR $
/// ```
-///
-/// Display: Blackboard Bold
-/// Category: math
-#[func]
+#[func(title = "Blackboard Bold")]
pub fn bb(
/// The content to style.
body: Content,
@@ -155,14 +121,10 @@ pub fn bb(
///
/// This is the normal size for block equations.
///
-/// ## Example { #example }
/// ```example
/// $sum_i x_i/2 = display(sum_i x_i/2)$
/// ```
-///
-/// Display: Display Size
-/// Category: math
-#[func]
+#[func(title = "Display Size")]
pub fn display(
/// The content to size.
body: Content,
@@ -182,15 +144,11 @@ pub fn display(
///
/// This is the normal size for inline equations.
///
-/// ## Example { #example }
/// ```example
/// $ sum_i x_i/2
/// = inline(sum_i x_i/2) $
/// ```
-///
-/// Display: Inline Size
-/// Category: math
-#[func]
+#[func(title = "Inline Size")]
pub fn inline(
/// The content to size.
body: Content,
@@ -210,14 +168,10 @@ pub fn inline(
///
/// This is the smaller size used in powers or sub- or superscripts.
///
-/// ## Example { #example }
/// ```example
/// $sum_i x_i/2 = script(sum_i x_i/2)$
/// ```
-///
-/// Display: Script Size
-/// Category: math
-#[func]
+#[func(title = "Script Size")]
pub fn script(
/// The content to size.
body: Content,
@@ -238,14 +192,10 @@ pub fn script(
/// This is the smallest size, used in second-level sub- and superscripts
/// (script of the script).
///
-/// ## Example { #example }
/// ```example
/// $sum_i x_i/2 = sscript(sum_i x_i/2)$
/// ```
-///
-/// Display: Script-Script Size
-/// Category: math
-#[func]
+#[func(title = "Script-Script Size")]
pub fn sscript(
/// The content to size.
body: Content,
@@ -262,10 +212,7 @@ pub fn sscript(
}
/// A font variant in math.
-///
-/// Display: Bold
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct MathStyleElem {
/// The content to style.
#[required]
diff --git a/crates/typst-library/src/math/underover.rs b/crates/typst-library/src/math/underover.rs
index 796c9ebc..3e8dba1a 100644
--- a/crates/typst-library/src/math/underover.rs
+++ b/crates/typst-library/src/math/underover.rs
@@ -11,14 +11,10 @@ enum LineKind {
/// A horizontal line under content.
///
-/// ## Example { #example }
/// ```example
/// $ underline(1 + 2 + ... + 5) $
/// ```
-///
-/// Display: Underline
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct UnderlineElem {
/// The content above the line.
#[required]
@@ -34,14 +30,10 @@ impl LayoutMath for UnderlineElem {
/// A horizontal line over content.
///
-/// ## Example { #example }
/// ```example
/// $ overline(1 + 2 + ... + 5) $
/// ```
-///
-/// Display: Overline
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct OverlineElem {
/// The content below the line.
#[required]
@@ -103,10 +95,10 @@ fn layout_underoverline(
frame.push(
line_pos,
FrameItem::Shape(
- Geometry::Line(Point::with_x(width)).stroked(Stroke {
+ Geometry::Line(Point::with_x(width)).stroked(FixedStroke {
paint: TextElem::fill_in(ctx.styles()),
thickness: bar_height,
- ..Stroke::default()
+ ..FixedStroke::default()
}),
span,
),
@@ -119,14 +111,10 @@ fn layout_underoverline(
/// A horizontal brace under content, with an optional annotation below.
///
-/// ## Example { #example }
/// ```example
/// $ underbrace(1 + 2 + ... + 5, "numbers") $
/// ```
-///
-/// Display: Underbrace
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct UnderbraceElem {
/// The content above the brace.
#[required]
@@ -154,14 +142,10 @@ impl LayoutMath for UnderbraceElem {
/// A horizontal brace over content, with an optional annotation above.
///
-/// ## Example { #example }
/// ```example
/// $ overbrace(1 + 2 + ... + 5, "numbers") $
/// ```
-///
-/// Display: Overbrace
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct OverbraceElem {
/// The content below the brace.
#[required]
@@ -189,14 +173,10 @@ impl LayoutMath for OverbraceElem {
/// A horizontal bracket under content, with an optional annotation below.
///
-/// ## Example { #example }
/// ```example
/// $ underbracket(1 + 2 + ... + 5, "numbers") $
/// ```
-///
-/// Display: Underbracket
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct UnderbracketElem {
/// The content above the bracket.
#[required]
@@ -224,14 +204,10 @@ impl LayoutMath for UnderbracketElem {
/// A horizontal bracket over content, with an optional annotation above.
///
-/// ## Example { #example }
/// ```example
/// $ overbracket(1 + 2 + ... + 5, "numbers") $
/// ```
-///
-/// Display: Overbracket
-/// Category: math
-#[element(LayoutMath)]
+#[elem(LayoutMath)]
pub struct OverbracketElem {
/// The content below the bracket.
#[required]
@@ -294,7 +270,7 @@ fn layout_underoverspreader(
baseline = rows.len() - 1;
}
- let frame = stack(ctx, rows, Align::Center, gap, baseline);
+ let frame = stack(ctx, rows, FixedAlign::Center, gap, baseline);
ctx.push(FrameFragment::new(ctx, frame).with_class(body_class));
Ok(())
@@ -307,7 +283,7 @@ fn layout_underoverspreader(
pub(super) fn stack(
ctx: &MathContext,
rows: Vec<MathRow>,
- align: Align,
+ align: FixedAlign,
gap: Abs,
baseline: usize,
) -> Frame {