mirror of
https://github.com/typst/typst
synced 2025-05-13 12:36:23 +08:00
Export target docs (#5812)
Co-authored-by: Martin Haug <3874949+reknih@users.noreply.github.com>
This commit is contained in:
parent
25f6a7ab16
commit
029ae4a5ea
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2822,6 +2822,8 @@ dependencies = [
|
||||
"typst-assets",
|
||||
"typst-dev-assets",
|
||||
"typst-render",
|
||||
"typst-utils",
|
||||
"unicode-math-class",
|
||||
"unscanny",
|
||||
"yaml-front-matter",
|
||||
]
|
||||
|
@ -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.
|
||||
|
@ -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]
|
||||
|
@ -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()?))
|
||||
|
@ -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.
|
||||
///
|
||||
/// Integrates content that requires layout (e.g. a plot) into HTML output
|
||||
/// by turning it into 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.
|
||||
///
|
||||
/// 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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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.
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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>();
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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(
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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()?,
|
||||
})
|
||||
}
|
||||
}
|
@ -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.
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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.
|
||||
|
61
docs/reference/export/html.md
Normal file
61
docs/reference/export/html.md
Normal file
@ -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.
|
71
docs/reference/export/pdf.md
Normal file
71
docs/reference/export/pdf.md
Normal file
@ -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.
|
61
docs/reference/export/png.md
Normal file
61
docs/reference/export/png.md
Normal file
@ -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-`.
|
48
docs/reference/export/svg.md
Normal file
48
docs/reference/export/svg.md
Normal file
@ -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-`.
|
4
docs/reference/library/data-loading.md
Normal file
4
docs/reference/library/data-loading.md
Normal file
@ -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.
|
4
docs/reference/library/foundations.md
Normal file
4
docs/reference/library/foundations.md
Normal file
@ -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.
|
10
docs/reference/library/introspection.md
Normal file
10
docs/reference/library/introspection.md
Normal file
@ -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.
|
3
docs/reference/library/layout.md
Normal file
3
docs/reference/library/layout.md
Normal file
@ -0,0 +1,3 @@
|
||||
Arranging elements on the page in different ways.
|
||||
|
||||
By combining layout functions, you can create complex and automatic layouts.
|
101
docs/reference/library/math.md
Normal file
101
docs/reference/library/math.md
Normal file
@ -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.
|
5
docs/reference/library/model.md
Normal file
5
docs/reference/library/model.md
Normal file
@ -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.
|
5
docs/reference/library/symbols.md
Normal file
5
docs/reference/library/symbols.md
Normal file
@ -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.
|
3
docs/reference/library/text.md
Normal file
3
docs/reference/library/text.md
Normal file
@ -0,0 +1,3 @@
|
||||
Text styling.
|
||||
|
||||
The [text function]($text) is of particular interest.
|
5
docs/reference/library/visualize.md
Normal file
5
docs/reference/library/visualize.md
Normal file
@ -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.
|
@ -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.
|
@ -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;
|
||||
|
184
docs/src/lib.rs
184
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)]
|
||||
|
@ -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('-');
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user