summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock2
-rw-r--r--crates/typst-library/src/foundations/mod.rs10
-rw-r--r--crates/typst-library/src/foundations/scope.rs46
-rw-r--r--crates/typst-library/src/foundations/target.rs46
-rw-r--r--crates/typst-library/src/html/mod.rs50
-rw-r--r--crates/typst-library/src/introspection/mod.rs18
-rw-r--r--crates/typst-library/src/layout/mod.rs11
-rw-r--r--crates/typst-library/src/lib.rs52
-rw-r--r--crates/typst-library/src/loading/cbor.rs3
-rw-r--r--crates/typst-library/src/loading/csv.rs3
-rw-r--r--crates/typst-library/src/loading/json.rs3
-rw-r--r--crates/typst-library/src/loading/mod.rs12
-rw-r--r--crates/typst-library/src/loading/toml.rs3
-rw-r--r--crates/typst-library/src/loading/xml.rs3
-rw-r--r--crates/typst-library/src/loading/yaml.rs3
-rw-r--r--crates/typst-library/src/math/mod.rs113
-rw-r--r--crates/typst-library/src/model/mod.rs13
-rw-r--r--crates/typst-library/src/pdf/mod.rs19
-rw-r--r--crates/typst-library/src/symbols.rs13
-rw-r--r--crates/typst-library/src/text/mod.rs15
-rw-r--r--crates/typst-library/src/visualize/image/mod.rs25
-rw-r--r--crates/typst-library/src/visualize/mod.rs13
-rw-r--r--crates/typst-library/src/visualize/path.rs3
-rw-r--r--crates/typst-macros/src/category.rs59
-rw-r--r--crates/typst-macros/src/lib.rs10
-rw-r--r--docs/Cargo.toml4
-rw-r--r--docs/guides/guide-for-latex-users.md7
-rw-r--r--docs/reference/export/html.md61
-rw-r--r--docs/reference/export/pdf.md71
-rw-r--r--docs/reference/export/png.md61
-rw-r--r--docs/reference/export/svg.md48
-rw-r--r--docs/reference/language/context.md (renamed from docs/reference/context.md)0
-rw-r--r--docs/reference/language/scripting.md (renamed from docs/reference/scripting.md)0
-rw-r--r--docs/reference/language/styling.md (renamed from docs/reference/styling.md)0
-rw-r--r--docs/reference/language/syntax.md (renamed from docs/reference/syntax.md)0
-rw-r--r--docs/reference/library/data-loading.md4
-rw-r--r--docs/reference/library/foundations.md4
-rw-r--r--docs/reference/library/introspection.md10
-rw-r--r--docs/reference/library/layout.md3
-rw-r--r--docs/reference/library/math.md101
-rw-r--r--docs/reference/library/model.md5
-rw-r--r--docs/reference/library/symbols.md5
-rw-r--r--docs/reference/library/text.md3
-rw-r--r--docs/reference/library/visualize.md5
-rw-r--r--docs/reference/packages.md6
-rw-r--r--docs/src/html.rs13
-rw-r--r--docs/src/lib.rs184
-rw-r--r--docs/src/link.rs9
-rw-r--r--docs/src/model.rs5
49 files changed, 709 insertions, 448 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e5daf731..140dccf7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2822,6 +2822,8 @@ dependencies = [
"typst-assets",
"typst-dev-assets",
"typst-render",
+ "typst-utils",
+ "unicode-math-class",
"unscanny",
"yaml-front-matter",
]
diff --git a/crates/typst-library/src/foundations/mod.rs b/crates/typst-library/src/foundations/mod.rs
index c335484f..8e3aa060 100644
--- a/crates/typst-library/src/foundations/mod.rs
+++ b/crates/typst-library/src/foundations/mod.rs
@@ -85,16 +85,9 @@ use crate::engine::Engine;
use crate::routines::EvalMode;
use crate::{Feature, Features};
-/// Foundational types and functions.
-///
-/// Here, you'll find documentation for basic data types like [integers]($int)
-/// and [strings]($str) as well as details about core computational functions.
-#[category]
-pub static FOUNDATIONS: Category;
-
/// Hook up all `foundations` definitions.
pub(super) fn define(global: &mut Scope, inputs: Dict, features: &Features) {
- global.start_category(FOUNDATIONS);
+ global.start_category(crate::Category::Foundations);
global.define_type::<bool>();
global.define_type::<i64>();
global.define_type::<f64>();
@@ -125,6 +118,7 @@ pub(super) fn define(global: &mut Scope, inputs: Dict, features: &Features) {
}
global.define("calc", calc::module());
global.define("sys", sys::module(inputs));
+ global.reset_category();
}
/// Fails with an error.
diff --git a/crates/typst-library/src/foundations/scope.rs b/crates/typst-library/src/foundations/scope.rs
index d6c5a8d0..e1ce61b8 100644
--- a/crates/typst-library/src/foundations/scope.rs
+++ b/crates/typst-library/src/foundations/scope.rs
@@ -1,6 +1,3 @@
-#[doc(inline)]
-pub use typst_macros::category;
-
use std::fmt::{self, Debug, Formatter};
use std::hash::{Hash, Hasher};
@@ -8,14 +5,13 @@ use ecow::{eco_format, EcoString};
use indexmap::map::Entry;
use indexmap::IndexMap;
use typst_syntax::Span;
-use typst_utils::Static;
use crate::diag::{bail, DeprecationSink, HintedStrResult, HintedString, StrResult};
use crate::foundations::{
Element, Func, IntoValue, NativeElement, NativeFunc, NativeFuncData, NativeType,
Type, Value,
};
-use crate::Library;
+use crate::{Category, Library};
/// A stack of scopes.
#[derive(Debug, Default, Clone)]
@@ -361,46 +357,6 @@ pub enum Capturer {
Context,
}
-/// A group of related definitions.
-#[derive(Copy, Clone, Eq, PartialEq, Hash)]
-pub struct Category(Static<CategoryData>);
-
-impl Category {
- /// Create a new category from raw data.
- pub const fn from_data(data: &'static CategoryData) -> Self {
- Self(Static(data))
- }
-
- /// The category's name.
- pub fn name(&self) -> &'static str {
- self.0.name
- }
-
- /// The type's title case name, for use in documentation (e.g. `String`).
- pub fn title(&self) -> &'static str {
- self.0.title
- }
-
- /// Documentation for the category.
- pub fn docs(&self) -> &'static str {
- self.0.docs
- }
-}
-
-impl Debug for Category {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "Category({})", self.name())
- }
-}
-
-/// Defines a category.
-#[derive(Debug)]
-pub struct CategoryData {
- pub name: &'static str,
- pub title: &'static str,
- pub docs: &'static str,
-}
-
/// The error message when trying to mutate a variable from the standard
/// library.
#[cold]
diff --git a/crates/typst-library/src/foundations/target.rs b/crates/typst-library/src/foundations/target.rs
index 5841552e..2a21fd42 100644
--- a/crates/typst-library/src/foundations/target.rs
+++ b/crates/typst-library/src/foundations/target.rs
@@ -3,7 +3,7 @@ use comemo::Tracked;
use crate::diag::HintedStrResult;
use crate::foundations::{elem, func, Cast, Context};
-/// The compilation target.
+/// The export target.
#[derive(Debug, Default, Copy, Clone, PartialEq, Hash, Cast)]
pub enum Target {
/// The target that is used for paged, fully laid-out content.
@@ -28,7 +28,49 @@ pub struct TargetElem {
pub target: Target,
}
-/// Returns the current compilation target.
+/// Returns the current export target.
+///
+/// This function returns either
+/// - `{"paged"}` (for PDF, PNG, and SVG export), or
+/// - `{"html"}` (for HTML export).
+///
+/// The design of this function is not yet finalized and for this reason it is
+/// guarded behind the `html` feature. Visit the [HTML documentation
+/// page]($html) for more details.
+///
+/// # When to use it
+/// This function allows you to format your document properly across both HTML
+/// and paged export targets. It should primarily be used in templates and show
+/// rules, rather than directly in content. This way, the document's contents
+/// can be fully agnostic to the export target and content can be shared between
+/// PDF and HTML export.
+///
+/// # Varying targets
+/// This function is [contextual]($context) as the target can vary within a
+/// single compilation: When exporting to HTML, the target will be `{"paged"}`
+/// while within an [`html.frame`].
+///
+/// # Example
+/// ```example
+/// #let kbd(it) = context {
+/// if target() == "html" {
+/// html.elem("kbd", it)
+/// } else {
+/// set text(fill: rgb("#1f2328"))
+/// let r = 3pt
+/// box(
+/// fill: rgb("#f6f8fa"),
+/// stroke: rgb("#d1d9e0b3"),
+/// outset: (y: r),
+/// inset: (x: r),
+/// radius: r,
+/// raw(it)
+/// )
+/// }
+/// }
+///
+/// Press #kbd("F1") for help.
+/// ```
#[func(contextual)]
pub fn target(context: Tracked<Context>) -> HintedStrResult<Target> {
Ok(TargetElem::target_in(context.styles()?))
diff --git a/crates/typst-library/src/html/mod.rs b/crates/typst-library/src/html/mod.rs
index c412b460..1d88781c 100644
--- a/crates/typst-library/src/html/mod.rs
+++ b/crates/typst-library/src/html/mod.rs
@@ -6,53 +6,77 @@ pub use self::dom::*;
use ecow::EcoString;
-use crate::foundations::{category, elem, Category, Content, Module, Scope};
-
-/// HTML output.
-#[category]
-pub static HTML: Category;
+use crate::foundations::{elem, Content, Module, Scope};
/// Create a module with all HTML definitions.
pub fn module() -> Module {
let mut html = Scope::deduplicating();
- html.start_category(HTML);
+ html.start_category(crate::Category::Html);
html.define_elem::<HtmlElem>();
html.define_elem::<FrameElem>();
Module::new("html", html)
}
-/// A HTML element that can contain Typst content.
+/// An HTML element that can contain Typst content.
+///
+/// Typst's HTML export automatically generates the appropriate tags for most
+/// elements. However, sometimes, it is desirable to retain more control. For
+/// example, when using Typst to generate your blog, you could use this function
+/// to wrap each article in an `<article>` tag.
+///
+/// Typst is aware of what is valid HTML. A tag and its attributes must form
+/// syntactically valid HTML. Some tags, like `meta` do not accept content.
+/// Hence, you must not provide a body for them. We may add more checks in the
+/// future, so be sure that you are generating valid HTML when using this
+/// function.
+///
+/// Normally, Typst will generate `html`, `head`, and `body` tags for you. If
+/// you instead create them with this function, Typst will omit its own tags.
+///
+/// ```typ
+/// #html.elem("div", attrs: (style: "background: aqua"))[
+/// A div with _Typst content_ inside!
+/// ]
+/// ```
#[elem(name = "elem")]
pub struct HtmlElem {
/// The element's tag.
#[required]
pub tag: HtmlTag,
- /// The element's attributes.
+ /// The element's HTML attributes.
#[borrowed]
pub attrs: HtmlAttrs,
/// The contents of the HTML element.
+ ///
+ /// The body can be arbitrary Typst content.
#[positional]
#[borrowed]
pub body: Option<Content>,
}
impl HtmlElem {
- /// Add an atribute to the element.
+ /// Add an attribute to the element.
pub fn with_attr(mut self, attr: HtmlAttr, value: impl Into<EcoString>) -> Self {
self.attrs.get_or_insert_with(Default::default).push(attr, value);
self
}
}
-/// An element that forces its contents to be laid out.
+/// An element that lays out its content as an inline SVG.
+///
+/// Sometimes, converting Typst content to HTML is not desirable. This can be
+/// the case for plots and other content that relies on positioning and styling
+/// to convey its message.
///
-/// Integrates content that requires layout (e.g. a plot) into HTML output
-/// by turning it into an inline SVG.
+/// This function allows you to use the Typst layout engine that would also be
+/// used for PDF, SVG, and PNG export to render a part of your document exactly
+/// how it would appear when exported in one of these formats. It embeds the
+/// content as an inline SVG.
#[elem]
pub struct FrameElem {
- /// The contents that shall be laid out.
+ /// The content that shall be laid out.
#[positional]
#[required]
pub body: Content,
diff --git a/crates/typst-library/src/introspection/mod.rs b/crates/typst-library/src/introspection/mod.rs
index d8184330..995fbd7b 100644
--- a/crates/typst-library/src/introspection/mod.rs
+++ b/crates/typst-library/src/introspection/mod.rs
@@ -25,24 +25,11 @@ pub use self::query_::*;
pub use self::state::*;
pub use self::tag::*;
-use crate::foundations::{category, Category, Scope};
-
-/// Interactions between document parts.
-///
-/// This category is home to Typst's introspection capabilities: With the
-/// `counter` function, you can access and manipulate page, section, figure, and
-/// equation counters or create custom ones. Meanwhile, the `query` function
-/// lets you search for elements in the document to construct things like a list
-/// of figures or headers which show the current chapter title.
-///
-/// Most of the functions are _contextual._ It is recommended to read the chapter
-/// on [context] before continuing here.
-#[category]
-pub static INTROSPECTION: Category;
+use crate::foundations::Scope;
/// Hook up all `introspection` definitions.
pub fn define(global: &mut Scope) {
- global.start_category(INTROSPECTION);
+ global.start_category(crate::Category::Introspection);
global.define_type::<Location>();
global.define_type::<Counter>();
global.define_type::<State>();
@@ -50,4 +37,5 @@ pub fn define(global: &mut Scope) {
global.define_func::<here>();
global.define_func::<query>();
global.define_func::<locate>();
+ global.reset_category();
}
diff --git a/crates/typst-library/src/layout/mod.rs b/crates/typst-library/src/layout/mod.rs
index 57518fe7..ef1ecdb3 100644
--- a/crates/typst-library/src/layout/mod.rs
+++ b/crates/typst-library/src/layout/mod.rs
@@ -64,17 +64,11 @@ pub use self::spacing::*;
pub use self::stack::*;
pub use self::transform::*;
-use crate::foundations::{category, Category, Scope};
-
-/// Arranging elements on the page in different ways.
-///
-/// By combining layout functions, you can create complex and automatic layouts.
-#[category]
-pub static LAYOUT: Category;
+use crate::foundations::Scope;
/// Hook up all `layout` definitions.
pub fn define(global: &mut Scope) {
- global.start_category(LAYOUT);
+ global.start_category(crate::Category::Layout);
global.define_type::<Length>();
global.define_type::<Angle>();
global.define_type::<Ratio>();
@@ -103,4 +97,5 @@ pub fn define(global: &mut Scope) {
global.define_elem::<HideElem>();
global.define_func::<measure>();
global.define_func::<layout>();
+ global.reset_category();
}
diff --git a/crates/typst-library/src/lib.rs b/crates/typst-library/src/lib.rs
index 460321aa..c39024f7 100644
--- a/crates/typst-library/src/lib.rs
+++ b/crates/typst-library/src/lib.rs
@@ -29,6 +29,7 @@ pub mod visualize;
use std::ops::{Deref, Range};
+use serde::{Deserialize, Serialize};
use typst_syntax::{FileId, Source, Span};
use typst_utils::{LazyHash, SmallBitSet};
@@ -236,31 +237,72 @@ pub enum Feature {
Html,
}
+/// A group of related standard library definitions.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum Category {
+ Foundations,
+ Introspection,
+ Layout,
+ DataLoading,
+ Math,
+ Model,
+ Symbols,
+ Text,
+ Visualize,
+ Pdf,
+ Html,
+ Svg,
+ Png,
+}
+
+impl Category {
+ /// The kebab-case name of the category.
+ pub fn name(&self) -> &'static str {
+ match self {
+ Self::Foundations => "foundations",
+ Self::Introspection => "introspection",
+ Self::Layout => "layout",
+ Self::DataLoading => "data-loading",
+ Self::Math => "math",
+ Self::Model => "model",
+ Self::Symbols => "symbols",
+ Self::Text => "text",
+ Self::Visualize => "visualize",
+ Self::Pdf => "pdf",
+ Self::Html => "html",
+ Self::Svg => "svg",
+ Self::Png => "png",
+ }
+ }
+}
+
/// Construct the module with global definitions.
fn global(math: Module, inputs: Dict, features: &Features) -> Module {
let mut global = Scope::deduplicating();
+
self::foundations::define(&mut global, inputs, features);
self::model::define(&mut global);
self::text::define(&mut global);
- global.reset_category();
- global.define("math", math);
self::layout::define(&mut global);
self::visualize::define(&mut global);
self::introspection::define(&mut global);
self::loading::define(&mut global);
self::symbols::define(&mut global);
- self::pdf::define(&mut global);
- global.reset_category();
+
+ global.define("math", math);
+ global.define("pdf", self::pdf::module());
if features.is_enabled(Feature::Html) {
global.define("html", self::html::module());
}
+
prelude(&mut global);
+
Module::new("global", global)
}
/// Defines scoped values that are globally available, too.
fn prelude(global: &mut Scope) {
- global.reset_category();
global.define("black", Color::BLACK);
global.define("gray", Color::GRAY);
global.define("silver", Color::SILVER);
diff --git a/crates/typst-library/src/loading/cbor.rs b/crates/typst-library/src/loading/cbor.rs
index bd65e844..801ca617 100644
--- a/crates/typst-library/src/loading/cbor.rs
+++ b/crates/typst-library/src/loading/cbor.rs
@@ -34,9 +34,6 @@ pub fn cbor(
#[scope]
impl cbor {
/// Reads structured data from CBOR bytes.
- ///
- /// This function is deprecated. The [`cbor`] function now accepts bytes
- /// directly.
#[func(title = "Decode CBOR")]
#[deprecated = "`cbor.decode` is deprecated, directly pass bytes to `cbor` instead"]
pub fn decode(
diff --git a/crates/typst-library/src/loading/csv.rs b/crates/typst-library/src/loading/csv.rs
index d01d687b..6fdec445 100644
--- a/crates/typst-library/src/loading/csv.rs
+++ b/crates/typst-library/src/loading/csv.rs
@@ -96,9 +96,6 @@ pub fn csv(
#[scope]
impl csv {
/// Reads structured data from a CSV string/bytes.
- ///
- /// This function is deprecated. The [`csv`] function now accepts bytes
- /// directly.
#[func(title = "Decode CSV")]
#[deprecated = "`csv.decode` is deprecated, directly pass bytes to `csv` instead"]
pub fn decode(
diff --git a/crates/typst-library/src/loading/json.rs b/crates/typst-library/src/loading/json.rs
index 52c87371..185bac14 100644
--- a/crates/typst-library/src/loading/json.rs
+++ b/crates/typst-library/src/loading/json.rs
@@ -65,9 +65,6 @@ pub fn json(
#[scope]
impl json {
/// Reads structured data from a JSON string/bytes.
- ///
- /// This function is deprecated. The [`json`] function now accepts bytes
- /// directly.
#[func(title = "Decode JSON")]
#[deprecated = "`json.decode` is deprecated, directly pass bytes to `json` instead"]
pub fn decode(
diff --git a/crates/typst-library/src/loading/mod.rs b/crates/typst-library/src/loading/mod.rs
index c645b691..c57e0288 100644
--- a/crates/typst-library/src/loading/mod.rs
+++ b/crates/typst-library/src/loading/mod.rs
@@ -29,19 +29,12 @@ pub use self::yaml_::*;
use crate::diag::{At, SourceResult};
use crate::foundations::OneOrMultiple;
-use crate::foundations::{cast, category, Bytes, Category, Scope, Str};
+use crate::foundations::{cast, Bytes, Scope, Str};
use crate::World;
-/// Data loading from external files.
-///
-/// These functions help you with loading and embedding data, for example from
-/// the results of an experiment.
-#[category]
-pub static DATA_LOADING: Category;
-
/// Hook up all `data-loading` definitions.
pub(super) fn define(global: &mut Scope) {
- global.start_category(DATA_LOADING);
+ global.start_category(crate::Category::DataLoading);
global.define_func::<read>();
global.define_func::<csv>();
global.define_func::<json>();
@@ -49,6 +42,7 @@ pub(super) fn define(global: &mut Scope) {
global.define_func::<yaml>();
global.define_func::<cbor>();
global.define_func::<xml>();
+ global.reset_category();
}
/// Something we can retrieve byte data from.
diff --git a/crates/typst-library/src/loading/toml.rs b/crates/typst-library/src/loading/toml.rs
index 45611246..2660e7e7 100644
--- a/crates/typst-library/src/loading/toml.rs
+++ b/crates/typst-library/src/loading/toml.rs
@@ -44,9 +44,6 @@ pub fn toml(
#[scope]
impl toml {
/// Reads structured data from a TOML string/bytes.
- ///
- /// This function is deprecated. The [`toml`] function now accepts bytes
- /// directly.
#[func(title = "Decode TOML")]
#[deprecated = "`toml.decode` is deprecated, directly pass bytes to `toml` instead"]
pub fn decode(
diff --git a/crates/typst-library/src/loading/xml.rs b/crates/typst-library/src/loading/xml.rs
index 0172071b..32ed6f24 100644
--- a/crates/typst-library/src/loading/xml.rs
+++ b/crates/typst-library/src/loading/xml.rs
@@ -77,9 +77,6 @@ pub fn xml(
#[scope]
impl xml {
/// Reads structured data from an XML string/bytes.
- ///
- /// This function is deprecated. The [`xml`] function now accepts bytes
- /// directly.
#[func(title = "Decode XML")]
#[deprecated = "`xml.decode` is deprecated, directly pass bytes to `xml` instead"]
pub fn decode(
diff --git a/crates/typst-library/src/loading/yaml.rs b/crates/typst-library/src/loading/yaml.rs
index 511c676c..4eeec28f 100644
--- a/crates/typst-library/src/loading/yaml.rs
+++ b/crates/typst-library/src/loading/yaml.rs
@@ -55,9 +55,6 @@ pub fn yaml(
#[scope]
impl yaml {
/// Reads structured data from a YAML string/bytes.
- ///
- /// This function is deprecated. The [`yaml`] function now accepts bytes
- /// directly.
#[func(title = "Decode YAML")]
#[deprecated = "`yaml.decode` is deprecated, directly pass bytes to `yaml` instead"]
pub fn decode(
diff --git a/crates/typst-library/src/math/mod.rs b/crates/typst-library/src/math/mod.rs
index a97a19b0..2e6d42b1 100644
--- a/crates/typst-library/src/math/mod.rs
+++ b/crates/typst-library/src/math/mod.rs
@@ -27,119 +27,10 @@ pub use self::underover::*;
use typst_utils::singleton;
use unicode_math_class::MathClass;
-use crate::foundations::{
- category, elem, Category, Content, Module, NativeElement, Scope,
-};
+use crate::foundations::{elem, Content, Module, NativeElement, Scope};
use crate::layout::{Em, HElem};
use crate::text::TextElem;
-/// Typst has special [syntax]($syntax/#math) and library functions to typeset
-/// mathematical formulas. Math formulas can be displayed inline with text or as
-/// separate blocks. They will be typeset into their own block if they start and
-/// end with at least one space (e.g. `[$ x^2 $]`).
-///
-/// # Variables
-/// In math, single letters are always displayed as is. Multiple letters,
-/// however, are interpreted as variables and functions. To display multiple
-/// letters verbatim, you can place them into quotes and to access single letter
-/// variables, you can use the [hash syntax]($scripting/#expressions).
-///
-/// ```example
-/// $ A = pi r^2 $
-/// $ "area" = pi dot "radius"^2 $
-/// $ cal(A) :=
-/// { x in RR | x "is natural" } $
-/// #let x = 5
-/// $ #x < 17 $
-/// ```
-///
-/// # Symbols
-/// Math mode makes a wide selection of [symbols]($category/symbols/sym) like
-/// `pi`, `dot`, or `RR` available. Many mathematical symbols are available in
-/// different variants. You can select between different variants by applying
-/// [modifiers]($symbol) to the symbol. Typst further recognizes a number of
-/// shorthand sequences like `=>` that approximate a symbol. When such a
-/// shorthand exists, the symbol's documentation lists it.
-///
-/// ```example
-/// $ x < y => x gt.eq.not y $
-/// ```
-///
-/// # Line Breaks
-/// Formulas can also contain line breaks. Each line can contain one or multiple
-/// _alignment points_ (`&`) which are then aligned.
-///
-/// ```example
-/// $ sum_(k=0)^n k
-/// &= 1 + ... + n \
-/// &= (n(n+1)) / 2 $
-/// ```
-///
-/// # Function calls
-/// Math mode supports special function calls without the hash prefix. In these
-/// "math calls", the argument list works a little differently than in code:
-///
-/// - Within them, Typst is still in "math mode". Thus, you can write math
-/// directly into them, but need to use hash syntax to pass code expressions
-/// (except for strings, which are available in the math syntax).
-/// - They support positional and named arguments, as well as argument
-/// spreading.
-/// - They don't support trailing content blocks.
-/// - They provide additional syntax for 2-dimensional argument lists. The
-/// semicolon (`;`) merges preceding arguments separated by commas into an
-/// array argument.
-///
-/// ```example
-/// $ frac(a^2, 2) $
-/// $ vec(1, 2, delim: "[") $
-/// $ mat(1, 2; 3, 4) $
-/// $ mat(..#range(1, 5).chunks(2)) $
-/// $ lim_x =
-/// op("lim", limits: #true)_x $
-/// ```
-///
-/// To write a verbatim comma or semicolon in a math call, escape it with a
-/// backslash. The colon on the other hand is only recognized in a special way
-/// if directly preceded by an identifier, so to display it verbatim in those
-/// cases, you can just insert a space before it.
-///
-/// Functions calls preceded by a hash are normal code function calls and not
-/// affected by these rules.
-///
-/// # Alignment
-/// When equations include multiple _alignment points_ (`&`), this creates
-/// blocks of alternatingly right- and left-aligned columns. In the example
-/// below, the expression `(3x + y) / 7` is right-aligned and `= 9` is
-/// left-aligned. The word "given" is also left-aligned because `&&` creates two
-/// alignment points in a row, alternating the alignment twice. `& &` and `&&`
-/// behave exactly the same way. Meanwhile, "multiply by 7" is right-aligned
-/// because just one `&` precedes it. Each alignment point simply alternates
-/// between right-aligned/left-aligned.
-///
-/// ```example
-/// $ (3x + y) / 7 &= 9 && "given" \
-/// 3x + y &= 63 & "multiply by 7" \
-/// 3x &= 63 - y && "subtract y" \
-/// x &= 21 - y/3 & "divide by 3" $
-/// ```
-///
-/// # Math fonts
-/// You can set the math font by with a [show-set rule]($styling/#show-rules) as
-/// demonstrated below. Note that only special OpenType math fonts are suitable
-/// for typesetting maths.
-///
-/// ```example
-/// #show math.equation: set text(font: "Fira Math")
-/// $ sum_(i in NN) 1 + i $
-/// ```
-///
-/// # Math module
-/// All math functions are part of the `math` [module]($scripting/#modules),
-/// which is available by default in equations. Outside of equations, they can
-/// be accessed with the `math.` prefix.
-#[category]
-pub static MATH: Category;
-
// Spacings.
pub const THIN: Em = Em::new(1.0 / 6.0);
pub const MEDIUM: Em = Em::new(2.0 / 9.0);
@@ -150,7 +41,7 @@ pub const WIDE: Em = Em::new(2.0);
/// Create a module with all math definitions.
pub fn module() -> Module {
let mut math = Scope::deduplicating();
- math.start_category(MATH);
+ math.start_category(crate::Category::Math);
math.define_elem::<EquationElem>();
math.define_elem::<TextElem>();
math.define_elem::<LrElem>();
diff --git a/crates/typst-library/src/model/mod.rs b/crates/typst-library/src/model/mod.rs
index 586e10ec..9bdbf001 100644
--- a/crates/typst-library/src/model/mod.rs
+++ b/crates/typst-library/src/model/mod.rs
@@ -40,19 +40,11 @@ pub use self::strong::*;
pub use self::table::*;
pub use self::terms::*;
-use crate::foundations::{category, Category, Scope};
-
-/// Document structuring.
-///
-/// Here, you can find functions to structure your document and interact with
-/// that structure. This includes section headings, figures, bibliography
-/// management, cross-referencing and more.
-#[category]
-pub static MODEL: Category;
+use crate::foundations::Scope;
/// Hook up all `model` definitions.
pub fn define(global: &mut Scope) {
- global.start_category(MODEL);
+ global.start_category(crate::Category::Model);
global.define_elem::<DocumentElem>();
global.define_elem::<RefElem>();
global.define_elem::<LinkElem>();
@@ -72,4 +64,5 @@ pub fn define(global: &mut Scope) {
global.define_elem::<EmphElem>();
global.define_elem::<StrongElem>();
global.define_func::<numbering>();
+ global.reset_category();
}
diff --git a/crates/typst-library/src/pdf/mod.rs b/crates/typst-library/src/pdf/mod.rs
index 3bd3b0c5..786a3637 100644
--- a/crates/typst-library/src/pdf/mod.rs
+++ b/crates/typst-library/src/pdf/mod.rs
@@ -4,21 +4,12 @@ mod embed;
pub use self::embed::*;
-use crate::foundations::{category, Category, Module, Scope};
-
-/// PDF-specific functionality.
-#[category]
-pub static PDF: Category;
-
-/// Hook up the `pdf` module.
-pub(super) fn define(global: &mut Scope) {
- global.start_category(PDF);
- global.define("pdf", module());
-}
+use crate::foundations::{Module, Scope};
/// Hook up all `pdf` definitions.
pub fn module() -> Module {
- let mut scope = Scope::deduplicating();
- scope.define_elem::<EmbedElem>();
- Module::new("pdf", scope)
+ let mut pdf = Scope::deduplicating();
+ pdf.start_category(crate::Category::Pdf);
+ pdf.define_elem::<EmbedElem>();
+ Module::new("pdf", pdf)
}
diff --git a/crates/typst-library/src/symbols.rs b/crates/typst-library/src/symbols.rs
index 777f8172..0588ace9 100644
--- a/crates/typst-library/src/symbols.rs
+++ b/crates/typst-library/src/symbols.rs
@@ -1,19 +1,12 @@
//! Modifiable symbols.
-use crate::foundations::{category, Category, Module, Scope, Symbol, Value};
-
-/// These two modules give names to symbols and emoji to make them easy to
-/// insert with a normal keyboard. Alternatively, you can also always directly
-/// enter Unicode symbols into your text and formulas. In addition to the
-/// symbols listed below, math mode defines `dif` and `Dif`. These are not
-/// normal symbol values because they also affect spacing and font style.
-#[category]
-pub static SYMBOLS: Category;
+use crate::foundations::{Module, Scope, Symbol, Value};
/// Hook up all `symbol` definitions.
pub(super) fn define(global: &mut Scope) {
- global.start_category(SYMBOLS);
+ global.start_category(crate::Category::Symbols);
extend_scope_from_codex_module(global, codex::ROOT);
+ global.reset_category();
}
/// Hook up all math `symbol` definitions, i.e., elements of the `sym` module.
diff --git a/crates/typst-library/src/text/mod.rs b/crates/typst-library/src/text/mod.rs
index f506397e..12f4e4c5 100644
--- a/crates/typst-library/src/text/mod.rs
+++ b/crates/typst-library/src/text/mod.rs
@@ -45,9 +45,9 @@ use typst_utils::singleton;
use crate::diag::{bail, warning, HintedStrResult, SourceResult};
use crate::engine::Engine;
use crate::foundations::{
- cast, category, dict, elem, Args, Array, Cast, Category, Construct, Content, Dict,
- Fold, IntoValue, NativeElement, Never, NoneValue, Packed, PlainText, Regex, Repr,
- Resolve, Scope, Set, Smart, StyleChain,
+ cast, dict, elem, Args, Array, Cast, Construct, Content, Dict, Fold, IntoValue,
+ NativeElement, Never, NoneValue, Packed, PlainText, Regex, Repr, Resolve, Scope, Set,
+ Smart, StyleChain,
};
use crate::layout::{Abs, Axis, Dir, Em, Length, Ratio, Rel};
use crate::math::{EquationElem, MathSize};
@@ -55,15 +55,9 @@ use crate::model::ParElem;
use crate::visualize::{Color, Paint, RelativeTo, Stroke};
use crate::World;
-/// Text styling.
-///
-/// The [text function]($text) is of particular interest.
-#[category]
-pub static TEXT: Category;
-
/// Hook up all `text` definitions.
pub(super) fn define(global: &mut Scope) {
- global.start_category(TEXT);
+ global.start_category(crate::Category::Text);
global.define_elem::<TextElem>();
global.define_elem::<LinebreakElem>();
global.define_elem::<SmartQuoteElem>();
@@ -78,6 +72,7 @@ pub(super) fn define(global: &mut Scope) {
global.define_func::<lower>();
global.define_func::<upper>();
global.define_func::<lorem>();
+ global.reset_category();
}
/// Customizes the look and layout of text in a variety of ways.
diff --git a/crates/typst-library/src/visualize/image/mod.rs b/crates/typst-library/src/visualize/image/mod.rs
index 9306eb6f..18d40caa 100644
--- a/crates/typst-library/src/visualize/image/mod.rs
+++ b/crates/typst-library/src/visualize/image/mod.rs
@@ -50,6 +50,17 @@ pub struct ImageElem {
/// supported [formats]($image.format).
///
/// For more details about paths, see the [Paths section]($syntax/#paths).
+ ///
+ /// ```example
+ /// #let original = read("diagram.svg")
+ /// #let changed = original.replace(
+ /// "#2B80FF", // blue
+ /// green.to-hex(),
+ /// )
+ ///
+ /// #image(bytes(original))
+ /// #image(bytes(changed))
+ /// ```
#[required]
#[parse(
let source = args.expect::<Spanned<DataSource>>("source")?;
@@ -156,20 +167,6 @@ pub struct ImageElem {
#[allow(clippy::too_many_arguments)]
impl ImageElem {
/// Decode a raster or vector graphic from bytes or a string.
- ///
- /// This function is deprecated. The [`image`] function now accepts bytes
- /// directly.
- ///
- /// ```example
- /// #let original = read("diagram.svg")
- /// #let changed = original.replace(
- /// "#2B80FF", // blue
- /// green.to-hex(),
- /// )
- ///
- /// #image.decode(original)
- /// #image.decode(changed)
- /// ```
#[func(title = "Decode Image")]
#[deprecated = "`image.decode` is deprecated, directly pass bytes to `image` instead"]
pub fn decode(
diff --git a/crates/typst-library/src/visualize/mod.rs b/crates/typst-library/src/visualize/mod.rs
index 76849ac8..72a42065 100644
--- a/crates/typst-library/src/visualize/mod.rs
+++ b/crates/typst-library/src/visualize/mod.rs
@@ -24,19 +24,11 @@ pub use self::shape::*;
pub use self::stroke::*;
pub use self::tiling::*;
-use crate::foundations::{category, Category, Element, Scope, Type};
-
-/// Drawing and data visualization.
-///
-/// If you want to create more advanced drawings or plots, also have a look at
-/// the [CetZ](https://github.com/johannes-wolf/cetz) package as well as more
-/// specialized [packages]($universe) for your use case.
-#[category]
-pub static VISUALIZE: Category;
+use crate::foundations::{Element, Scope, Type};
/// Hook up all visualize definitions.
pub(super) fn define(global: &mut Scope) {
- global.start_category(VISUALIZE);
+ global.start_category(crate::Category::Visualize);
global.define_type::<Color>();
global.define_type::<Gradient>();
global.define_type::<Tiling>();
@@ -55,4 +47,5 @@ pub(super) fn define(global: &mut Scope) {
global
.define("pattern", Type::of::<Tiling>())
.deprecated("the name `pattern` is deprecated, use `tiling` instead");
+ global.reset_category();
}
diff --git a/crates/typst-library/src/visualize/path.rs b/crates/typst-library/src/visualize/path.rs
index 5d3439c0..c1cfde94 100644
--- a/crates/typst-library/src/visualize/path.rs
+++ b/crates/typst-library/src/visualize/path.rs
@@ -21,9 +21,6 @@ use crate::visualize::{FillRule, Paint, Stroke};
/// ((50%, 0pt), (40pt, 0pt)),
/// )
/// ```
-///
-/// # Deprecation
-/// This function is deprecated. The [`curve`] function should be used instead.
#[elem(Show)]
pub struct PathElem {
/// How to fill the path.
diff --git a/crates/typst-macros/src/category.rs b/crates/typst-macros/src/category.rs
deleted file mode 100644
index 26ec879c..00000000
--- a/crates/typst-macros/src/category.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-use heck::{ToKebabCase, ToTitleCase};
-use proc_macro2::TokenStream;
-use quote::quote;
-use syn::parse::{Parse, ParseStream};
-use syn::{Attribute, Ident, Result, Token, Type, Visibility};
-
-use crate::util::{documentation, foundations};
-
-/// Expand the `#[category]` macro.
-pub fn category(_: TokenStream, item: syn::Item) -> Result<TokenStream> {
- let syn::Item::Verbatim(stream) = item else {
- bail!(item, "expected bare static");
- };
-
- let BareStatic { attrs, vis, ident, ty, .. } = syn::parse2(stream)?;
-
- let name = ident.to_string().to_kebab_case();
- let title = name.to_title_case();
- let docs = documentation(&attrs);
-
- Ok(quote! {
- #(#attrs)*
- #[allow(rustdoc::broken_intra_doc_links)]
- #vis static #ident: #ty = {
- static DATA: #foundations::CategoryData = #foundations::CategoryData {
- name: #name,
- title: #title,
- docs: #docs,
- };
- #foundations::Category::from_data(&DATA)
- };
- })
-}
-
-/// Parse a bare `pub static CATEGORY: Category;` item.
-#[allow(dead_code)]
-pub struct BareStatic {
- pub attrs: Vec<Attribute>,
- pub vis: Visibility,
- pub static_token: Token![static],
- pub ident: Ident,
- pub colon_token: Token![:],
- pub ty: Type,
- pub semi_token: Token![;],
-}
-
-impl Parse for BareStatic {
- fn parse(input: ParseStream) -> Result<Self> {
- Ok(Self {
- attrs: input.call(Attribute::parse_outer)?,
- vis: input.parse()?,
- static_token: input.parse()?,
- ident: input.parse()?,
- colon_token: input.parse()?,
- ty: input.parse()?,
- semi_token: input.parse()?,
- })
- }
-}
diff --git a/crates/typst-macros/src/lib.rs b/crates/typst-macros/src/lib.rs
index 578389c7..82e63ddc 100644
--- a/crates/typst-macros/src/lib.rs
+++ b/crates/typst-macros/src/lib.rs
@@ -5,7 +5,6 @@ extern crate proc_macro;
#[macro_use]
mod util;
mod cast;
-mod category;
mod elem;
mod func;
mod scope;
@@ -266,15 +265,6 @@ pub fn scope(stream: BoundaryStream, item: BoundaryStream) -> BoundaryStream {
.into()
}
-/// Defines a category of definitions.
-#[proc_macro_attribute]
-pub fn category(stream: BoundaryStream, item: BoundaryStream) -> BoundaryStream {
- let item = syn::parse_macro_input!(item as syn::Item);
- category::category(stream.into(), item)
- .unwrap_or_else(|err| err.to_compile_error())
- .into()
-}
-
/// Implements `Reflect`, `FromValue`, and `IntoValue` for a type.
///
/// - `Reflect` makes Typst's runtime aware of the type's characteristics.
diff --git a/docs/Cargo.toml b/docs/Cargo.toml
index 41a5645e..acc55175 100644
--- a/docs/Cargo.toml
+++ b/docs/Cargo.toml
@@ -17,6 +17,8 @@ cli = ["clap", "typst-render", "serde_json"]
[dependencies]
typst = { workspace = true }
+typst-render = { workspace = true, optional = true }
+typst-utils = { workspace = true }
typst-assets = { workspace = true, features = ["fonts"] }
typst-dev-assets = { workspace = true }
clap = { workspace = true, optional = true }
@@ -28,7 +30,7 @@ serde_json = { workspace = true, optional = true }
serde_yaml = { workspace = true }
syntect = { workspace = true, features = ["html"] }
typed-arena = { workspace = true }
-typst-render = { workspace = true, optional = true }
+unicode-math-class = { workspace = true }
unscanny = { workspace = true }
yaml-front-matter = { workspace = true }
diff --git a/docs/guides/guide-for-latex-users.md b/docs/guides/guide-for-latex-users.md
index 743afa5a..5137ae1a 100644
--- a/docs/guides/guide-for-latex-users.md
+++ b/docs/guides/guide-for-latex-users.md
@@ -657,7 +657,8 @@ applicable, contains possible workarounds.
- **Well-established plotting ecosystem.** LaTeX users often create elaborate
charts along with their documents in PGF/TikZ. The Typst ecosystem does not
yet offer the same breadth of available options, but the ecosystem around the
- [`cetz`](https://github.com/cetz-package/cetz) package is catching up quickly.
+ [`cetz` package](https://typst.app/universe/package/cetz) is catching up
+ quickly.
- **Change page margins without a pagebreak.** In LaTeX, margins can always be
adjusted, even without a pagebreak. To change margins in Typst, you use the
@@ -670,4 +671,6 @@ applicable, contains possible workarounds.
format, but you can easily convert both into SVG files with [online
tools](https://cloudconvert.com/pdf-to-svg) or
[Inkscape](https://inkscape.org/). The web app will automatically convert PDF
- files to SVG files upon uploading them.
+ files to SVG files upon uploading them. You can also use the
+ community-provided [`muchpdf` package](https://typst.app/universe/package/muchpdf)
+ to embed PDFs. It internally converts PDFs to SVGs on-the-fly.
diff --git a/docs/reference/export/html.md b/docs/reference/export/html.md
new file mode 100644
index 00000000..330c2e13
--- /dev/null
+++ b/docs/reference/export/html.md
@@ -0,0 +1,61 @@
+<div class="info-box">
+
+Typst's HTML export is currently under active development. The feature is still
+very incomplete and only available for experimentation behind a feature flag. Do
+not use this feature for production use cases. In the CLI, you can experiment
+with HTML export by passing `--features html` or setting the `TYPST_FEATURES`
+environment variables to `html`. In the web app, HTML export is not available at
+this time. Visit the [tracking issue](https://github.com/typst/typst/issues/5512)
+to follow progress on HTML export and learn more about planned features.
+</div>
+
+HTML files describe a document structurally. The aim of Typst's HTML export is
+to capture the structure of an input document and produce semantically rich HTML
+that retains this structure. The resulting HTML should be accessible,
+human-readable, and editable by hand and downstream tools.
+
+PDF, PNG, and SVG export, in contrast, all produce _visual_ representations of a
+fully-laid out document. This divergence in the formats' intents means that
+Typst cannot simply produce perfect HTML for your existing Typst documents. It
+cannot always know what the best semantic HTML representation of your content
+is.
+
+Instead, it gives _you_ full control: You can check the current export format
+through the [`target`] function and when it is set to HTML, generate [raw HTML
+elements]($html.elem). The primary intended use of these elements is in
+templates and show rules. This way, the document's contents can be fully
+agnostic to the export target and content can be shared between PDF and HTML
+export.
+
+Currently, Typst will always output a single HTML file. Support for outputting
+directories with multiple HTML documents and assets, as well as support for
+outputting fragments that can be integrated into other HTML documents is
+planned.
+
+Typst currently does not output CSS style sheets, instead focussing on emitting
+semantic markup. You can of course write your own CSS styles and still benefit
+from sharing your _content_ between PDF and HTML. For the future, we plan to
+give you the option of automatically emitting CSS, taking more of your existing
+set rules into account.
+
+# Exporting as HTML
+## Command Line
+Pass `--format html` to the `compile` or `watch` subcommand or provide an output
+file name that ends with `.html`. Note that you must also pass `--features html`
+or set `TYPST_FEATURES=html` to enable this experimental export target.
+
+When using `typst watch`, Typst will spin up a live-reloading HTTP server. You
+can configure it as follows:
+
+- Pass `--port` to change the port. (Defaults to the first free port in the
+ range 3000-3005.)
+- Pass `--no-reload` to disable injection of a live reload script. (The HTML
+ that is written to disk isn't affected either way.)
+- Pass `--no-serve` to disable the server altogether.
+
+## Web App
+Not currently available.
+
+# HTML-specific functionality
+Typst exposes HTML-specific functionality in the global `html` module. See below
+for the definitions it contains.
diff --git a/docs/reference/export/pdf.md b/docs/reference/export/pdf.md
new file mode 100644
index 00000000..b220ae94
--- /dev/null
+++ b/docs/reference/export/pdf.md
@@ -0,0 +1,71 @@
+PDF files focus on accurately describing documents visually, but also have
+facilities for annotating their structure. This hybrid approach makes
+them a good fit for document exchange: They render exactly the same on every
+device, but also support extraction of a document's content and structure (at
+least to an extent). Unlike PNG files, PDFs are not bound to a specific
+resolution. Hence, you can view them at any size without incurring a loss of
+quality.
+
+# PDF standards
+The International Standards Organization (ISO) has published the base PDF
+standard and various standards that extend it to make PDFs more suitable for
+specific use-cases. By default, Typst exports PDF 1.7 files. Adobe Acrobat 8 and
+later as well as all other commonly used PDF viewers are compatible with this
+PDF version.
+
+## PDF/A
+Typst optionally supports emitting PDF/A-conformant files. PDF/A files are
+geared towards maximum compatibility with current and future PDF tooling. They
+do not rely on difficult-to-implement or proprietary features and contain
+exhaustive metadata. This makes them suitable for long-term archival.
+
+The PDF/A Standard has multiple versions (_parts_ in ISO terminology) and most
+parts have multiple profiles that indicate the file's conformance level.
+Currently, Typst supports these PDF/A output profiles:
+
+- PDF/A-2b: The basic conformance level of ISO 19005-2. This version of PDF/A is
+ based on PDF 1.7 and results in self-contained, archivable PDF files.
+
+- PDF/A-3b: The basic conformance level of ISO 19005-3. This version of PDF/A is
+ based on PDF 1.7 and results in archivable PDF files that can contain
+ arbitrary other related files as [attachments]($pdf.embed). The only
+ difference between it and PDF/A-2b is the capability to embed
+ non-PDF/A-conformant files within.
+
+When choosing between exporting PDF/A and regular PDF, keep in mind that PDF/A
+files contain additional metadata, and that some readers will prevent the user
+from modifying a PDF/A file. Some features of Typst may be disabled depending on
+the PDF standard you choose.
+
+# Exporting as PDF
+## Command Line
+PDF is Typst's default export format. Running the `compile` or `watch`
+subcommand without specifying a format will create a PDF. When exporting to PDF,
+you have the following configuration options:
+
+- Which PDF standards Typst should enforce conformance with by specifying
+ `--pdf-standard` followed by one or multiple comma-separated standards. Valid
+ standards are `1.7`, `a-2b`, and `a-3b`. By default, Typst outputs
+ PDF-1.7-compliant files.
+
+- Which pages to export by specifying `--pages` followed by a comma-separated
+ list of numbers or dash-separated number ranges. Ranges can be half-open.
+ Example: `2,3,7-9,11-`.
+
+## Web App
+Click the quick download button at the top right to export a PDF with default
+settings. For further configuration, click "File" > "Export as" > "PDF" or click
+the downwards-facing arrow next to the quick download button and select "Export
+as PDF". When exporting to PDF, you have the following configuration options:
+
+- Which PDF standards Typst should enforce conformance with. By default, Typst
+ outputs PDF-1.7-compliant files. Valid additional standards are `A-2b` and
+ `A-3b`.
+
+- Which pages to export. Valid options are "All pages", "Current page", and
+ "Custom ranges". Custom ranges are a comma-separated list of numbers or
+ dash-separated number ranges. Ranges can be half-open. Example: `2,3,7-9,11-`.
+
+# PDF-specific functionality
+Typst exposes PDF-specific functionality in the global `pdf` module. See below
+for the definitions it contains.
diff --git a/docs/reference/export/png.md b/docs/reference/export/png.md
new file mode 100644
index 00000000..fe122f4d
--- /dev/null
+++ b/docs/reference/export/png.md
@@ -0,0 +1,61 @@
+Instead of creating a PDF, Typst can also directly render pages to PNG raster
+graphics. PNGs are losslessly compressed images that can contain one page at a
+time. When exporting a multi-page document, Typst will emit multiple PNGs. PNGs
+are a good choice when you want to use Typst's output in an image editing
+software or when you can use none of Typst's other export formats.
+
+In contrast to Typst's other export formats, PNGs are bound to a specific
+resolution. When exporting to PNG, you can configure the resolution as pixels
+per inch (PPI). If the medium you view the PNG on has a finer resolution than
+the PNG you exported, you will notice a loss of quality. Typst calculates the
+resolution of your PNGs based on each page's physical dimensions and the PPI. If
+you need guidance for choosing a PPI value, consider the following:
+
+- A DPI value of 300 or 600 is typical for desktop printing.
+- Professional prints of detailed graphics can go up to 1200 PPI.
+- If your document is only viewed at a distance, e.g. a poster, you may choose a
+ smaller value than 300.
+- If your document is viewed on screens, a typical PPI value for a smartphone is
+ 400-500.
+
+Because PNGs only contain a pixel raster, the text within cannot be extracted
+automatically (without OCR), for example by copy/paste or a screen reader. If
+you need the text to be accessible, export a PDF or HTML file instead.
+
+PNGs can have transparent backgrounds. By default, Typst will output a PNG with
+an opaque white background. You can make the background transparent using
+`[#set page(fill: none)]`. Learn more on the
+[`page` function's reference page]($page.fill).
+
+# Exporting as PNG
+## Command Line
+Pass `--format png` to the `compile` or `watch` subcommand or provide an output
+file name that ends with `.png`.
+
+If your document has more than one page, Typst will create multiple image files.
+The output file name must then be a template string containing at least one of
+- `[{p}]`, which will be replaced by the page number
+- `[{0p}]`, which will be replaced by the zero-padded page number (so that all
+ numbers have the same length)
+- `[{t}]`, which will be replaced by the total number of pages
+
+When exporting to PNG, you have the following configuration options:
+
+- Which resolution to render at by specifying `--ppi` followed by a number of
+ pixels per inch. The default is `144`.
+
+- Which pages to export by specifying `--pages` followed by a comma-separated
+ list of numbers or dash-separated number ranges. Ranges can be half-open.
+ Example: `2,3,7-9,11-`.
+
+## Web App
+Click "File" > "Export as" > "PNG" or click the downwards-facing arrow next to
+the quick download button and select "Export as PNG". When exporting to PNG, you
+have the following configuration options:
+
+- The resolution at which the pages should be rendered, as a number of pixels
+ per inch. The default is `144`.
+
+- Which pages to export. Valid options are "All pages", "Current page", and
+ "Custom ranges". Custom ranges are a comma-separated list of numbers or
+ dash-separated number ranges. Ranges can be half-open. Example: `2,3,7-9,11-`.
diff --git a/docs/reference/export/svg.md b/docs/reference/export/svg.md
new file mode 100644
index 00000000..630ab845
--- /dev/null
+++ b/docs/reference/export/svg.md
@@ -0,0 +1,48 @@
+Instead of creating a PDF, Typst can also directly render pages to scalable
+vector graphics (SVGs), which are the preferred format for embedding vector
+graphics in web pages. Like PDF files, SVGs display your document exactly how
+you have laid it out in Typst. Likewise, they share the benefit of not being
+bound to a specific resolution. Hence, you can print or view SVG files on any
+device without incurring a loss of quality. (Note that font printing quality may
+be better with a PDF.) In contrast to a PDF, an SVG cannot contain multiple
+pages. When exporting a multi-page document, Typst will emit multiple SVGs.
+
+SVGs can represent text in two ways: By embedding the text itself and rendering
+it with the fonts available on the viewer's computer or by embedding the shapes
+of each glyph in the font used to create the document. To ensure that the SVG
+file looks the same across all devices it is viewed on, Typst chooses the latter
+method. This means that the text in the SVG cannot be extracted automatically,
+for example by copy/paste or a screen reader. If you need the text to be
+accessible, export a PDF or HTML file instead.
+
+SVGs can have transparent backgrounds. By default, Typst will output an SVG with
+an opaque white background. You can make the background transparent using
+`[#set page(fill: none)]`. Learn more on the
+[`page` function's reference page]($page.fill).
+
+# Exporting as SVG
+## Command Line
+Pass `--format svg` to the `compile` or `watch` subcommand or provide an output
+file name that ends with `.svg`.
+
+If your document has more than one page, Typst will create multiple image files.
+The output file name must then be a template string containing at least one of
+- `[{p}]`, which will be replaced by the page number
+- `[{0p}]`, which will be replaced by the zero-padded page number (so that all
+ numbers have the same length)
+- `[{t}]`, which will be replaced by the total number of pages
+
+When exporting to SVG, you have the following configuration options:
+
+- Which pages to export by specifying `--pages` followed by a comma-separated
+ list of numbers or dash-separated number ranges. Ranges can be half-open.
+ Example: `2,3,7-9,11-`.
+
+## Web App
+Click "File" > "Export as" > "SVG" or click the downwards-facing arrow next to
+the quick download button and select "Export as SVG". When exporting to SVG, you
+have the following configuration options:
+
+- Which pages to export. Valid options are "All pages", "Current page", and
+ "Custom ranges". Custom ranges are a comma-separated list of numbers or
+ dash-separated number ranges. Ranges can be half-open. Example: `2,3,7-9,11-`.
diff --git a/docs/reference/context.md b/docs/reference/language/context.md
index bdd520f5..bdd520f5 100644
--- a/docs/reference/context.md
+++ b/docs/reference/language/context.md
diff --git a/docs/reference/scripting.md b/docs/reference/language/scripting.md
index 5e0f1555..5e0f1555 100644
--- a/docs/reference/scripting.md
+++ b/docs/reference/language/scripting.md
diff --git a/docs/reference/styling.md b/docs/reference/language/styling.md
index b0b7ab71..b0b7ab71 100644
--- a/docs/reference/styling.md
+++ b/docs/reference/language/styling.md
diff --git a/docs/reference/syntax.md b/docs/reference/language/syntax.md
index fdc4d154..fdc4d154 100644
--- a/docs/reference/syntax.md
+++ b/docs/reference/language/syntax.md
diff --git a/docs/reference/library/data-loading.md b/docs/reference/library/data-loading.md
new file mode 100644
index 00000000..659a8ccc
--- /dev/null
+++ b/docs/reference/library/data-loading.md
@@ -0,0 +1,4 @@
+Data loading from external files.
+
+These functions help you with loading and embedding data, for example from the
+results of an experiment.
diff --git a/docs/reference/library/foundations.md b/docs/reference/library/foundations.md
new file mode 100644
index 00000000..738c3789
--- /dev/null
+++ b/docs/reference/library/foundations.md
@@ -0,0 +1,4 @@
+Foundational types and functions.
+
+Here, you'll find documentation for basic data types like [integers]($int) and
+[strings]($str) as well as details about core computational functions.
diff --git a/docs/reference/library/introspection.md b/docs/reference/library/introspection.md
new file mode 100644
index 00000000..f48a9937
--- /dev/null
+++ b/docs/reference/library/introspection.md
@@ -0,0 +1,10 @@
+Interactions between document parts.
+
+This category is home to Typst's introspection capabilities: With the `counter`
+function, you can access and manipulate page, section, figure, and equation
+counters or create custom ones. Meanwhile, the `query` function lets you search
+for elements in the document to construct things like a list of figures or
+headers which show the current chapter title.
+
+Most of the functions are _contextual._ It is recommended to read the chapter on
+[context] before continuing here.
diff --git a/docs/reference/library/layout.md b/docs/reference/library/layout.md
new file mode 100644
index 00000000..450058d4
--- /dev/null
+++ b/docs/reference/library/layout.md
@@ -0,0 +1,3 @@
+Arranging elements on the page in different ways.
+
+By combining layout functions, you can create complex and automatic layouts.
diff --git a/docs/reference/library/math.md b/docs/reference/library/math.md
new file mode 100644
index 00000000..61f2bb58
--- /dev/null
+++ b/docs/reference/library/math.md
@@ -0,0 +1,101 @@
+Typst has special [syntax]($syntax/#math) and library functions to typeset
+mathematical formulas. Math formulas can be displayed inline with text or as
+separate blocks. They will be typeset into their own block if they start and end
+with at least one space (e.g. `[$ x^2 $]`).
+
+# Variables
+In math, single letters are always displayed as is. Multiple letters, however,
+are interpreted as variables and functions. To display multiple letters
+verbatim, you can place them into quotes and to access single letter variables,
+you can use the [hash syntax]($scripting/#expressions).
+
+```example
+$ A = pi r^2 $
+$ "area" = pi dot "radius"^2 $
+$ cal(A) :=
+ { x in RR | x "is natural" } $
+#let x = 5
+$ #x < 17 $
+```
+
+# Symbols
+Math mode makes a wide selection of [symbols]($category/symbols/sym) like `pi`,
+`dot`, or `RR` available. Many mathematical symbols are available in different
+variants. You can select between different variants by applying
+[modifiers]($symbol) to the symbol. Typst further recognizes a number of
+shorthand sequences like `=>` that approximate a symbol. When such a shorthand
+exists, the symbol's documentation lists it.
+
+```example
+$ x < y => x gt.eq.not y $
+```
+
+# Line Breaks
+Formulas can also contain line breaks. Each line can contain one or multiple
+_alignment points_ (`&`) which are then aligned.
+
+```example
+$ sum_(k=0)^n k
+ &= 1 + ... + n \
+ &= (n(n+1)) / 2 $
+```
+
+# Function calls
+Math mode supports special function calls without the hash prefix. In these
+"math calls", the argument list works a little differently than in code:
+
+- Within them, Typst is still in "math mode". Thus, you can write math directly
+ into them, but need to use hash syntax to pass code expressions (except for
+ strings, which are available in the math syntax).
+- They support positional and named arguments, as well as argument spreading.
+- They don't support trailing content blocks.
+- They provide additional syntax for 2-dimensional argument lists. The semicolon
+ (`;`) merges preceding arguments separated by commas into an array argument.
+
+```example
+$ frac(a^2, 2) $
+$ vec(1, 2, delim: "[") $
+$ mat(1, 2; 3, 4) $
+$ mat(..#range(1, 5).chunks(2)) $
+$ lim_x =
+ op("lim", limits: #true)_x $
+```
+
+To write a verbatim comma or semicolon in a math call, escape it with a
+backslash. The colon on the other hand is only recognized in a special way if
+directly preceded by an identifier, so to display it verbatim in those cases,
+you can just insert a space before it.
+
+Functions calls preceded by a hash are normal code function calls and not
+affected by these rules.
+
+# Alignment
+When equations include multiple _alignment points_ (`&`), this creates blocks of
+alternatingly right- and left-aligned columns. In the example below, the
+expression `(3x + y) / 7` is right-aligned and `= 9` is left-aligned. The word
+"given" is also left-aligned because `&&` creates two alignment points in a row,
+alternating the alignment twice. `& &` and `&&` behave exactly the same way.
+Meanwhile, "multiply by 7" is right-aligned because just one `&` precedes it.
+Each alignment point simply alternates between right-aligned/left-aligned.
+
+```example
+$ (3x + y) / 7 &= 9 && "given" \
+ 3x + y &= 63 & "multiply by 7" \
+ 3x &= 63 - y && "subtract y" \
+ x &= 21 - y/3 & "divide by 3" $
+```
+
+# Math fonts
+You can set the math font by with a [show-set rule]($styling/#show-rules) as
+demonstrated below. Note that only special OpenType math fonts are suitable for
+typesetting maths.
+
+```example
+#show math.equation: set text(font: "Fira Math")
+$ sum_(i in NN) 1 + i $
+```
+
+# Math module
+All math functions are part of the `math` [module]($scripting/#modules), which
+is available by default in equations. Outside of equations, they can be accessed
+with the `math.` prefix.
diff --git a/docs/reference/library/model.md b/docs/reference/library/model.md
new file mode 100644
index 00000000..e433ed53
--- /dev/null
+++ b/docs/reference/library/model.md
@@ -0,0 +1,5 @@
+Document structuring.
+
+Here, you can find functions to structure your document and interact with that
+structure. This includes section headings, figures, bibliography management,
+cross-referencing and more.
diff --git a/docs/reference/library/symbols.md b/docs/reference/library/symbols.md
new file mode 100644
index 00000000..2e6f48cd
--- /dev/null
+++ b/docs/reference/library/symbols.md
@@ -0,0 +1,5 @@
+These two modules give names to symbols and emoji to make them easy to insert
+with a normal keyboard. Alternatively, you can also always directly enter
+Unicode symbols into your text and formulas. In addition to the symbols listed
+below, math mode defines `dif` and `Dif`. These are not normal symbol values
+because they also affect spacing and font style.
diff --git a/docs/reference/library/text.md b/docs/reference/library/text.md
new file mode 100644
index 00000000..239c0b26
--- /dev/null
+++ b/docs/reference/library/text.md
@@ -0,0 +1,3 @@
+Text styling.
+
+The [text function]($text) is of particular interest.
diff --git a/docs/reference/library/visualize.md b/docs/reference/library/visualize.md
new file mode 100644
index 00000000..9259401f
--- /dev/null
+++ b/docs/reference/library/visualize.md
@@ -0,0 +1,5 @@
+Drawing and data visualization.
+
+If you want to create more advanced drawings or plots, also have a look at the
+[CetZ](https://github.com/johannes-wolf/cetz) package as well as more
+specialized [packages]($universe) for your use case.
diff --git a/docs/reference/packages.md b/docs/reference/packages.md
deleted file mode 100644
index bfd1ef58..00000000
--- a/docs/reference/packages.md
+++ /dev/null
@@ -1,6 +0,0 @@
-Typst [packages]($scripting/#packages) encapsulate reusable building blocks
-and make them reusable across projects. Below is a list of Typst packages
-created by the community. Due to the early and experimental nature of Typst's
-package management, they all live in a `preview` namespace. Click on a package's
-name to view its documentation and use the copy button on the right to get a
-full import statement for it.
diff --git a/docs/src/html.rs b/docs/src/html.rs
index 4eb3954c..9077d5c4 100644
--- a/docs/src/html.rs
+++ b/docs/src/html.rs
@@ -301,7 +301,10 @@ impl<'a> Handler<'a> {
return;
}
- let default = self.peeked.as_ref().map(|text| text.to_kebab_case());
+ let body = self.peeked.as_ref();
+ let default = body.map(|text| text.to_kebab_case());
+ let has_id = id_slot.is_some();
+
let id: &'a str = match (&id_slot, default) {
(Some(id), default) => {
if Some(*id) == default.as_deref() {
@@ -316,10 +319,10 @@ impl<'a> Handler<'a> {
*id_slot = (!id.is_empty()).then_some(id);
// Special case for things like "v0.3.0".
- let name = if id.starts_with('v') && id.contains('.') {
- id.into()
- } else {
- id.to_title_case().into()
+ let name = match &body {
+ _ if id.starts_with('v') && id.contains('.') => id.into(),
+ Some(body) if !has_id => body.as_ref().into(),
+ _ => id.to_title_case().into(),
};
let mut children = &mut self.outline;
diff --git a/docs/src/lib.rs b/docs/src/lib.rs
index ff745c9c..f9ee05bb 100644
--- a/docs/src/lib.rs
+++ b/docs/src/lib.rs
@@ -12,27 +12,20 @@ pub use self::model::*;
use std::collections::HashSet;
use ecow::{eco_format, EcoString};
+use heck::ToTitleCase;
use serde::Deserialize;
use serde_yaml as yaml;
use std::sync::LazyLock;
use typst::diag::{bail, StrResult};
-use typst::foundations::Binding;
use typst::foundations::{
- AutoValue, Bytes, CastInfo, Category, Func, Module, NoneValue, ParamInfo, Repr,
- Scope, Smart, Type, Value, FOUNDATIONS,
+ AutoValue, Binding, Bytes, CastInfo, Func, Module, NoneValue, ParamInfo, Repr, Scope,
+ Smart, Type, Value,
};
-use typst::html::HTML;
-use typst::introspection::INTROSPECTION;
-use typst::layout::{Abs, Margin, PageElem, PagedDocument, LAYOUT};
-use typst::loading::DATA_LOADING;
-use typst::math::MATH;
-use typst::model::MODEL;
-use typst::pdf::PDF;
-use typst::symbols::SYMBOLS;
-use typst::text::{Font, FontBook, TEXT};
+use typst::layout::{Abs, Margin, PageElem, PagedDocument};
+use typst::text::{Font, FontBook};
use typst::utils::LazyHash;
-use typst::visualize::VISUALIZE;
-use typst::{Feature, Library, LibraryBuilder};
+use typst::{Category, Feature, Library, LibraryBuilder};
+use unicode_math_class::MathClass;
macro_rules! load {
($path:literal) => {
@@ -64,9 +57,10 @@ static LIBRARY: LazyLock<LazyHash<Library>> = LazyLock::new(|| {
let scope = lib.global.scope_mut();
// Add those types, so that they show up in the docs.
- scope.start_category(FOUNDATIONS);
+ scope.start_category(Category::Foundations);
scope.define_type::<NoneValue>();
scope.define_type::<AutoValue>();
+ scope.reset_category();
// Adjust the default look.
lib.styles
@@ -155,21 +149,24 @@ fn reference_pages(resolver: &dyn Resolver) -> PageModel {
let mut page = md_page(resolver, resolver.base(), load!("reference/welcome.md"));
let base = format!("{}reference/", resolver.base());
page.children = vec![
- md_page(resolver, &base, load!("reference/syntax.md")).with_part("Language"),
- md_page(resolver, &base, load!("reference/styling.md")),
- md_page(resolver, &base, load!("reference/scripting.md")),
- md_page(resolver, &base, load!("reference/context.md")),
- category_page(resolver, FOUNDATIONS).with_part("Library"),
- category_page(resolver, MODEL),
- category_page(resolver, TEXT),
- category_page(resolver, MATH),
- category_page(resolver, SYMBOLS),
- category_page(resolver, LAYOUT),
- category_page(resolver, VISUALIZE),
- category_page(resolver, INTROSPECTION),
- category_page(resolver, DATA_LOADING),
- category_page(resolver, PDF),
- category_page(resolver, HTML),
+ md_page(resolver, &base, load!("reference/language/syntax.md"))
+ .with_part("Language"),
+ md_page(resolver, &base, load!("reference/language/styling.md")),
+ md_page(resolver, &base, load!("reference/language/scripting.md")),
+ md_page(resolver, &base, load!("reference/language/context.md")),
+ category_page(resolver, Category::Foundations).with_part("Library"),
+ category_page(resolver, Category::Model),
+ category_page(resolver, Category::Text),
+ category_page(resolver, Category::Math),
+ category_page(resolver, Category::Symbols),
+ category_page(resolver, Category::Layout),
+ category_page(resolver, Category::Visualize),
+ category_page(resolver, Category::Introspection),
+ category_page(resolver, Category::DataLoading),
+ category_page(resolver, Category::Pdf).with_part("Export"),
+ category_page(resolver, Category::Html),
+ category_page(resolver, Category::Png),
+ category_page(resolver, Category::Svg),
];
page
}
@@ -219,14 +216,16 @@ fn category_page(resolver: &dyn Resolver, category: Category) -> PageModel {
let mut markup = vec![];
let mut math = vec![];
- let (module, path): (&Module, &[&str]) = if category == MATH {
- (&LIBRARY.math, &["math"])
- } else {
- (&LIBRARY.global, &[])
+ let docs = category_docs(category);
+ let (module, path): (&Module, &[&str]) = match category {
+ Category::Math => (&LIBRARY.math, &["math"]),
+ Category::Pdf => (get_module(&LIBRARY.global, "pdf").unwrap(), &["pdf"]),
+ Category::Html => (get_module(&LIBRARY.global, "html").unwrap(), &["html"]),
+ _ => (&LIBRARY.global, &[]),
};
// Add groups.
- for group in GROUPS.iter().filter(|g| g.category == category.name()).cloned() {
+ for group in GROUPS.iter().filter(|g| g.category == category).cloned() {
if matches!(group.name.as_str(), "sym" | "emoji") {
let subpage = symbols_page(resolver, &route, &group);
let BodyModel::Symbols(model) = &subpage.body else { continue };
@@ -243,7 +242,7 @@ fn category_page(resolver: &dyn Resolver, category: Category) -> PageModel {
items.push(CategoryItem {
name: group.name.clone(),
route: subpage.route.clone(),
- oneliner: oneliner(category.docs()).into(),
+ oneliner: oneliner(docs).into(),
code: true,
});
children.push(subpage);
@@ -256,15 +255,15 @@ fn category_page(resolver: &dyn Resolver, category: Category) -> PageModel {
}
// Add symbol pages. These are ordered manually.
- if category == SYMBOLS {
+ if category == Category::Symbols {
shorthands = Some(ShorthandsModel { markup, math });
}
let mut skip = HashSet::new();
- if category == MATH {
+ if category == Category::Math {
skip = GROUPS
.iter()
- .filter(|g| g.category == category.name())
+ .filter(|g| g.category == category)
.flat_map(|g| &g.filter)
.map(|s| s.as_str())
.collect();
@@ -273,6 +272,11 @@ fn category_page(resolver: &dyn Resolver, category: Category) -> PageModel {
skip.insert("text");
}
+ // Tiling would be duplicate otherwise.
+ if category == Category::Visualize {
+ skip.insert("pattern");
+ }
+
// Add values and types.
let scope = module.scope();
for (name, binding) in scope.iter() {
@@ -287,8 +291,8 @@ fn category_page(resolver: &dyn Resolver, category: Category) -> PageModel {
match binding.read() {
Value::Func(func) => {
let name = func.name().unwrap();
-
- let subpage = func_page(resolver, &route, func, path);
+ let subpage =
+ func_page(resolver, &route, func, path, binding.deprecation());
items.push(CategoryItem {
name: name.into(),
route: subpage.route.clone(),
@@ -311,31 +315,39 @@ fn category_page(resolver: &dyn Resolver, category: Category) -> PageModel {
}
}
- if category != SYMBOLS {
+ if category != Category::Symbols {
children.sort_by_cached_key(|child| child.title.clone());
items.sort_by_cached_key(|item| item.name.clone());
}
- let name = category.title();
- let details = Html::markdown(resolver, category.docs(), Some(1));
+ let title = EcoString::from(match category {
+ Category::Pdf | Category::Html | Category::Png | Category::Svg => {
+ category.name().to_uppercase()
+ }
+ _ => category.name().to_title_case(),
+ });
+
+ let details = Html::markdown(resolver, docs, Some(1));
let mut outline = vec![OutlineItem::from_name("Summary")];
outline.extend(details.outline());
- outline.push(OutlineItem::from_name("Definitions"));
+ if !items.is_empty() {
+ outline.push(OutlineItem::from_name("Definitions"));
+ }
if shorthands.is_some() {
outline.push(OutlineItem::from_name("Shorthands"));
}
PageModel {
route,
- title: name.into(),
+ title: title.clone(),
description: eco_format!(
- "Documentation for functions related to {name} in Typst."
+ "Documentation for functions related to {title} in Typst."
),
part: None,
outline,
body: BodyModel::Category(CategoryModel {
name: category.name(),
- title: category.title(),
+ title,
details,
items,
shorthands,
@@ -344,14 +356,34 @@ fn category_page(resolver: &dyn Resolver, category: Category) -> PageModel {
}
}
+/// Retrieve the docs for a category.
+fn category_docs(category: Category) -> &'static str {
+ match category {
+ Category::Foundations => load!("reference/library/foundations.md"),
+ Category::Introspection => load!("reference/library/introspection.md"),
+ Category::Layout => load!("reference/library/layout.md"),
+ Category::DataLoading => load!("reference/library/data-loading.md"),
+ Category::Math => load!("reference/library/math.md"),
+ Category::Model => load!("reference/library/model.md"),
+ Category::Symbols => load!("reference/library/symbols.md"),
+ Category::Text => load!("reference/library/text.md"),
+ Category::Visualize => load!("reference/library/visualize.md"),
+ Category::Pdf => load!("reference/export/pdf.md"),
+ Category::Html => load!("reference/export/html.md"),
+ Category::Svg => load!("reference/export/svg.md"),
+ Category::Png => load!("reference/export/png.md"),
+ }
+}
+
/// Create a page for a function.
fn func_page(
resolver: &dyn Resolver,
parent: &str,
func: &Func,
path: &[&str],
+ deprecation: Option<&'static str>,
) -> PageModel {
- let model = func_model(resolver, func, path, false);
+ let model = func_model(resolver, func, path, false, deprecation);
let name = func.name().unwrap();
PageModel {
route: eco_format!("{parent}{}/", urlify(name)),
@@ -370,6 +402,7 @@ fn func_model(
func: &Func,
path: &[&str],
nested: bool,
+ deprecation: Option<&'static str>,
) -> FuncModel {
let name = func.name().unwrap();
let scope = func.scope().unwrap();
@@ -383,7 +416,11 @@ fn func_model(
}
let mut returns = vec![];
- casts(resolver, &mut returns, &mut vec![], func.returns().unwrap());
+ let mut strings = vec![];
+ casts(resolver, &mut returns, &mut strings, func.returns().unwrap());
+ if !strings.is_empty() && !returns.contains(&"str") {
+ returns.push("str");
+ }
returns.sort_by_key(|ty| type_index(ty));
if returns == ["none"] {
returns.clear();
@@ -401,6 +438,7 @@ fn func_model(
oneliner: oneliner(details),
element: func.element().is_some(),
contextual: func.contextual().unwrap_or(false),
+ deprecation,
details: Html::markdown(resolver, details, nesting),
example: example.map(|md| Html::markdown(resolver, md, None)),
self_,
@@ -483,7 +521,7 @@ fn scope_models(resolver: &dyn Resolver, name: &str, scope: &Scope) -> Vec<FuncM
.iter()
.filter_map(|(_, binding)| {
let Value::Func(func) = binding.read() else { return None };
- Some(func_model(resolver, func, &[name], true))
+ Some(func_model(resolver, func, &[name], true, binding.deprecation()))
})
.collect()
}
@@ -559,9 +597,11 @@ fn group_page(
let mut outline_items = vec![];
for name in &group.filter {
- let value = group.module().scope().get(name).unwrap().read();
- let Ok(ref func) = value.clone().cast::<Func>() else { panic!("not a function") };
- let func = func_model(resolver, func, &path, true);
+ let binding = group.module().scope().get(name).unwrap();
+ let Ok(ref func) = binding.read().clone().cast::<Func>() else {
+ panic!("not a function")
+ };
+ let func = func_model(resolver, func, &path, true, binding.deprecation());
let id_base = urlify(&eco_format!("functions-{}", func.name));
let children = func_outline(&func, &id_base);
outline_items.push(OutlineItem {
@@ -628,7 +668,7 @@ fn type_model(resolver: &dyn Resolver, ty: &Type) -> TypeModel {
constructor: ty
.constructor()
.ok()
- .map(|func| func_model(resolver, &func, &[], true)),
+ .map(|func| func_model(resolver, &func, &[], true, None)),
scope: scope_models(resolver, ty.short_name(), ty.scope()),
}
}
@@ -682,10 +722,19 @@ fn symbols_model(resolver: &dyn Resolver, group: &GroupData) -> SymbolsModel {
list.iter().copied().find(|&(_, x)| x == c).map(|(s, _)| s)
};
+ let name = complete(variant);
+ let deprecation = match name.as_str() {
+ "integral.sect" => {
+ Some("`integral.sect` is deprecated, use `integral.inter` instead")
+ }
+ _ => binding.deprecation(),
+ };
+
list.push(SymbolModel {
- name: complete(variant),
+ name,
markup_shorthand: shorthand(typst::syntax::ast::Shorthand::LIST),
math_shorthand: shorthand(typst::syntax::ast::MathShorthand::LIST),
+ math_class: typst_utils::default_math_class(c).map(math_class_name),
codepoint: c as _,
accent: typst::math::Accent::combine(c).is_some(),
alternates: symbol
@@ -693,6 +742,7 @@ fn symbols_model(resolver: &dyn Resolver, group: &GroupData) -> SymbolsModel {
.filter(|(other, _)| other != &variant)
.map(|(other, _)| complete(other))
.collect(),
+ deprecation,
});
}
}
@@ -769,12 +819,32 @@ const TYPE_ORDER: &[&str] = &[
"stroke",
];
+fn math_class_name(class: MathClass) -> &'static str {
+ match class {
+ MathClass::Normal => "Normal",
+ MathClass::Alphabetic => "Alphabetic",
+ MathClass::Binary => "Binary",
+ MathClass::Closing => "Closing",
+ MathClass::Diacritic => "Diacritic",
+ MathClass::Fence => "Fence",
+ MathClass::GlyphPart => "Glyph Part",
+ MathClass::Large => "Large",
+ MathClass::Opening => "Opening",
+ MathClass::Punctuation => "Punctuation",
+ MathClass::Relation => "Relation",
+ MathClass::Space => "Space",
+ MathClass::Unary => "Unary",
+ MathClass::Vary => "Vary",
+ MathClass::Special => "Special",
+ }
+}
+
/// Data about a collection of functions.
#[derive(Debug, Clone, Deserialize)]
struct GroupData {
name: EcoString,
title: EcoString,
- category: EcoString,
+ category: Category,
#[serde(default)]
path: Vec<EcoString>,
#[serde(default)]
diff --git a/docs/src/link.rs b/docs/src/link.rs
index c55261b8..2e836b6c 100644
--- a/docs/src/link.rs
+++ b/docs/src/link.rs
@@ -44,6 +44,8 @@ fn resolve_known(head: &str, base: &str) -> Option<String> {
"$styling" => format!("{base}reference/styling"),
"$scripting" => format!("{base}reference/scripting"),
"$context" => format!("{base}reference/context"),
+ "$html" => format!("{base}reference/html"),
+ "$pdf" => format!("{base}reference/pdf"),
"$guides" => format!("{base}guides"),
"$changelog" => format!("{base}changelog"),
"$universe" => "https://typst.app/universe".into(),
@@ -73,11 +75,14 @@ fn resolve_definition(head: &str, base: &str) -> StrResult<String> {
// Handle grouped functions.
if let Some(group) = GROUPS.iter().find(|group| {
- group.category == category.name() && group.filter.iter().any(|func| func == name)
+ group.category == category && group.filter.iter().any(|func| func == name)
}) {
let mut route = format!(
"{}reference/{}/{}/#functions-{}",
- base, group.category, group.name, name
+ base,
+ group.category.name(),
+ group.name,
+ name
);
if let Some(param) = parts.next() {
route.push('-');
diff --git a/docs/src/model.rs b/docs/src/model.rs
index b222322a..801c60c7 100644
--- a/docs/src/model.rs
+++ b/docs/src/model.rs
@@ -64,7 +64,7 @@ pub enum BodyModel {
#[derive(Debug, Serialize)]
pub struct CategoryModel {
pub name: &'static str,
- pub title: &'static str,
+ pub title: EcoString,
pub details: Html,
pub items: Vec<CategoryItem>,
pub shorthands: Option<ShorthandsModel>,
@@ -89,6 +89,7 @@ pub struct FuncModel {
pub oneliner: &'static str,
pub element: bool,
pub contextual: bool,
+ pub deprecation: Option<&'static str>,
pub details: Html,
/// This example is only for nested function models. Others can have
/// their example directly in their details.
@@ -163,6 +164,8 @@ pub struct SymbolModel {
pub alternates: Vec<EcoString>,
pub markup_shorthand: Option<&'static str>,
pub math_shorthand: Option<&'static str>,
+ pub math_class: Option<&'static str>,
+ pub deprecation: Option<&'static str>,
}
/// Shorthands listed on a category page.