Docs generation for types

This commit is contained in:
Laurenz 2023-09-11 15:53:20 +02:00
parent 305524d005
commit 3a979e88da
26 changed files with 1506 additions and 3000 deletions

1
Cargo.lock generated

@ -2962,6 +2962,7 @@ name = "typst-docs"
version = "0.7.0"
dependencies = [
"comemo",
"ecow",
"heck",
"include_dir",
"once_cell",

@ -14,6 +14,7 @@ bench = false
typst = { path = "../typst" }
typst-library = { path = "../typst-library" }
comemo = "0.3"
ecow = { version = "0.1.2", features = ["serde"] }
heck = "0.4"
include_dir = "0.7"
once_cell = "1"

@ -1,17 +1,22 @@
use std::fmt::{self, Debug, Formatter};
use std::ops::Range;
use comemo::Prehashed;
use ecow::EcoString;
use heck::{ToKebabCase, ToTitleCase};
use pulldown_cmark as md;
use serde::{Deserialize, Serialize};
use typed_arena::Arena;
use typst::diag::FileResult;
use typst::eval::{Bytes, Datetime, Tracer};
use typst::diag::{FileResult, StrResult};
use typst::eval::{Bytes, Datetime, Library, Tracer};
use typst::font::{Font, FontBook};
use typst::geom::{Point, Size};
use typst::geom::{Abs, Point, Size};
use typst::syntax::{FileId, Source, VirtualPath};
use typst::World;
use unscanny::Scanner;
use yaml_front_matter::YamlFrontMatter;
use super::*;
use super::{contributors, OutlineItem, Resolver, FILE_DIR, FONTS, LIBRARY};
/// HTML documentation.
#[derive(Serialize)]
@ -21,7 +26,7 @@ pub struct Html {
#[serde(skip)]
md: String,
#[serde(skip)]
description: Option<String>,
description: Option<EcoString>,
#[serde(skip)]
outline: Vec<OutlineItem>,
}
@ -39,18 +44,7 @@ impl Html {
/// Convert markdown to HTML.
#[track_caller]
pub fn markdown(resolver: &dyn Resolver, md: &str) -> Self {
Self::markdown_with_id_base(resolver, md, "")
}
/// Convert markdown to HTML, preceding all fragment identifiers with the
/// `id_base`.
#[track_caller]
pub fn markdown_with_id_base(
resolver: &dyn Resolver,
md: &str,
id_base: &str,
) -> Self {
pub fn markdown(resolver: &dyn Resolver, md: &str, nesting: Option<usize>) -> Self {
let mut text = md;
let mut description = None;
let document = YamlFrontMatter::parse::<Metadata>(md);
@ -62,9 +56,18 @@ impl Html {
let options = md::Options::ENABLE_TABLES | md::Options::ENABLE_HEADING_ATTRIBUTES;
let ids = Arena::new();
let mut handler = Handler::new(resolver, id_base.into(), &ids);
let iter = md::Parser::new_ext(text, options)
.filter_map(|mut event| handler.handle(&mut event).then_some(event));
let mut handler = Handler::new(text, resolver, nesting, &ids);
let mut events = md::Parser::new_ext(text, options).peekable();
let iter = std::iter::from_fn(|| loop {
let mut event = events.next()?;
handler.peeked = events.peek().and_then(|event| match event {
md::Event::Text(text) => Some(text.clone()),
_ => None,
});
if handler.handle(&mut event) {
return Some(event);
}
});
let mut raw = String::new();
md::html::push_html(&mut raw, iter);
@ -93,7 +96,11 @@ impl Html {
/// Returns `None` if the HTML doesn't start with an `h1` tag.
pub fn title(&self) -> Option<&str> {
let mut s = Scanner::new(&self.raw);
s.eat_if("<h1>").then(|| s.eat_until("</h1>"))
s.eat_if("<h1").then(|| {
s.eat_until('>');
s.eat_if('>');
s.eat_until("</h1>")
})
}
/// The outline of the HTML.
@ -102,7 +109,7 @@ impl Html {
}
/// The description from the front matter.
pub fn description(&self) -> Option<String> {
pub fn description(&self) -> Option<EcoString> {
self.description.clone()
}
}
@ -116,26 +123,35 @@ impl Debug for Html {
/// Front matter metadata.
#[derive(Deserialize)]
struct Metadata {
description: String,
description: EcoString,
}
struct Handler<'a> {
text: &'a str,
resolver: &'a dyn Resolver,
lang: Option<String>,
code: String,
peeked: Option<md::CowStr<'a>>,
lang: Option<EcoString>,
code: EcoString,
outline: Vec<OutlineItem>,
id_base: String,
nesting: Option<usize>,
ids: &'a Arena<String>,
}
impl<'a> Handler<'a> {
fn new(resolver: &'a dyn Resolver, id_base: String, ids: &'a Arena<String>) -> Self {
fn new(
text: &'a str,
resolver: &'a dyn Resolver,
nesting: Option<usize>,
ids: &'a Arena<String>,
) -> Self {
Self {
text,
resolver,
peeked: None,
lang: None,
code: String::new(),
code: EcoString::new(),
outline: vec![],
id_base,
nesting,
ids,
}
}
@ -157,15 +173,13 @@ impl<'a> Handler<'a> {
}
// Register HTML headings for the outline.
md::Event::Start(md::Tag::Heading(level, Some(id), _)) => {
md::Event::Start(md::Tag::Heading(level, id, _)) => {
self.handle_heading(id, level);
}
// Also handle heading closings.
md::Event::End(md::Tag::Heading(level, Some(_), _)) => {
if *level > md::HeadingLevel::H1 && !self.id_base.is_empty() {
nest_heading(level);
}
md::Event::End(md::Tag::Heading(level, _, _)) => {
nest_heading(level, self.nesting());
}
// Rewrite contributor sections.
@ -185,10 +199,10 @@ impl<'a> Handler<'a> {
"unsupported link type: {ty:?}",
);
*dest = self
.handle_link(dest)
.unwrap_or_else(|| panic!("invalid link: {dest}"))
.into();
*dest = match self.handle_link(dest) {
Ok(link) => link.into(),
Err(err) => panic!("invalid link: {dest} ({err})"),
};
}
// Inline raw.
@ -208,7 +222,7 @@ impl<'a> Handler<'a> {
// Code blocks.
md::Event::Start(md::Tag::CodeBlock(md::CodeBlockKind::Fenced(lang))) => {
self.lang = Some(lang.as_ref().into());
self.code = String::new();
self.code = EcoString::new();
return false;
}
md::Event::End(md::Tag::CodeBlock(md::CodeBlockKind::Fenced(_))) => {
@ -232,7 +246,7 @@ impl<'a> Handler<'a> {
}
fn handle_image(&self, link: &str) -> String {
if let Some(file) = FILES.get_file(link) {
if let Some(file) = FILE_DIR.get_file(link) {
self.resolver.image(link, file.contents())
} else if let Some(url) = self.resolver.link(link) {
url
@ -241,16 +255,35 @@ impl<'a> Handler<'a> {
}
}
fn handle_heading(&mut self, id: &mut &'a str, level: &mut md::HeadingLevel) {
fn handle_heading(
&mut self,
id_slot: &mut Option<&'a str>,
level: &mut md::HeadingLevel,
) {
nest_heading(level, self.nesting());
if *level == md::HeadingLevel::H1 {
return;
}
let default = self.peeked.as_ref().map(|text| text.to_kebab_case());
let id: &'a str = match (&id_slot, default) {
(Some(id), default) => {
if Some(*id) == default.as_deref() {
eprintln!("heading id #{id} was specified unnecessarily");
}
id
}
(None, Some(default)) => self.ids.alloc(default).as_str(),
(None, None) => panic!("missing heading id {}", self.text),
};
*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.to_string()
id.into()
} else {
id.to_title_case()
id.to_title_case().into()
};
let mut children = &mut self.outline;
@ -262,106 +295,22 @@ impl<'a> Handler<'a> {
depth -= 1;
}
// Put base before id.
if !self.id_base.is_empty() {
nest_heading(level);
*id = self.ids.alloc(format!("{}-{id}", self.id_base)).as_str();
}
children.push(OutlineItem { id: id.to_string(), name, children: vec![] });
children.push(OutlineItem { id: id.into(), name, children: vec![] });
}
fn handle_link(&self, link: &str) -> Option<String> {
if link.starts_with('#') || link.starts_with("http") {
return Some(link.into());
fn handle_link(&self, link: &str) -> StrResult<String> {
if let Some(link) = self.resolver.link(link) {
return Ok(link);
}
if !link.starts_with('$') {
return self.resolver.link(link);
crate::link::resolve(link)
}
fn nesting(&self) -> usize {
match self.nesting {
Some(nesting) => nesting,
None => panic!("headings are not allowed here:\n{}", self.text),
}
let root = link.split('/').next()?;
let rest = &link[root.len()..].trim_matches('/');
let base = match root {
"$tutorial" => "/docs/tutorial/",
"$reference" => "/docs/reference/",
"$category" => "/docs/reference/",
"$syntax" => "/docs/reference/syntax/",
"$styling" => "/docs/reference/styling/",
"$scripting" => "/docs/reference/scripting/",
"$types" => "/docs/reference/types/",
"$type" => "/docs/reference/types/",
"$func" => "/docs/reference/",
"$guides" => "/docs/guides/",
"$packages" => "/docs/packages/",
"$changelog" => "/docs/changelog/",
"$community" => "/docs/community/",
_ => panic!("unknown link root: {root}"),
};
let mut route = base.to_string();
if root == "$type" && rest.contains('.') {
let mut parts = rest.split('.');
let ty = parts.next()?;
let method = parts.next()?;
route.push_str(ty);
route.push_str("/#methods-");
route.push_str(method);
} else if root == "$func" {
let mut parts = rest.split('.').peekable();
let first = parts.peek().copied();
let mut focus = &LIBRARY.global;
while let Some(m) = first.and_then(|name| module(focus, name).ok()) {
focus = m;
parts.next();
}
let name = parts.next()?;
let value = focus.get(name).ok()?;
let Value::Func(func) = value else { return None };
let info = func.info()?;
route.push_str(info.category);
route.push('/');
if let Some(group) = GROUPS
.iter()
.filter(|_| first == Some("math"))
.find(|group| group.functions.iter().any(|func| func == info.name))
{
route.push_str(&group.name);
route.push_str("/#");
route.push_str(info.name);
if let Some(param) = parts.next() {
route.push_str("-parameters-");
route.push_str(param);
}
} else {
route.push_str(name);
route.push('/');
if let Some(next) = parts.next() {
if info.params.iter().any(|param| param.name == next) {
route.push_str("#parameters-");
route.push_str(next);
} else if info.scope.iter().any(|(name, _)| name == next) {
route.push('#');
route.push_str(info.name);
route.push('-');
route.push_str(next);
} else {
return None;
}
}
}
} else {
route.push_str(rest);
}
if !route.contains('#') && !route.ends_with('/') {
route.push('/');
}
Some(route)
}
}
@ -466,15 +415,10 @@ fn html_attr_range(html: &str, attr: &str) -> Option<Range<usize>> {
}
/// Increase the nesting level of a Markdown heading.
fn nest_heading(level: &mut md::HeadingLevel) {
*level = match &level {
md::HeadingLevel::H1 => md::HeadingLevel::H2,
md::HeadingLevel::H2 => md::HeadingLevel::H3,
md::HeadingLevel::H3 => md::HeadingLevel::H4,
md::HeadingLevel::H4 => md::HeadingLevel::H5,
md::HeadingLevel::H5 => md::HeadingLevel::H6,
v => **v,
};
fn nest_heading(level: &mut md::HeadingLevel, nesting: usize) {
*level = ((*level as usize) + nesting)
.try_into()
.unwrap_or(md::HeadingLevel::H6);
}
/// A world for example compilations.
@ -499,7 +443,7 @@ impl World for DocWorld {
fn file(&self, id: FileId) -> FileResult<Bytes> {
assert!(id.package().is_none());
Ok(FILES
Ok(FILE_DIR
.get_file(id.vpath().as_rootless_path())
.unwrap_or_else(|| panic!("failed to load {:?}", id.vpath()))
.contents()

File diff suppressed because it is too large Load Diff

@ -0,0 +1,102 @@
use typst::diag::{bail, StrResult};
use typst::eval::Func;
use super::{get_module, GROUPS, LIBRARY};
/// Resolve an intra-doc link.
pub fn resolve(link: &str) -> StrResult<String> {
if link.starts_with('#') || link.starts_with("http") {
return Ok(link.to_string());
}
let (head, tail) = split_link(link)?;
let mut route = match resolve_known(head) {
Some(route) => route.into(),
None => resolve_definition(head)?,
};
if !tail.is_empty() {
route.push('/');
route.push_str(tail);
}
if !route.contains('#') && !route.ends_with('/') {
route.push('/');
}
Ok(route)
}
/// Split a link at the first slash.
fn split_link(link: &str) -> StrResult<(&str, &str)> {
let first = link.split('/').next().unwrap_or(link);
let rest = link[first.len()..].trim_start_matches('/');
Ok((first, rest))
}
/// Resolve a `$` link head to a known destination.
fn resolve_known(head: &str) -> Option<&'static str> {
Some(match head {
"$tutorial" => "/docs/tutorial/",
"$reference" => "/docs/reference/",
"$category" => "/docs/reference/",
"$syntax" => "/docs/reference/syntax/",
"$styling" => "/docs/reference/styling/",
"$scripting" => "/docs/reference/scripting/",
"$guides" => "/docs/guides/",
"$packages" => "/docs/packages/",
"$changelog" => "/docs/changelog/",
"$community" => "/docs/community/",
_ => return None,
})
}
/// Resolve a `$` link to a global definition.
fn resolve_definition(head: &str) -> StrResult<String> {
let mut parts = head.trim_start_matches('$').split('.').peekable();
let mut focus = &LIBRARY.global;
while let Some(m) = parts.peek().and_then(|&name| get_module(focus, name).ok()) {
focus = m;
parts.next();
}
let name = parts.next().ok_or("link is missing first part")?;
let value = focus.field(name)?;
let Some(category) = focus.scope().get_category(name) else {
bail!("{name} has no category");
};
// Handle grouped functions.
if let Some(group) = GROUPS
.iter()
.filter(|_| category == "math")
.find(|group| group.functions.iter().any(|func| func == name))
{
let mut route =
format!("/docs/reference/math/{}/#functions-{}", group.name, name);
if let Some(param) = parts.next() {
route.push('-');
route.push_str(param);
}
return Ok(route);
}
let mut route = format!("/docs/reference/{category}/{name}/");
if let Some(next) = parts.next() {
if value.field(next).is_ok() {
route.push_str("#definitions-");
route.push_str(next);
} else if value
.clone()
.cast::<Func>()
.map_or(false, |func| func.param(next).is_some())
{
route.push_str("#parameters-");
route.push_str(next);
} else {
bail!("field {next} not found");
}
}
Ok(route)
}

@ -0,0 +1,170 @@
use ecow::EcoString;
use heck::ToKebabCase;
use serde::Serialize;
use crate::html::Html;
/// Details about a documentation page and its children.
#[derive(Debug, Serialize)]
pub struct PageModel {
pub route: EcoString,
pub title: EcoString,
pub description: EcoString,
pub part: Option<&'static str>,
pub outline: Vec<OutlineItem>,
pub body: BodyModel,
pub children: Vec<Self>,
}
impl PageModel {
pub fn with_route(self, route: &str) -> Self {
Self { route: route.into(), ..self }
}
pub fn with_part(self, part: &'static str) -> Self {
Self { part: Some(part), ..self }
}
}
/// An element in the "On This Page" outline.
#[derive(Debug, Clone, Serialize)]
pub struct OutlineItem {
pub id: EcoString,
pub name: EcoString,
pub children: Vec<Self>,
}
impl OutlineItem {
/// Create an outline item from a name with auto-generated id.
pub fn from_name(name: &str) -> Self {
Self {
id: name.to_kebab_case().into(),
name: name.into(),
children: vec![],
}
}
}
/// Details about the body of a documentation page.
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
#[serde(tag = "kind", content = "content")]
pub enum BodyModel {
Html(Html),
Category(CategoryModel),
Func(FuncModel),
Group(GroupModel),
Type(TypeModel),
Symbols(SymbolsModel),
Packages(Html),
}
/// Details about a category.
#[derive(Debug, Serialize)]
pub struct CategoryModel {
pub name: EcoString,
pub details: Html,
pub items: Vec<CategoryItem>,
pub shorthands: Option<ShorthandsModel>,
}
/// Details about a category item.
#[derive(Debug, Serialize)]
pub struct CategoryItem {
pub name: EcoString,
pub route: EcoString,
pub oneliner: EcoString,
pub code: bool,
}
/// Details about a function.
#[derive(Debug, Serialize)]
pub struct FuncModel {
pub path: Vec<EcoString>,
pub name: EcoString,
pub title: &'static str,
pub keywords: &'static [&'static str],
pub oneliner: &'static str,
pub element: bool,
pub details: Html,
/// This example is only for nested function models. Others can have
/// their example directly in their detals.
pub example: Option<Html>,
#[serde(rename = "self")]
pub self_: bool,
pub params: Vec<ParamModel>,
pub returns: Vec<&'static str>,
pub scope: Vec<FuncModel>,
}
/// Details about a function parameter.
#[derive(Debug, Serialize)]
pub struct ParamModel {
pub name: &'static str,
pub details: Html,
pub example: Option<Html>,
pub types: Vec<&'static str>,
pub strings: Vec<StrParam>,
pub default: Option<Html>,
pub positional: bool,
pub named: bool,
pub required: bool,
pub variadic: bool,
pub settable: bool,
}
/// A specific string that can be passed as an argument.
#[derive(Debug, Serialize)]
pub struct StrParam {
pub string: EcoString,
pub details: Html,
}
/// Details about a group of functions.
#[derive(Debug, Serialize)]
pub struct GroupModel {
pub name: EcoString,
pub title: EcoString,
pub details: Html,
pub functions: Vec<FuncModel>,
}
/// Details about a type.
#[derive(Debug, Serialize)]
pub struct TypeModel {
pub name: &'static str,
pub title: &'static str,
pub keywords: &'static [&'static str],
pub oneliner: &'static str,
pub details: Html,
pub constructor: Option<FuncModel>,
pub scope: Vec<FuncModel>,
}
/// A collection of symbols.
#[derive(Debug, Serialize)]
pub struct SymbolsModel {
pub name: &'static str,
pub details: Html,
pub list: Vec<SymbolModel>,
}
/// Details about a symbol.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SymbolModel {
pub name: EcoString,
pub codepoint: u32,
pub accent: bool,
pub unicode_name: Option<EcoString>,
pub alternates: Vec<EcoString>,
pub markup_shorthand: Option<&'static str>,
pub math_shorthand: Option<&'static str>,
}
/// Shorthands listed on a category page.
#[derive(Debug, Serialize)]
pub struct ShorthandsModel {
pub markup: Vec<SymbolModel>,
pub math: Vec<SymbolModel>,
}

@ -207,7 +207,7 @@ impl Array {
.ok_or_else(|| out_of_bounds_no_default(index, self.len()))
}
/// Add a value to the end of the array.
/// Adds a value to the end of the array.
#[func]
pub fn push(
&mut self,
@ -217,14 +217,14 @@ impl Array {
self.0.push(value);
}
/// Remove the last item from the array and return it. Fails with an error
/// Removes the last item from the array and returns it. Fails with an error
/// if the array is empty.
#[func]
pub fn pop(&mut self) -> StrResult<Value> {
self.0.pop().ok_or_else(array_is_empty)
}
/// Insert a value into the array at the specified index. Fails with an
/// Inserts a value into the array at the specified index. Fails with an
/// error if the index is out of bounds.
#[func]
pub fn insert(
@ -240,7 +240,7 @@ impl Array {
Ok(())
}
/// Remove the value at the specified index from the array and return it.
/// Removes the value at the specified index from the array and return it.
#[func]
pub fn remove(
&mut self,
@ -252,7 +252,7 @@ impl Array {
Ok(self.0.remove(i))
}
/// Extract a subslice of the array. Fails with an error if the start or
/// Extracts a subslice of the array. Fails with an error if the start or
/// index is out of bounds.
#[func]
pub fn slice(

@ -154,7 +154,7 @@ impl Dict {
.ok_or_else(|| missing_key_no_default(&key))
}
/// Insert a new pair into the dictionary and return the value. If the
/// Inserts a new pair into the dictionary and return the value. If the
/// dictionary already contains this key, the value is updated.
#[func]
pub fn insert(
@ -167,7 +167,7 @@ impl Dict {
Arc::make_mut(&mut self.0).insert(key, value);
}
/// Remove a pair from the dictionary by key and return the value.
/// Removes a pair from the dictionary by key and return the value.
#[func]
pub fn remove(&mut self, key: Str) -> StrResult<Value> {
match Arc::make_mut(&mut self.0).shift_remove(&key) {

@ -8,25 +8,25 @@ description: |
## Version 0.7.0 (August 7, 2023) { #v0.7.0 }
- Text and Layout
- Added support for floating figures through the
[`placement`]($func/figure.placement) argument on the figure function
[`placement`]($figure.placement) argument on the figure function
- Added support for arbitrary floating content through the
[`float`]($func/place.float) argument on the place function
[`float`]($place.float) argument on the place function
- Added support for loading `.sublime-syntax` files as highlighting
[syntaxes]($func/raw.syntaxes) for raw blocks
[syntaxes]($raw.syntaxes) for raw blocks
- Added support for loading `.tmTheme` files as highlighting
[themes]($func/raw.theme) for raw blocks
- Added _bounds_ option to [`top-edge`]($func/text.top-edge) and
[`bottom-edge`]($func/text.bottom-edge) arguments of text function for tight
[themes]($raw.theme) for raw blocks
- Added _bounds_ option to [`top-edge`]($text.top-edge) and
[`bottom-edge`]($text.bottom-edge) arguments of text function for tight
bounding boxes
- Removed nonsensical top- and bottom-edge options, e.g. _ascender_ for the
bottom edge (**Breaking change**)
- Added [`script`]($func/text.script) argument to text function
- Added [`alternative`]($func/smartquote.alternative) argument to smart quote
- Added [`script`]($text.script) argument to text function
- Added [`alternative`]($smartquote.alternative) argument to smart quote
function
- Added basic i18n for Japanese
- Added hyphenation support for `nb` and `nn` language codes in addition to
`no`
- Fixed positioning of [placed elements]($func/place) in containers
- Fixed positioning of [placed elements]($place) in containers
- Fixed overflowing containers due to optimized line breaks
- Export
@ -38,21 +38,21 @@ description: |
- Math
- Improved layout of primes (e.g. in `[$a'_1$]`)
- Improved display of multi-primes (e.g. in `[$a''$]`)
- Improved layout of [roots]($func/math.root)
- Changed relations to show attachments as [limits]($func/math.limits) by
default (e.g. in `[$a ->^x b$]`)
- Improved layout of [roots]($math.root)
- Changed relations to show attachments as [limits]($math.limits) by default
(e.g. in `[$a ->^x b$]`)
- Large operators and delimiters are now always vertically centered
- [Boxes]($func/box) in equations now sit on the baseline instead of being
- [Boxes]($box) in equations now sit on the baseline instead of being
vertically centered by default. Notably, this does not affect
[blocks]($func/block) because they are not inline elements.
- Added support for [weak spacing]($func/h.weak)
[blocks]($block) because they are not inline elements.
- Added support for [weak spacing]($h.weak)
- Added support for OpenType character variants
- Added support for customizing the [math class]($func/math.class) of content
- Added support for customizing the [math class]($math.class) of content
- Fixed spacing around `.`, `\/`, and `...`
- Fixed spacing between closing delimiters and large operators
- Fixed a bug with math font weight selection
- Symbols and Operators (**Breaking changes**)
- Added `id`, `im`, and `tr` text [operators]($func/math.op)
- Added `id`, `im`, and `tr` text [operators]($math.op)
- Renamed `ident` to `equiv` with alias `eq.triple` and removed
`ident.strict` in favor of `eq.quad`
- Renamed `ast.sq` to `ast.square` and `integral.sq` to `integral.square`
@ -65,36 +65,32 @@ description: |
- Scripting
- Fields
- Added `abs` and `em` field to [lengths]($type/length)
- Added `ratio` and `length` field to
[relative lengths]($type/relative-length)
- Added `x` and `y` field to [2d alignments]($func/align.alignment)
- Added `abs` and `em` field to [lengths]($length)
- Added `ratio` and `length` field to [relative lengths]($relative)
- Added `x` and `y` field to [2d alignments]($align.alignment)
- Added `paint`, `thickness`, `cap`, `join`, `dash`, and `miter-limit` field
to [strokes]($func/line.stroke)
to [strokes]($stroke)
- Accessor and utility methods
- Added [`dedup`]($type/array.dedup) method to arrays
- Added `pt`, `mm`, `cm`, and `inches` method to [lengths]($type/length)
- Added `deg` and `rad` method to [angles]($type/angle)
- Added `kind`, `hex`, `rgba`, `cmyk`, and `luma` method to
[colors]($type/color)
- Added `axis`, `start`, `end`, and `inv` method to
[directions]($func/stack.dir)
- Added `axis` and `inv` method to [alignments]($func/align.alignment)
- Added `inv` method to [2d alignments]($func/align.alignment)
- Added `start` argument to [`enumerate`]($type/array.enumerate) method on
arrays
- Added [`color.mix`]($func/color.mix) function
- Added `mode` and `scope` arguments to [`eval`]($func/eval) function
- Added [`bytes`]($type/bytes) type for holding large byte buffers
- Added [`encoding`]($func/read.encoding) argument to read function to read
a file as bytes instead of a string
- Added [`image.decode`]($func/image.decode) function for decoding an image
- Added [`dedup`]($array.dedup) method to arrays
- Added `pt`, `mm`, `cm`, and `inches` method to [lengths]($length)
- Added `deg` and `rad` method to [angles]($angle)
- Added `kind`, `hex`, `rgba`, `cmyk`, and `luma` method to [colors]($color)
- Added `axis`, `start`, `end`, and `inv` method to [directions]($stack.dir)
- Added `axis` and `inv` method to [alignments]($align.alignment)
- Added `inv` method to [2d alignments]($align.alignment)
- Added `start` argument to [`enumerate`]($array.enumerate) method on arrays
- Added [`color.mix`]($color.mix) function
- Added `mode` and `scope` arguments to [`eval`]($eval) function
- Added [`bytes`]($bytes) type for holding large byte buffers
- Added [`encoding`]($read.encoding) argument to read function to read a
file as bytes instead of a string
- Added [`image.decode`]($image.decode) function for decoding an image
directly from a string or bytes
- Added [`bytes`]($func/bytes) function for converting a string or an array
of integers to bytes
- Added [`array`]($func/array) function for converting bytes to an array of
- Added [`bytes`]($bytes) function for converting a string or an array of
integers to bytes
- Added [`array`]($array) function for converting bytes to an array of
integers
- Added support for converting bytes to a string with the [`str`]($func/str)
- Added support for converting bytes to a string with the [`str`]($str)
function
- Tooling and Diagnostics
@ -126,19 +122,19 @@ description: |
- Fixed displayed compilation time (now includes export)
- Miscellaneous Improvements
- Added [`bookmarked`]($func/heading.bookmarked) argument to heading to
control whether a heading becomes part of the PDF outline
- Added [`caption-pos`]($func/figure.caption-pos) argument to control the
position of a figure's caption
- Added [`metadata`]($func/metadata) function for exposing an arbitrary value
to the introspection system
- Fixed that a [`state`]($func/state) was identified by the pair `(key, init)`
- Added [`bookmarked`]($heading.bookmarked) argument to heading to control
whether a heading becomes part of the PDF outline
- Added [`caption-pos`]($figure.caption-pos) argument to control the position
of a figure's caption
- Added [`metadata`]($metadata) function for exposing an arbitrary value to
the introspection system
- Fixed that a [`state`]($state) was identified by the pair `(key, init)`
instead of just its `key`
- Improved indent logic of [enumerations]($func/enum). Instead of requiring at
- Improved indent logic of [enumerations]($enum). Instead of requiring at
least as much indent as the end of the marker, they now require only one
more space indent than the start of the marker. As a result, even long
markers like `12.` work with just 2 spaces of indent.
- Fixed bug with indent logic of [`raw`]($func/raw) blocks
- Fixed bug with indent logic of [`raw`]($raw) blocks
- Fixed a parsing bug with dictionaries
- Development
@ -158,26 +154,26 @@ description: |
- Math
- Added support for optical size variants of glyphs in math mode
- Added argument to enable [`limits`]($func/math.limits) conditionally
depending on whether the equation is set in [`display`]($func/math.display)
or [`inline`]($func/math.inline) style
- Added argument to enable [`limits`]($math.limits) conditionally depending on
whether the equation is set in [`display`]($math.display) or
[`inline`]($math.inline) style
- Added `gt.eq.slant` and `lt.eq.slant` symbols
- Increased precedence of factorials in math mode (`[$1/n!$]` works correctly
now)
- Improved [underlines]($func/math.underline) and
[overlines]($func/math.overline) in math mode
- Fixed usage of [`limits`]($func/math.limits) function in show rules
- Improved [underlines]($math.underline) and [overlines]($math.overline) in
math mode
- Fixed usage of [`limits`]($math.limits) function in show rules
- Fixed bugs with line breaks in equations
- Text and Layout
- Added support for alternating page [margins]($func/page.margin) with the
`inside` and `outside` keys
- Added support for specifying the page [`binding`]($func/page.binding)
- Added [`to`]($func/pagebreak.to) argument to pagebreak function to skip to
the next even or odd page
- Added support for alternating page [margins]($page.margin) with the `inside`
and `outside` keys
- Added support for specifying the page [`binding`]($page.binding)
- Added [`to`]($pagebreak.to) argument to pagebreak function to skip to the
next even or odd page
- Added basic i18n for a few more languages (TR, SQ, TL)
- Fixed bug with missing table row at page break
- Fixed bug with [underlines]($func/underline)
- Fixed bug with [underlines]($underline)
- Fixed bug superfluous table lines
- Fixed smart quotes after line breaks
- Fixed a crash related to text layout
@ -193,13 +189,13 @@ description: |
- Now displays compilation time
- Miscellaneous Improvements
- Added [`outline.entry`]($func/outline.entry) to customize outline entries
with show rules
- Added [`outline.entry`]($outline.entry) to customize outline entries with
show rules
- Added some hints for error messages
- Added some missing syntaxes for [`raw`]($func/raw) highlighting
- Added some missing syntaxes for [`raw`]($raw) highlighting
- Improved rendering of rotated images in PNG export and web app
- Made [footnotes]($func/footnote) reusable and referenceable
- Fixed bug with citations and bibliographies in [`locate`]($func/locate)
- Made [footnotes]($footnote) reusable and referenceable
- Fixed bug with citations and bibliographies in [`locate`]($locate)
- Fixed inconsistent tense in documentation
- Development
@ -211,45 +207,44 @@ description: |
## Version 0.5.0 (June 9, 2023) { #v0.5.0 }
- Text and Layout
- Added [`raw`]($func/raw) syntax highlighting for many more languages
- Added support for Korean [numbering]($func/numbering)
- Added [`raw`]($raw) syntax highlighting for many more languages
- Added support for Korean [numbering]($numbering)
- Added basic i18n for a few more languages (NL, SV, DA)
- Improved line breaking for East Asian languages
- Expanded functionality of outline [`indent`]($func/outline.indent) property
- Expanded functionality of outline [`indent`]($outline.indent) property
- Fixed footnotes in columns
- Fixed page breaking bugs with [footnotes]($func/footnote)
- Fixed page breaking bugs with [footnotes]($footnote)
- Fixed bug with handling of footnotes in lists, tables, and figures
- Fixed a bug with CJK punctuation adjustment
- Fixed a crash with rounded rectangles
- Fixed alignment of [`line`]($func/line) elements
- Fixed alignment of [`line`]($line) elements
- Math
- **Breaking change:** The syntax rules for mathematical
[attachments]($func/math.attach) were improved: `[$f^abs(3)$]` now parses as
[attachments]($math.attach) were improved: `[$f^abs(3)$]` now parses as
`[$f^(abs(3))$]` instead of `[$(f^abs)(3)$]`. To disambiguate, add a space:
`[$f^zeta (3)$]`.
- Added [forced size]($category/math/sizes) commands for math
(e.g., [`display`]($func/math.display))
- Added [`supplement`]($func/math.equation.supplement) parameter to
[`equation`]($func/math.equation), used by [references]($func/ref)
- Added [forced size]($category/math/sizes) commands for math (e.g.,
[`display`]($math.display))
- Added [`supplement`]($math.equation.supplement) parameter to
[`equation`]($math.equation), used by [references]($ref)
- New [symbols]($category/symbols/sym): `bullet`, `xor`, `slash.big`,
`sigma.alt`, `tack.r.not`, `tack.r.short`, `tack.r.double.not`
- Fixed a bug with symbols in matrices
- Fixed a crash in the [`attach`]($func/math.attach) function
- Fixed a crash in the [`attach`]($math.attach) function
- Scripting
- Added new [`datetime`]($type/datetime) type and
[`datetime.today`]($func/datetime.today) to retrieve the current date
- Added [`str.from-unicode`]($func/str.from-unicode) and
[`str.to-unicode`]($func/str.to-unicode) functions
- Added [`fields`]($type/content.fields) method on content
- Added `base` parameter to [`str`]($func/str) function
- Added [`calc.exp`]($func/calc.exp) and [`calc.ln`]($func/calc.ln)
- Improved accuracy of [`calc.pow`]($func/calc.pow) and
[`calc.log`]($func/calc.log) for specific bases
- Fixed [removal]($type/dictionary.remove) order for dictionary
- Fixed `.at(default: ..)` for [strings]($type/string.at) and
[content]($type/content.at)
- Added new [`datetime`]($datetime) type and
[`datetime.today`]($datetime.today) to retrieve the current date
- Added [`str.from-unicode`]($str.from-unicode) and
[`str.to-unicode`]($str.to-unicode) functions
- Added [`fields`]($content.fields) method on content
- Added `base` parameter to [`str`]($str) function
- Added [`calc.exp`]($calc.exp) and [`calc.ln`]($calc.ln)
- Improved accuracy of [`calc.pow`]($calc.pow) and [`calc.log`]($calc.log) for
specific bases
- Fixed [removal]($dictionary.remove) order for dictionary
- Fixed `.at(default: ..)` for [strings]($str.at) and [content]($content.at)
- Fixed field access on styled elements
- Removed deprecated `calc.mod` function
@ -266,8 +261,8 @@ description: |
- Improved error message for failed length comparisons
- Fixed a bug with images not showing up in Apple Preview
- Fixed multiple bugs with the PDF outline
- Fixed citations and other searchable elements in [`hide`]($func/hide)
- Fixed bugs with [reference supplements]($func/ref.supplement)
- Fixed citations and other searchable elements in [`hide`]($hide)
- Fixed bugs with [reference supplements]($ref.supplement)
- Fixed Nix flake
<contributors from="v0.4.0" to="v0.5.0" />
@ -275,29 +270,28 @@ description: |
## Version 0.4.0 (May 20, 2023) { #v0.4.0 }
- Footnotes
- Implemented support for footnotes
- The [`footnote`]($func/footnote) function inserts a footnote
- The [`footnote.entry`]($func/footnote.entry) function can be used to
customize the footnote listing
- The `{"chicago-notes"}` [citation style]($func/cite.style) is now available
- The [`footnote`]($footnote) function inserts a footnote
- The [`footnote.entry`]($footnote.entry) function can be used to customize
the footnote listing
- The `{"chicago-notes"}` [citation style]($cite.style) is now available
- Documentation
- Added a [Guide for LaTeX users]($guides/guide-for-latex-users)
- Now shows default values for optional arguments
- Added richer outlines in "On this Page"
- Added initial support for search keywords: "Table of Contents" will now find
the [outline]($func/outline) function. Suggestions for more keywords are
welcome!
the [outline]($outline) function. Suggestions for more keywords are welcome!
- Fixed issue with search result ranking
- Fixed many more small issues
- Math
- **Breaking change**: Alignment points (`&`) in equations now alternate
between left and right alignment
- Added support for writing roots with Unicode:
For example, `[$root(x+y)$]` can now also be written as `[$√(x+y)$]`
- Fixed uneven vertical [`attachment`]($func/math.attach) alignment
- Fixed spacing on decorated elements
(e.g., spacing around a [canceled]($func/math.cancel) operator)
- Added support for writing roots with Unicode: For example, `[$root(x+y)$]`
can now also be written as `[$√(x+y)$]`
- Fixed uneven vertical [`attachment`]($math.attach) alignment
- Fixed spacing on decorated elements (e.g., spacing around a
[canceled]($math.cancel) operator)
- Fixed styling for stretchable symbols
- Added `tack.r.double`, `tack.l.double`, `dotless.i` and `dotless.j`
[symbols]($category/symbols/sym)
@ -307,40 +301,37 @@ description: |
- Scripting
- Added function scopes: A function can now hold related definitions in its
own scope, similar to a module. The new [`assert.eq`]($func/assert.eq)
function, for instance, is part of the [`assert`]($func/assert) function's
scope. Note that function scopes are currently only available for built-in
functions.
- Added [`assert.eq`]($func/assert.eq) and [`assert.ne`]($func/assert.ne)
functions for simpler equality and inequality assertions with more helpful
error messages
- Exposed [list]($func/list.item), [enum]($func/enum.item), and
[term list]($func/terms.item) items in their respective functions' scope
- The `at` methods on [strings]($type/string.at), [arrays]($type/array.at),
[dictionaries]($type/dictionary.at), and [content]($type/content.at) now support
own scope, similar to a module. The new [`assert.eq`]($assert.eq) function,
for instance, is part of the [`assert`]($assert) function's scope. Note that
function scopes are currently only available for built-in functions.
- Added [`assert.eq`]($assert.eq) and [`assert.ne`]($assert.ne) functions for
simpler equality and inequality assertions with more helpful error messages
- Exposed [list]($list.item), [enum]($enum.item), and [term list]($terms.item)
items in their respective functions' scope
- The `at` methods on [strings]($str.at), [arrays]($array.at),
[dictionaries]($dictionary.at), and [content]($content.at) now support
specifying a default value
- Added support for passing a function to [`replace`]($type/string.replace)
that is called with each match.
- Fixed [replacement]($type/string.replace) strings: They are now inserted
completely verbatim instead of supporting the previous (unintended) magic
dollar syntax for capture groups
- Added support for passing a function to [`replace`]($str.replace) that is
called with each match.
- Fixed [replacement]($str.replace) strings: They are now inserted completely
verbatim instead of supporting the previous (unintended) magic dollar syntax
for capture groups
- Fixed bug with trailing placeholders in destructuring patterns
- Fixed bug with underscore in parameter destructuring
- Fixed crash with nested patterns and when hovering over an invalid pattern
- Better error messages when casting to an [integer]($func/int) or
[float]($func/float) fails
- Better error messages when casting to an [integer]($int) or [float]($float)
fails
- Text and Layout
- Implemented sophisticated CJK punctuation adjustment
- Disabled [overhang]($func/text.overhang) for CJK punctuation
- Disabled [overhang]($text.overhang) for CJK punctuation
- Added basic translations for Traditional Chinese
- Fixed [alignment]($func/raw.align) of text inside raw blocks (centering a
raw block, e.g. through a figure, will now keep the text itself
left-aligned)
- Fixed [alignment]($raw.align) of text inside raw blocks (centering a raw
block, e.g. through a figure, will now keep the text itself left-aligned)
- Added support for passing a array instead of a function to configure table
cell [alignment]($func/table.align) and [fill]($func/table.fill) per column
- Fixed automatic figure [`kind`]($func/figure.kind) detection
- Made alignment of [enum numbers]($func/enum.number-align) configurable,
cell [alignment]($table.align) and [fill]($table.fill) per column
- Fixed automatic figure [`kind`]($figure.kind) detection
- Made alignment of [enum numbers]($enum.number-align) configurable,
defaulting to `end`
- Figures can now be made breakable with a show-set rule for blocks in figure
- Initial fix for smart quotes in RTL languages
@ -372,8 +363,8 @@ description: |
- Improved incremental parsing for more efficient recompilations
- Added support for `.yaml` extension in addition to `.yml` for bibliographies
- The CLI now emits escape codes only if the output is a TTY
- For users of the `typst` crate: The `Document` is now `Sync` again and
the `World` doesn't have to be `'static` anymore
- For users of the `typst` crate: The `Document` is now `Sync` again and the
`World` doesn't have to be `'static` anymore
<contributors from="v0.3.0" to="v0.4.0" />
@ -381,41 +372,41 @@ description: |
- **Breaking changes:**
- Renamed a few symbols: What was previous `dot.op` is now just `dot` and the
basic dot is `dot.basic`. The same applies to `ast` and `tilde`.
- Renamed `mod` to [`rem`]($func/calc.rem) to more accurately reflect
the behaviour. It will remain available as `mod` until the next update as a
- Renamed `mod` to [`rem`]($calc.rem) to more accurately reflect the
behaviour. It will remain available as `mod` until the next update as a
grace period.
- A lone underscore is not a valid identifier anymore, it can now only be used
in patterns
- Removed `before` and `after` arguments from [`query`]($func/query). This is
now handled through flexible [selectors]($type/selector) combinator methods
- Added support for [attachments]($func/math.attach) (sub-, superscripts) that
- Removed `before` and `after` arguments from [`query`]($query). This is now
handled through flexible [selectors]($selector) combinator methods
- Added support for [attachments]($math.attach) (sub-, superscripts) that
precede the base symbol. The `top` and `bottom` arguments have been renamed
to `t` and `b`.
- New features
- Added support for more complex [strokes]($func/line.stroke)
(configurable caps, joins, and dash patterns)
- Added [`cancel`]($func/math.cancel) function for equations
- Added support for more complex [strokes]($stroke) (configurable caps, joins,
and dash patterns)
- Added [`cancel`]($math.cancel) function for equations
- Added support for [destructuring]($scripting/#bindings) in argument lists
and assignments
- Added [`alt`]($func/image.alt) text argument to image function
- Added [`toml`]($func/toml) function for loading data from a TOML file
- Added [`zip`]($type/array.zip), [`sum`]($type/array.sum), and
[`product`]($type/array.product) methods for arrays
- Added [`alt`]($image.alt) text argument to image function
- Added [`toml`]($toml) function for loading data from a TOML file
- Added [`zip`]($array.zip), [`sum`]($array.sum), and
[`product`]($array.product) methods for arrays
- Added `fact`, `perm`, `binom`, `gcd`, `lcm`, `atan2`, `quo`, `trunc`, and
`fract` [calculation]($category/calculate)
- Improvements
- Text in SVGs now displays properly
- Typst now generates a PDF heading outline
- [References]($func/ref) now provides the referenced element as a field in
show rules
- [References]($ref) now provides the referenced element as a field in show
rules
- Refined linebreak algorithm for better Chinese justification
- Locations are now a valid kind of selector
- Added a few symbols for algebra
- Added Spanish smart quote support
- Added [`selector`]($func/selector) function to turn a selector-like value
into a selector on which combinator methods can be called
- Added [`selector`]($selector) function to turn a selector-like value into a
selector on which combinator methods can be called
- Improved some error messages
- The outline and bibliography headings can now be styled with show-set rules
- Operations on numbers now produce an error instead of overflowing
@ -423,7 +414,7 @@ description: |
- Bug fixes
- Fixed wrong linebreak before punctuation that follows inline equations,
citations, and other elements
- Fixed a bug with [argument sinks]($type/arguments)
- Fixed a bug with [argument sinks]($arguments)
- Fixed strokes with thickness zero
- Fixed hiding and show rules in math
- Fixed alignment in matrices
@ -431,13 +422,13 @@ description: |
- Fixed grid cell alignment
- Fixed alignment of list marker and enum markers in presence of global
alignment settings
- Fixed [path]($func/path) closing
- Fixed [path]($path) closing
- Fixed compiler crash with figure references
- A single trailing line breaks is now ignored in math, just like in text
- Command line interface
- Font path and compilation root can now be set with the environment
variables `TYPST_FONT_PATHS` and `TYPST_ROOT`
- Font path and compilation root can now be set with the environment variables
`TYPST_FONT_PATHS` and `TYPST_ROOT`
- The output of `typst fonts` now includes the embedded fonts
- Development
@ -453,18 +444,18 @@ description: |
- **Breaking changes:**
- Removed support for iterating over index and value in
[for loops]($scripting/#loops). This is now handled via unpacking and
enumerating. Same goes for the [`map`]($type/array.map) method.
- [Dictionaries]($type/dictionary) now iterate in insertion order instead of
enumerating. Same goes for the [`map`]($array.map) method.
- [Dictionaries]($dictionary) now iterate in insertion order instead of
alphabetical order.
- New features
- Added [unpacking syntax]($scripting/#bindings) for let bindings, which
allows things like `{let (1, 2) = array}`
- Added [`enumerate`]($type/array.enumerate) method
- Added [`path`]($func/path) function for drawing Bézier paths
- Added [`layout`]($func/layout) function to access the size of the
surrounding page or container
- Added `key` parameter to [`sorted`]($type/array.sorted) method
- Added [`enumerate`]($array.enumerate) method
- Added [`path`]($path) function for drawing Bézier paths
- Added [`layout`]($layout) function to access the size of the surrounding
page or container
- Added `key` parameter to [`sorted`]($array.sorted) method
- Command line interface
- Fixed `--open` flag blocking the program
@ -478,17 +469,16 @@ description: |
- Added basic i18n for a few more languages
(AR, NB, CS, NN, PL, SL, ES, UA, VI)
- Added a few numbering patterns (Ihora, Chinese)
- Added `sinc` [operator]($func/math.op)
- Fixed bug where math could not be hidden with [`hide`]($func/hide)
- Added `sinc` [operator]($math.op)
- Fixed bug where math could not be hidden with [`hide`]($hide)
- Fixed sizing issues with box, block, and shapes
- Fixed some translations
- Fixed inversion of "R" in [`cal`]($func/math.cal) and
[`frak`]($func/math.frak) styles
- Fixed inversion of "R" in [`cal`]($math.cal) and [`frak`]($math.frak) styles
- Fixed some styling issues in math
- Fixed supplements of references to headings
- Fixed syntax highlighting of identifiers in certain scenarios
- [Ratios]($type/ratio) can now be multiplied with more types and be converted
to [floats]($type/float) with the [`float`]($func/float) function
- [Ratios]($ratio) can now be multiplied with more types and be converted to
[floats]($float) with the [`float`]($float) function
<contributors from="v0.1.0" to="v0.2.0" />
@ -499,22 +489,22 @@ description: |
- `typst watch file.typ` or `typst w file.typ` to compile and watch
- `typst fonts` to list all fonts
- Manual counters now start at zero. Read the "How to step" section
[here]($func/counter) for more details
- The [bibliography styles]($func/bibliography.style)
`{"author-date"}` and `{"author-title"}` were renamed to
`{"chicago-author-date"}` and `{"chicago-author-title"}`
[here]($counter) for more details
- The [bibliography styles]($bibliography.style) `{"author-date"}` and
`{"author-title"}` were renamed to `{"chicago-author-date"}` and
`{"chicago-author-title"}`
- Figure improvements
- Figures now automatically detect their content and adapt their
behaviour. Figures containing tables, for instance, are automatically
prefixed with "Table X" and have a separate counter
- Figures now automatically detect their content and adapt their behaviour.
Figures containing tables, for instance, are automatically prefixed with
"Table X" and have a separate counter
- The figure's supplement (e.g. "Figure" or "Table") can now be customized
- In addition, figures can now be completely customized because the show rule
gives access to the automatically resolved kind, supplement, and counter
- Bibliography improvements
- The [`bibliography`]($func/bibliography) now also accepts multiple
bibliography paths (as an array)
- The [`bibliography`]($bibliography) now also accepts multiple bibliography
paths (as an array)
- Parsing of BibLaTeX files is now more permissive (accepts non-numeric
edition, pages, volumes, dates, and Jabref-style comments; fixed
abbreviation parsing)
@ -522,9 +512,8 @@ description: |
- Fixed APA bibliography ordering
- Drawing additions
- Added [`polygon`]($func/polygon) function for drawing polygons
- Added support for clipping in [boxes]($func/box.clip) and
[blocks]($func/block.clip)
- Added [`polygon`]($polygon) function for drawing polygons
- Added support for clipping in [boxes]($box.clip) and [blocks]($block.clip)
- Command line interface
- Now returns with non-zero status code if there is an error
@ -534,27 +523,26 @@ description: |
- Added `--open` flag to directly open the PDF
- Miscellaneous improvements
- Added [`yaml`]($func/yaml) function to load data from YAML files
- Added [`yaml`]($yaml) function to load data from YAML files
- Added basic i18n for a few more languages (IT, RU, ZH, FR, PT)
- Added numbering support for Hebrew
- Added support for [integers]($type/integer) with base 2, 8, and 16
- Added support for [integers]($int) with base 2, 8, and 16
- Added symbols for double bracket and laplace operator
- The [`link`]($func/link) function now accepts [labels]($func/label)
- The [`link`]($link) function now accepts [labels]($label)
- The link syntax now allows more characters
- Improved justification of Japanese and Chinese text
- Calculation functions behave more consistently w.r.t to non-real results
- Replaced deprecated angle brackets
- Reduced maximum function call depth from 256 to 64
- Fixed [`first-line-indent`]($func/par.first-line-indent) being not applied
when a paragraph starts with styled text
- Fixed [`first-line-indent`]($par.first-line-indent) being not applied when a
paragraph starts with styled text
- Fixed extraneous spacing in unary operators in equations
- Fixed block spacing, e.g. in `{block(above: 1cm, below: 1cm, ..)}`
- Fixed styling of text operators in math
- Fixed invalid parsing of language tag in raw block with a single backtick
- Fixed bugs with displaying counters and state
- Fixed crash related to page counter
- Fixed crash when [`symbol`]($func/symbol) function was called without
arguments
- Fixed crash when [`symbol`]($symbol) function was called without arguments
- Fixed crash in bibliography generation
- Fixed access to label of certain content elements
- Fixed line number in error message for CSV parsing
@ -562,12 +550,12 @@ description: |
<contributors from="v23-03-28" to="v0.1.0" />
## March 28, 2023
## March 28, 2023 { #_ }
- **Breaking changes:**
- Enumerations now require a space after their marker, that is, `[1.ok]` must
now be written as `[1. ok]`
- Changed default style for [term lists]($func/terms): Does not include a
colon anymore and has a bit more indent
- Changed default style for [term lists]($terms): Does not include a colon
anymore and has a bit more indent
- Command line interface
- Added `--font-path` argument for CLI
@ -575,16 +563,15 @@ description: |
- Fixed build of CLI if `git` is not installed
- Miscellaneous improvements
- Added support for disabling [matrix]($func/math.mat) and
[vector]($func/math.vec) delimiters. Generally with
`[#set math.mat(delim: none)]` or one-off with
- Added support for disabling [matrix]($math.mat) and [vector]($math.vec)
delimiters. Generally with `[#set math.mat(delim: none)]` or one-off with
`[$mat(delim: #none, 1, 2; 3, 4)$]`.
- Added [`separator`]($func/terms.separator) argument to term lists
- Added [`round`]($func/math.round) function for equations
- Added [`separator`]($terms.separator) argument to term lists
- Added [`round`]($math.round) function for equations
- Numberings now allow zeros. To reset a counter, you can write
`[#counter(..).update(0)]`
- Added documentation for `{page()}` and `{position()}` methods on
[`location`]($func/locate) type
[`location`]($location) type
- Added symbols for double, triple, and quadruple dot accent
- Added smart quotes for Norwegian Bokmål
- Added Nix flake
@ -593,92 +580,90 @@ description: |
- Fixed parsing of unbalanced delimiters in fractions: `[$1/(2 (x)$]`
- Fixed unexpected parsing of numbers as enumerations, e.g. in `[1.2]`
- Fixed combination of page fill and header
- Fixed compiler crash if [`repeat`]($func/repeat) is used in page with
automatic width
- Fixed [matrices]($func/math.mat) with explicit delimiter
- Fixed [`indent`]($func/terms.indent) property of term lists
- Fixed compiler crash if [`repeat`]($repeat) is used in page with automatic
width
- Fixed [matrices]($math.mat) with explicit delimiter
- Fixed [`indent`]($terms.indent) property of term lists
- Numerous documentation fixes
- Links in bibliographies are now affected by link styling
- Fixed hovering over comments in web app
<contributors from="v23-03-21" to="v23-03-28" />
## March 21, 2023
## March 21, 2023 { #_ }
- Reference and bibliography management
- [Bibliographies]($func/bibliography) and [citations]($func/cite) (currently
supported styles are APA, Chicago Author Date, IEEE, and MLA)
- You can now [reference]($func/ref) sections, figures, formulas, and works
from the bibliography with `[@label]`
- [Bibliographies]($bibliography) and [citations]($cite) (currently supported
styles are APA, Chicago Author Date, IEEE, and MLA)
- You can now [reference]($ref) sections, figures, formulas, and works from
the bibliography with `[@label]`
- You can make an element referenceable with a label:
- `[= Introduction <intro>]`
- `[$ A = pi r^2 $ <area>]`
- Introspection system for interactions between different parts of the document
- [`counter`]($func/counter) function
- [`counter`]($counter) function
- Access and modify counters for pages, headings, figures, and equations
- Define and use your own custom counters
- Time travel: Find out what the counter value was or will be at some other
point in the document (e.g. when you're building a list of figures, you
can determine the value of the figure counter at any given figure).
- Counters count in layout order and not in code order
- [`state`]($func/state) function
- [`state`]($state) function
- Manage arbitrary state across your document
- Time travel: Find out the value of your state at any position in the
document
- State is modified in layout order and not in code order
- [`query`]($func/query) function
- Find all occurrences of an element or a label, either in the whole document
or before/after some location
- [`query`]($query) function
- Find all occurrences of an element or a label, either in the whole
document or before/after some location
- Link to elements, find out their position on the pages and access their
fields
- Example use cases: Custom list of figures or page header with current
chapter title
- [`locate`]($func/locate) function
- [`locate`]($locate) function
- Determines the location of itself in the final layout
- Can be accessed to get the `page` and `x`, `y` coordinates
- Can be used with counters and state to find out their values at that
location
- Can be used with queries to find elements before or after its location
- New [`measure`]($func/measure) function
- New [`measure`]($measure) function
- Measure the layouted size of elements
- To be used in combination with the new [`style`]($func/style) function that
lets you generate different content based on the style context something is
- To be used in combination with the new [`style`]($style) function that lets
you generate different content based on the style context something is
inserted into (because that affects the measured size of content)
- Exposed content representation
- Content is not opaque anymore
- Content can be compared for equality
- The tree of content elements can be traversed with code
- Can be observed in hover tooltips or with [`repr`]($func/repr)
- New [methods]($type/content) on content: `func`, `has`, `at`, and `location`
- Can be observed in hover tooltips or with [`repr`]($repr)
- New [methods]($content) on content: `func`, `has`, `at`, and `location`
- All optional fields on elements are now settable
- More uniform field names (`heading.title` becomes `heading.body`,
`list.items` becomes `list.children`, and a few more changes)
- Further improvements
- Added [`figure`]($func/figure) function
- Added [`numbering`]($func/math.equation.numbering) parameter on equation function
- Added [`numbering`]($func/page.numbering) and
[`number-align`]($func/page.number-align) parameters on page function
- The page function's [`header`]($func/page.header) and
[`footer`]($func/page.footer) parameters do not take functions anymore. If
you want to customize them based on the page number, use the new
[`numbering`]($func/page.numbering) parameter or [`counter`]($func/counter)
function instead.
- Added [`footer-descent`]($func/page.footer-descent) and
[`header-ascent`]($func/page.header-ascent) parameters
- Added [`figure`]($figure) function
- Added [`numbering`]($math.equation.numbering) parameter on equation function
- Added [`numbering`]($page.numbering) and
[`number-align`]($page.number-align) parameters on page function
- The page function's [`header`]($page.header) and [`footer`]($page.footer)
parameters do not take functions anymore. If you want to customize them
based on the page number, use the new [`numbering`]($page.numbering)
parameter or [`counter`]($counter) function instead.
- Added [`footer-descent`]($page.footer-descent) and
[`header-ascent`]($page.header-ascent) parameters
- Better default alignment in header and footer
- Fixed Arabic vowel placement
- Fixed PDF font embedding issues
- Renamed `math.formula` to [`math.equation`]($func/math.equation)
- Renamed `math.formula` to [`math.equation`]($math.equation)
- Font family must be a named argument now: `[#set text(font: "..")]`
- Added support for [hanging indent]($func/par.hanging-indent)
- Renamed paragraph `indent` to
[`first-line-indent`]($func/par.first-line-indent)
- More accurate [logarithm]($func/calc.log) when base is `2` or `10`
- Added support for [hanging indent]($par.hanging-indent)
- Renamed paragraph `indent` to [`first-line-indent`]($par.first-line-indent)
- More accurate [logarithm]($calc.log) when base is `2` or `10`
- Improved some error messages
- Fixed layout of [`terms`]($func/terms) list
- Fixed layout of [`terms`]($terms) list
- Web app improvements
- Added template gallery
@ -697,76 +682,75 @@ description: |
- New back button instead of four-dots button
- Lots of bug fixes
## February 25, 2023
## February 25, 2023 { #_ }
- Font changes
- New default font: Linux Libertine
- New default font for raw blocks: DejaVu Sans Mono
- New default font for math: Book weight of New Computer Modern Math
- Lots of new math fonts available
- Removed Latin Modern fonts in favor of New Computer Modern family
- Removed unnecessary smallcaps fonts which are already accessible through
the corresponding main font and the [`smallcaps`]($func/smallcaps) function
- Removed unnecessary smallcaps fonts which are already accessible through the
corresponding main font and the [`smallcaps`]($smallcaps) function
- Improved default spacing for headings
- Added [`panic`]($func/panic) function
- Added [`clusters`]($type/string.clusters) and
[`codepoints`]($type/string.codepoints)
methods for strings
- Support for multiple authors in [`set document`]($func/document.author)
- Added [`panic`]($panic) function
- Added [`clusters`]($str.clusters) and [`codepoints`]($str.codepoints) methods
for strings
- Support for multiple authors in [`set document`]($document.author)
- Fixed crash when string is accessed at a position that is not a char boundary
- Fixed semicolon parsing in `[#var ;]`
- Fixed incremental parsing when inserting backslash at end of `[#"abc"]`
- Fixed names of a few font families
(including Noto Sans Symbols and New Computer Modern families)
- Fixed names of a few font families (including Noto Sans Symbols and New
Computer Modern families)
- Fixed autocompletion for font families
- Improved incremental compilation for user-defined functions
## February 15, 2023
- [Box]($func/box) and [block]($func/block) have gained `fill`, `stroke`,
`radius`, and `inset` properties
- Blocks may now be explicitly sized, fixed-height blocks can still break
across pages
- Blocks can now be configured to be [`breakable`]($func/block.breakable) or not
- [Numbering style]($func/enum.numbering) can now be configured for nested enums
- [Markers]($func/list.marker) can now be configured for nested lists
- The [`eval`]($func/eval) function now expects code instead of markup and
returns an arbitrary value. Markup can still be evaluated by surrounding the
string with brackets.
## February 15, 2023 { #_ }
- [Box]($box) and [block]($block) have gained `fill`, `stroke`, `radius`, and
`inset` properties
- Blocks may now be explicitly sized, fixed-height blocks can still break across
pages
- Blocks can now be configured to be [`breakable`]($block.breakable) or not
- [Numbering style]($enum.numbering) can now be configured for nested enums
- [Markers]($list.marker) can now be configured for nested lists
- The [`eval`]($eval) function now expects code instead of markup and returns an
arbitrary value. Markup can still be evaluated by surrounding the string with
brackets.
- PDFs generated by Typst now contain XMP metadata
- Link boxes are now disabled in PDF output
- Tables don't produce small empty cells before a pagebreak anymore
- Fixed raw block highlighting bug
## February 12, 2023
## February 12, 2023 { #_ }
- Shapes, images, and transformations (move/rotate/scale/repeat) are now
block-level. To integrate them into a paragraph, use a [`box`]($func/box) as
with other elements.
block-level. To integrate them into a paragraph, use a [`box`]($box) as with
other elements.
- A colon is now required in an "everything" show rule: Write `{show: it => ..}`
instead of `{show it => ..}`. This prevents intermediate states that ruin
your whole document.
instead of `{show it => ..}`. This prevents intermediate states that ruin your
whole document.
- Non-math content like a shape or table in a math formula is now centered
vertically
- Support for widow and orphan prevention within containers
- Support for [RTL]($func/text.dir) in lists, grids, and tables
- Support for [RTL]($text.dir) in lists, grids, and tables
- Support for explicit `{auto}` sizing for boxes and shapes
- Support for fractional (i.e. `{1fr}`) widths for boxes
- Fixed bug where columns jump to next page
- Fixed bug where list items have no leading
- Fixed relative sizing in lists, squares and grid auto columns
- Fixed relative displacement in [`place`]($func/place) function
- Fixed relative displacement in [`place`]($place) function
- Fixed that lines don't have a size
- Fixed bug where `{set document(..)}` complains about being after content
- Fixed parsing of `{not in}` operation
- Fixed hover tooltips in math
- Fixed bug where a heading show rule may not contain a pagebreak when an
outline is present
- Added [`baseline`]($func/box.baseline) property on [`box`]($func/box)
- Added [`tg`]($func/math.op) and [`ctg`]($func/math.op) operators in math
- Added delimiter setting for [`cases`]($func/math.cases) function
- Added [`baseline`]($box.baseline) property on [`box`]($box)
- Added [`tg`]($math.op) and [`ctg`]($math.op) operators in math
- Added delimiter setting for [`cases`]($math.cases) function
- Parentheses are now included when accepting a function autocompletion
## February 2, 2023
- Merged text and math symbols, renamed a few symbols
(including `infty` to `infinity` with the alias `oo`)
## February 2, 2023 { #_ }
- Merged text and math symbols, renamed a few symbols (including `infty` to
`infinity` with the alias `oo`)
- Fixed missing italic mappings
- Math italics correction is now applied properly
- Parentheses now scale in `[$zeta(x/2)$]`
@ -779,17 +763,17 @@ description: |
- Heading and list markers now parse consistently
- Allow arbitrary math directly in content
## January 30, 2023
## January 30, 2023 { #_ }
[Go to the announcement blog post.](https://typst.app/blog/2023/january-update)
- New expression syntax in markup/math
- Blocks cannot be directly embedded in markup anymore
- Like other expressions, they now require a leading hashtag
- More expressions available with hashtag, including literals
(`[#"string"]`) as well as field access and method call
without space: `[#emoji.face]`
- More expressions available with hashtag, including literals (`[#"string"]`)
as well as field access and method call without space: `[#emoji.face]`
- New import syntax
- `[#import "module.typ"]` creates binding named `module`
- `[#import "module.typ": a, b]` or `[#import "module.typ": *]` to import items
- `[#import "module.typ": a, b]` or `[#import "module.typ": *]` to import
items
- `[#import emoji: face, turtle]` to import from already bound module
- New symbol handling
- Removed symbol notation
@ -811,8 +795,8 @@ description: |
- To forcibly match two delimiters, use `lr` function
- Line breaks may occur between matched delimiters
- Delimiters may also be unbalanced
- You can also use the `lr` function to scale the brackets
(or just one bracket) to a specific size manually
- You can also use the `lr` function to scale the brackets (or just one
bracket) to a specific size manually
- Multi-line math with alignment
- The `\` character inserts a line break
- The `&` character defines an alignment point
@ -835,10 +819,11 @@ description: |
- New shorthands: `[|`, `|]`, and `||`
- New `attach` function, overridable attachments with `script` and `limit`
- Manual spacing in math, with `h`, `thin`, `med`, `thick` and `quad`
- Symbols and other content may now be used like a function, e.g. `[$zeta(x)$]`
- Symbols and other content may now be used like a function, e.g.
`[$zeta(x)$]`
- Added Fira Math font, removed Noto Sans Math font
- Support for alternative math fonts through
`[#show math.formula: set text("Fira Math")]`
- Support for alternative math fonts through `[#show math.formula: set
text("Fira Math")]`
- More library improvements
- New `calc` module, `abs`, `min`, `max`, `even`, `odd` and `mod` moved there
- New `message` argument on `{assert}` function

@ -6,8 +6,8 @@ description: |
# Community
Hey and welcome to the Community page! We're so glad you're here. Typst is
developed by an early-stage startup and is still in its infancy, but it
would be pointless without people like you who are interested in it.
developed by an early-stage startup and is still in its infancy, but it would be
pointless without people like you who are interested in it.
We would love to not only hear from you but to also provide spaces where you can
discuss any topic around Typst, typesetting, writing, the sciences, and
@ -22,9 +22,9 @@ Of course, you are also very welcome to connect with us on social media
[GitHub](https://github.com/typst)).
## What to share? { #want-to-share }
For our community, we want to foster versatility and inclusivity.
You are welcome to post about any topic that you think would interest other
community members, but if you need a little inspiration, here are a few ideas:
For our community, we want to foster versatility and inclusivity. You are
welcome to post about any topic that you think would interest other community
members, but if you need a little inspiration, here are a few ideas:
- Share and discuss your thoughts and ideas for new features or improvements
you'd like to see in Typst
@ -33,16 +33,15 @@ community members, but if you need a little inspiration, here are a few ideas:
- Share importable files or templates that you use to style your documents
- Alert us of bugs you encounter while using Typst
## Beta test { #beta-test }
We are starting a public beta test of our product on March 21st, 2023.
The Typst compiler is still under active development and breaking changes can
occur at any point. The compiler is developed in the open on
## Beta test
We are starting a public beta test of our product on March 21st, 2023. The Typst
compiler is still under active development and breaking changes can occur at any
point. The compiler is developed in the open on
[GitHub](https://github.com/typst/typst).
We will update the members of our Discord server and our social media followers
when new features become available. We'll also update you on the
development progress of large features. A development tracker will become
available on the documentation pages soon.
when new features become available. We'll also update you on the development
progress of large features.
## How to support Typst { #support-typst }
If you want to support Typst, there are multiple ways to do that! You can

@ -4,7 +4,7 @@ description: |
similarities between Typst and LaTeX so you can get started quickly.
---
# Guide for LaTeX users
# Guide for LaTeX users { # }
This page is a good starting point if you have used LaTeX before and want to try
out Typst. We will explore the main differences between these two systems from a
user perspective. Although Typst is not built upon LaTeX and has a different
@ -32,8 +32,8 @@ That's easy. You just create a new, empty text file (the file extension is
`.typ`). No boilerplate is needed to get started. Simply start by writing your
text. It will be set on an empty A4-sized page. If you are using the web app,
click "+ Empty document" to create a new project with a file and enter the
editor. [Paragraph breaks]($func/parbreak) work just as they do in LaTeX, just
use a blank line.
editor. [Paragraph breaks]($parbreak) work just as they do in LaTeX, just use a
blank line.
```example
Hey there!
@ -47,8 +47,8 @@ LaTeX uses the command `\section` to create a section heading. Nested headings
are indicated with `\subsection`, `\subsubsection`, etc. Depending on your
document class, there is also `\part` or `\chapter`.
In Typst, [headings]($func/heading) are less verbose: You prefix the line with
the heading on it with an equals sign and a space to get a first-order heading:
In Typst, [headings]($heading) are less verbose: You prefix the line with the
heading on it with an equals sign and a space to get a first-order heading:
`[= Introduction]`. If you need a second-order heading, you use two equals
signs: `[== In this paper]`. You can nest headings as deeply as you'd like by
adding more equals signs.
@ -60,23 +60,23 @@ Emphasis (usually rendered as italic text) is expressed by enclosing text in
Here is a list of common markup commands used in LaTeX and their Typst
equivalents. You can also check out the [full syntax cheat sheet]($syntax).
| Element | LaTeX | Typst | See |
|:-----------------|:--------------------------|:-----------------------|:-------------------------|
| Strong emphasis | `\textbf{strong}` | `[*strong*]` | [`strong`]($func/strong) |
| Emphasis | `\emph{emphasis}` | `[_emphasis_]` | [`emph`]($func/emph) |
| Monospace / code | `\texttt{print(1)}` | ``[`print(1)`]`` | [`raw`]($func/raw) |
| Link | `\url{https://typst.app}` | `[https://typst.app/]` | [`link`]($func/link) |
| Label | `\label{intro}` | `[<intro>]` | [`label`]($func/label) |
| Reference | `\ref{intro}` | `[@intro]` | [`ref`]($func/ref) |
| Citation | `\cite{humphrey97}` | `[@humphrey97]` | [`cite`]($func/cite) |
| Bullet list | `itemize` environment | `[- List]` | [`list`]($func/list) |
| Numbered list | `enumerate` environment | `[+ List]` | [`enum`]($func/enum) |
| Term list | `description` environment | `[/ Term: List]` | [`terms`]($func/terms) |
| Figure | `figure` environment | `figure` function | [`figure`]($func/figure) |
| Table | `table` environment | `table` function | [`table`]($func/table) |
| Equation | `$x$`, `align` / `equation` environments | `[$x$]`, `[$ x = y $]` | [`equation`]($func/math.equation) |
| Element | LaTeX | Typst | See
|:-----------------|:--------------------------|:-----------------------|:--------------------
| Strong emphasis | `\textbf{strong}` | `[*strong*]` | [`strong`]($strong) |
| Emphasis | `\emph{emphasis}` | `[_emphasis_]` | [`emph`]($emph) |
| Monospace / code | `\texttt{print(1)}` | ``[`print(1)`]`` | [`raw`]($raw) |
| Link | `\url{https://typst.app}` | `[https://typst.app/]` | [`link`]($link) |
| Label | `\label{intro}` | `[<intro>]` | [`label`]($label) |
| Reference | `\ref{intro}` | `[@intro]` | [`ref`]($ref) |
| Citation | `\cite{humphrey97}` | `[@humphrey97]` | [`cite`]($cite) |
| Bullet list | `itemize` environment | `[- List]` | [`list`]($list) |
| Numbered list | `enumerate` environment | `[+ List]` | [`enum`]($enum) |
| Term list | `description` environment | `[/ Term: List]` | [`terms`]($terms) |
| Figure | `figure` environment | `figure` function | [`figure`]($figure) |
| Table | `table` environment | `table` function | [`table`]($table) |
| Equation | `$x$`, `align` / `equation` environments | `[$x$]`, `[$ x = y $]` | [`equation`]($math.equation) |
[Lists]($func/list) do not rely on environments in Typst. Instead, they have
[Lists]($list) do not rely on environments in Typst. Instead, they have
lightweight syntax like headings. To create an unordered list (`itemize`),
prefix each line of an item with a hyphen:
@ -100,11 +100,11 @@ To write this list in Typst...
````
Nesting lists works just by using proper indentation. Adding a blank line in
between items results in a more [widely]($func/list.tight) spaced list.
between items results in a more [widely]($list.tight) spaced list.
To get a [numbered list]($func/enum) (`enumerate`) instead, use a `+` instead of
the hyphen. For a [term list]($func/terms) (`description`), write
`[/ Term: Description]` instead.
To get a [numbered list]($enum) (`enumerate`) instead, use a `+` instead of the
hyphen. For a [term list]($terms) (`description`), write `[/ Term: Description]`
instead.
## How do I use a command? { #commands }
LaTeX heavily relies on commands (prefixed by backslashes). It uses these
@ -115,16 +115,16 @@ braces: `\cite{rasmus}`.
Typst differentiates between [markup mode and code mode]($scripting/#blocks).
The default is markup mode, where you compose text and apply syntactic
constructs such as `[*stars for bold text*]`. Code mode, on the other hand,
parallels programming languages like Python, providing the option to input
and execute segments of code.
parallels programming languages like Python, providing the option to input and
execute segments of code.
Within Typst's markup, you can switch to code mode for a single command (or
rather, _expression_) using a hashtag (`#`). This is how you call functions to,
for example, split your project into different [files]($scripting/#modules)
or render text based on some [condition]($scripting/#conditionals).
Within code mode, it is possible to include normal markup
[_content_]($type/content) by using square brackets. Within code mode, this
content is treated just as any other normal value for a variable.
for example, split your project into different [files]($scripting/#modules) or
render text based on some [condition]($scripting/#conditionals). Within code
mode, it is possible to include normal markup [_content_]($content) by using
square brackets. Within code mode, this content is treated just as any other
normal value for a variable.
```example
First, a rectangle:
@ -142,15 +142,14 @@ And finally a little loop:
]
```
A function call always involves the name of the function ([`rect`]($func/rect),
[`underline`]($func/underline), [`calc.max`]($func/calc.max),
[`range`]($func/range)) followed by parentheses (as opposed to LaTeX where the
square brackets and curly braces are optional if the macro requires no
arguments). The expected list of arguments passed within those parentheses
depends on the concrete function and is specified in the
[reference]($reference).
A function call always involves the name of the function ([`rect`]($rect),
[`underline`]($underline), [`calc.max`]($calc.max), [`range`]($range)) followed
by parentheses (as opposed to LaTeX where the square brackets and curly braces
are optional if the macro requires no arguments). The expected list of arguments
passed within those parentheses depends on the concrete function and is
specified in the [reference]($reference).
### Arguments { #arguments }
### Arguments
A function can have multiple arguments. Some arguments are positional, i.e., you
just provide the value: The function `[#lower("SCREAM")]` returns its argument
in all-lowercase. Many functions use named arguments instead of positional
@ -173,13 +172,13 @@ Named arguments are similar to how some LaTeX environments are configured, for
example, you would type `\begin{enumerate}[label={\alph*)}]` to start a list
with the labels `a)`, `b)`, and so on.
Often, you want to provide some [content]($type/content) to a function. For
example, the LaTeX command `\underline{Alternative A}` would translate to
Often, you want to provide some [content]($content) to a function. For example,
the LaTeX command `\underline{Alternative A}` would translate to
`[#underline([Alternative A])]` in Typst. The square brackets indicate that a
value is [content]($type/content). Within these brackets, you can use normal
markup. However, that's a lot of parentheses for a pretty simple construct.
This is why you can also move trailing content arguments after the parentheses
(and omit the parentheses if they would end up empty).
value is [content]($content). Within these brackets, you can use normal markup.
However, that's a lot of parentheses for a pretty simple construct. This is why
you can also move trailing content arguments after the parentheses (and omit the
parentheses if they would end up empty).
```example
Typst is an #underline[alternative]
@ -188,20 +187,20 @@ to LaTeX.
#rect(fill: aqua)[Get started here!]
```
### Data types { #data-types }
### Data types
You likely already noticed that the arguments have distinctive data types. Typst
supports [many data types]($type). Below, there is a table with some of the most
supports many data types. Below, there is a table with some of the most
important ones and how to write them. In order to specify values of any of these
types, you have to be in code mode!
| Data type | Example |
|:-------------------------------------|:----------------------------------|
| [Content]($type/content) | `{[*fast* typesetting]}` |
| [String]($type/string) | `{"Pietro S. Author"}` |
| [Integer]($type/integer) | `{23}` |
| [Floating point number]($type/float) | `{1.459}` |
| [Absolute length]($type/length) | `{12pt}`, `{5in}`, `{0.3cm}`, ... |
| [Relative length]($type/ratio) | `{65%}` |
| Data type | Example |
|:--------------------------------|:----------------------------------|
| [Content]($content) | `{[*fast* typesetting]}` |
| [String]($str) | `{"Pietro S. Author"}` |
| [Integer]($int) | `{23}` |
| [Floating point number]($float) | `{1.459}` |
| [Absolute length]($length) | `{12pt}`, `{5in}`, `{0.3cm}`, ... |
| [Relative length]($ratio) | `{65%}` |
The difference between content and string is that content can contain markup,
including function calls, while a string really is just a plain sequence of
@ -219,9 +218,9 @@ braces and only affect that argument. Other commands such as
content within the document or current scope.
In Typst, the same function can be used both to affect the appearance for the
remainder of the document, a block (or scope), or just its arguments. For example,
`[#text(weight: "bold")[bold text]]` will only embolden its argument, while
`[#set text(weight: "bold")]` will embolden any text until the end of the
remainder of the document, a block (or scope), or just its arguments. For
example, `[#text(weight: "bold")[bold text]]` will only embolden its argument,
while `[#set text(weight: "bold")]` will embolden any text until the end of the
current block, or, if there is none, document. The effects of a function are
immediately obvious based on whether it is used in a call or a
[set rule.]($styling/#set-rules)
@ -249,9 +248,9 @@ Good results can only be obtained by
```
The `+` is syntactic sugar (think of it as an abbreviation) for a call to the
[`{enum}`]($func/enum) function, to which we apply a set rule above. [Most
syntax is linked to a function in this way.]($syntax) If you need to style an
element beyond what its arguments enable, you can completely redefine its
[`{enum}`]($enum) function, to which we apply a set rule above.
[Most syntax is linked to a function in this way.]($syntax) If you need to style
an element beyond what its arguments enable, you can completely redefine its
appearance with a [show rule]($styling/#show-rules) (somewhat comparable to
`\renewcommand`).
@ -261,7 +260,7 @@ command to define how your document is supposed to look. In that command, you
may have replaced `article` with another value such as `report` and `amsart` to
select a different look.
When using Typst, you style your documents with [functions]($type/function).
When using Typst, you style your documents with [functions]($function).
Typically, you use a template that provides a function that styles your whole
document. First, you import the function from a template file. Then, you apply
it to your whole document. This is accomplished with a
@ -357,7 +356,7 @@ paragraphs right here!
```
The [`{import}`]($scripting/#modules) statement makes
[functions]($type/function) (and other definitions) from another file available.
[functions]($function) (and other definitions) from another file available.
In this example, it imports the `conf` function from the `conf.typ` file. This
function formats a document as a conference article. We use a show rule to apply
it to the document and also configure some metadata of the article. After
@ -393,23 +392,23 @@ Typst is "batteries included," so the equivalent of many popular LaTeX packages
is built right-in. Below, we compiled a table with frequently loaded packages
and their corresponding Typst functions.
| LaTeX Package | Typst Alternative |
|:--------------------------------|:---------------------------------------------------------------------|
| graphicx, svg | [`image`]($func/image) function |
| tabularx | [`table`]($func/table), [`grid`]($func/grid) functions |
| fontenc, inputenc, unicode-math | Just start writing! |
| babel, polyglossia | [`text`]($func/text.lang) function: `[#set text(lang: "zh")]` |
| amsmath | [Math mode]($category/math) |
| amsfonts, amssymb | [`sym`]($category/symbols) module and [syntax]($syntax/#math) |
| geometry, fancyhdr | [`page`]($func/page) function |
| xcolor | [`text`]($func/text.fill) function: `[#set text(fill: rgb("#0178A4"))]` |
| hyperref | [`link`]($func/link) function |
| bibtex, biblatex, natbib | [`cite`]($func/cite), [`bibliography`]($func/bibliography) functions |
| lstlisting, minted | [`raw`]($func/raw) function and syntax |
| parskip | [`block`]($func/block.spacing) and [`par`]($func/par.first-line-indent) functions |
| csquotes | Set the [`text`]($func/text.lang) language and type `["]` or `[']` |
| caption | [`figure`]($func/figure) function |
| enumitem | [`list`]($func/list), [`enum`]($func/enum), [`terms`]($func/terms) functions |
| LaTeX Package | Typst Alternative |
|:--------------------------------|:------------------------------------------------------------- |
| graphicx, svg | [`image`]($image) function |
| tabularx | [`table`]($table), [`grid`]($grid) functions |
| fontenc, inputenc, unicode-math | Just start writing! |
| babel, polyglossia | [`text`]($text.lang) function: `[#set text(lang: "zh")]` |
| amsmath | [Math mode]($category/math) |
| amsfonts, amssymb | [`sym`]($category/symbols) module and [syntax]($syntax/#math) |
| geometry, fancyhdr | [`page`]($page) function |
| xcolor | [`text`]($text.fill) function: `[#set text(fill: rgb("#0178A4"))]` |
| hyperref | [`link`]($link) function |
| bibtex, biblatex, natbib | [`cite`]($cite), [`bibliography`]($bibliography) functions |
| lstlisting, minted | [`raw`]($raw) function and syntax |
| parskip | [`block`]($block.spacing) and [`par`]($par.first-line-indent) functions |
| csquotes | Set the [`text`]($text.lang) language and type `["]` or `[']` |
| caption | [`figure`]($figure) function |
| enumitem | [`list`]($list), [`enum`]($enum), [`terms`]($terms) functions |
If you need to load functions and variables from another file, for example, to
use a template, you can use an [`import`]($scripting/#modules) statement. If you
@ -444,12 +443,12 @@ Typst pre-defines a lot of useful variables in math mode. All Greek (`alpha`,
their name. Some symbols are additionally available through shorthands, such as
`<=`, `>=`, and `->`.
Refer to the [symbol page]($func/symbol) for a full list of the symbols.
Refer to the [symbol pages]($reference/symbols) for a full list of the symbols.
If a symbol is missing, you can also access it through a
[Unicode escape sequence]($syntax/#escapes).
Alternate and related forms of symbols can often be selected by
[appending a modifier]($type/symbol) after a period. For example,
[appending a modifier]($symbol) after a period. For example,
`arrow.l.squiggly` inserts a squiggly left-pointing arrow. If you want to insert
multiletter text in your expression instead, enclose it in double quotes:
@ -459,7 +458,7 @@ $ delta "if" x <= 5 $
In Typst, delimiters will scale automatically for their expressions, just as if
`\left` and `\right` commands were implicitly inserted in LaTeX. You can
customize delimiter behavior using the [`lr` function]($func/math.lr). To
customize delimiter behavior using the [`lr` function]($math.lr). To
prevent a pair of delimiters from scaling, you can escape them with backslashes.
Typst will automatically set terms around a slash `/` as a fraction while
@ -470,7 +469,7 @@ fraction will appear in the output.
$ f(x) = (x + 1) / x $
```
[Sub- and superscripts]($func/math.attach) work similarly in Typst and LaTeX.
[Sub- and superscripts]($math.attach) work similarly in Typst and LaTeX.
`{$x^2$}` will produce a superscript, `{$x_2$}` yields a subscript. If you want
to include more than one value in a sub- or superscript, enclose their contents
in parentheses: `{$x_(a -> epsilon)$}`.
@ -487,7 +486,7 @@ $ f(x, y) := cases(
) $
```
The above example uses the [`cases` function]($func/math.cases) to describe f. Within
The above example uses the [`cases` function]($math.cases) to describe f. Within
the cases function, arguments are delimited using commas and the arguments are
also interpreted as math. If you need to interpret arguments as Typst
values instead, prefix them with a `#`:
@ -514,7 +513,7 @@ If you'd like to enter your mathematical symbols directly as Unicode, that is
possible, too!
Math calls can have two-dimensional argument lists using `;` as a delimiter. The
most common use for this is the [`mat` function]($func/math.mat) that creates
most common use for this is the [`mat` function]($math.mat) that creates
matrices:
```example
@ -531,13 +530,13 @@ Papers set in LaTeX have an unmistakeable look. This is mostly due to their
font, Computer Modern, justification, narrow line spacing, and wide margins.
The example below
- sets wide [margins]($func/page.margin)
- enables [justification]($func/par.justify), [tighter lines]($func/par.leading)
and [first-line-indent]($func/par.first-line-indent)
- [sets the font]($func/text.font) to "New Computer Modern", an OpenType
derivate of Computer Modern for both text and [code blocks]($func/raw)
- disables paragraph [spacing]($func/block.spacing)
- increases [spacing]($func/block.spacing) around [headings]($func/heading)
- sets wide [margins]($page.margin)
- enables [justification]($par.justify), [tighter lines]($par.leading) and
[first-line-indent]($par.first-line-indent)
- [sets the font]($text.font) to "New Computer Modern", an OpenType derivate of
Computer Modern for both text and [code blocks]($raw)
- disables paragraph [spacing]($block.spacing)
- increases [spacing]($block.spacing) around [headings]($heading)
```typ
#set page(margin: 1.75in)
@ -566,9 +565,9 @@ applicable, contains possible workarounds.
- **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
[`page` function]($func/page) which will force a page break. If you just want
a few paragraphs to stretch into the margins, then reverting to the old
margins, you can use the [`pad` function]($func/pad) with negative padding.
[`page` function]($page) which will force a page break. If you just want a few
paragraphs to stretch into the margins, then reverting to the old margins, you
can use the [`pad` function]($pad) with negative padding.
- **Floating figures.** The figure command of LaTeX will smartly choose where to
place a figure, be it on the top or bottom of the page, or a dedicated figure
@ -589,9 +588,9 @@ applicable, contains possible workarounds.
orphans, it uses less sophisticated algorithms to determine page breaks. You
can insert custom page breaks in Typst using `[#pagebreak(weak: true)]` before
submitting your document. The argument `weak` ensures that no double page
break will be created if this spot would be a natural page break
anyways. You can also use `[#v(1fr)]` to distribute space on your page. It
works quite similar to LaTeX's `\vfill`.
break will be created if this spot would be a natural page break anyways. You
can also use `[#v(1fr)]` to distribute space on your page. It works quite
similar to LaTeX's `\vfill`.
- **Bibliographies are not customizable.** In LaTeX, the packages `bibtex`,
`biblatex`, and `natbib` provide a wide range of reference and bibliography

@ -16,28 +16,29 @@ you can get started with writing.
In Typst, each page has a width, a height, and margins on all four sides. The
top and bottom margins may contain a header and footer. The set rule of the
[`{page}`]($func/page) element is where you control all of the page setup. If
you make changes with this set rule, Typst will ensure that there is a new and
conforming empty page afterward, so it may insert a page break. Therefore, it
is best to specify your [`{page}`]($func/page) set rule at the start of your
document or in your template.
[`{page}`]($page) element is where you control all of the page setup. If you
make changes with this set rule, Typst will ensure that there is a new and
conforming empty page afterward, so it may insert a page break. Therefore, it is
best to specify your [`{page}`]($page) set rule at the start of your document or
in your template.
```example
#set rect(
width: 100%,
height: 100%,
inset: 4pt
inset: 4pt,
)
>>> #set text(6pt)
>>> #set page(margin: auto)
#set page(
"iso-b7",
header: rect[Header],
footer: rect[Footer],
paper: "iso-b7",
header: rect(fill: aqua)[Header],
footer: rect(fill: aqua)[Footer],
number-align: center,
)
#rect(fill: rgb("#565565"))
#rect(fill: aqua)
```
This example visualizes the dimensions for page content, headers, and footers.
@ -45,45 +46,46 @@ The page content is the page size (ISO B7) minus each side's default margin. In
the top and the bottom margin, there are stroked rectangles visualizing the
header and footer. They do not touch the main content, instead, they are offset
by 30% of the respective margin. You can control this offset by specifying the
[`header-ascent`]($func/page.header-ascent) and
[`footer-descent`]($func/page.footer-descent) arguments.
[`header-ascent`]($page.header-ascent) and
[`footer-descent`]($page.footer-descent) arguments.
Below, the guide will go more into detail on how to accomplish common page setup
requirements with examples.
## Customize page size and margins { #customize-margins }
Typst's default page size is A4 paper. Depending on your region and your
use case, you will want to change this. You can do this by using the
[`{page}`]($func/page) set rule and passing it a string argument to use a common
page size. Options include the complete ISO 216 series (e.g. `"iso-a4"`,
`"iso-c2"`), customary US formats like `"us-legal"` or `"us-letter"`, and more.
Check out the reference for the [page's paper argument]($func/page.paper) to
learn about all available options.
Typst's default page size is A4 paper. Depending on your region and your use
case, you will want to change this. You can do this by using the
[`{page}`]($page) set rule and passing it a string argument to use a common page
size. Options include the complete ISO 216 series (e.g. `"iso-a4"`, `"iso-c2"`),
customary US formats like `"us-legal"` or `"us-letter"`, and more. Check out the
reference for the [page's paper argument]($page.paper) to learn about all
available options.
```example
>>> #set page(margin: auto)
#set page("us-letter")
This page likes freedom.
```
If you need to customize your page size to some dimensions, you can specify the
named arguments [`width`]($func/page.width) and [`height`]($func/page.height)
instead.
named arguments [`width`]($page.width) and [`height`]($page.height) instead.
```example
>>> #set page(margin: auto)
#set page(width: 12cm, height: 12cm)
This page is a square.
```
### Change the page's margins { #change-margins }
Margins are a vital ingredient for good typography: [Typographers consider lines
that fit between 45 and 75 characters best length for
legibility](http://webtypography.net/2.1.2) and your margins and
Margins are a vital ingredient for good typography:
[Typographers consider lines that fit between 45 and 75 characters best length
for legibility](http://webtypography.net/2.1.2) and your margins and
[columns](#columns) help define line widths. By default, Typst will create
margins proportional to the page size of your document. To set custom margins,
you will use the [`margin`]($func/page.margin) argument in the
[`{page}`]($func/page) set rule.
you will use the [`margin`]($page.margin) argument in the [`{page}`]($page) set
rule.
The `margin` argument will accept a length if you want to set all margins to the
same width. However, you often want to set different margins on each side. To do
@ -119,11 +121,7 @@ the margin dictionary. The `inside` margin points towards the spine, and the
`outside` margin points towards the edge of the bound book.
```typ
#set page(margin: (
inside: 2.5cm,
outside: 2cm,
y: 1.75cm,
))
#set page(margin: (inside: 2.5cm, outside: 2cm, y: 1.75cm))
```
Typst will assume that documents written in Left-to-Right scripts are bound on
@ -133,13 +131,12 @@ output by a different app, the binding is reversed from Typst's perspective.
Also, some books, like English-language Mangas are customarily bound on the
right, despite English using Left-to-Right script. To change the binding side
and explicitly set where the `inside` and `outside` are, set the
[`binding`]($func/page.binding) argument in the [`{page}`]($func/page) set rule.
[`binding`]($page.binding) argument in the [`{page}`]($page) set rule.
```typ
#set text(lang: "es")
// Produce a book bound on the right,
// even though it is set in Spanish.
#set text(lang: "es")
#set page(binding: right)
```
@ -151,9 +148,9 @@ Headers and footers are inserted in the top and bottom margins of every page.
You can add custom headers and footers or just insert a page number.
In case you need more than just a page number, the best way to insert a header
and a footer are the [`header`]($func/page.header) and
[`footer`]($func/page.footer) arguments of the [`{page}`]($func/page) set rule.
You can pass any content as their values:
and a footer are the [`header`]($page.header) and [`footer`]($page.footer)
arguments of the [`{page}`]($page) set rule. You can pass any content as their
values:
```example
>>> #set page("a5", margin: (x: 2.5cm, y: 3cm))
@ -168,7 +165,7 @@ You can pass any content as their values:
Headers are bottom-aligned by default so that they do not collide with the top
edge of the page. You can change this by wrapping your header in the
[`{align}`]($func/align) function.
[`{align}`]($align) function.
### Different header and footer on specific pages { #specific-pages }
You'll need different headers and footers on some pages. For example, you may
@ -191,13 +188,13 @@ conditionally remove the header on the first page:
```
This example may look intimidating, but let's break it down: We are telling
Typst that the header depends on the current [location]($func/locate). The `loc`
Typst that the header depends on the current [location]($locate). The `loc`
value allows other functions to find out where on the page we currently are. We
then ask Typst if the page [counter]($func/counter) is larger than one at our
current position. The page counter starts at one, so we are skipping the header
on a single page. Counters may have multiple levels. This feature is used for
items like headings, but the page counter will always have a single level, so we
can just look at the first one.
then ask Typst if the page [counter]($counter) is larger than one at our current
position. The page counter starts at one, so we are skipping the header on a
single page. Counters may have multiple levels. This feature is used for items
like headings, but the page counter will always have a single level, so we can
just look at the first one.
You can, of course, add an `else` to this example to add a different header to
the first page instead.
@ -206,8 +203,8 @@ the first page instead.
The technique described in the previous section can be adapted to perform more
advanced tasks using Typst's labels. For example, pages with big tables could
omit their headers to help keep clutter down. We will mark our tables with a
`<big-table>` [label]($type/label) and use the [query system]($func/query) to
find out if such a label exists on the current page:
`<big-table>` [label]($label) and use the [query system]($query) to find out if
such a label exists on the current page:
```typ
>>> #set page("a5", margin: (x: 2.5cm, y: 3cm))
@ -232,8 +229,10 @@ find out if such a label exists on the current page:
#pagebreak()
#table(
columns: 2 * (1fr, )
)[A][B][C][D] <big-table>
columns: 2 * (1fr,),
[A], [B],
[C], [D],
) <big-table>
```
Here, we query for all instances of the `<big-table>` label. We then check that
@ -243,10 +242,10 @@ could add an `else` to add another header instead of deleting it.
## Add and customize page numbers { #page-numbers }
Page numbers help readers keep track of and reference your document more easily.
The simplest way to insert footnotes is the [`numbering`]($func/page.numbering)
argument of the [`{page}`]($func/page) set rule. You can pass a [_numbering
pattern_]($func/numbering.numbering) string that shows how you want your pages
to be numbered.
The simplest way to insert footnotes is the [`numbering`]($page.numbering)
argument of the [`{page}`]($page) set rule. You can pass a [_numbering
pattern_]($numbering.numbering) string that shows how you want your pages to be
numbered.
```example
>>> #set page("iso-b6", margin: 1.75cm)
@ -278,21 +277,21 @@ the string.
This is one of many numbered pages.
```
Go to the [`{numbering}` function reference]($func/numbering.numbering) to learn
more about the arguments you can pass here.
Go to the [`{numbering}` function reference]($numbering.numbering) to learn more
about the arguments you can pass here.
In case you need to right- or left-align the page number, use the
[`number-align`]($func/page.number-align) argument of the [`{page}`]($func/page)
set rule. Alternating alignment between even and odd pages is not currently
supported using this property. To do this, you'll need to specify a custom
footer with your footnote and query the page counter as described in the section
on conditionally omitting headers and footers.
[`number-align`]($page.number-align) argument of the [`{page}`]($page) set rule.
Alternating alignment between even and odd pages is not currently supported
using this property. To do this, you'll need to specify a custom footer with
your footnote and query the page counter as described in the section on
conditionally omitting headers and footers.
### Custom footer with page numbers { #custom-footer-with-page-numbers }
### Custom footer with page numbers
Sometimes, you need to add other content than a page number to your footer.
However, once a footer is specified, the [`numbering`]($func/page.numbering)
argument of the [`{page}`]($func/page) set rule is ignored. This section shows
you how to add a custom footer with page numbers and more.
However, once a footer is specified, the [`numbering`]($page.numbering) argument
of the [`{page}`]($page) set rule is ignored. This section shows you how to add
a custom footer with page numbers and more.
```example
>>> #set page("iso-b6", margin: 1.75cm)
@ -319,7 +318,7 @@ This page has a custom footer.
The example above shows how to add a custom footer with page numbers. First, we
need to recover the page number using the page counter. For this, we are using
the [`{locate}` function]($func/locate) to check the page counter, just like in
the [`{locate}` function]($locate) to check the page counter, just like in
the conditional header section. We then store the current and final page number
in variables.
@ -328,8 +327,8 @@ insert all the free space on the line, and finally display the current page
number and the page total. This would work just the same in the header and with
any content.
We can, of course, use the [`{numbering}` function]($func/numbering) to use
numbering pattern strings like before:
We can, of course, use the [`{numbering}` function]($numbering) to use numbering
pattern strings like before:
```example
>>> #set page("iso-b6", margin: 1.75cm)
@ -395,10 +394,10 @@ This page has a custom footer.
```
In this example, we use the number of pages to create an array of
[circles]($func/circle). The circles are wrapped in a [box]($func/box) so they
can all appear on the same line because they are blocks and would otherwise
create paragraph breaks. The length of this [array]($type/array) depends on the
current page number.
[circles]($circle). The circles are wrapped in a [box]($box) so they can all
appear on the same line because they are blocks and would otherwise create
paragraph breaks. The length of this [array]($array) depends on the current page
number.
We then insert the circles at the right side of the footer, with 1pt of space
between them. The join method of an array will attempt to
@ -406,8 +405,8 @@ between them. The join method of an array will attempt to
value, interspersed with its argument. In our case, we get a single content
value with circles and spaces between them that we can use with the align
function. Finally, we use another box to ensure that the text and the circles
can share a line and use the [`inset` argument]($func/box.inset) to raise the
circles a bit so they line up nicely with the text.
can share a line and use the [`inset` argument]($box.inset) to raise the circles
a bit so they line up nicely with the text.
### Reset the page number and skip pages { #skip-pages }
Do you, at some point in your document, need to reset the page number? Maybe you
@ -416,8 +415,7 @@ to skip a few page numbers because you will insert pages into the final printed
product.
The right way to modify the page number is to manipulate the page
[counter]($func/counter). The simplest manipulation is to set the counter back
to 1.
[counter]($counter). The simplest manipulation is to set the counter back to 1.
```typ
#counter(page).update(1)
@ -435,8 +433,8 @@ In this example, we skip five pages. `i` is the current value of the page
counter and `i + 5` is the return value of our function.
In case you need to retrieve the actual page number instead of the value of the
page counter, you can use the [`page`]($func/locate) method on the argument of
the `{locate}` closure:
page counter, you can use the [`page`]($locate) method on the argument of the
`{locate}` closure:
```example
#counter(page).update(i => i + 5)
@ -447,7 +445,7 @@ the `{locate}` closure:
```
You can also obtain the page numbering pattern from the `{locate}` closure
parameter with the [`page-numbering`]($func/locate) method.
parameter with the [`page-numbering`]($locate) method.
## Add columns { #columns }
Add columns to your document to fit more on a page while maintaining legible
@ -455,7 +453,7 @@ line lengths. Columns are vertical blocks of text which are separated by some
whitespace. This space is called the gutter.
If all of your content needs to be laid out in columns, you can just specify the
desired number of columns in the [`{page}`]($func/page.columns) set rule:
desired number of columns in the [`{page}`]($page.columns) set rule:
```example
>>> #set page(height: 120pt)
@ -469,8 +467,8 @@ in the next section.
### Use columns anywhere in your document { #columns-anywhere }
Very commonly, scientific papers have a single-column title and abstract, while
the main body is set in two-columns. To achieve this effect, Typst includes a
standalone [`{columns}` function]($func/columns) that can be used to insert
columns anywhere on a page.
standalone [`{columns}` function]($columns) that can be used to insert columns
anywhere on a page.
Conceptually, the `columns` function must wrap the content of the columns:
@ -502,8 +500,8 @@ nesting and write more legible Typst markup:
```
The show rule will wrap everything that comes after it in its function. The
[`with` mehtod]($type/function.with) allows us to pass arguments, in this case,
the column count, to a function without calling it.
[`with` mehtod]($function.with) allows us to pass arguments, in this case, the
column count, to a function without calling it.
Another use of the `columns` function is to create columns inside of a container
like a rectangle or to customize gutter size:
@ -523,24 +521,23 @@ like a rectangle or to customize gutter size:
)
```
### Balanced columns { #balanced-columns }
### Balanced columns
If the columns on the last page of a document differ greatly in length, they may
create a lopsided and unappealing layout. That's why typographers will often
equalize the length of columns on the last page. This effect is called balancing
columns. Typst cannot yet balance columns automatically. However, you can
balance columns manually by placing [`[#colbreak()]`]($func/colbreak) at an
balance columns manually by placing [`[#colbreak()]`]($colbreak) at an
appropriate spot in your markup, creating the desired column break manually.
## One-off modifications { #one-off-modifications }
## One-off modifications
You do not need to override your page settings if you need to insert a single
page with a different setup. For example, you may want to insert a page that's
flipped to landscape to insert a big table or change the margin and columns for
your title page. In this case, you can call [`{page}`]($func/page) as a function
with your content as an argument and the overrides as the other arguments. This
will insert enough new pages with your overridden settings to place your content
on them. Typst will revert to the page settings from the set rule after the
call.
your title page. In this case, you can call [`{page}`]($page) as a function with
your content as an argument and the overrides as the other arguments. This will
insert enough new pages with your overridden settings to place your content on
them. Typst will revert to the page settings from the set rule after the call.
```example
>>> #set page("a6")

@ -7,6 +7,6 @@ Welcome to the Guides section! Here, you'll find helpful material for specific
user groups or use cases. Currently, one guide is available: An introduction
to Typst for LaTeX users. Feel free to propose other topics for guides!
## List of Guides { #list-of-guides }
## List of Guides
- [Guide for LaTeX users]($guides/guide-for-latex-users)
- [Page setup guide]($guides/page-setup-guide)

@ -10,6 +10,9 @@ for the sciences. It is designed to be an alternative both to advanced tools
like LaTeX and simpler tools like Word and Google Docs. Our goal with Typst is
to build a typesetting tool that is highly capable _and_ a pleasure to use.
This documentation is split into two parts: A beginner-friendly tutorial that introduces Typst through a practical use case and a comprehensive reference that explains all of Typst's concepts and features.
This documentation is split into two parts: A beginner-friendly tutorial that
introduces Typst through a practical use case and a comprehensive reference that
explains all of Typst's concepts and features.
We also invite you to join the community we're building around Typst. Typst is still a very young project, so your feedback is more than valuable.
We also invite you to join the community we're building around Typst. Typst is
still a very young project, so your feedback is more than valuable.

@ -1,33 +1,26 @@
types: |
To style your document, you need to work with values of different kinds: Lengths
specifying the size of your elements, colors for your text and shapes, and more.
Typst categorizes these into clearly defined _types_ and tells you where it
expects which type of value.
# Descriptions of the documentation categories.
Apart from very basic types for numeric values and typical types known from
programming languages, Typst provides a special type for _content._ A value of
this type can hold anything that you can enter into your document: Text,
elements like headings and shapes, and style information.
foundations: |
Foundational types and functions.
In some places of Typst more specialized data types are used. Instead of listing
all of them here, they are explained where they are relevant.
Here, you'll find documentation for basic data types like [integers]($int) and
[strings]($int) as well as details about core computational functions.
text: |
Text styling.
The [text function]($func/text) is of particular interest.
The [text function]($text) is of particular interest.
math: |
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 $]`).
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 $]`).
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
[hashtag syntax]($scripting/#expressions).
variables, you can use the [hashtag syntax]($scripting/#expressions).
```example
$ A = pi r^2 $
@ -41,7 +34,7 @@ math: |
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]($type/symbol) to the symbol. Typst further recognizes a number of
[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.
@ -51,6 +44,7 @@ math: |
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 \
@ -60,11 +54,11 @@ math: |
Math mode supports special function calls without the hashtag 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 hashtag syntax to pass code expressions (except
for strings, which are available in the math syntax).
- They support positional and named arguments, but don't support
trailing content blocks and argument spreading.
- Within them, Typst is still in "math mode". Thus, you can write math
directly into them, but need to use hashtag syntax to pass code expressions
(except for strings, which are available in the math syntax).
- They support positional and named arguments, but don't support trailing
content blocks and argument spreading.
- They provide additional syntax for 2-dimensional argument lists. The
semicolon (`;`) merges preceding arguments separated by commas into an array
argument.
@ -143,27 +137,11 @@ emoji: |
certain emojis, you can also import them from the `emoji` module (`[#import
emoji: face]`) to use them without the `#emoji.` prefix.
foundations: |
Foundational functions for computation.
calculate: |
Calculations and processing of numeric values.
These functions are part of the `calc` module and not imported by default. In
addition to the functions listed below, the `calc` module also defines the
constants `pi`, `tau`, `e`, `inf`, and `nan`.
construct: |
Construction of and conversions between values of different types.
data-loading: |
Data loading from external files.
These functions help you with embedding data from experiments in your
documents.
utility: |
Useful utility functions.
These functions help you with loading and embedding data, for example from
the results of an experiment.
packages: |
Typst [packages]($scripting/#packages) encapsulate reusable building blocks

@ -3,24 +3,27 @@
- name: variants
display: Variants
category: math
functions: ["serif", "sans", "frak", "mono", "bb", "cal"]
description: |
Alternate typefaces within formulas.
These functions are distinct from the [`text`]($func/text) function because
math fonts contain multiple variants of each letter.
These functions are distinct from the [`text`]($text) function because math
fonts contain multiple variants of each letter.
- name: styles
display: Styles
category: math
functions: ["upright", "italic", "bold"]
description: |
Alternate letterforms within formulas.
These functions are distinct from the [`text`]($func/text) function because
math fonts contain multiple variants of each letter.
These functions are distinct from the [`text`]($text) function because math
fonts contain multiple variants of each letter.
- name: sizes
display: Sizes
category: math
functions: ["display", "inline", "script", "sscript"]
description: |
Forced size styles for expressions within formulas.
@ -31,6 +34,7 @@
- name: underover
display: Under/Over
category: math
functions: [
"underline",
"overline",
@ -47,23 +51,41 @@
- name: roots
display: Roots
category: math
functions: ["root", "sqrt"]
description: Square and non-square roots.
description: |
Square and non-square roots.
# Example
```example
$ sqrt(3 - 2 sqrt(2)) = sqrt(2) - 1 $
$ root(3, x) $
```
- name: attach
display: Attach
category: math
functions: ["attach", "scripts", "limits"]
description: |
Subscript, superscripts, and limits.
The `attach` function backs the `[$a_b^c$]` syntax that adds top and bottom
attachments to a part of an equation. Attachments can be displayed either as
sub/superscripts, or limits. Typst automatically decides which is more
suitable depending on the base, but you can also control this manually with
the `scripts` and `limits` functions.
Attachments can be displayed either as sub/superscripts, or limits. Typst
automatically decides which is more suitable depending on the base, but you
can also control this manually with the `scripts` and `limits` functions.
# Example
```example
$ sum_(i=0)^n a_i = 2^(1+i) $
```
# Syntax
This function also has dedicated syntax for attachments after the base: Use
the underscore (`_`) to indicate a subscript i.e. bottom attachment and the
hat (`^`) to indicate a superscript i.e. top attachment.
- name: lr
display: Left/Right
category: math
functions: ["lr", "abs", "norm", "floor", "ceil", "round"]
description: |
Delimiter matching.
@ -74,3 +96,21 @@
and control their size exactly. Apart from the `lr` function, Typst provides
a few more functions that create delimiter pairings for absolute, ceiled,
and floored values as well as norms.
# Example
```example
$ [a, b/2] $
$ lr(]sum_(x=1)^n] x, size: #50%) $
$ abs((x + y) / 2) $
```
- name: calc
display: Calculation
category: foundations
path: ["calc"]
description: |
Calculations and processing of numeric values.
These functions are part of the `calc` module and not imported by default.
In addition to the functions listed below, the `calc` module also defines
the constants `pi`, `tau`, `e`, `inf`, and `nan`.

@ -7,7 +7,7 @@ Typst embeds a powerful scripting language. You can automate your documents and
create more sophisticated styles with code. Below is an overview over the
scripting concepts.
## Expressions { #expressions }
## Expressions
In Typst, markup and code are fused into one. All but the most common elements
are created with _functions._ To make this as convenient as possible, Typst
provides compact syntax to embed a code expression into markup: An expression is
@ -23,14 +23,13 @@ be interpreted as text, the expression can forcibly be ended with a semicolon
```
The example above shows a few of the available expressions, including
[function calls]($type/function),
[field accesses]($scripting/#fields), and
[function calls]($function), [field accesses]($scripting/#fields), and
[method calls]($scripting/#methods). More kinds of expressions are
discussed in the remainder of this chapter. A few kinds of expressions are not
compatible with the hashtag syntax (e.g. binary operator expressions). To embed
these into markup, you can use parentheses, as in `[#(1 + 2)]`.
## Blocks { #blocks }
## Blocks
To structure your code and embed markup into it, Typst provides two kinds of
_blocks:_
@ -45,9 +44,9 @@ _blocks:_
- **Content block:** `{[*Hey* there!]}` \
With content blocks, you can handle markup/content as a programmatic value,
store it in variables and pass it to [functions]($type/function). Content
store it in variables and pass it to [functions]($function). Content
blocks are delimited by square brackets and can contain arbitrary markup. A
content block results in a value of type [content]($type/content). An
content block results in a value of type [content]($content). An
arbitrary number of content blocks can be passed as trailing arguments to
functions. That is, `{list([A], [B])}` is equivalent to `{list[A][B]}`.
@ -69,7 +68,7 @@ As already demonstrated above, variables can be defined with `{let}` bindings.
The variable is assigned the value of the expression that follows the `=` sign.
The assignment of a value is optional, if no value is assigned, the variable
will be initialized as `{none}`. The `{let}` keyword can also be used to create
a [custom named function]($type/function/#definitions). Let bindings can be
a [custom named function]($function/#defining-functions). Let bindings can be
accessed for the rest of the containing block or document.
```example
@ -81,8 +80,8 @@ It explains #name.
Sum is #add(2, 3).
```
Let bindings can also be used to destructure [arrays]($type/array) and
[dictionaries]($type/dictionary). In this case, the left-hand side of the
Let bindings can also be used to destructure [arrays]($array) and
[dictionaries]($dictionary). In this case, the left-hand side of the
assignment should mirror an array or dictionary. The `..` operator can be used
once in the pattern to collect the remainder of the array's or dictionary's
items.
@ -142,7 +141,7 @@ swap variables among other things.
}
```
## Conditionals { #conditionals }
## Conditionals
With a conditional, you can display or compute different things depending on
whether some condition is fulfilled. Typst supports `{if}`, `{else if}` and
`{else}` expression. When the condition evaluates to `{true}`, the conditional
@ -164,7 +163,7 @@ Each branch can have a code or content block as its body.
- `{if condition [..] else {..}}`
- `{if condition [..] else if condition {..} else [..]}`
## Loops { #loops }
## Loops
With loops, you can repeat content or compute something iteratively. Typst
supports two types of loops: `{for}` and `{while}` loops. The former iterate
over a specified collection whereas the latter iterate as long as a condition
@ -190,18 +189,18 @@ together into one larger array.
For loops can iterate over a variety of collections:
- `{for letter in "abc" {..}}` \
Iterates over the characters of the [string]($type/string).
Iterates over the characters of the [string]($str).
(Technically, iterates over the grapheme clusters of the string. Most of the
time, a grapheme cluster is just a single character/codepoint. However, some
constructs like flag emojis that consist of multiple codepoints are still only
one cluster.)
- `{for value in array {..}}` \
Iterates over the items in the [array]($type/array). The destructuring syntax
Iterates over the items in the [array]($array). The destructuring syntax
described in [Let binding]($scripting/#bindings) can also be used here.
- `{for pair in dict {..}}` \
Iterates over the key-value pairs of the [dictionary]($type/dictionary).
Iterates over the key-value pairs of the [dictionary]($dictionary).
The pairs can also be destructured by using `{for (key, value) in dict {..}}`.
To control the execution of the loop, Typst provides the `{break}` and
@ -225,16 +224,16 @@ The body of a loop can be a code or content block:
- `{while condition {..}}`
- `{while condition [..]}`
## Fields { #fields }
## Fields
You can use _dot notation_ to access fields on a value. The value in question
can be either:
- a [dictionary]($type/dictionary) that has the specified key,
- a [symbol]($type/symbol) that has the specified modifier,
- a [module]($type/module) containing the specified definition,
- [content]($type/content) consisting of an element that has the specified
field. The available fields match the arguments of the
[element function]($type/function/#element-functions) that were given when
the element was constructed.
- a [dictionary]($dictionary) that has the specified key,
- a [symbol]($symbol) that has the specified modifier,
- a [module]($module) containing the specified definition,
- [content]($content) consisting of an element that has the specified field. The
available fields match the arguments of the
[element function]($function/#element-functions) that were given when the
element was constructed.
```example
#let dict = (greet: "Hello")
@ -246,12 +245,20 @@ can be either:
#it.level
```
## Methods { #methods }
A method is a kind of a [function]($type/function) that is tightly coupled with
a specific type. It is called on a value of its type using the same dot notation
that is also used for fields: `{value.method(..)}`. The
[type documentation]($type) lists the available methods for each of the built-in
types. You cannot define your own methods.
## Methods
A _method call_ is a convenient way to call a function that is scoped to a
value's [type]($type). For example, we can call the [`str.len`]($str.len)
function in the following two equivalent ways:
```example
#str.len("abc") is the same as
#"abc".len()
```
The structure of a method call is `{value.method(..args)}` and its equivalent
full function call is `{type(value).method(value, ..args)}`. The documentation
of each type lists it's scoped functions. You cannot currently define your own
methods.
```example
#let array = (1, 2, 3, 4)
@ -261,26 +268,29 @@ types. You cannot define your own methods.
#("a, b, c"
.split(", ")
.join[ --- ])
#"abc".len() is the same as
#str.len("abc")
```
Methods are the only functions in Typst that can modify the value they are
called on. In some cases, this means that a method is only called for its side
effect and its return value should be ignored (and not participate in joining).
The canonical way to discard a value is with a let binding:
`{let _ = array.remove(1)}`.
There are a few special functions that modify the value they are called on (e.g.
[`array.push`]($array.push)). These functions _must_ be called in method form.
In some cases, when the method is only called for its side effect, its return
value should be ignored (and not participate in joining). The canonical way to
discard a value is with a let binding: `{let _ = array.remove(1)}`.
## Modules { #modules }
## Modules
You can split up your Typst projects into multiple files called _modules._ A
module can refer to the content and definitions of another module in multiple
ways:
- **Including:** `{include "bar.typ"}` \
Evaluates the file at the path `bar.typ` and returns the resulting
[content]($type/content).
[content]($content).
- **Import:** `{import "bar.typ"}` \
Evaluates the file at the path `bar.typ` and inserts the resulting
[module]($type/module) into the current scope as `bar` (filename without
[module]($module) into the current scope as `bar` (filename without
extension).
- **Import items:** `{import "bar.typ": a, b}` \
@ -289,15 +299,15 @@ ways:
bindings) and defines them in the current file. Replacing `a, b` with `*` loads
all variables defined in a module.
Instead of a path, you can also use a [module value]($type/module), as shown in
the following example:
Instead of a path, you can also use a [module value]($module), as shown in the
following example:
```example
#import emoji: face
#face.grin
```
## Packages { #packages }
## Packages
To reuse building blocks across projects, you can also create and import Typst
_packages._ A package import is specified as a triple of a namespace, a name,
and a version.
@ -316,7 +326,7 @@ If you are using Typst locally, you can also create your own system-local
packages. For more details on this, see the
[package repository](https://github.com/typst/packages).
## Operators { #operators }
## Operators
The following table lists all available unary and binary operators with effect,
arity (unary, binary) and precedence level (higher binds stronger).

@ -10,15 +10,14 @@ might not be a built-in property for everything you wish to do. For this reason,
Typst further supports _show rules_ that can completely redefine the appearance
of elements.
## Set rules { #set-rules }
## Set rules
With set rules, you can customize the appearance of elements. They are written
as a [function call]($type/function) to an
[element function]($type/function/#element-functions) preceded by the `{set}`
keyword (or `[#set]` in markup). Only optional parameters of that function can
be provided to the set rule. Refer to each function's documentation to see which
parameters are optional. In the example below, we use two set rules to change
the [font family]($func/text.font) and
[heading numbering]($func/heading.numbering).
as a [function call]($function) to an [element
function]($function/#element-functions) preceded by the `{set}` keyword (or
`[#set]` in markup). Only optional parameters of that function can be provided
to the set rule. Refer to each function's documentation to see which parameters
are optional. In the example below, we use two set rules to change the
[font family]($text.font) and [heading numbering]($heading.numbering).
```example
#set heading(numbering: "I.")
@ -60,13 +59,14 @@ a _set-if_ rule.
#task(critical: false)[Work deadline]
```
## Show rules { #show-rules }
## Show rules
With show rules, you can deeply customize the look of a type of element. The
most basic form of show rule is a _show-set rule._ Such a rule is written as the
`{show}` keyword followed by a [selector]($type/selector), a colon and then a set rule. The most basic form of selector is an
[element function]($type/function/#element-functions). This lets the set rule
only apply to the selected element. In the example below, headings become dark
blue while all other text stays black.
`{show}` keyword followed by a [selector]($selector), a colon and then a set
rule. The most basic form of selector is an
[element function]($function/#element-functions). This lets the set rule only
apply to the selected element. In the example below, headings become dark blue
while all other text stays black.
```example
#show heading: set text(navy)
@ -79,12 +79,11 @@ With show-set rules you can mix and match properties from different functions to
achieve many different effects. But they still limit you to what is predefined
in Typst. For maximum flexibility, you can instead write a show rule that
defines how to format an element from scratch. To write such a show rule,
replace the set rule after the colon with an arbitrary
[function]($type/function). This function receives the element in question and
can return arbitrary content. Different
[fields]($scripting/#fields) are available on the element passed
to the function. Below, we define a show rule that formats headings for a
fantasy encyclopedia.
replace the set rule after the colon with an arbitrary [function]($function).
This function receives the element in question and can return arbitrary content.
Different [fields]($scripting/#fields) are available on the element passed to
the function. Below, we define a show rule that formats headings for a fantasy
encyclopedia.
```example
#set heading(numbering: "(I)")
@ -125,15 +124,15 @@ to:
- **Regex:** `{show regex("\w+"): ..}` \
Select and transform text with a regular expression for even more flexibility.
See the documentation of the [`regex` function]($func/regex) for details.
See the documentation of the [`regex` type]($regex) for details.
- **Function with fields:** `{show heading.where(level: 1): ..}` \
Transform only elements that have the specified fields. For example, you might
want to only change the style of level-1 headings.
- **Label:** `{show <intro>: ..}` \
Select and transform elements that have the specified label.
See the documentation of the [`label` function]($func/label) for more details.
Select and transform elements that have the specified label. See the
documentation of the [`label` type]($label) for more details.
```example
#show "Project": smallcaps

@ -11,7 +11,7 @@ set and show rules, which let you style your document easily and automatically.
All this is backed by a tightly integrated scripting language with built-in and
user-defined functions.
## Markup { #markup }
## Markup
Typst provides built-in markup for the most common document elements. Most of
the syntax elements are just shortcuts for a corresponding function. The table
below lists all markup that is available and links to the best place to learn
@ -19,20 +19,20 @@ more about their syntax and usage.
| Name | Example | See |
| ------------------ | ------------------------ | ---------------------------- |
| Paragraph break | Blank line | [`parbreak`]($func/parbreak) |
| Strong emphasis | `[*strong*]` | [`strong`]($func/strong) |
| Emphasis | `[_emphasis_]` | [`emph`]($func/emph) |
| Raw text | ``[`print(1)`]`` | [`raw`]($func/raw) |
| Link | `[https://typst.app/]` | [`link`]($func/link) |
| Label | `[<intro>]` | [`label`]($func/label) |
| Reference | `[@intro]` | [`ref`]($func/ref) |
| Heading | `[= Heading]` | [`heading`]($func/heading) |
| Bullet list | `[- item]` | [`list`]($func/list) |
| Numbered list | `[+ item]` | [`enum`]($func/enum) |
| Term list | `[/ Term: description]` | [`terms`]($func/terms) |
| Paragraph break | Blank line | [`parbreak`]($parbreak) |
| Strong emphasis | `[*strong*]` | [`strong`]($strong) |
| Emphasis | `[_emphasis_]` | [`emph`]($emph) |
| Raw text | ``[`print(1)`]`` | [`raw`]($raw) |
| Link | `[https://typst.app/]` | [`link`]($link) |
| Label | `[<intro>]` | [`label`]($label) |
| Reference | `[@intro]` | [`ref`]($ref) |
| Heading | `[= Heading]` | [`heading`]($heading) |
| Bullet list | `[- item]` | [`list`]($list) |
| Numbered list | `[+ item]` | [`enum`]($enum) |
| Term list | `[/ Term: description]` | [`terms`]($terms) |
| Math | `[$x^2$]` | [Math]($category/math) |
| Line break | `[\]` | [`linebreak`]($func/linebreak) |
| Smart quote | `['single' or "double"]` | [`smartquote`]($func/smartquote) |
| Line break | `[\]` | [`linebreak`]($linebreak) |
| Smart quote | `['single' or "double"]` | [`smartquote`]($smartquote) |
| Symbol shorthand | `[~, ---]` | [Symbols]($category/symbols/sym) |
| Code expression | `[#rect(width: 1cm)]` | [Scripting]($scripting/#expressions) |
| Character escape | `[Tweet at us \#ad]` | [Below](#escapes) |
@ -52,8 +52,8 @@ follows:
| Block-level math | `[$ x^2 $]` | [Math]($category/math) |
| Bottom attachment | `[$x_1$]` | [`attach`]($category/math/attach) |
| Top attachment | `[$x^2$]` | [`attach`]($category/math/attach) |
| Fraction | `[$1 + (a+b)/5$]` | [`frac`]($func/math.frac) |
| Line break | `[$x \ y$]` | [`linebreak`]($func/linebreak) |
| Fraction | `[$1 + (a+b)/5$]` | [`frac`]($math.frac) |
| Line break | `[$x \ y$]` | [`linebreak`]($linebreak) |
| Alignment point | `[$x &= 2 \ &= 3$]` | [Math]($category/math) |
| Variable access | `[$#x$, $pi$]` | [Math]($category/math) |
| Field access | `[$arrow.r.long$]` | [Scripting]($scripting/#fields) |
@ -73,22 +73,22 @@ a table listing all syntax that is available in code mode:
| Name | Example | See |
| ------------------------ | ----------------------------- | ---------------------------------- |
| Variable access | `{x}` | [Scripting]($scripting/#blocks) |
| Any literal | `{1pt, "hey"}` | [Types]($types) |
| Any literal | `{1pt, "hey"}` | [Scripting]($scripting/#expressions) |
| Code block | `{{ let x = 1; x + 2 }}` | [Scripting]($scripting/#blocks) |
| Content block | `{[*Hello*]}` | [Scripting]($scripting/#blocks) |
| Parenthesized expression | `{(1 + 2)}` | [Scripting]($scripting/#blocks) |
| Array | `{(1, 2, 3)}` | [Array]($type/array) |
| Dictionary | `{(a: "hi", b: 2)}` | [Dictionary]($type/dictionary) |
| Array | `{(1, 2, 3)}` | [Array]($array) |
| Dictionary | `{(a: "hi", b: 2)}` | [Dictionary]($dictionary) |
| Unary operator | `{-x}` | [Scripting]($scripting/#operators) |
| Binary operator | `{x + y}` | [Scripting]($scripting/#operators) |
| Assignment | `{x = 1}` | [Scripting]($scripting/#operators) |
| Field access | `{x.y}` | [Scripting]($scripting/#fields) |
| Method call | `{x.flatten()}` | [Scripting]($scripting/#methods) |
| Function call | `{min(x, y)}` | [Function]($type/function) |
| Argument spreading | `{min(..nums)}` | [Arguments]($type/arguments) |
| Unnamed function | `{(x, y) => x + y}` | [Function]($type/function) |
| Function call | `{min(x, y)}` | [Function]($function) |
| Argument spreading | `{min(..nums)}` | [Arguments]($arguments) |
| Unnamed function | `{(x, y) => x + y}` | [Function]($function) |
| Let binding | `{let x = 1}` | [Scripting]($scripting/#bindings) |
| Named function | `{let f(x) = 2 * x}` | [Function]($type/function) |
| Named function | `{let f(x) = 2 * x}` | [Function]($function) |
| Set rule | `{set text(14pt)}` | [Styling]($styling/#set-rules) |
| Set-if rule | `{set text(..) if .. }` | [Styling]($styling/#set-rules) |
| Show-set rule | `{show par: set block(..)}` | [Styling]($styling/#show-rules) |
@ -98,16 +98,16 @@ a table listing all syntax that is available in code mode:
| For loop | `{for x in (1, 2, 3) {..}}` | [Scripting]($scripting/#loops) |
| While loop | `{while x < 10 {..}}` | [Scripting]($scripting/#loops) |
| Loop control flow | `{break, continue}` | [Scripting]($scripting/#loops) |
| Return from function | `{return x}` | [Function]($type/function) |
| Return from function | `{return x}` | [Function]($function) |
| Include module | `{include "bar.typ"}` | [Scripting]($scripting/#modules) |
| Import module | `{import "bar.typ"}` | [Scripting]($scripting/#modules) |
| Import items from module | `{import "bar.typ": a, b, c}` | [Scripting]($scripting/#modules) |
| Comment | `[/* block */, // line]` | [Below](#comments) |
## Comments { #comments }
Comments are ignored by Typst and will not be included in the output. This
is useful to exclude old versions or to add annotations.
To comment out a single line, start it with `//`:
## Comments
Comments are ignored by Typst and will not be included in the output. This is
useful to exclude old versions or to add annotations. To comment out a single
line, start it with `//`:
```example
// our data barely supports
// this claim
@ -129,9 +129,9 @@ Our study design is as follows:
## Escape sequences { #escapes }
Escape sequences are used to insert special characters that are hard to type or
otherwise have special meaning in Typst. To escape a character, precede it with
a backslash. To insert any Unicode codepoint, you can write a hexadecimal
escape sequence: `[\u{1f600}]`. The same kind of escape sequences also work in
[strings]($type/string).
a backslash. To insert any Unicode codepoint, you can write a hexadecimal escape
sequence: `[\u{1f600}]`. The same kind of escape sequences also work in
[strings]($str).
```example
I got an ice cream for

File diff suppressed because it is too large Load Diff

@ -10,14 +10,13 @@ syntax, concepts, types, and functions. If you are completely new to Typst, we
recommend starting with the [tutorial]($tutorial) and then coming back to
the reference to learn more about Typst's features as you need them.
## Language { #language }
The reference starts with a language part that gives an overview over [Typst's
syntax]($syntax) and contains information about concepts involved in
## Language
The reference starts with a language part that gives an overview over
[Typst's syntax]($syntax) and contains information about concepts involved in
[styling documents,]($styling) using
[Typst's scripting capabilities,]($scripting) and a detailed documentation of
all [data types]($types) in Typst.
[Typst's scripting capabilities.]($scripting)
## Functions { #functions }
## Functions
The second part includes chapters on all functions used to insert, style, transform,
and layout content in Typst documents. Each function is documented with a
description of its purpose, a list of its parameters, and examples of how to use

@ -14,7 +14,7 @@ user to plan for and prioritize new features. Get started by filing a new issue
on [GitHub](https://github.com/typst/typst/issues) or discuss your feature
request with the [community]($community).
## Language and Compiler { #language-and-compiler }
## Language and Compiler
- **Structure and Styling**
- Fix show rule recursion
- Fix show-set order
@ -24,7 +24,7 @@ request with the [community]($community).
- Custom elements (that work with set and show rules)
- Possibly a capability system, e.g. to make your own element referenceable
- **Layout**
- Floating layout
- Advanced floating layout
- Rework layout engine to a more flexible model that has first-class support
for both "normal" text layout and more canvas-like layout
- Unified layout primitives across normal content and math
@ -36,8 +36,6 @@ request with the [community]($community).
- Layout with collision
- **Export**
- Implement emoji export
- Implement transparency
- Fix SVG export issues
- HTML export
- EPUB export
- Tagged PDF for Accessibility
@ -51,17 +49,11 @@ request with the [community]($community).
- Ruby and Warichu
- Kashida justification
- **Scripting**
- More fields and methods on primitives
- Import renaming with as
- Allow expressions as dictionary keys
- Make types first-class values and bring methods and functions closer
together
- Function hoisting if possible
- Get values of set rules
- Doc comments
- Type hints
- WebAssembly integration
- Query from CLI
- **Visualization**
- Arrows
- Gradients
@ -75,13 +67,12 @@ request with the [community]($community).
- Benchmarking
- Better contributor documentation
## Library { #library }
## Library
- **Customization**
- Integrate CSL (Citation Style Language)
- Bibliography and citation customization
- Outline customization
- Table stroke customization
- Themes for raw text and more/custom syntaxes
- **Numbering**
- Relative counters, e.g. for figure numbering per section
- Improve equation numbering
@ -97,12 +88,11 @@ request with the [community]($community).
- Fix font handling
- Provide more primitives
- Smarter automatic delimiter sizing
- Augmented matrices
- Big fractions
- **Other**
- Plotting
## Web App { #web-app }
## Web App
- **Editing**
- Smarter & more action buttons
- Basic, built-in image editor (cropping, etc.)

@ -85,7 +85,7 @@ and emphasized text, respectively. However, having a special symbol for
everything we want to insert into our document would soon become cryptic and
unwieldy. For this reason, Typst reserves markup symbols only for the most
common things. Everything else is inserted with _functions._ For our image to
show up on the page, we use Typst's [`image`]($func/image) function.
show up on the page, we use Typst's [`image`]($image) function.
```example
#image("glacier.jpg")
@ -98,8 +98,8 @@ result (the function's _return value_) into the document. In our case, the
function in markup, we first need to type the `#` character, immediately
followed by the name of the function. Then, we enclose the arguments in
parentheses. Typst recognizes many different data types within argument lists.
Our file path is a short [string of text]($type/string), so we need to enclose
it in double quotes.
Our file path is a short [string of text]($str), so we need to enclose it in
double quotes.
The inserted image uses the whole width of the page. To change that, pass the
`width` argument to the `image` function. This is a _named_ argument and
@ -110,14 +110,14 @@ they are separated by commas, so we first need to put a comma behind the path.
#image("glacier.jpg", width: 70%)
```
The `width` argument is a [relative length]($type/relative-length). In our case,
we specified a percentage, determining that the image shall take up `{70%}` of
the page's width. We also could have specified an absolute value like `{1cm}` or
The `width` argument is a [relative length]($relative). In our case, we
specified a percentage, determining that the image shall take up `{70%}` of the
page's width. We also could have specified an absolute value like `{1cm}` or
`{0.7in}`.
Just like text, the image is now aligned at the left side of the page by
default. It's also lacking a caption. Let's fix that by using the
[figure]($func/figure) function. This function takes the figure's contents as a
[figure]($figure) function. This function takes the figure's contents as a
positional argument and an optional caption as a named argument.
Within the argument list of the `figure` function, Typst is already in code mode. This means, you can now remove the hashtag before the image function call.
@ -176,9 +176,8 @@ valid kind of content.
## Adding a bibliography { #bibliography }
As you write up your report, you need to back up some of your claims. You can
add a bibliography to your document with the
[`bibliography`]($func/bibliography) function. This function expects a path
to a bibliography file.
add a bibliography to your document with the [`bibliography`]($bibliography)
function. This function expects a path to a bibliography file.
Typst's native bibliography format is
[Hayagriva](https://github.com/typst/hayagriva/blob/main/docs/file-format.md),
@ -190,7 +189,7 @@ Once the document contains a bibliography, you can start citing from it.
Citations use the same syntax as references to a label. As soon as you cite a
source for the first time, it will appear in the bibliography section of your
document. Typst supports different citation and bibliography styles. Consult the
[reference]($func/bibliography.style) for more details.
[reference]($bibliography.style) for more details.
```example
= Methods
@ -200,7 +199,7 @@ established in @glacier-melt.
#bibliography("works.bib")
```
## Maths { #maths }
## Maths
After fleshing out the methods section, you move on to the meat of the document:
Your equations. Typst has built-in mathematical typesetting and uses its own
math notation. Let's start with a simple equation. We wrap it in `[$]` signs
@ -269,17 +268,17 @@ $ 7.32 beta +
Not all math constructs have special syntax. Instead, we use functions, just
like the `image` function we have seen before. For example, to insert a column
vector, we can use the [`vec`]($func/math.vec) function. Within math mode,
function calls don't need to start with the `#` character.
vector, we can use the [`vec`]($math.vec) function. Within math mode, function
calls don't need to start with the `#` character.
```example
$ v := vec(x_1, x_2, x_3) $
```
Some functions are only available within math mode. For example, the
[`cal`]($func/math.cal) function is used to typeset calligraphic letters
commonly used for sets. The [math section of the reference]($category/math)
provides a complete list of all functions that math mode makes available.
[`cal`]($math.cal) function is used to typeset calligraphic letters commonly
used for sets. The [math section of the reference]($category/math) provides a
complete list of all functions that math mode makes available.
One more thing: Many symbols, such as the arrow, have a lot of variants. You can
select among these variants by appending a dot and a modifier name to a symbol's
@ -293,14 +292,14 @@ This notation is also available in markup mode, but the symbol name must be
preceded with `#sym.` there. See the [symbols section]($category/symbols/sym)
for a list of all available symbols.
## Review { #review }
## Review
You have now seen how to write a basic document in Typst. You learned how to
emphasize text, write lists, insert images, align content, and typeset
mathematical expressions. You also learned about Typst's functions. There are
many more kinds of content that Typst lets you insert into your document, such
as [tables]($func/table), [shapes]($category/visualize), and
[code blocks]($func/raw). You can peruse the [reference]($reference) to learn
more about these and other features.
as [tables]($table), [shapes]($category/visualize), and [code blocks]($raw). You
can peruse the [reference]($reference) to learn more about these and other
features.
For the moment, you have completed writing your report. You have already saved a
PDF by clicking on the download button in the top right corner. However, you

@ -9,13 +9,13 @@ that you are using a new typesetting system, and you want your report to fit in
with the other student's submissions. In this chapter, we will see how to format
your report using Typst's styling system.
## Set rules { #set-rules }
## Set rules
As we have seen in the previous chapter, Typst has functions that _insert_
content (e.g. the [`image`]($func/image) function) and others that _manipulate_
content that they received as arguments (e.g. the [`align`]($func/align)
function). The first impulse you might have when you want, for example, to
justify the report, could be to look for a function that does that and wrap the
complete document in it.
content (e.g. the [`image`]($image) function) and others that _manipulate_
content that they received as arguments (e.g. the [`align`]($align) function).
The first impulse you might have when you want, for example, to justify the
report, could be to look for a function that does that and wrap the complete
document in it.
```example
#par(justify: true)[
@ -38,9 +38,9 @@ do in Typst, there is special syntax for it: Instead of putting the content
inside of the argument list, you can write it in square brackets directly after
the normal arguments, saving on punctuation.
As seen above, that works. The [`par`]($func/par) function justifies all
paragraphs within it. However, wrapping the document in countless functions and
applying styles selectively and in-situ can quickly become cumbersome.
As seen above, that works. The [`par`]($par) function justifies all paragraphs
within it. However, wrapping the document in countless functions and applying
styles selectively and in-situ can quickly become cumbersome.
Fortunately, Typst has a more elegant solution. With _set rules,_ you can apply
style properties to all occurrences of some kind of content. You write a set
@ -89,15 +89,13 @@ Back to set rules: When writing a rule, you choose the function depending on
what type of element you want to style. Here is a list of some functions that
are commonly used in set rules:
- [`text`]($func/text) to set font family, size, color, and other properties of
text
- [`page`]($func/page) to set the page size, margins, headers, enable columns,
and footers
- [`par`]($func/par) to justify paragraphs, set line spacing, and more
- [`heading`]($func/heading) to set the appearance of headings and enable
numbering
- [`document`]($func/document) to set the metadata contained in the PDF output,
such as title and author
- [`text`]($text) to set font family, size, color, and other properties of text
- [`page`]($page) to set the page size, margins, headers, enable columns, and
footers
- [`par`]($par) to justify paragraphs, set line spacing, and more
- [`heading`]($heading) to set the appearance of headings and enable numbering
- [`document`]($document) to set the metadata contained in the PDF output, such
as title and author
Not all function parameters can be set. In general, only parameters that tell
a function _how_ to do something can be set, not those that tell it _what_ to
@ -151,23 +149,22 @@ behavior of these natural structures.
There are a few things of note here.
First is the [`page`]($func/page) set rule. It receives two arguments: the page
size and margins for the page. The page size is a string. Typst accepts
[many standard page sizes,]($func/page.paper) but you can also specify a custom
page size. The margins are specified as a [dictionary.]($type/dictionary)
Dictionaries are a collection of key-value pairs. In this case, the keys are `x`
and `y`, and the values are the horizontal and vertical margins, respectively.
We could also have specified separate margins for each side by passing a
dictionary with the keys `{left}`, `{right}`, `{top}`, and `{bottom}`.
First is the [`page`]($page) set rule. It receives two arguments: the page size
and margins for the page. The page size is a string. Typst accepts
[many standard page sizes,]($page.paper) but you can also specify a custom page
size. The margins are specified as a [dictionary.]($dictionary) Dictionaries are
a collection of key-value pairs. In this case, the keys are `x` and `y`, and the
values are the horizontal and vertical margins, respectively. We could also have
specified separate margins for each side by passing a dictionary with the keys
`{left}`, `{right}`, `{top}`, and `{bottom}`.
Next is the set [`text`]($func/text) set rule. Here, we set the font size to
`{10pt}` and font family to `{"New Computer Modern"}`. The Typst app comes with
many fonts that you can try for your document. When you are in the text
function's argument list, you can discover the available fonts in the
autocomplete panel.
Next is the set [`text`]($text) set rule. Here, we set the font size to `{10pt}`
and font family to `{"New Computer Modern"}`. The Typst app comes with many
fonts that you can try for your document. When you are in the text function's
argument list, you can discover the available fonts in the autocomplete panel.
We have also set the spacing between lines (a.k.a. leading): It is specified as
a [length]($type/length) value, and we used the `em` unit to specify the leading
a [length]($length) value, and we used the `em` unit to specify the leading
relative to the size of the font: `{1em}` is equivalent to the current font size
(which defaults to `{11pt}`).
@ -177,8 +174,8 @@ center alignment. Vertical and horizontal alignments can be combined with the
## A hint of sophistication { #sophistication }
To structure our document more clearly, we now want to number our headings. We
can do this by setting the `numbering` parameter of the
[`heading`]($func/heading) function.
can do this by setting the `numbering` parameter of the [`heading`]($heading)
function.
```example
>>> #set text(font: "New Computer Modern")
@ -196,8 +193,8 @@ can do this by setting the `numbering` parameter of the
We specified the string `{"1."}` as the numbering parameter. This tells Typst to
number the headings with arabic numerals and to put a dot between the number of
each level. We can also use
[letters, roman numerals, and symbols]($func/numbering) for our headings:
each level. We can also use [letters, roman numerals, and symbols]($numbering)
for our headings:
```example
>>> #set text(font: "New Computer Modern")
@ -213,7 +210,7 @@ each level. We can also use
#lorem(15)
```
This example also uses the [`lorem`]($func/lorem) function to generate some
This example also uses the [`lorem`]($lorem) function to generate some
placeholder text. This function takes a number as an argument and generates that
many words of _Lorem Ipsum_ text.
@ -222,13 +219,13 @@ many words of _Lorem Ipsum_ text.
Did you wonder why the headings and text set rules apply to all text and headings,
even if they are not produced with the respective functions?
Typst internally calls the `heading` function every time you write `[= Conclusion]`.
In fact, the function call `[#heading[Conclusion]]` is equivalent to the heading
markup above. Other markup elements work similarly, they are only
_syntax sugar_ for the corresponding function calls.
Typst internally calls the `heading` function every time you write
`[= Conclusion]`. In fact, the function call `[#heading[Conclusion]]` is
equivalent to the heading markup above. Other markup elements work similarly,
they are only _syntax sugar_ for the corresponding function calls.
</div>
## Show rules { #show-rules }
## Show rules
You are already pretty happy with how this turned out. But one last thing needs
to be fixed: The report you are writing is intended for a larger project and
that project's name should always be accompanied by a logo, even in prose.
@ -236,7 +233,8 @@ that project's name should always be accompanied by a logo, even in prose.
You consider your options. You could add an `[#image("logo.svg")]` call before
every instance of the logo using search and replace. That sounds very tedious.
Instead, you could maybe
[define a custom function]($type/function/#definitions) that always yields the logo with its image. However, there is an even easier way:
[define a custom function]($function/#defining-functions) that always yields the
logo with its image. However, there is an even easier way:
With show rules, you can redefine how Typst displays certain elements. You
specify which elements Typst should show differently and how they should look.
@ -272,7 +270,7 @@ expects code instead of markup, the leading `#` is not needed to access
functions, keywords, and variables. This can be observed in parameter lists,
function definitions, and [code blocks]($scripting).
## Review { #review }
## Review
You now know how to apply basic formatting to your Typst documents. You learned
how to set the font, justify your paragraphs, change the page dimensions, and
add numbering to your headings with set rules. You also learned how to use a

@ -78,7 +78,7 @@ by the conference style guide. We use the `align` function to align the text to
the right.
Last but not least is the `numbering` argument. Here, we can provide a
[numbering pattern]($func/numbering) that defines how to number the pages. By
[numbering pattern]($numbering) that defines how to number the pages. By
setting into to `{"1"}`, Typst only displays the bare page number. Setting it to
`{"(1/1)"}` would have displayed the current page and total number of pages
surrounded by parentheses. And we could even have provided a completely custom
@ -126,16 +126,16 @@ supervisor, we'll add our own and their name.
```
The two author blocks are laid out next to each other. We use the
[`grid`]($func/grid) function to create this layout. With a grid, we can control
[`grid`]($grid) function to create this layout. With a grid, we can control
exactly how large each column is and which content goes into which cell. The
`columns` argument takes an array of [relative lengths]($type/relative-length)
or [fractions]($type/fraction). In this case, we passed it two equal fractional
sizes, telling it to split the available space into two equal columns. We then
passed two content arguments to the grid function. The first with our own
details, and the second with our supervisors'. We again use the `align` function
to center the content within the column. The grid takes an arbitrary number of
content arguments specifying the cells. Rows are added automatically, but they
can also be manually sized with the `rows` argument.
`columns` argument takes an array of [relative lengths]($relative) or
[fractions]($fraction). In this case, we passed it two equal fractional sizes,
telling it to split the available space into two equal columns. We then passed
two content arguments to the grid function. The first with our own details, and
the second with our supervisors'. We again use the `align` function to center
the content within the column. The grid takes an arbitrary number of content
arguments specifying the cells. Rows are added automatically, but they can also
be manually sized with the `rows` argument.
Now, let's add the abstract. Remember that the conference wants the abstract to
be set ragged and centered.
@ -249,7 +249,7 @@ on another title, we can easily change it in one place.
## Adding columns and headings { #columns-and-headings }
The paper above unfortunately looks like a wall of lead. To fix that, let's add
some headings and switch our paper to a two-column layout. The
[`columns`]($func/columns) function takes a number and content, and layouts the
[`columns`]($columns) function takes a number and content, and layouts the
content into the specified number of columns. Since we want everything after the
abstract to be in two columns, we need to apply the column function to our whole
document.
@ -386,7 +386,8 @@ function that gets passed the heading as a parameter. That parameter can be used
as content but it also has some fields like `title`, `numbers`, and `level` from
which we can compose a custom look. Here, we are center-aligning, setting the
font weight to `{"regular"}` because headings are bold by default, and use the
[`smallcaps`]($func/smallcaps) function to render the heading's title in small capitals.
[`smallcaps`]($smallcaps) function to render the heading's title in small
capitals.
The only remaining problem is that all headings look the same now. The
"Motivation" and "Problem Statement" subsections ought to be italic run in
@ -493,9 +494,9 @@ the conference! The finished paper looks like this:
style="box-shadow: 0 4px 12px rgb(89 85 101 / 20%); width: 500px; max-width: 100%; display: block; margin: 24px auto;"
>
## Review { #review }
## Review
You have now learned how to create headers and footers, how to use functions and
scopes to locally override styles, how to create more complex layouts with the [`grid`]($func/grid) function and how to write show rules for individual functions, and the whole document. You also learned how to use the
scopes to locally override styles, how to create more complex layouts with the [`grid`]($grid) function and how to write show rules for individual functions, and the whole document. You also learned how to use the
[`where` selector]($styling/#show-rules) to filter the headings by their level.
The paper was a great success! You've met a lot of like-minded researchers at

@ -195,26 +195,26 @@ Next, we copy the code that generates title, abstract and authors from the
previous chapter into the template, replacing the fixed details with the
parameters.
The new `authors` parameter expects an [array]($type/array) of
[dictionaries]($type/dictionary) with the keys `name`, `affiliation` and
`email`. Because we can have an arbitrary number of authors, we dynamically
determine if we need one, two or three columns for the author list. First, we
determine the number of authors using the [`.len()`]($type/array.len) method on
the `authors` array. Then, we set the number of columns as the minimum of this
count and three, so that we never create more than three columns. If there are
more than three authors, a new row will be inserted instead. For this purpose,
we have also added a `row-gutter` parameter to the `grid` function. Otherwise,
the rows would be too close together. To extract the details about the authors
from the dictionary, we use the [field access syntax]($scripting/#fields).
The new `authors` parameter expects an [array]($array) of
[dictionaries]($dictionary) with the keys `name`, `affiliation` and `email`.
Because we can have an arbitrary number of authors, we dynamically determine if
we need one, two or three columns for the author list. First, we determine the
number of authors using the [`.len()`]($array.len) method on the `authors`
array. Then, we set the number of columns as the minimum of this count and
three, so that we never create more than three columns. If there are more than
three authors, a new row will be inserted instead. For this purpose, we have
also added a `row-gutter` parameter to the `grid` function. Otherwise, the rows
would be too close together. To extract the details about the authors from the
dictionary, we use the [field access syntax]($scripting/#fields).
We still have to provide an argument to the grid for each author: Here is where
the array's [`map` method]($type/array.map) comes in handy. It takes a function
as an argument that gets called with each item of the array. We pass it a
function that formats the details for each author and returns a new array
containing content values. We've now got one array of values that we'd like to
use as multiple arguments for the grid. We can do that by using the [`spread`
operator]($type/arguments). It takes an array and applies each of its items as a
separate argument to the function.
the array's [`map` method]($array.map) comes in handy. It takes a function as an
argument that gets called with each item of the array. We pass it a function
that formats the details for each author and returns a new array containing
content values. We've now got one array of values that we'd like to use as
multiple arguments for the grid. We can do that by using the
[`spread` operator]($arguments). It takes an array and applies each of its items
as a separate argument to the function.
The resulting template function looks like this:
@ -365,7 +365,7 @@ conference! Why not share it on
[Typst's Discord server](https://discord.gg/2uDybryKPe) so that others can use
it too?
## Review { #review }
## Review
Congratulations, you have completed Typst's Tutorial! In this section, you have
learned how to define your own functions and how to create and apply templates
that define reusable document styles. You've made it far and learned a lot. You