diff --git a/sources/CONTRIBUTING.md b/sources/CONTRIBUTING.md
new file mode 100644
index 0000000000000000000000000000000000000000..33c5343c5ccb810f10cd0b96bbaf87a61455b2bd
--- /dev/null
+++ b/sources/CONTRIBUTING.md
@@ -0,0 +1,73 @@
+# Contributing to Typst
+Thank you for considering to contribute to Typst. We want to foster a welcoming
+and productive atmosphere for contributors. Therefore, we outline a few steps to
+land your contribution below.
+
+1. Before starting significant work on a feature or refactoring, please
+ find/open an [issue] or start a thread in the [#contributors] channel on
+ Discord to discuss the design. Feel also free to ping a maintainer/team
+ member to get some input on your idea. Don't be shy! Typst is a complex
+ project with a long-term vision and it's frustrating to find out that your
+ idea does not align with that vision _after_ you have already implemented
+ something.
+2. Fork the Typst repository and start with your contribution. If you, at any
+ point in this process, are unsure about how to do something in the Typst
+ codebase, reach out to a maintainer or a more experienced contributor. Also
+ have a look at the [`architecture.md`][architecture] file. It explains how
+ the compiler works.
+3. Create a pull request (PR) in the Typst repository, outlining your
+ contribution, the technical rationale behind it, and, if it includes a new
+ feature, how users will use it. Best to link to an existing issue with this
+ information here.
+4. When you send a PR, automated CI checks will run. Your PR can only be merged
+ if CI passes and will often also only get its first review round once it has
+ the green checkmark. You can ping a maintainer if you need guidance with
+ failing CI (or anything else).
+5. A maintainer will review your PR. In this review, we check code quality,
+ bugs, and whether the contribution aligns with what was previously discussed.
+ If you think that a review comment misses something or is not quite right,
+ please challenge it!
+6. If the review passes, your PR will be merged and ship in the next version of
+ Typst. You will appear as one of the contributors in the [changelog].
+ Thank you!
+
+Below are some signs of a good PR:
+- Implements a single, self-contained feature or bugfix that has been discussed
+ previously.
+- Adds/changes as little code and as few interfaces as possible. Should changes
+ to larger-scale abstractions be necessary, these should be discussed
+ throughout the implementation process.
+- Adds tests if appropriate (with reference output for visual/HTML tests). See
+ the [testing] readme for more details.
+- Contains documentation comments on all new Rust types.
+- Comes with brief documentation for all new Typst definitions
+ (elements/functions), ideally with a concise example that fits into ~5-10
+ lines with <38 columns (check out existing examples for inspiration). This
+ part is not too critical, as we will touch up the documentation before making
+ a release.
+
+Sometimes, a contributor can become unresponsive during a review process. This
+is okay! We will, however, close PRs on which we are waiting for a contributor
+response after an extended period of time to avoid filling up the PR tracker
+with many stale PRs. In the same way, it may take a while for us to find time to
+review your PR. If there is no response after a longer while (1-2 weeks), feel
+free to ping us, as we may have missed it.
+
+While Typst is an open-source project, it is also the product of a startup. We
+always judge technical contributions to the project based on their technical
+merits. However, as a company, our immediate priorities can and do change often
+and sometimes without prior notice. This affects the design and decision making
+process as well as the development and review velocity. Some proposals may also
+have direct impact on our viability as a company, in which case we carefully
+consider them from the business perspective.
+
+If you are unsure whether your idea is a good fit for this project, please
+discuss it with us! The core question is "Does this help to make Typst the prime
+technical typesetting app?". If the answer is yes, your idea is likely right for
+Typst!
+
+[issue]: https://github.com/typst/typst/issues
+[testing]: https://github.com/typst/typst/blob/main/tests/README.md
+[#contributors]: https://discord.com/channels/1054443721975922748/1088371867913572452
+[architecture]: https://github.com/typst/typst/blob/main/docs/dev/architecture.md
+[changelog]: https://typst.app/docs/changelog/
diff --git a/sources/README.md b/sources/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..9526f3df480c5845cd98f5948c93293d134cfba4
--- /dev/null
+++ b/sources/README.md
@@ -0,0 +1,261 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Typst is a new markup-based typesetting system that is designed to be as powerful
+as LaTeX while being much easier to learn and use. Typst has:
+
+- Built-in markup for the most common formatting tasks
+- Flexible functions for everything else
+- A tightly integrated scripting system
+- Math typesetting, bibliography management, and more
+- Fast compile times thanks to incremental compilation
+- Friendly error messages in case something goes wrong
+
+This repository contains the Typst compiler and its CLI, which is everything you
+need to compile Typst documents locally. For the best writing experience,
+consider signing up to our [collaborative online editor][app] for free.
+
+## Example
+A [gentle introduction][tutorial] to Typst is available in our documentation.
+However, if you want to see the power of Typst encapsulated in one image, here
+it is:
+
+
+
+
+
+Let's dissect what's going on:
+
+- We use _set rules_ to configure element properties like the size of pages or
+ the numbering of headings. By setting the page height to `auto`, it scales to
+ fit the content. Set rules accommodate the most common configurations. If you
+ need full control, you can also use [show rules][show] to completely redefine
+ the appearance of an element.
+
+- We insert a heading with the `= Heading` syntax. One equals sign creates a top
+ level heading, two create a subheading and so on. Typst has more lightweight
+ markup like this, see the [syntax] reference for a full list.
+
+- [Mathematical equations][math] are enclosed in dollar signs. By adding extra
+ spaces around the contents of an equation, we can put it into a separate block.
+ Multi-letter identifiers are interpreted as Typst definitions and functions
+ unless put into quotes. This way, we don't need backslashes for things like
+ `floor` and `sqrt`. And `phi.alt` applies the `alt` modifier to the `phi` to
+ select a particular symbol variant.
+
+- Now, we get to some [scripting]. To input code into a Typst document, we can
+ write a hash followed by an expression. We define two variables and a
+ recursive function to compute the n-th fibonacci number. Then, we display the
+ results in a center-aligned table. The table function takes its cells
+ row-by-row. Therefore, we first pass the formulas `$F_1$` to `$F_8$` and then
+ the computed fibonacci numbers. We apply the spreading operator (`..`) to both
+ because they are arrays and we want to pass the arrays' items as individual
+ arguments.
+
+
+ Text version of the code example.
+
+ ```typst
+ #set page(width: 10cm, height: auto)
+ #set heading(numbering: "1.")
+
+ = Fibonacci sequence
+ The Fibonacci sequence is defined through the
+ recurrence relation $F_n = F_(n-1) + F_(n-2)$.
+ It can also be expressed in _closed form:_
+
+ $ F_n = round(1 / sqrt(5) phi.alt^n), quad
+ phi.alt = (1 + sqrt(5)) / 2 $
+
+ #let count = 8
+ #let nums = range(1, count + 1)
+ #let fib(n) = (
+ if n <= 2 { 1 }
+ else { fib(n - 1) + fib(n - 2) }
+ )
+
+ The first #count numbers of the sequence are:
+
+ #align(center, table(
+ columns: count,
+ ..nums.map(n => $F_#n$),
+ ..nums.map(n => str(fib(n))),
+ ))
+ ```
+
+
+## Installation
+Typst's CLI is available from different sources:
+
+- You can get sources and pre-built binaries for the latest release of Typst
+ from the [releases page][releases]. Download the archive for your platform and
+ place it in a directory that is in your `PATH`. To stay up to date with future
+ releases, you can simply run `typst update`.
+
+- You can install Typst through different package managers. Note that the
+ versions in the package managers might lag behind the latest release.
+ - Linux:
+ - View [Typst on Repology][repology]
+ - View [Typst's Snap][snap]
+ - macOS: `brew install typst`
+ - Windows: `winget install --id Typst.Typst`
+
+- If you have a [Rust][rust] toolchain installed, you can install
+ - the latest released Typst version with
+ `cargo install --locked typst-cli`
+ - a development version with
+ `cargo install --git https://github.com/typst/typst --locked typst-cli`
+
+- Nix users can
+ - use the `typst` package with `nix-shell -p typst`
+ - build and run a development version with
+ `nix run github:typst/typst -- --version`.
+
+- Docker users can run a prebuilt image with
+ `docker run ghcr.io/typst/typst:latest --help`.
+
+## Usage
+Once you have installed Typst, you can use it like this:
+```sh
+# Creates `file.pdf` in working directory.
+typst compile file.typ
+
+# Creates PDF file at the desired path.
+typst compile path/to/source.typ path/to/output.pdf
+```
+
+You can also watch source files and automatically recompile on changes. This is
+faster than compiling from scratch each time because Typst has incremental
+compilation.
+```sh
+# Watches source files and recompiles on changes.
+typst watch file.typ
+```
+
+Typst further allows you to add custom font paths for your project and list all
+of the fonts it discovered:
+```sh
+# Adds additional directories to search for fonts.
+typst compile --font-path path/to/fonts file.typ
+
+# Lists all of the discovered fonts in the system and the given directory.
+typst fonts --font-path path/to/fonts
+
+# Or via environment variable (Linux syntax).
+TYPST_FONT_PATHS=path/to/fonts typst fonts
+```
+
+For other CLI subcommands and options, see below:
+```sh
+# Prints available subcommands and options.
+typst help
+
+# Prints detailed usage of a subcommand.
+typst help watch
+```
+
+If you prefer an integrated IDE-like experience with autocompletion and instant
+preview, you can also check out [Typst's free web app][app].
+
+## Community
+The main places where the community gathers are our [Forum][forum] and our
+[Discord server][discord]. The Forum is a great place to ask questions, help
+others, and share cool things you created with Typst. The Discord server is more
+suitable for quicker questions, discussions about contributing, or just to chat.
+We'd be happy to see you there!
+
+[Typst Universe][universe] is where the community shares templates and packages.
+If you want to share your own creations, you can submit them to our
+[package repository][packages].
+
+If you had a bad experience in our community, please [reach out to us][contact].
+
+## Contributing
+We love to see contributions from the community. If you experience bugs, feel
+free to open an issue. If you would like to implement a new feature or bug fix,
+please follow the steps outlined in the [contribution guide][contributing].
+
+To build Typst yourself, first ensure that you have the
+[latest stable Rust][rust] installed. Then, clone this repository and build the
+CLI with the following commands:
+
+```sh
+git clone https://github.com/typst/typst
+cd typst
+cargo build --release
+```
+
+The optimized binary will be stored in `target/release/`.
+
+Another good way to contribute is by [sharing packages][packages] with the
+community.
+
+## Pronunciation and Spelling
+IPA: /taɪpst/. "Ty" like in **Ty**pesetting and "pst" like in Hi**pst**er. When
+writing about Typst, capitalize its name as a proper noun, with a capital "T".
+
+## Design Principles
+All of Typst has been designed with three key goals in mind: Power,
+simplicity, and performance. We think it's time for a system that matches the
+power of LaTeX, is easy to learn and use, all while being fast enough to realize
+instant preview. To achieve these goals, we follow three core design principles:
+
+- **Simplicity through Consistency:**
+ If you know how to do one thing in Typst, you should be able to transfer that
+ knowledge to other things. If there are multiple ways to do the same thing,
+ one of them should be at a different level of abstraction than the other. E.g.
+ it's okay that `= Introduction` and `#heading[Introduction]` do the same thing
+ because the former is just syntax sugar for the latter.
+
+- **Power through Composability:**
+ There are two ways to make something flexible: Have a knob for everything or
+ have a few knobs that you can combine in many ways. Typst is designed with the
+ second way in mind. We provide systems that you can compose in ways we've
+ never even thought of. TeX is also in the second category, but it's a bit
+ low-level and therefore people use LaTeX instead. But there, we don't really
+ have that much composability. Instead, there's a package for everything
+ (`\usepackage{knob}`).
+
+- **Performance through Incrementality:**
+ All Typst language features must accommodate for incremental compilation.
+ Luckily we have [`comemo`], a system for incremental compilation which does
+ most of the hard work in the background.
+
+[docs]: https://typst.app/docs/
+[app]: https://typst.app/
+[discord]: https://discord.gg/2uDybryKPe
+[forum]: https://forum.typst.app/
+[universe]: https://typst.app/universe/
+[tutorial]: https://typst.app/docs/tutorial/
+[show]: https://typst.app/docs/reference/styling/#show-rules
+[math]: https://typst.app/docs/reference/math/
+[syntax]: https://typst.app/docs/reference/syntax/
+[scripting]: https://typst.app/docs/reference/scripting/
+[rust]: https://rustup.rs/
+[releases]: https://github.com/typst/typst/releases/
+[repology]: https://repology.org/project/typst/versions
+[contact]: https://typst.app/contact
+[architecture]: https://github.com/typst/typst/blob/main/docs/dev/architecture.md
+[contributing]: https://github.com/typst/typst/blob/main/CONTRIBUTING.md
+[packages]: https://github.com/typst/packages/
+[`comemo`]: https://github.com/typst/comemo/
+[snap]: https://snapcraft.io/typst
diff --git a/sources/crates/typst-syntax/README.md b/sources/crates/typst-syntax/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ced4096ef6cb314590fca3193d6d59c1ccd6bcda
--- /dev/null
+++ b/sources/crates/typst-syntax/README.md
@@ -0,0 +1,40 @@
+# typst-syntax
+
+Welcome to the Typst Syntax crate! This crate manages the syntactical structure
+of Typst by holding some core abstractions like assigning source file ids,
+parsing Typst syntax, creating an Abstract Syntax Tree (AST), initializing
+source "spans" (for linking AST elements to their outputs in a document), and
+syntax highlighting.
+
+Below are quick descriptions of the files you might be editing if you find
+yourself here :)
+
+- `lexer.rs`: The lexical foundation of the parser, which converts a string of
+ characters into tokens.
+- `parser.rs`: The main parser definition, preparing a Concrete Syntax Tree made
+ of nested vectors of `SyntaxNode`s.
+- `reparser.rs`: The algorithm for reparsing the minimal required amount of
+ source text for efficient incremental compilation.
+- `ast.rs`: The conversion layer between the Concrete Syntax Tree of the parser
+ and the Abstract Syntax Tree used for code evaluation.
+- `node.rs` & `span.rs`: The underlying data structure for the Concrete Syntax
+ Tree and the definitions of source spans used for efficiently pointing to a
+ syntax node in things like diagnostics.
+- `kind.rs` & `set.rs`: An enum with all syntactical tokens and nodes and
+ bit-set data structure for sets of `SyntaxKind`s.
+- `highlight.rs`: Extracting of syntax highlighting information out of the
+ Concrete Syntax Tree (and outputting as HTML).
+- `path.rs`, `file.rs`, `package.rs`: The system for interning project and
+ package paths as unique file IDs and resolving them in a virtual filesystem
+ (not actually for _opening_ files).
+
+The structure of the parser is largely adapted from Rust Analyzer. Their
+[documentation][ra] is a good reference for a number of the design decisions
+around the parser and AST.
+
+The reparsing algorithm is explained in Section 4 of [Martin's thesis][thesis]
+(though it changed a bit since).
+
+[ra]: https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/syntax.md
+[thesis]:
+ https://www.researchgate.net/publication/364622490_Fast_Typesetting_with_Incremental_Compilation
diff --git a/sources/docs/changelog/0.1.0.md b/sources/docs/changelog/0.1.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..396390e1d7941ae8c5386df8730678e5e50e8033
--- /dev/null
+++ b/sources/docs/changelog/0.1.0.md
@@ -0,0 +1,73 @@
+---
+title: 0.1.0
+description: Changes in Typst 0.1.0
+---
+
+# Version 0.1.0 (April 04, 2023)
+
+## Breaking changes
+- When using the CLI, you now have to use subcommands:
+ - `typst compile file.typ` or `typst c file.typ` to create a PDF
+ - `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]($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 behavior.
+ 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`] 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)
+- Labels and references can now include `:` and `.` except at the end
+- Fixed APA bibliography ordering
+
+## Drawing additions
+- Added [`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
+- Now watches the root directory instead of the current one
+- Now puts the PDF file next to input file by default
+- Now accepts more kinds of input files (e.g. `/dev/stdin`)
+- Added `--open` flag to directly open the PDF
+
+## Miscellaneous improvements
+- Added [`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]($int) with base 2, 8, and 16
+- Added symbols for double bracket and laplace operator
+- The [`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`]($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`] 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
+- Fixed invalid autocompletion after certain markup elements
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.10.0.md b/sources/docs/changelog/0.10.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..5a2a3dea3081db2f9947c89c363aba218b83a8be
--- /dev/null
+++ b/sources/docs/changelog/0.10.0.md
@@ -0,0 +1,130 @@
+---
+title: 0.10.0
+description: Changes in Typst 0.10.0
+---
+
+# Version 0.10.0 (December 4, 2023)
+
+## Bibliography management
+- Added support for citation collapsing (e.g. `[[1]-[3]]` instead of
+ `[[1], [2], [3]]`) if requested by a CSL style
+- Fixed bug where an additional space would appear after a group of citations
+- Fixed link show rules for links in the bibliography
+- Fixed show-set rules on citations
+- Fixed bibliography-related crashes that happened on some systems
+- Corrected name of the GB/T 7714 family of styles from 7114 to 7714
+- Fixed missing title in some bibliography styles
+- Fixed printing of volumes in some styles
+- Fixed delimiter order for contributors in some styles (e.g. APA)
+- Fixed behavior of alphanumeric style
+- Fixed multiple bugs with GB/T 7714 style
+- Fixed escaping in Hayagriva values
+- Fixed crashes with empty dates in Hayagriva files
+- Fixed bug with spacing around math blocks
+- Fixed title case formatting after verbatim text and apostrophes
+- Page ranges in `.bib` files can now be arbitrary strings
+- Multi-line values in `.bib` files are now parsed correctly
+- Entry keys in `.bib` files now allow more characters
+- Fixed error message for empty dates in `.bib` files
+- Added support for years of lengths other than 4 without leading zeros in
+ `.bib` files
+- More LaTeX commands (e.g. for quotes) are now respected in `.bib` files
+
+## Visualization
+- Added support for [patterns]($tiling) as fills and strokes
+- The `alpha` parameter of the [`components`]($color.components) function on
+ colors is now a named parameter **(Breaking change)**
+- Added support for the [Oklch]($color.oklch) color space
+- Improved conversions between colors in different color spaces
+- Removed restrictions on [Oklab]($color.oklab) chroma component
+- Fixed [clipping]($block.clip) on blocks and boxes without a stroke
+- Fixed bug with [gradients]($gradient) on math
+- Fixed bug with gradient rotation on text
+- Fixed bug with gradient colors in PDF
+- Fixed relative base of Oklab chroma ratios
+- Fixed Oklab color negation
+
+## Text and Layout
+- CJK text can now be emphasized with the `*` and `_` syntax even when there are
+ no spaces
+- Added basic i18n for Greek and Estonian
+- Improved default [figure caption separator]($figure.caption.separator) for
+ Chinese, French, and Russian
+- Changed default [figure supplement]($figure.supplement) for Russian to short
+ form
+- Fixed [CJK-Latin-spacing]($text.cjk-latin-spacing) before line breaks and in
+ [`locate`] calls
+- Fixed line breaking at the end of links
+
+## Math
+- Added [`mid`]($math.mid) function for scaling a delimiter up to the height of
+ the surrounding [`lr`]($math.lr) group
+- The [`op`]($math.op) function can now take any content, not just strings
+- Improved documentation for [math alignment]($category/math/#alignment)
+- Fixed swallowing of trailing comma when a symbol is used in a function-like
+ way (e.g. `pi(a,b,)`)
+
+## Scripting
+- Any non-identifier dictionary key is now interpreted as an expression: For
+ instance, `{((key): value)}` will create a dictionary with a dynamic key
+- The [`stroke`] type now has a constructor that converts a value to a stroke or
+ creates one from its parts
+- Added constructor for [`arguments`] type
+- Added [`calc.div-euclid`]($calc.div-euclid) and
+ [`calc.rem-euclid`]($calc.rem-euclid) functions
+- Fixed equality of [`arguments`]
+- Fixed [`repr`]of [`cmyk`]($color.cmyk) colors
+- Fixed crashes with provided elements like figure captions, outline entries,
+ and footnote entries
+
+## Tooling and Diagnostics
+- Show rules that match on their own output now produce an appropriate error
+ message instead of a crash (this is a first step, in the future they will just
+ work)
+- Too highly or infinitely nested layouts now produce error messages instead of
+ crashes
+- Added hints for invalid identifiers
+- Added hint when trying to use a manually constructed footnote or outline entry
+- Added missing details to autocompletions for types
+- Improved error message when passing a named argument where a positional one is
+ expected
+- Jump from click now works on raw blocks
+
+## Export
+- PDF compilation output is now again fully byte-by-byte reproducible if the
+ document's [`date`]($document.date) is set manually
+- Fixed color export in SVG
+- Fixed PDF metadata encoding of multiple [authors]($document.author)
+
+## Command line interface
+- Fixed a major bug where `typst watch` would confuse files and fail to pick up
+ updates
+- Fetching of the release metadata in `typst update` now respects proxies
+- Fixed bug with `--open` flag on Windows when the path contains a space
+- The `TYPST_FONT_PATHS` environment variable can now contain multiple paths
+ (separated by `;` on Windows and `:` elsewhere)
+- Updated embedded New Computer Modern fonts to version 4.7
+- The watching process doesn't stop anymore when the main file contains invalid
+ UTF-8
+
+## Miscellaneous Improvements
+- Parallelized image encoding in PDF export
+- Improved the internal representation of content for improved performance
+- Optimized introspection (query, counter, etc.) performance
+- The [document title]($document.title) can now be arbitrary content instead of
+ just a string
+- The [`number-align`]($enum.number-align) parameter on numbered lists now also
+ accepts vertical alignments
+- Fixed selectors on [quote] elements
+- Fixed parsing of `[#return]` expression in markup
+- Fixed bug where inline equations were displayed in equation outlines
+- Fixed potential CRLF issue in [`raw`] blocks
+- Fixed a bug where Chinese numbering couldn't exceed the number 255
+
+## Development
+- Merged `typst` and `typst-library` and extracted `typst-pdf`, `typst-svg`, and
+ `typst-render` into separate crates
+- The Nix flake now includes the git revision when running `typst --version`
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.11.0.md b/sources/docs/changelog/0.11.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..27478862d11ee2bb2a4989435ef0c13fa8deba6c
--- /dev/null
+++ b/sources/docs/changelog/0.11.0.md
@@ -0,0 +1,270 @@
+---
+title: 0.11.0
+description: Changes in Typst 0.11.0
+---
+
+# Version 0.11.0 (March 15, 2024)
+
+## Tables
+- Tables are now _much_ more flexible, read the new
+ [table guide]($guides/table-guide) to get started
+- Added [`table.cell`] element for per-cell configuration
+- Cells can now span multiple [columns]($table.cell.colspan) or
+ [rows]($table.cell.rowspan)
+- The [stroke]($table.cell.stroke) of individual cells can now be customized
+- The [`align`]($table.align) and [`inset`]($table.inset) arguments of the table
+ function now also take `{(x, y) => ..}` functions
+- Added [`table.hline`] and [`table.vline`] for convenient line customization
+- Added [`table.header`] element for table headers that repeat on every page
+- Added [`table.footer`] element for table footers that repeat on every page
+- All the new table functionality is also available for [grids]($grid)
+- Fixed gutter-related bugs
+
+_Thanks to [@PgBiel](https://github.com/PgBiel) for his work on tables!_
+
+## Templates
+- You can now use template packages to get started with new projects. Click
+ _Start from template_ on the web app's dashboard and choose your preferred
+ template or run the `typst init ` command in the CLI. You can
+ [browse the available templates here]($universe/search/?kind=templates).
+- Switching templates after the fact has become easier. You can just import a
+ styling function from a different template package.
+- Package authors can now submit their own templates to the
+ [package repository](https://github.com/typst/packages). Share a template
+ for a paper, your institution, or an original work to help the community get
+ a head start on their projects.
+- Templates and packages are now organized by category and discipline. Filter
+ packages by either taxonomy in the _Start from template_ wizard. If you are a
+ package author, take a look at the new documentation for
+ [categories](https://github.com/typst/packages/blob/main/CATEGORIES.md) and
+ [disciplines](https://github.com/typst/packages/blob/main/DISCIPLINES.md).
+
+## Context
+- Added _context expressions:_ Read the chapter on [context] to get started
+- With context, you can access settable properties, e.g. `{context text.lang}`
+ to access the language set via `{set text(lang: "..")}`
+- The following existing functions have been made contextual: [`query`],
+ [`locate`], [`measure`], [`counter.display`], [`counter.at`],
+ [`counter.final`], [`state.at`], and [`state.final`]
+- Added contextual methods [`counter.get`] and [`state.get`] to retrieve the
+ value of a counter or state in the current context
+- Added contextual function [`here`] to retrieve the [location] of the current
+ context
+- The [`locate`] function now returns the location of a selector's unique match.
+ Its old behavior has been replaced by context expressions and only remains
+ temporarily available for compatibility.
+- The [`counter.at`] and [`state.at`] methods are now more flexible: They
+ directly accept any kind of [locatable]($location/#locatable) selector with a
+ unique match (e.g. a label) instead of just locations
+- When context is available, [`counter.display`] now directly returns the result
+ of applying the numbering instead of yielding opaque content. It should not be
+ used anymore without context. (Deprecation planned)
+- The `state.display` function should not be used anymore, use [`state.get`]
+ instead (Deprecation planned)
+- The `location` argument of [`query`], [`counter.final`], and [`state.final`]
+ should not be used anymore (Deprecation planned)
+- The `styles` argument of the `measure` function should not be used anymore
+ (Deprecation planned)
+- The `style` function should not be used anymore, use context instead
+ (Deprecation planned)
+- The correct context is now also provided in various other places where it is
+ available, e.g. in show rules, layout callbacks, and numbering functions in
+ the outline
+
+## Styling
+- Fixed priority of multiple [show-set rules]($styling/#show-rules): They now
+ apply in the same order as normal set rules would
+- Show-set rules on the same element (e.g. `{show heading.where(level: 1): set
+ heading(numbering: "1.")}`) now work properly
+- Setting properties on an element within a transformational show rule (e.g.
+ `{show heading: it => { set heading(..); it }}`) is **not** supported anymore
+ (previously it also only worked sometimes); use show-set rules instead
+ **(Breaking change)**
+- Text show rules that match their own output now work properly (e.g.
+ `` {show "cmd": `cmd`} ``)
+- The elements passed to show rules and returned by queries now contain all
+ fields of their respective element functions rather than just specific ones
+- All settable properties can now be used in [where]($function.where) selectors
+- [And]($selector.and) and [or]($selector.or) selectors can now be used with
+ show rules
+- Errors within show rules and context expressions are now ignored in all but
+ the last introspection iteration, in line with the behavior of the old
+ [`locate`]
+- Fixed a bug where document set rules were allowed after content
+
+## Layout
+- Added `reflow` argument to [`rotate`]($rotate) and [`scale`]($scale) which
+ lets them affect the layout
+- Fixed a bug where [floating placement]($place.float) or
+ [floating figures]($figure.placement) could end up out of order
+- Fixed overlap of text and figure for full-page floating figures
+- Fixed various cases where the [`hide`] function didn't hide its contents
+ properly
+- Fixed usage of [`h`] and [`v`] in [stacks]($stack)
+- Invisible content like a counter update will no longer force a visible block
+ for just itself
+- Fixed a bug with horizontal spacing followed by invisible content (like a
+ counter update) directly at the start of a paragraph
+
+## Text
+- Added [`stroke`]($text.stroke) property for text
+- Added basic i18n for Serbian and Catalan
+- Added support for contemporary Japanese [numbering] method
+- Added patches for various wrong metadata in specific fonts
+- The [text direction]($text.dir) can now be overridden within a paragraph
+- Fixed Danish [smart quotes]($smartquote)
+- Fixed font fallback next to a line break
+- Fixed width adjustment of JIS-style Japanese punctuation
+- Fixed Finnish translation of "Listing"
+- Fixed Z-ordering of multiple text decorations (underlines, etc.)
+- Fixed a bug due to which text [features]($text.features) could not be
+ overridden in consecutive set rules
+
+## Model
+- Added [`depth`]($heading.depth) and [`offset`]($heading.offset) arguments to
+ heading to increase or decrease the heading level for a bunch of content; the
+ heading syntax now sets `depth` rather than `level` **(Breaking change)**
+- List [markers]($list.marker) now cycle by default
+- The [`quote`] function now more robustly selects the correct quotes based on
+ language and nesting
+- Fixed indent bugs related to the default show rule of [terms]
+
+## Math
+- Inline equations now automatically linebreak at appropriate places
+- Added [`number-align`]($math.equation.number-align) argument to equations
+- Added support for adjusting the [`size`]($math.accent.size) of accents
+ relative to their base
+- Improved positioning of accents
+- [Primes]($math.primes) are now always attached as [scripts]($math.scripts) by
+ default
+- Exposed [`math.primes`] element which backs the `[$f'$]` syntax in math
+- Math mode is not affected by [`strong`] and [`emph`] anymore
+- Fixed [`attach`]($math.attach) under [fractions]($math.frac)
+- Fixed that [`math.class`] did not affect smart limit placement
+- Fixed weak spacing in [`lr`]($math.lr) groups
+- Fixed layout of large operators for Cambria Math font
+- Fixed math styling of Hebrew symbol codepoints
+
+## Symbols
+- Added `gradient` as an alias for `nabla`
+- Added `partial` as an alias for `diff`, `diff` will be deprecated in the
+ future
+- Added `colon.double`, `gt.approx`, `gt.napprox`, `lt.approx`, and `lt.napprox`
+- Added `arrow.r.tilde` and `arrow.l.tilde`
+- Added `tilde.dot`
+- Added `forces` and `forces.not`
+- Added `space.nobreak.narrow`
+- Added `lrm` (Left-to-Right Mark) and `rlm` (Right-to-Left Mark)
+- Fixed `star.stroked` symbol (which previously had the wrong codepoint)
+
+## Scripting
+- Arrays can now be compared lexicographically
+- Added contextual method [`to-absolute`]($length.to-absolute) to lengths
+- Added [`calc.root`]($calc.root)
+- Added [`int.signum`] and [`float.signum`] methods
+- Added [`float.is-nan`] and [`float.is-infinite`] methods
+- Added [`int.bit-not`], [`int.bit-and`], [`int.bit-or`], [`int.bit-xor`],
+ [`int.bit-lshift`], and [`int.bit-rshift`] methods
+- Added [`array.chunks`] method
+- A module can now be converted to a dictionary with the
+ [dictionary constructor]($dictionary/#constructor) to access its contents
+ dynamically
+- Added [`row-type`]($csv.row-type) argument to `csv` function to configure
+ how rows will be represented
+- [XML parsing]($xml) now allows DTDs (document type definitions)
+- Improved formatting of negative numbers with [`str`]($str) and [`repr`]($repr)
+- For loops can now iterate over [bytes]
+- Fixed a bug with pattern matching in for loops
+- Fixed a bug with labels not being part of [`{.fields()}`]($content.fields)
+ dictionaries
+- Fixed a bug where unnamed argument sinks wouldn't capture excess arguments
+- Fixed typo in `repr` output of strokes
+
+## Syntax
+- Added support for nested [destructuring patterns]($scripting/#bindings)
+- Special spaces (like thin or non-breaking spaces) are now parsed literally
+ instead of being collapsed into normal spaces **(Breaking change)**
+- Korean text can now use emphasis syntax without adding spaces
+ **(Breaking change)**
+- The token [`context`] is now a keyword and cannot be used as an identifier
+ anymore **(Breaking change)**
+- Nested line comments aren't allowed anymore in block comments
+ **(Breaking change)**
+- Fixed a bug where `x.)` would be treated as a field access
+- Text elements can now span across curly braces in markup
+- Fixed silently wrong parsing when function name is parenthesized
+- Fixed various bugs with parsing of destructuring patterns, arrays, and
+ dictionaries
+
+## Tooling & Diagnostics
+- Click-to-jump now works properly within [`raw`] text
+- Added suggestion for accessing a field if a method doesn't exist
+- Improved hint for calling a function stored in a dictionary
+- Improved errors for mutable accessor functions on arrays and dictionaries
+- Fixed error message when calling constructor of type that doesn't have one
+- Fixed confusing error message with nested dictionaries for strokes on
+ different sides
+- Fixed autocompletion for multiple packages with the same name from different
+ namespaces
+
+## Visualization
+- The [`image`] function doesn't upscale images beyond their natural size
+ anymore
+- The [`image`] function now respects rotation stored in EXIF metadata
+- Added support for SVG filters
+- Added alpha component to [`luma`]($color.luma) colors
+- Added [`color.transparentize`] and [`color.opacify`] methods
+- Improved [`color.negate`] function
+- Added [`stroke`]($highlight.stroke) and [`radius`]($highlight.radius)
+ arguments to `highlight` function
+- Changed default [`highlight`] color to be transparent
+- CMYK to RGB conversion is now color-managed
+- Fixed crash with gradients in Oklch color space
+- Fixed color-mixing for hue-based spaces
+- Fixed bugs with color conversion
+- SVG sizes are not rounded anymore, preventing slightly wrong aspect ratios
+- Fixed a few other SVG-related bugs
+- [`color.components`] doesn't round anything anymore
+
+## Export
+- PDFs now contain named destinations for headings derived from their labels
+- The internal PDF structure was changed to make it easier for external tools to
+ extract or modify individual pages, avoiding a bug with Typst PDFs in Apple
+ Preview
+- PDFs produced by Typst should now be byte-by-byte reproducible when
+ `{set document(date: none)}` is set
+- Added missing flag to PDF annotation
+- Fixed multiple bugs with gradients in PDF export
+- Fixed a bug with patterns in PDF export
+- Fixed a bug with embedding of grayscale images in PDF export
+- Fixed a bug with To-Unicode mapping of CFF fonts in PDF export
+- Fixed a bug with the generation of the PDF outline
+- Fixed a sorting bug in PDF export leading to non-reproducible output
+- Fixed a bug with transparent text in PNG export
+- Exported SVG files now include units in their top-level `width` and `height`
+
+## Command line interface
+- Added support for passing [inputs]($category/foundations/sys) via a CLI flag
+- When passing the filename `-`, Typst will now read input from stdin
+- Now uses the system-native TLS implementation for network fetching which
+ should be generally more robust
+- Watch mode will now properly detect when a previously missing file is created
+- Added `--color` flag to configure whether to print colored output
+- Fixed user agent with which packages are downloaded
+- Updated bundled fonts to the newest versions
+
+## Development
+- Added `--vendor-openssl` to CLI to configure whether to link OpenSSL
+ statically instead of dynamically (not applicable to Windows and Apple
+ platforms)
+- Removed old tracing (and its verbosity) flag from the CLI
+- Added new `--timings` flag which supersedes the old flamegraph profiling in
+ the CLI
+- Added minimal CLI to `typst-docs` crate for extracting the language and
+ standard library documentation as JSON
+- The `typst_pdf::export` function's `ident` argument switched from `Option` to
+ `Smart`. It should only be set to `Smart::Custom` if you can provide a stable
+ identifier (like the web app can). The CLI sets `Smart::Auto`.
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.11.1.md b/sources/docs/changelog/0.11.1.md
new file mode 100644
index 0000000000000000000000000000000000000000..e045914b50517ea219f462c50a64d070182848bb
--- /dev/null
+++ b/sources/docs/changelog/0.11.1.md
@@ -0,0 +1,62 @@
+---
+title: 0.11.1
+description: Changes in Typst 0.11.1
+---
+
+# Version 0.11.1 (May 17, 2024)
+
+## Security
+- Fixed a vulnerability where image files at known paths could be embedded into
+ the PDF even if they were outside of the project directory
+
+## Bibliography
+- Fixed et-al handling in subsequent citations
+- Fixed suppression of title for citations and bibliography references with no
+ author
+- Fixed handling of initials in citation styles without a delimiter
+- Fixed bug with citations in footnotes
+
+## Text and Layout
+- Fixed interaction of [`first-line-indent`]($par.first-line-indent) and
+ [`outline`]
+- Fixed compression of CJK punctuation marks at line start and end
+- Fixed handling of [rectangles]($rect) with negative dimensions
+- Fixed layout of [`path`] in explicitly sized container
+- Fixed broken [`raw`] text in right-to-left paragraphs
+- Fixed tab rendering in `raw` text with language `typ` or `typc`
+- Fixed highlighting of multi-line `raw` text enclosed by single backticks
+- Fixed indentation of overflowing lines in `raw` blocks
+- Fixed extra space when `raw` text ends with a backtick
+
+## Math
+- Fixed broken [equations]($math.equation) in right-to-left paragraphs
+- Fixed missing [blackboard bold]($math.bb) letters
+- Fixed error on empty arguments in 2D math argument list
+- Fixed stretching via [`mid`]($math.mid) for various characters
+- Fixed that alignment points in equations were affected by `{set align(..)}`
+
+## Export
+- Fixed [smart quotes]($smartquote) in PDF outline
+- Fixed [patterns]($tiling) with spacing in PDF
+- Fixed wrong PDF page labels when [page numbering]($page.numbering) was
+ disabled after being previously enabled
+
+## Scripting
+- Fixed overflow for large numbers in external data files (by converting to
+ floats instead)
+- Fixed [`{str.trim(regex, at: end)}`]($str.trim) when the whole string is
+ matched
+
+## Miscellaneous
+- Fixed deformed strokes for specific shapes and thicknesses
+- Fixed newline handling in code mode: There can now be comments within chained
+ method calls and between an `if` branch and the `else` keyword
+- Fixed inefficiency with incremental reparsing
+- Fixed autocompletions for relative file imports
+- Fixed crash in autocompletion handler
+- Fixed a bug where the path and entrypoint printed by `typst init` were not
+ properly escaped
+- Fixed various documentation errors
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.12.0.md b/sources/docs/changelog/0.12.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..e8152c531f3e9b67c1aedc4c06cd0c86fb8b02cf
--- /dev/null
+++ b/sources/docs/changelog/0.12.0.md
@@ -0,0 +1,402 @@
+---
+title: 0.12.0
+description: Changes in Typst 0.12.0
+---
+
+# Version 0.12.0 (October 18, 2024)
+
+## Highlights
+- Added support for multi-column floating [placement]($place.scope) and
+ [figures]($figure.scope)
+- Added support for automatic [line numbering]($par.line) (often used in
+ academic papers)
+- Typst's layout engine is now multithreaded. Typical speedups are 2-3x for
+ larger documents. The multithreading operates on page break boundaries, so
+ explicit page breaks are necessary for it to kick in.
+- Paragraph justification was optimized with a new two-pass algorithm. Speedups
+ are larger for shorter paragraphs and go up to 6x.
+- Highly reduced PDF file sizes due to better font subsetting (thanks to
+ [@LaurenzV](https://github.com/LaurenzV))
+- Emoji are now exported properly in PDF
+- Added initial support for PDF/A. For now, only the PDF/A-2b profile is
+ supported, but more is planned for the future.
+- Added various options for configuring the CLI's environment (fonts, package
+ paths, etc.)
+- Text show rules now match across multiple text elements
+- Block-level equations can now optionally break over multiple pages
+- Fixed a bug where some fonts would not print correctly on professional
+ printers
+- Fixed a long-standing bug which could cause headings to be orphaned at the
+ bottom of the page
+
+## Layout
+- Added support for multi-column floating placement and figures via
+ [`place.scope`] and [`figure.scope`]. Two-column documents should now prefer
+ `{set page(columns: 2)}` over `{show: column.with(2)}` (see the
+ [page setup guide]($guides/page-setup-guide/#columns)).
+- Added support for automatic [line numbering]($par.line) (often used in
+ academic papers)
+- Added [`par.spacing`] property for configuring paragraph spacing. This should
+ now be used instead of `{show par: set block(spacing: ..)}`
+ **(Breaking change)**
+- Block-level elements like lists, grids, and stacks now show themselves as
+ blocks and are thus affected by all block properties (e.g. `stroke`) rather
+ than just `spacing` **(Breaking change)**
+- Added [`block.sticky`] property which prevents a page break after a block
+- Added [`place.flush`] function which forces all floating figures to be placed
+ before any further content
+- Added [`skew`] function
+- Added `{auto}` option for [`page.header`] and [`page.footer`] which results in
+ an automatic header/footer based on the numbering (which was previously
+ inaccessible after a change)
+- Added `gap` and `justify` parameters to [`repeat`] function
+- Added `width` and `height` parameters to the [`measure`] function to define
+ the space in which the content should be measured. Especially useful in
+ combination with [`layout`].
+- The height of a `block`, `image`, `rect`, `square`, `ellipse`, or `circle` can
+ now be specified in [fractional units]($fraction)
+- The [`scale`] function now supports absolute lengths for `x`, `y`, `factor`.
+ This way an element of unknown size can be scaled to a fixed size.
+- The values of `block.above` and `block.below` can now be retrieved in context
+ expressions.
+- Increased accuracy of conversions between absolute units (pt, mm, cm, in)
+- Fixed a bug which could cause headings to be orphaned at the bottom of the
+ page
+- Fixed footnotes within breakable blocks appearing on the page where the
+ breakable block ends instead of at the page where the footnote marker is
+- Fixed numbering of nested footnotes and footnotes in floats
+- Fixed empty pages appearing when a [context] expression wraps whole pages
+- Fixed `{set block(spacing: x)}` behaving differently from
+ `{set block(above: x, below: x)}`
+- Fixed behavior of [`rotate`] and [`scale`] with `{reflow: true}`
+- Fixed interaction of `{align(horizon)}` and `{v(1fr)}`
+- Fixed various bugs where floating placement would yield overlapping results
+- Fixed a bug where widow/orphan prevention would unnecessarily move text into
+ the next column
+- Fixed [weak spacing]($h.weak) not being trimmed at the start and end of lines
+ in a paragraph (only at the start and end of paragraphs)
+- Fixed interaction of weak page break and [`pagebreak.to`]
+- Fixed compilation output of a single weak page break
+- Fixed crash when [padding]($pad) by `{100%}`
+
+## Text
+- Tuned hyphenation: It is less eager by default and hyphenations close to the
+ edges of words are now discouraged more strongly
+ **(May lead to larger layout reflows)**
+- New default font: Libertinus Serif. This is the maintained successor to the
+ old default font Linux Libertine. **(May lead to smaller reflows)**
+- Setting the font to an unavailable family will now result in a warning
+- Implemented a new smart quote algorithm, fixing various bugs where smart
+ quotes weren't all that smart
+- Added [`text.costs`] parameter for tweaking various parameters that affect the
+ choices of the layout engine during text layout
+- Added `typm` highlighting mode for math in [raw blocks]($raw.lang)
+- Added basic i18n for Galician, Catalan, Latin, Icelandic, Hebrew
+- Implemented hyphenation duplication for Czech, Croatian, Lower Sorbian,
+ Polish, Portuguese, Slovak, and Spanish.
+- The [`smallcaps`] function is now an element function and can thereby be used
+ in show(-set) rules.
+- The [`raw.theme`] parameter can now be set to `{none}` to disable highlighting
+ even in the presence of a language tag, and to `{auto}` to reset to the
+ default
+- Multiple [stylistic sets]($text.stylistic-set) can now be enabled at once
+- Fixed the Chinese translation for "Equation"
+- Fixed that hyphenation could occur outside of words
+- Fixed incorrect layout of bidirectional text in edge cases
+- Fixed layout of paragraphs with explicit trailing whitespace
+- Fixed bugs related to empty paragraphs created via `#""`
+- Fixed accidental trailing spaces for line breaks immediately preceding an
+ inline equation
+- Fixed [`text.historical-ligatures`] not working correctly
+- Fixed accidental repetition of Thai characters around line breaks in some
+ circumstances
+- Fixed [smart quotes]($smartquote) for Swiss French
+- New font metadata exceptions for Archivo, Kaiti SC, and Kaiti TC
+- Updated bundled New Computer Modern fonts to version 6.0
+
+## Math
+- Block-level equations can now break over multiple pages if enabled via
+ `{show math.equation: set block(breakable: true)}`.
+- Matrix and vector sizing is now more consistent across different cell contents
+- Added [`stretch`]($math.stretch) function for manually or automatically
+ stretching characters like arrows or parentheses horizontally or vertically
+- Improved layout of attachments on parenthesized as well as under- or overlined
+ expressions
+- Improved layout of nested attachments resulting from code like
+ `[#let a0 = $a_0$; $a0^1$]`
+- Improved layout of primes close to superscripts
+- Improved layout of fractions
+- Typst now makes use of math-specific height-dependent kerning information in
+ some fonts for better attachment layout
+- The `floor` and `ceil` functions in math are now callable symbols, such that
+ `[$ floor(x) = lr(floor.l x floor.r) $]`
+- The [`mat.delim`]($math.mat.delim), [`vec.delim`]($math.vec.delim), and
+ [`cases.delim`]($math.cases.delim) parameters now allow any character that is
+ considered a delimiter or "fence" (e.g. |) by Unicode. The `{delim: "||"}`
+ notation is _not_ supported anymore and should be replaced by
+ `{delim: bar.double}` **(Minor breaking change)**
+- Added [`vec.align`]($math.vec.align) and [`mat.align`]($math.mat.align)
+ parameters
+- Added [`underparen`]($math.underparen), [`overparen`]($math.overparen),
+ [`undershell`]($math.undershell), and [`overshell`]($math.overshell)
+- Added `~` shorthand for `tilde.op` in math mode **(Minor breaking change)**
+- Fixed baseline alignment of equation numbers
+- Fixed positioning of corner brackets (⌜, ⌝, ⌞, ⌟)
+- Fixed baseline of large roots
+- Fixed multiple minor layout bugs with attachments
+- Fixed that alignment points could affect line height in math
+- Fixed that spaces could show up between text and invisible elements like
+ [`metadata`] in math
+- Fixed a crash with recursive show rules in math
+- Fixed [`lr.size`]($math.lr.size) not affecting characters enclosed in
+ [`mid`]($math.mid) in some cases
+- Fixed resolving of em units in sub- and superscripts
+- Fixed bounding box of inline equations when a [text edge]($text.top-edge) is
+ set to `{"bounds"}`
+
+## Introspection
+- Implemented a new system by which Typst tracks where elements end up on the
+ pages. This may lead to subtly different behavior in introspections.
+ **(Breaking change)**
+- Fixed various bugs with wrong counter behavior in complex layout situations,
+ through a new, more principled implementation
+- Counter updates can now be before the first, in between, and after the last
+ page when isolated by weak page breaks. This allows, for instance, updating a
+ counter before the first page header and background.
+- Fixed logical ordering of introspections within footnotes and figures
+- Fixed incorrect [`here().position()`]($here) when [`place`] was used in a
+ context expression
+- Fixed resolved positions of elements (in particular, headings) whose show rule
+ emits an invisible element (like a state update) before a page break
+- Fixed behavior of stepping a counter at a deeper level than its current state
+ has
+- Fixed citation formatting not working in table headers and a few other places
+- Displaying the footnote counter will now respect the footnote numbering style
+
+## Model
+- Document set rules do not need to be at the very start of the document
+ anymore. The only restriction is that they must not occur inside of layout
+ containers.
+- The `spacing` property of [lists]($list.spacing),
+ [enumerations]($enum.spacing), and [term lists]($terms.spacing) is now also
+ respected for tight lists
+- Tight lists now only attach (with tighter spacing) to preceding paragraphs,
+ not arbitrary blocks
+- The [`quote`] element is now locatable (can be used in queries)
+- The bibliography heading now uses `depth` instead of `level` so that its level
+ can still be configured via a show-set rule
+- Added support for more [numbering] formats: Devanagari, Eastern Arabic,
+ Bengali, and circled numbers
+- Added [`hanging-indent`]($heading.hanging-indent) parameter to heading
+ function to tweak the appearance of multi-line headings and improved default
+ appearance of multi-line headings
+- Improved handling of bidirectional text in outline entry
+- Fixed document set rules being ignored in an otherwise empty document
+- Fixed document set rules not being usable in context expressions
+- Fixed bad interaction between `{set document}` and `{set page}`
+- Fixed `{show figure: set align(..)}`. Since the default figure alignment is
+ now a show-set rule, it is not revoked by `{show figure: it => it.body}`
+ anymore. **(Minor breaking change)**
+- Fixed numbering of footnote references
+- Fixed spacing after bibliography heading
+
+## Bibliography
+- The Hayagriva YAML `publisher` field can now accept a dictionary with a
+ `location` key. The top-level `location` key is now primarily intended for
+ event and item locations.
+- Multiple page ranges with prefixes and suffixes are now allowed
+- Added `director` and catch-all editor types to BibLaTeX parsing
+- Added support for disambiguation to alphanumeric citation style
+- The year 0 will now render as 1BC
+- Fixes for sorting of bibliography entries
+- Fixed pluralization of page range labels
+- Fixed sorting of citations by their number
+- Fixed how citation number ranges collapse
+- Fixed when the short form of a title is used
+- Fixed parsing of unbalanced dollars in BibLaTeX `url` field
+- Updated built-in citation styles
+
+## Visualization
+- Added `fill-rule` parameter to [`path`]($path.fill-rule) and
+ [`polygon`]($polygon.fill-rule) functions
+- Fixed color mixing and gradients for [Luma colors]($color.luma)
+- Fixed conversion from Luma to CMYK colors
+- Fixed offset gradient strokes in PNG export
+- Fixed unintended cropping of some SVGs
+- SVGs with foreign objects now produce a warning as they will likely not render
+ correctly in Typst
+
+## Syntax
+- Added support for nested imports like `{import "file.typ": module.item}`
+- Added support for parenthesized imports like `{import "file.typ": (a, b, c)}`.
+ With those, the import list can break over multiple lines.
+- Fixed edge case in parsing of reference syntax
+- Fixed edge case in parsing of heading, list, enum, and term markers
+ immediately followed by comments
+- Fixed rare crash in parsing of parenthesized expressions
+
+## Scripting
+- Added new fixed-point [`decimal`] number type for highly precise arithmetic on
+ numbers in base 10, as needed for finance
+- Added `std` module for accessing standard library definitions even when a
+ variable with the same name shadows/overwrites it
+- Added [`array.to-dict`], [`array.reduce`], [`array.windows`] methods
+- Added `exact` argument to [`array.zip`]
+- Added [`arguments.at`] method
+- Added [`int.from-bytes`], [`int.to-bytes`], [`float.from-bytes`], and
+ [`float.to-bytes`]
+- Added proper support for negative values of the `digits` parameter of
+ [`calc.round`] (the behaviour existed before but was subtly broken)
+- Conversions from [`int`] to [`float`] will now error instead of saturating if
+ the float is too large **(Minor breaking change)**
+- Added `float.nan` and `float.inf`, removed `calc.nan`
+ **(Minor breaking change)**
+- Certain symbols are now generally callable like functions and not only
+ specifically in math. Examples are accents or [`floor`]($math.floor) and
+ [`ceil`]($math.ceil).
+- Improved [`repr`] of relative values, sequences, infinities, NaN,
+ `{type(none)}` and `{type(auto)}`
+- Fixed crash on whole packages (rather than just files) cyclically importing
+ each other
+- Fixed return type of [`calc.round`] on integers when a non-zero value is
+ provided for `digits`
+
+## Styling
+- Text show rules now match across multiple text elements
+- The string `{"}` in a text show rule now matches smart quotes
+- Fixed a long-standing styling bug where the header and footer would
+ incorrectly inherit styles from a lone element on the page (e.g. a heading)
+- Fixed `{set page}` not working directly after a counter/state update
+- Page fields configured via an explicit `{page(..)[..]}` call can now be
+ properly retrieved in context expressions
+
+## Export
+- Highly reduced PDF file sizes due to better font subsetting
+- Emoji are now exported properly in PDF
+- Added initial support for PDF/A. For now, only the standard PDF/A-2b is
+ supported, but more is planned for the future. Enabled via `--pdf-standard
+ a-2b` in the CLI and via the UI in File > Export as > PDF in the web app.
+- Setting [`page.fill`] to `{none}` will now lead to transparent pages instead
+ of white ones in PNG and SVG. The new default of `{auto}` means transparent
+ for PDF and white for PNG and SVG.
+- Improved text copy-paste from PDF in complex scenarios
+- Exported SVGs now contain the `data-typst-label` attribute on groups resulting
+ from labelled [boxes]($box) and [blocks]($block)
+- Fixed a bug where some fonts would not print correctly on professional
+ printers
+- Fixed a bug where transparency could leak from one PDF object to another
+- Fixed a bug with CMYK gradients in PDF
+- Fixed various bugs with export of Oklab gradients in PDF
+- Fixed crashes related to rendering of non-outline glyphs
+- Two small fixes for PDF standard conformance
+
+## Performance
+- Typst's layout engine is now multithreaded. Typical speedups are 2-3x for
+ larger documents. The multithreading operates on page break boundaries, so
+ explicit page breaks are necessary for it to kick in.
+- Paragraph justification was optimized with a new two-pass algorithm. Speedups
+ are larger for shorter paragraphs and range from 1-6x.
+
+## Command Line Interface
+- Added `--pages` option to select specific page ranges to export
+- Added `--package-path` and `--package-cache-path` as well as
+ `TYPST_PACKAGE_PATH` and `TYPST_PACKAGE_CACHE_PATH` environment variables for
+ configuring where packages are loaded from and cached in, respectively
+- Added `--ignore-system-fonts` flag to disable system fonts fully for better
+ reproducibility
+- Added `--make-deps` argument for outputting the dependencies of the current
+ compilation as a Makefile
+- Added `--pretty` option to `typst query`, with the default now being to minify
+ (only applies to JSON format)
+- Added `--backup-path` to `typst update` to configure where the previous
+ version is backed up
+- Added useful links to help output
+- The CLI will now greet users who invoke just `typst` for the first time
+- The document can now be written to stdout by passing `-` as the output
+ filename (for PDF or single-page image export)
+- Typst will now emit a proper error message instead of failing silently when
+ the certificate specified by `--cert` or `TYPST_CERT` could not be loaded
+- The CLI now respects the `SOURCE_DATE_EPOCH` environment variable for better
+ reproducibility
+- When exporting multiple images, you can now use `{t}` (total pages), `{p}`
+ (current page), and `{0p}` (zero-padded current page, same as current `{n}`)
+ in the output path
+- The input and output paths now allow non-UTF-8 values
+- Times are now formatted more consistently across the CLI
+- Fixed a bug related to the `--open` flag
+- Fixed path completions for `typst` not working in zsh
+
+## Tooling and Diagnostics
+- The "compiler" field for specifying the minimum Typst version required by a
+ package now supports imprecise bounds like 0.11 instead of 0.11.0
+- Added warning when a label is ignored by Typst because no preceding labellable
+ element exists
+- Added hint when trying to apply labels in code mode
+- Added hint when trying to call a standard library function that has been
+ shadowed/overwritten by a local definition
+- Added hint when trying to set both the language and the region in the `lang`
+ parameter
+- Added hints when trying to compile non-Typst files (e.g. after having typed
+ `typst c file.pdf` by accident)
+- Added hint when a string is used where a label is expected
+- Added hint when a stray end of a block comment (`*/`) is encountered
+- Added hints when destructuring arrays with the wrong number of elements
+- Improved error message when trying to use a keyword as an identifier in a let
+ binding
+- Improved error messages when accessing nonexistent fields
+- Improved error message when a package exists, but not the specified version
+- Improved hints for unknown variables
+- Improved hint when trying to convert a length with non-zero em component to an
+ absolute unit
+- Fixed a crash that could be triggered by certain hover tooltips
+- Fixed an off-by-one error in to-source jumps when first-line-indent is enabled
+- Fixed suggestions for `.` after the end of an inline code expressions
+- Fixed autocompletions being duplicated in a specific case
+
+## Symbols
+- New: `parallelogram`, `original`, `image`, `crossmark`, `rest`, `natural`,
+ `flat`, `sharp`, `tiny`, `miny`, `copyleft`, `trademark`, `emoji.beet`,
+ `emoji.fingerprint`, `emoji.harp`, `emoji.shovel`, `emoji.splatter`,
+ `emoji.tree.leafless`,
+- New variants: `club.stroked`, `diamond.stroked`, `heart.stroked`,
+ `spade.stroked`, `gt.neq`, `lt.neq`, `checkmark.heavy`, `paren.double`,
+ `brace.double`, `shell.double`, `arrow.turn`, `plus.double`, `plus.triple`,
+ `infinity.bar`, `infinity.incomplete`, `infinity.tie`, `multimap.double`,
+ `ballot.check`, `ballot.check.heavy`, `emptyset.bar`, `emptyset.circle`,
+ `emptyset.arrow.l`, `emptyset.arrow.r`, `parallel.struck`, `parallel.eq`,
+ `parallel.equiv`, `parallel.slanted`, `parallel.tilde`, `angle.l.curly`,
+ `angle.l.dot`, `angle.r.curly`, `angle.r.dot`, `angle.oblique`, `angle.s`,
+ `em.two`, `em.three`
+- Renamed: `turtle` to `shell`, `notes` to `note`, `ballot.x` to `ballot.cross`,
+ `succ.eq` to `succ.curly.eq`, `prec.eq` to `prec.curly.eq`, `servicemark` to
+ `trademark.service`, `emoji.face.tired` to `emoji.face.distress`
+ **(Breaking change)**
+- Changed codepoint: `prec.eq`, `prec.neq`, `succ.eq`, `succ.neq`, `triangle`
+ from ▷ to △, `emoji.face.tired` **(Breaking change)**
+- Removed: `lt.curly` in favor of `prec`, `gt.curly` in favor of `succ`
+ **(Breaking change)**
+
+## Deprecations
+- [`counter.display`] without an established context
+- [`counter.final`] with a location
+- [`state.final`] with a location
+- `state.display`
+- [`query`] with a location as the second argument
+- [`locate`] with a callback function
+- [`measure`] with styles
+- `style`
+
+## Development
+- Added `typst-kit` crate which provides useful APIs for `World` implementors
+- Added go-to-definition API in `typst-ide`
+- Added package manifest parsing APIs to `typst-syntax`
+- As the compiler is now capable of multithreading, `World` implementations must
+ satisfy `Send` and `Sync`
+- Changed signature of `World::main` to allow for the scenario where the main
+ file could not be loaded
+- Removed `Tracer` in favor of `Warned` and `typst::trace` function
+- The `xz2` dependency used by the self-updater is now statically linked
+- The Dockerfile now has an `ENTRYPOINT` directive
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.13.0.md b/sources/docs/changelog/0.13.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..1cca48aa20400cf6ab8deb1dc9472e7f125a21b3
--- /dev/null
+++ b/sources/docs/changelog/0.13.0.md
@@ -0,0 +1,344 @@
+---
+title: 0.13.0
+description: Changes in Typst 0.13.0
+---
+
+# Version 0.13.0 (February 19, 2025)
+
+## Highlights
+- There is now a distinction between [proper paragraphs]($par) and just
+ inline-level content. This is important for future work on accessibility and
+ means that [first line indent]($par.first-line-indent) can now be enabled for
+ all paragraphs instead of just consecutive ones.
+- The [`outline`] has a better out-of-the-box look and is more customizable
+- The new [`curve`] function (that supersedes the `path` function) provides a
+ simpler and more flexible interface for creating Bézier curves
+- The `image` function now supports raw [pixel raster formats]($image.format)
+ for generating images from within Typst
+- Functions that accept [file paths]($syntax/#paths) now also accept raw
+ [bytes], for full flexibility
+- WebAssembly [plugins]($plugin) are more flexible and automatically run
+ multi-threaded
+- Fixed a long-standing bug where single-letter strings in math (`[$"a"$]`)
+ would be displayed in italics
+- You can now specify which charset should be [covered]($text.font) by which
+ font family
+- The [`pdf.embed`] function lets you embed arbitrary files in the exported
+ PDF
+- HTML export is currently under active development. The feature is still _very_
+ incomplete, but already available for experimentation behind a feature flag.
+
+## Model
+- There is now a distinction between [proper paragraphs]($par) and just
+ inline-level content **(Breaking change)**
+ - All text at the root of a document is wrapped in paragraphs. Meanwhile, text
+ in a container (like a block) is only wrapped in a paragraph if the
+ container holds any block-level content. If all of the content is
+ inline-level, no paragraph is created.
+ - In the laid-out document, it's not immediately visible whether text became
+ part of a paragraph. However, it is still important for accessibility, HTML
+ export, and for properties like `first-line-indent`.
+ - Show rules on `par` now only affect proper paragraphs
+ - The `first-line-indent` and `hanging-indent` properties also only affect
+ proper paragraphs
+ - Creating a `{par[..]}` with body content that is not fully inline-level will
+ result in a warning
+ - The default show rules of various built-in elements like lists, quotes, etc.
+ were adjusted to ensure they produce/don't produce paragraphs as appropriate
+ - Removed support for booleans and content in [`outline.indent`]
+- The [`outline`] function was fully reworked to improve its out-of-the-box
+ behavior **(Breaking change)**
+ - [Outline entries]($outline.entry) are now [blocks]($block) and are thus
+ affected by block spacing
+ - The `{auto}` indentation mode now aligns numberings and titles outline-wide
+ for a grid-like look
+ - Automatic indentation now also indents entries without a numbering
+ - Titles wrapping over multiple lines now have hanging indent
+ - The page number won't appear alone on its own line anymore
+ - The link now spans the full entry instead of just the title and page number
+ - The default spacing between outline leader dots was increased
+ - The [`fill`]($outline.entry.fill) parameter was moved from `outline` to
+ `outline.entry` and can thus be configured through show-set rules
+ - Removed `body` and `page` fields from outline entry
+ - Added `indented`, `prefix`, `inner`, `body`, and `page` methods on outline
+ entries to simplify writing of show rules
+- Added configuration to [`par.first-line-indent`] for indenting all paragraphs
+ instead of just consecutive ones
+- Added [`form`]($ref.form) parameter to `ref` function. Setting the form to
+ `{"page"}` will produce a page reference instead of a textual one.
+- Added [`document.description`] field, which results in corresponding PDF and
+ HTML metadata
+- Added [`enum.reversed`] parameter
+- Added support for Greek [numbering]
+- When the [`link`] function wraps around a container like a [block], it will
+ now generate only one link for the whole block instead of individual links for
+ all the visible leaf elements. This significantly reduces PDF file sizes when
+ combining `link` and [`repeat`].
+- The [`link`] function will now only strip one prefix (like `mailto:` or
+ `tel:`) instead of multiple
+- The link function now suppresses hyphenation via a built-in show-set rule
+ rather than through its default show rule
+- Displaying the page counter without a specified numbering will now take the
+ page numbering into account
+
+## Visualization
+- Added new [`curve`] function that supersedes the [`path`] function and
+ provides a simpler and more flexible interface. The `path` function is now
+ deprecated.
+- The `image` function now supports raw [pixel raster formats]($image.format).
+ This can be used to generate images from within Typst without the need for
+ encoding in an image exchange format.
+- Added [`image.scaling`] parameter for configuring how an image is scaled by
+ PNG export and PDF viewers (smooth or pixelated)
+- Added [`image.icc`] parameter for providing or overriding the ICC profile of
+ an image
+- Renamed `pattern` to [`tiling`]. The name `pattern` remains as a deprecated
+ alias.
+- Added [`gradient.center`], [`gradient.radius`], [`gradient.focal-center`], and
+ [`gradient.focal-radius`] methods
+- Fixed interaction of clipping and outset on [`box`] and [`block`]
+- Fixed panic with [`path`] of infinite length
+- Fixed non-solid (e.g. tiling) text fills in clipped blocks
+- Fixed a crash for images with a DPI value of zero
+- Fixed floating-point error in [`gradient.repeat`]
+- Auto-detection of image formats from a raw buffer now has support for SVGs
+
+## Scripting
+- Functions that accept [file paths]($syntax/#paths) now also accept raw
+ [bytes]
+ - [`image`], [`cbor`], [`csv`], [`json`], [`toml`], [`xml`], and [`yaml`] now
+ support a path string or bytes and their `.decode` variants are deprecated
+ - [`plugin`], [`bibliography`], [`bibliography.style`], [`cite.style`],
+ [`raw.theme`], and [`raw.syntaxes`] now accept bytes in addition to path
+ strings. These did not have `.decode` variants, so this adds new
+ flexibility.
+ - The `path` argument/field of [`image`] and [`bibliography`] was renamed to
+ `source` and `sources`, respectively **(Minor breaking change)**
+- Improved WebAssembly [plugins]($plugin)
+ - The `plugin` type is replaced by a [`plugin` function]($plugin) that returns
+ a [module] containing normal Typst functions. This module can be used with
+ import syntax. **(Breaking change)**
+ - Plugins now automatically run in multiple threads without any changes by
+ plugin authors
+ - A new [`plugin.transition`] API is introduced which allows plugins to run
+ impure initialization in a way that doesn't break Typst's purity guarantees
+- The variable name bound by a bare import (no renaming, no import list) is now
+ determined statically and dynamic imports without `{as}` renaming (e.g.
+ `{import "ot" + "her.typ"}`) are a hard error **(Breaking change)**
+- Values of the [`arguments`] type can now be added with `+` and
+ [joined]($scripting/#blocks) in curly-braced code blocks
+- Functions in an element function's scope can now be called with method syntax,
+ bringing elements and types closer (in anticipation of a future full
+ unification of the two). Currently, this is only useful for [`outline.entry`]
+ as no other element function defines methods.
+- Added [`calc.norm`] function
+- Added support for 32-bit floats in [`float.from-bytes`] and [`float.to-bytes`]
+- The [`decimal`] constructor now also accepts decimal values
+- Improved `repr` of [symbols]($symbol), [arguments], and [types]($type)
+- Duplicate [symbol] variants and modifiers are now a hard error
+ **(Breaking change)**
+
+## Math
+- Fixed a bug where single letter strings in math (`[$"a"$]`) would be displayed
+ in italics
+- Math function calls can now have hyphenated named arguments and support
+ [argument spreading]($arguments/#spreading)
+- Better looking accents thanks to support for the `flac` (Flattened Accent
+ Forms) and `dtls` (Dotless Forms) OpenType features
+- Added `lcm` [text operator]($math.op)
+- The [`bold`]($math.bold) function now works with ϝ and Ϝ
+- The [`italic`]($math.italic) function now works with ħ
+- Fixed a bug where the extent of a math equation was wrongly affected by
+ internal metadata
+- Fixed interaction of [`lr`]($math.lr) and [context] expressions
+- Fixed weak spacing being unconditionally ignored in [`lr`]($math.lr)
+- Fixed sub/superscripts sometimes being in the wrong position with
+ [`lr`]($math.lr)
+- Fixed multi-line annotations (e.g. overbrace) changing the math baseline
+- Fixed merging of attachments when the base is a nested equation
+- Fixed resolving of contextual (em-based) text sizes within math
+- Fixed spacing around up tacks (⊥)
+
+## Bibliography
+- Prose and author-only citations now use editor names if the author names are
+ unavailable
+- Some non-standard but widely used BibLaTeX `editortype`s like `producer`,
+ `writer`, `scriptwriter`, and `none` (defined by widespread style
+ `biblatex-chicago` to mean performers within `music` and `video` entries) are
+ now recognized
+- CSL styles can now render affixes around the bibliography
+- For BibTeX entries with `eprinttype = {pubmed}`, the PubMed ID will now be
+ correctly processed
+- Whitespace handling for strings delimiting initialized names has been improved
+- Uppercase spelling after apostrophes used as quotation marks is now possible
+- Fixed bugs around the handling of CSL delimiting characters
+- Fixed a problem with parsing multibyte characters in page ranges that could
+ prevent Hayagriva from parsing some BibTeX page ranges
+- Updated CSL APA style
+- Updated CSL locales for Finnish, Swiss German, Austrian German, German, and
+ Arabic
+
+## Text
+- Added support for specifying which charset should be [covered]($text.font) by
+ which font family
+- Added [`all`]($smallcaps.all) parameter to `smallcaps` function that also
+ enables small capitals on uppercase letters
+- Added basic i18n for Basque and Bulgarian
+- [Justification]($par.justify) does not affect [raw] blocks anymore
+- [CJK-Latin-spacing]($text.cjk-latin-spacing) does not affect [raw] text
+ anymore
+- Fixed wrong language codes being used for Greek and Ukrainian
+- Fixed default quotes for Croatian and Bulgarian
+- Fixed crash in RTL text handling
+- Added support for [`raw`] syntax highlighting for a few new languages: CFML,
+ NSIS, and WGSL
+- New font metadata exception for New Computer Modern Sans Math
+- Updated bundled New Computer Modern fonts to version 7.0.1
+
+## Layout
+- Fixed various bugs with footnotes
+ - Fixed footnotes getting lost when multiple footnotes were nested within
+ another footnote
+ - Fixed endless loops with empty and overlarge footnotes
+ - Fixed crash with overlarge footnotes within a floating placement
+- Fixed sizing of quadratic shapes ([`square`] and [`circle`])
+- Fixed [`block.sticky`] not working properly at the top of a container
+- Fixed crash due to consecutive weak spacing
+- Fixed crash when a [block] or text have negative sizes
+- Fixed unnecessary hyphenations occurring in rare scenarios due to a bad
+ interaction between padding and paragraph optimization
+- Fixed lone [citations]($cite) in [`align`] not becoming their own paragraph
+
+## Syntax
+- Top-level closing square brackets that do not have a matching opening square
+ bracket are now a hard error **(Minor breaking change)**
+- Adding a space between the identifier and the parentheses in a set rule is not
+ allowed anymore **(Minor breaking change)**
+- Numbers with a unit cannot have a base prefix anymore, e.g. `0b100000pt` is
+ not allowed anymore. Previously, it was syntactically allowed but always
+ resolved to a value of zero. **(Minor breaking change)**
+- Using `is` as an identifier will now warn as it might become a keyword in the
+ future
+- Fixed minor whitespace handling bugs
+ - in math mode argument lists
+ - at the end of headings
+ - between a term list's term and description
+- Fixed parsing of empty single line raw blocks with 3+ backticks and a language
+ tag
+- Fixed minor bug with parentheses parsing in math
+- Markup that can only appear at the start of the line (headings, lists) can now
+ also appear at the start of a list item
+- A shebang `#!` at the very start of a file is now ignored
+
+## PDF export
+- Added [`pdf.embed`] function for embedding arbitrary files in the exported PDF
+- Added support for PDF/A-3b export
+- The PDF timestamp will now contain the timezone by default
+
+## HTML export
+**Note:** HTML export is currently under active development. The feature is
+still _very_ incomplete, but already available for experimentation behind a
+feature flag.
+
+- Added HTML output support for some (but not all) of the built-in elements
+- Added [`html.elem`] function for outputting an arbitrary HTML element
+- Added [`html.frame`] function for integrating content that requires layout
+ into HTML (by embedding an SVG)
+- Added [`target`] function which returns either `{"paged"}` or `{"html"}`
+ depending on the export target
+
+## Tooling and Diagnostics
+- Autocompletion improvements
+ - Added autocompletion for file paths
+ - Smarter autocompletion of variables: Completing `{rect(fill: |)}` will now
+ only show variables which contain a valid fill (either directly or nested,
+ e.g. a dictionary containing a valid fill)
+ - Different functions will now autocomplete with different brackets (round vs
+ square) depending on which kind is more useful
+ - Positional parameters which are already provided aren't autocompleted again
+ anymore
+ - Fixed variable autocompletion not considering parameters
+ - Added autocompletion snippets for common figure usages
+ - Fixed autocompletion after half-completed import item
+ - Fixed autocompletion for `cite` function
+- Added warning when an unconditional return in a code block discards joined
+ content
+- Fixed error message when accessing non-existent label
+- Fixed handling of nested imports in IDE functionality
+
+## Command Line Interface
+- Added `--features` argument and `TYPST_FEATURES` environment variable for
+ opting into experimental features. The only feature so far is `html`.
+- Added a live reloading HTTP server to `typst watch` when targeting HTML
+- Fixed self-update not being aware about certain target architectures
+- Fixed crash when piping `typst fonts` output to another command
+- Fixed handling of relative paths in `--make-deps` output
+- Fixed handling of multipage SVG and PNG export in `--make-deps` output
+- Colons in filenames are now correctly escaped in `--make-deps` output
+
+## Symbols
+- New
+ - `inter`, `inter.and`, `inter.big`, `inter.dot`, `inter.double`, `inter.sq`,
+ `inter.sq.big`, `inter.sq.double`, `integral.inter`
+ - `asymp`, `asymp.not`
+ - `mapsto`, `mapsto.long`
+ - `divides.not.rev`, `divides.struck`
+ - `interleave`, `interleave.big`, `interleave.struck`
+ - `eq.triple.not`, `eq.dots`, `eq.dots.down`, `eq.dots.up`
+ - `smt`, `smt.eq`, `lat`, `lat.eq`
+ - `colon.tri`, `colon.tri.op`
+ - `dagger.triple`, `dagger.l`, `dagger.r`, `dagger.inv`
+ - `hourglass.stroked`, `hourglass.filled`
+ - `die.six`, `die.five`, `die.four`, `die.three`, `die.two`, `die.one`
+ - `errorbar.square.stroked`, `errorbar.square.filled`,
+ `errorbar.diamond.stroked`, `errorbar.diamond.filled`,
+ `errorbar.circle.stroked`, `errorbar.circle.filled`
+ - `numero`
+- Renamed **(Breaking change)**
+ - `ohm.inv` to `Omega.inv`
+- Changed codepoint **(Breaking change)**
+ - `angle.l.double` from `《` to `⟪`
+ - `angle.r.double` from `》` to `⟫`
+ - `angstrom` from U+212B (`Å`) to U+00C5 (`Å`)
+- Deprecated
+ - `sect` and all its variants in favor of `inter`
+ - `integral.sect` in favor of `integral.inter`
+- Removed **(Breaking change)**
+ - `degree.c` in favor of `°C` (`[$upright(°C)$]` or `[$upright(degree C)$]` in math)
+ - `degree.f` in favor of `°F` (`[$upright(°F)$]` or `[$upright(degree F)$]` in math)
+ - `kelvin` in favor of just K (`[$upright(K)$]` in math)
+ - `ohm` in favor of `Omega`
+
+## Deprecations
+- The [`path`] function in favor of the [`curve`] function
+- The name `pattern` for tiling patterns in favor of the new name [`tiling`]
+- [`image.decode`], [`cbor.decode`], [`csv.decode`], [`json.decode`],
+ [`toml.decode`], [`xml.decode`], [`yaml.decode`] in favor of the top-level
+ functions directly accepting both paths and bytes
+- The `sect` and its variants in favor of `inter`, and `integral.sect` in favor
+ of `integral.inter`
+- The compatibility behavior of type/str comparisons (e.g. `{int == "integer"}`)
+ which was temporarily introduced in Typst 0.8 now emits warnings. It will be
+ removed in Typst 0.14.
+
+## Removals
+- Removed `style` function and `styles` argument of [`measure`], use a [context]
+ expression instead **(Breaking change)**
+- Removed `state.display` function, use [`state.get`] instead
+ **(Breaking change)**
+- Removed `location` argument of [`state.at`], [`counter.at`], and [`query`]
+ **(Breaking change)**
+- Removed compatibility behavior where [`counter.display`] worked without
+ [context] **(Breaking change)**
+- Removed compatibility behavior of [`locate`] **(Breaking change)**
+
+## Development
+- The `typst::compile` function is now generic and can return either a
+ `PagedDocument` or an `HtmlDocument`
+- `typst-timing` now supports WebAssembly targets via `web-sys` when the `wasm`
+ feature is enabled
+- Increased minimum supported Rust version to 1.80
+- Fixed linux/arm64 Docker image
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.13.1.md b/sources/docs/changelog/0.13.1.md
new file mode 100644
index 0000000000000000000000000000000000000000..caf523e1c15cb0f81dd0217f948a995e55d0dc0c
--- /dev/null
+++ b/sources/docs/changelog/0.13.1.md
@@ -0,0 +1,29 @@
+---
+title: 0.13.1
+description: Changes in Typst 0.13.1
+---
+
+# Version 0.13.1 (March 7, 2025)
+
+## Command Line Interface
+- Fixed high CPU usage for `typst watch` on Linux. Depending on the project
+ size, CPU usage would spike for varying amounts of time. This bug appeared
+ with 0.13.0 due to a behavioral change in the inotify file watching backend.
+
+## HTML export
+- Fixed export of tables with [gutters]($table.gutter)
+- Fixed usage of `` and `` element within [context]
+- Fixed querying of [metadata] next to `` and `` element
+
+## Visualization
+- Fixed [curves]($curve) with multiple non-closed components
+
+## Introspection
+- Fixed a regression where labelled [symbols]($symbol) could not be
+ [queried]($query) by label
+
+## Deprecations
+- Fixed false positives in deprecation warnings for type/str comparisons
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.2.0.md b/sources/docs/changelog/0.2.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..294e832bf9145b0d1ce0278ff19e1dc18b1f6f05
--- /dev/null
+++ b/sources/docs/changelog/0.2.0.md
@@ -0,0 +1,47 @@
+---
+title: 0.2.0
+description: Changes in Typst 0.2.0
+---
+
+# Version 0.2.0 (April 11, 2023)
+
+## 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`]($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`]($array.enumerate) method
+- Added [`path`] function for drawing Bézier paths
+- Added [`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
+- New Computer Modern font is now embedded into the binary
+- Shell completions and man pages can now be generated by setting the
+ `GEN_ARTIFACTS` environment variable to a target directory and then building
+ Typst
+
+## Miscellaneous improvements
+- Fixed page numbering in outline
+- 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]($math.op)
+- Fixed bug where math could not be hidden with [`hide`]
+- Fixed sizing issues with box, block, and shapes
+- Fixed some translations
+- 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]($ratio) can now be multiplied with more types and be converted to
+ [floats]($float) with the [`float`] function
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.3.0.md b/sources/docs/changelog/0.3.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..dda47b69393c7c2614c93534e0369c0ba566f981
--- /dev/null
+++ b/sources/docs/changelog/0.3.0.md
@@ -0,0 +1,77 @@
+---
+title: 0.3.0
+description: Changes in Typst 0.3.0
+---
+
+# Version 0.3.0 (April 26, 2023)
+
+## 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`]($calc.rem) to more accurately reflect the behavior.
+ 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`]. 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]($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`]($image.alt) text argument to image function
+- Added [`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/foundations/calc) functions
+
+## Improvements
+- Text in SVGs now displays properly
+- Typst now generates a PDF heading outline
+- [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`] 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
+
+## Bug fixes
+- Fixed wrong linebreak before punctuation that follows inline equations,
+ citations, and other elements
+- Fixed a bug with [argument sinks]($arguments)
+- Fixed strokes with thickness zero
+- Fixed hiding and show rules in math
+- Fixed alignment in matrices
+- Fixed some alignment bugs in equations
+- Fixed grid cell alignment
+- Fixed alignment of list marker and enum markers in presence of global
+ alignment settings
+- 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`
+- The output of `typst fonts` now includes the embedded fonts
+
+## Development
+- Added instrumentation for debugging and optimization
+- Added `--update` flag and `UPDATE_EXPECT` environment variable to update
+ reference images for tests
+- You can now run a specific subtest with `--subtest`
+- Tests now run on multiple threads
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.4.0.md b/sources/docs/changelog/0.4.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..a5c30cdd7b2f9e44fc45c9f45b04c85af1060b1a
--- /dev/null
+++ b/sources/docs/changelog/0.4.0.md
@@ -0,0 +1,106 @@
+---
+title: 0.4.0
+description: Changes in Typst 0.4.0
+---
+
+# Version 0.4.0 (May 20, 2023)
+
+## Footnotes
+- Implemented support for footnotes
+- The [`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] 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`]($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)
+- Fixed show rules on symbols (e.g. `{show sym.tack: set text(blue)}`)
+- Fixed missing rename from `ast.op` to `ast` that should have been in the
+ previous release
+
+## Scripting
+- Added function scopes: A function can now hold related definitions in its own
+ scope, similar to a module. The new [`assert.eq`]($assert.eq) function, for
+ instance, is part of the [`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`]($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]($int) or [float]($float)
+ fails
+
+## Text and Layout
+- Implemented sophisticated CJK punctuation adjustment
+- Disabled [overhang]($text.overhang) for CJK punctuation
+- Added basic translations for Traditional Chinese
+- 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]($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
+
+## Export
+- Fixed ligatures in PDF export: They are now copyable and searchable
+- Exported PDFs now embed ICC profiles for images that have them
+- Fixed export of strokes with zero thickness
+
+## Web app
+- Projects can now contain folders
+- Added upload by drag-and-drop into the file panel
+- Files from the file panel can now be dragged into the editor to insert them
+ into a Typst file
+- You can now copy-paste images and other files from your computer directly into
+ the editor
+- Added a button to resend confirmation email
+- Added an option to invert preview colors in dark mode
+- Added tips to the loading screen and the Help menu. Feel free to propose more!
+- Added syntax highlighting for YAML files
+- Allowed middle mouse button click on many buttons to navigate into a new tab
+- Allowed more project names
+- Fixed overridden Vim mode keybindings
+- Fixed many bugs regarding file upload and more
+
+## Miscellaneous Improvements
+- Improved performance of counters, state, and queries
+- 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
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.5.0.md b/sources/docs/changelog/0.5.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..19a90ea55c9dd51b0373024354b85b6c25d3a104
--- /dev/null
+++ b/sources/docs/changelog/0.5.0.md
@@ -0,0 +1,68 @@
+---
+title: 0.5.0
+description: Changes in Typst 0.5.0
+---
+
+# Version 0.5.0 (June 9, 2023)
+
+## Text and Layout
+- Added [`raw`] syntax highlighting for many more languages
+- Added support for Korean [numbering]
+- Added basic i18n for a few more languages (NL, SV, DA)
+- Improved line breaking for East Asian languages
+- Expanded functionality of outline [`indent`]($outline.indent) property
+- Fixed footnotes in columns
+- 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`] elements
+
+## Math
+- **Breaking change:** The syntax rules for mathematical
+ [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`]($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`]($math.attach) function
+
+## Scripting
+- Added new [`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`] 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
+
+## Command line interface
+- Added PNG export via `typst compile source.typ output-{n}.png`. The output
+ path must contain `[{n}]` if the document has multiple pages.
+- Added `--diagnostic-format=short` for Unix-style short diagnostics
+- Doesn't emit color codes anymore if stderr isn't a TTY
+- Now sets the correct exit when invoked with a nonexistent file
+- Now ignores UTF-8 BOM in Typst files
+
+## Miscellaneous Improvements
+- Improved errors for mismatched delimiters
+- 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`]
+- Fixed bugs with [reference supplements]($ref.supplement)
+- Fixed Nix flake
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.6.0.md b/sources/docs/changelog/0.6.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..f81afefcc84e29c804696966f34a47a0a8885ebb
--- /dev/null
+++ b/sources/docs/changelog/0.6.0.md
@@ -0,0 +1,66 @@
+---
+title: 0.6.0
+description: Changes in Typst 0.6.0
+---
+
+# Version 0.6.0 (June 30, 2023)
+
+## Package Management
+- Typst now has built-in [package management]($scripting/#packages)
+- You can import [published]($universe) community packages or create and use
+ [system-local](https://github.com/typst/packages#local-packages) ones
+- Published packages are also supported in the web app
+
+## Math
+- Added support for optical size variants of glyphs in math mode
+- 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]($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]($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]($underline)
+- Fixed bug superfluous table lines
+- Fixed smart quotes after line breaks
+- Fixed a crash related to text layout
+
+## Command line interface
+- **Breaking change:** Added requirement for `--root`/`TYPST_ROOT` directory to
+ contain the input file because it designates the _project_ root. Existing
+ setups that use `TYPST_ROOT` to emulate package management should switch to
+ [local packages](https://github.com/typst/packages#local-packages)
+- **Breaking change:** Now denies file access outside of the project root
+- Added support for local packages and on-demand package download
+- Now watches all relevant files, within the root and all packages
+- Now displays compilation time
+
+## Miscellaneous Improvements
+- Added [`outline.entry`]($outline.entry) to customize outline entries with show
+ rules
+- Added some hints for error messages
+- Added some missing syntaxes for [`raw`] highlighting
+- Improved rendering of rotated images in PNG export and web app
+- Made [footnotes]($footnote) reusable and referenceable
+- Fixed bug with citations and bibliographies in [`locate`]
+- Fixed inconsistent tense in documentation
+
+## Development
+- Added [contribution guide](https://github.com/typst/typst/blob/main/CONTRIBUTING.md)
+- Reworked `World` interface to accommodate for package management and make it a
+ bit simpler to implement _(Breaking change for implementors)_
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.7.0.md b/sources/docs/changelog/0.7.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..9ea2ec21c18d4aa02d754a0879224b6f8a687ce5
--- /dev/null
+++ b/sources/docs/changelog/0.7.0.md
@@ -0,0 +1,142 @@
+---
+title: 0.7.0
+description: Changes in Typst 0.7.0
+---
+
+# Version 0.7.0 (August 7, 2023)
+
+## Text and Layout
+- Added support for floating figures through the
+ [`placement`]($figure.placement) argument on the figure function
+- Added support for arbitrary floating content through the
+ [`float`]($place.float) argument on the place function
+- Added support for loading `.sublime-syntax` files as highlighting
+ [syntaxes]($raw.syntaxes) for raw blocks
+- Added support for loading `.tmTheme` files as highlighting
+ [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`]($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]($place) in containers
+- Fixed overflowing containers due to optimized line breaks
+
+## Export
+- Greatly improved export of SVG images to PDF. Many thanks to
+ [@LaurenzV](https://github.com/LaurenzV) for their work on this.
+- Added support for the alpha channel of RGBA colors in PDF export
+- Fixed a bug with PPI (pixels per inch) for PNG export
+
+## Math
+- Improved layout of primes (e.g. in `[$a'_1$]`)
+- Improved display of multi-primes (e.g. in `[$a''$]`)
+- 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]($box) in equations now sit on the baseline instead of being vertically
+ centered by default. Notably, this does not affect [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]($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]($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`
+ - Renamed `.eqq` modifier to `.equiv` (and `.neqq` to `.nequiv`) for `tilde`,
+ `gt`, `lt`, `prec`, and `succ`
+ - Added `emptyset` as alias for `nothing`
+ - Added `lt.curly` and `gt.curly` as aliases for `prec` and `succ`
+ - Added `aleph`, `beth`, and `gimmel` as alias for `alef`, `bet`, and `gimel`
+
+## Scripting
+- Fields
+ - 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]($stroke)
+- Accessor and utility methods
+ - 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`] function
+- Added [`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`] function for converting a string or an array of integers to
+ bytes
+ - Added [`array`] function for converting bytes to an array of integers
+ - Added support for converting bytes to a string with the [`str`] function
+
+## Tooling and Diagnostics
+- Added support for compiler warnings
+- Added warning when compilation does not converge within five attempts due to
+ intense use of introspection features
+- Added warnings for empty emphasis (`__` and `**`)
+- Improved error message for invalid field assignments
+- Improved error message after single `#`
+- Improved error message when a keyword is used where an identifier is expected
+- Fixed parameter autocompletion for functions that are in modules
+- Import autocompletion now only shows the latest package version until a colon
+ is typed
+- Fixed autocompletion for dictionary key containing a space
+- Fixed autocompletion for `for` loops
+
+## Command line interface
+- Added `typst query` subcommand to execute a
+ [query]($reference/introspection/query/#command-line-queries) on the command
+ line
+- The `--root` and `--font-paths` arguments cannot appear in front of the
+ command anymore **(Breaking change)**
+- Local and cached packages are now stored in directories of the form
+ `[{namespace}/{name}/{version}]` instead of `[{namespace}/{name}-{version}]`
+ **(Breaking change)**
+- Now prioritizes explicitly given fonts (via `--font-paths`) over system and
+ embedded fonts when both exist
+- Fixed `typst watch` not working with some text editors
+- Fixed displayed compilation time (now includes export)
+
+## Miscellaneous Improvements
+- Added [`bookmarked`]($heading.bookmarked) argument to heading to control
+ whether a heading becomes part of the PDF outline
+- Added [`caption-pos`]($figure.caption.position) argument to control the
+ position of a figure's caption
+- Added [`metadata`] function for exposing an arbitrary value to the
+ introspection system
+- Fixed that a [`state`] was identified by the pair `(key, init)` instead of
+ just its `key`
+- 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`] blocks
+- Fixed a parsing bug with dictionaries
+
+## Development
+- Extracted parser and syntax tree into `typst-syntax` crate
+- The `World::today` implementation of Typst dependents may need fixing if they
+ have the same [bug](https://github.com/typst/typst/issues/1842) that the CLI
+ world had
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.8.0.md b/sources/docs/changelog/0.8.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..330cdf1b84a324a9d29d403047e752cfa0f4f293
--- /dev/null
+++ b/sources/docs/changelog/0.8.0.md
@@ -0,0 +1,124 @@
+---
+title: 0.8.0
+description: Changes in Typst 0.8.0
+---
+
+# Version 0.8.0 (September 13, 2023)
+
+## Scripting
+- Plugins (thanks to [@astrale-sharp](https://github.com/astrale-sharp) and
+ [@arnaudgolfouse](https://github.com/arnaudgolfouse))
+ - Typst can now load [plugins]($plugin) that are compiled to WebAssembly
+ - Anything that can be compiled to WebAssembly can thus be loaded as a plugin
+ - These plugins are fully encapsulated (no access to file system or network)
+ - Plugins can be shipped as part of [packages]($scripting/#packages)
+ - Plugins work just the same in the web app
+- Types are now first-class values **(Breaking change)**
+ - A [type] is now itself a value
+ - Some types can be called like functions (those that have a constructor),
+ e.g. [`int`] and [`str`]
+ - Type checks are now of the form `{type(10) == int}` instead of the old
+ `{type(10) == "integer"}`. [Compatibility]($type/#compatibility) with the
+ old way will remain for a while to give package authors time to upgrade, but
+ it will be removed at some point.
+ - Methods are now syntax sugar for calling a function scoped to a type,
+ meaning that `{"hello".len()}` is equivalent to `{str.len("hello")}`
+- Added support for [`import`]($scripting/#modules) renaming with `as`
+- Added a [`duration`] type
+- Added support for [CBOR]($cbor) encoding and decoding
+- Added encoding and decoding functions from and to bytes for data formats:
+ [`json.decode`]($json.decode), [`json.encode`]($json.encode), and similar
+ functions for other formats
+- Added [`array.intersperse`]($array.intersperse) function
+- Added [`str.rev`]($str.rev) function
+- Added `calc.tau` constant
+- Made [bytes] joinable and addable
+- Made [`array.zip`]($array.zip) function variadic
+- Fixed bug with [`eval`] when the `mode` was set to `{"math"}`
+- Fixed bug with [`ends-with`]($str.ends-with) function on strings
+- Fixed bug with destructuring in combination with break, continue, and return
+- Fixed argument types of [hyperbolic functions]($calc.cosh), they don't allow
+ angles anymore **(Breaking change)**
+- Renamed some color methods: `rgba` becomes `to-rgba`, `cmyk` becomes
+ `to-cmyk`, and `luma` becomes `to-luma` **(Breaking change)**
+
+## Export
+- Added SVG export (thanks to [@Enter-tainer](https://github.com/Enter-tainer))
+- Fixed bugs with PDF font embedding
+- Added support for page labels that reflect the
+ [page numbering]($page.numbering) style in the PDF
+
+## Text and Layout
+- Added [`highlight`] function for highlighting text with a background color
+- Added [`polygon.regular`]($polygon.regular) function for drawing a regular
+ polygon
+- Added support for tabs in [`raw`] elements alongside
+ [`tab-width`]($raw.tab-size) parameter
+- The layout engine now tries to prevent "runts" (final lines consisting of just
+ a single word)
+- Added Finnish translations
+- Added hyphenation support for Polish
+- Improved handling of consecutive smart quotes of different kinds
+- Fixed vertical alignments for [`number-align`]($page.number-align) argument on
+ page function **(Breaking change)**
+- Fixed weak pagebreaks after counter updates
+- Fixed missing text in SVG when the text font is set to "New Computer Modern"
+- Fixed translations for Chinese
+- Fixed crash for empty text in show rule
+- Fixed leading spaces when there's a linebreak after a number and a comma
+- Fixed placement of floating elements in columns and other containers
+- Fixed sizing of block containing just a single box
+
+## Math
+- Added support for [augmented matrices]($math.mat.augment)
+- Removed support for automatic matching of fences like `|` and `||` as
+ there were too many false positives. You can use functions like
+ [`abs`]($math.abs) or [`norm`]($math.norm) or an explicit [`lr`]($math.lr)
+ call instead. **(Breaking change)**
+- Fixed spacing after number with decimal point in math
+- Fixed bug with primes in subscript
+- Fixed weak spacing
+- Fixed crash when text within math contains a newline
+
+## Tooling and Diagnostics
+- Added hints when trying to call a function stored in a dictionary without
+ extra parentheses
+- Fixed hint when referencing an equation without numbering
+- Added more details to some diagnostics (e.g. when SVG decoding fails)
+
+## Command line interface
+- Added `typst update` command for self-updating the CLI
+ (thanks to [@jimvdl](https://github.com/jimvdl))
+- Added download progress indicator for packages and updates
+- Added `--format` argument to explicitly specify the output format
+- The CLI now respects proxy configuration through environment variables and has
+ a new `--cert` option for setting a custom CA certificate
+- Fixed crash when field wasn't present and `--one` is passed to `typst query`
+
+## Miscellaneous Improvements
+- Added [page setup guide]($guides/page-setup-guide)
+- Added [`figure.caption`]($figure.caption) function that can be used for
+ simpler figure customization (**Breaking change** because `it.caption` now
+ renders the full caption with supplement in figure show rules and manual
+ outlines)
+- Moved `caption-pos` argument to `figure.caption` function and renamed it to
+ `position` **(Breaking change)**
+- Added [`separator`]($figure.caption.separator) argument to `figure.caption`
+ function
+- Added support for combination of and/or and before/after
+ [selectors]($selector)
+- Packages can now specify a
+ [minimum compiler version](https://github.com/typst/packages#package-format)
+ they require to work
+- Fixed parser bug where method calls could be moved onto their own line for
+ `[#let]` expressions in markup **(Breaking change)**
+- Fixed bugs in sentence and title case conversion for bibliographies
+- Fixed supplements for alphanumeric and author-title bibliography styles
+- Fixed off-by-one error in APA bibliography style
+
+## Development
+- Made `Span` and `FileId` more type-safe so that all error conditions must be
+ handled by `World` implementors
+
+## Contributors
+
diff --git a/sources/docs/changelog/0.9.0.md b/sources/docs/changelog/0.9.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..0cf3c1bd8858ab0a6adcb8942303bf1a24e1e6ab
--- /dev/null
+++ b/sources/docs/changelog/0.9.0.md
@@ -0,0 +1,189 @@
+---
+title: 0.9.0
+description: Changes in Typst 0.9.0
+---
+
+# Version 0.9.0 (October 31, 2023)
+
+## Bibliography management
+- New bibliography engine based on [CSL](https://citationstyles.org/) (Citation
+ Style Language). Ships with about 100 commonly used citation styles and can
+ load custom `.csl` files.
+- Added new [`form`]($cite.form) argument to the `cite` function to produce
+ different forms of citations (e.g. for producing a citation suitable for
+ inclusion in prose)
+- The [`cite`] function now takes only a single label/key instead of allowing
+ multiple. Adjacent citations are merged and formatted according to the
+ citation style's rules automatically. This works both with the reference
+ syntax and explicit calls to the `cite` function. **(Breaking change)**
+- The `cite` function now takes a [label] instead of a string
+ **(Breaking change)**
+- Added [`full`]($bibliography.full) argument to bibliography function to print
+ the full bibliography even if not all works were cited
+- Bibliography entries can now contain Typst equations (wrapped in `[$..$]` just
+ like in markup), this works both for `.yml` and `.bib` bibliographies
+- The hayagriva YAML format was improved. See its
+ [changelog](https://github.com/typst/hayagriva/blob/main/CHANGELOG.md) for
+ more details. **(Breaking change)**
+- A few bugs with `.bib` file parsing were fixed
+- Removed `brackets` argument of `cite` function in favor of `form`
+
+## Visualization
+- Gradients and colors (thanks to [@Dherse](https://github.com/Dherse))
+ - Added support for [gradients]($gradient) on shapes and text
+ - Supports linear, radial, and conic gradients
+ - Added support for defining colors in more color spaces, including
+ [Oklab]($color.oklab), [Linear RGB(A)]($color.linear-rgb),
+ [HSL]($color.hsl), and [HSV]($color.hsv)
+ - Added [`saturate`]($color.saturate), [`desaturate`]($color.desaturate), and
+ [`rotate`]($color.rotate) functions on colors
+ - Added [`color.map`]($color/#predefined-color-maps) module with predefined
+ color maps that can be used with gradients
+ - Rename `kind` function on colors to [`space`]($color.space)
+ - Removed `to-rgba`, `to-cmyk`, and `to-luma` functions in favor of a new
+ [`components`]($color.components) function
+- Improved rendering of [rectangles]($rect) with corner radius and varying
+ stroke widths
+- Added support for properly clipping [boxes]($box.clip) and
+ [blocks]($block.clip) with a border radius
+- Added `background` parameter to [`overline`], [`underline`], and [`strike`]
+ functions
+- Fixed inaccurate color embedding in PDFs
+- Fixed ICC profile handling for images embedded in PDFs
+
+## Text and Layout
+- Added support for automatically adding proper
+ [spacing]($text.cjk-latin-spacing) between CJK and Latin text (enabled by
+ default)
+- Added support for automatic adjustment of more CJK punctuation
+- Added [`quote`] element for inserting inline and block quotes with optional
+ attributions
+- Added [`raw.line`]($raw.line) element for customizing the display of
+ individual lines of raw text, e.g. to add line numbers while keeping proper
+ syntax highlighting
+- Added support for per-side [inset]($table.inset) customization to table
+ function
+- Added Hungarian and Romanian translations
+- Added support for Czech hyphenation
+- Added support for setting custom [smart quotes]($smartquote)
+- The default [figure separator]($figure.caption.separator) now reacts to the
+ currently set language and region
+- Improved line breaking of links / URLs (especially helpful for bibliographies
+ with many URLs)
+- Improved handling of consecutive hyphens in justification algorithm
+- Fixed interaction of justification and hanging indent
+- Fixed a bug with line breaking of short lines without spaces when
+ justification is enabled
+- Fixed font fallback for hyphen generated by hyphenation
+- Fixed handling of word joiner and other no-break characters during hyphenation
+- Fixed crash when hyphenating after an empty line
+- Fixed line breaking of composite emoji like 🏳️🌈
+- Fixed missing text in some SVGs
+- Fixed font fallback in SVGs
+- Fixed behavior of [`to`]($pagebreak.to) argument on `pagebreak` function
+- Fixed `{set align(..)}` for equations
+- Fixed spacing around [placed]($place) elements
+- Fixed coalescing of [`above`]($block.above) and [`below`]($block.below)
+ spacing if given in em units and the font sizes differ
+- Fixed handling of `extent` parameter of [`underline`], [`overline`], and
+ [`strike`] functions
+- Fixed crash for [floating placed elements]($place.float) with no specified
+ vertical alignment
+- Partially fixed a bug with citations in footnotes
+
+## Math
+- Added `gap` argument for [`vec`]($math.vec.gap), [`mat`]($math.mat.gap), and
+ [`cases`]($math.cases.gap) function
+- Added `size` argument for [`abs`]($math.abs), [`norm`]($math.norm),
+ [`floor`]($math.floor), [`ceil`]($math.ceil), and [`round`]($math.round)
+ functions
+- Added [`reverse`]($math.cases.reverse) parameter to cases function
+- Added support for multinomial coefficients to [`binom`]($math.binom) function
+- Removed `rotation` argument on [`cancel`]($math.cancel) function in favor of a
+ new and more flexible `angle` argument **(Breaking change)**
+- Added `wide` constant, which inserts twice the spacing of `quad`
+- Added `csch` and `sech` [operators]($math.op)
+- `↼`, `⇀`, `↔`, and `⟷` can now be used as [accents]($math.accent)
+- Added `integral.dash`, `integral.dash.double`, and `integral.slash`
+ [symbols]($category/symbols/sym)
+- Added support for specifying negative indices for
+ [augmentation]($math.mat.augment) lines to position the line from the back
+- Fixed default color of matrix [augmentation]($math.mat.augment) lines
+- Fixed attachment of primes to inline expressions
+- Math content now respects the text [baseline]($text.baseline) setting
+
+## Performance
+- Fixed a bug related to show rules in templates which would effectively disable
+ incremental compilation in affected documents
+- Micro-optimized code in several hot paths, which brings substantial
+ performance gains, in particular in incremental compilations
+- Improved incremental parsing, which affects the whole incremental compilation
+ pipeline
+- Added support for incremental parsing in the CLI
+- Added support for incremental SVG encoding during PDF export, which greatly
+ improves export performance for documents with many SVG
+
+## Tooling and Diagnostics
+- Improved autocompletion for variables that are in-scope
+- Added autocompletion for package imports
+- Added autocompletion for [labels]($label)
+- Added tooltip that shows which variables a function captures (when hovering
+ over the equals sign or arrow of the function)
+- Diagnostics are now deduplicated
+- Improved diagnostics when trying to apply unary `+` or `-` to types that only
+ support binary `+` and `-`
+- Error messages now state which label or citation key isn't present in the
+ document or its bibliography
+- Fixed a bug where function argument parsing errors were shadowed by function
+ execution errors (e.g. when trying to call [`array.sorted`]($array.sorted) and
+ passing the key function as a positional argument instead of a named one).
+
+## Export
+- Added support for configuring the document's creation
+ [`date`]($document.date). If the `date` is set to `{auto}` (the default), the
+ PDF's creation date will be set to the current date and time.
+- Added support for configuring document [`keywords`]($document.keywords)
+- Generated PDFs now contain PDF document IDs
+- The PDF creator tool metadata now includes the Typst version
+
+## Web app
+- Added version picker to pin a project to an older compiler version
+ (with support for Typst 0.6.0+)
+- Fixed desyncs between editor and compiler and improved overall stability
+- The app now continues to highlight the document when typing while the document
+ is being compiled
+
+## Command line interface
+- Added support for discovering fonts through fontconfig
+- Now clears the screen instead of resetting the terminal
+- Now automatically picks correct file extension for selected output format
+- Now only regenerates images for changed pages when using `typst watch` with
+ PNG or SVG export
+
+## Miscellaneous Improvements
+- Added [`version`] type and `sys.version` constant specifying the current
+ compiler version. Can be used to gracefully support multiple versions.
+- The U+2212 MINUS SIGN is now used when displaying a numeric value, in the
+ [`repr`] of any numeric value and to replace a normal hyphen in text mode when
+ before a digit. This improves, in particular, how negative integer values are
+ displayed in math mode.
+- Added support for specifying a default value instead of failing for `remove`
+ function in [array]($array.remove) and [dictionary]($dictionary.remove)
+- Simplified page setup guide examples
+- Switched the documentation from using the word "hashtag" to the word "hash"
+ where appropriate
+- Added support for [`array.zip`]($array.zip) without any further arguments
+- Fixed crash when a plugin tried to read out of bounds memory
+- Fixed crashes when handling infinite [lengths]($length)
+- Fixed introspection (mostly bibliography) bugs due to weak page break close to
+ the end of the document
+
+## Development
+- Extracted `typst::ide` into separate `typst_ide` crate
+- Removed a few remaining `'static` bounds on `&dyn World`
+- Removed unnecessary dependency, which reduces the binary size
+- Fixed compilation of `typst` by itself (without `typst-library`)
+- Fixed warnings with Nix flake when using `lib.getExe`
+
+## Contributors
+
diff --git a/sources/docs/changelog/earlier.md b/sources/docs/changelog/earlier.md
new file mode 100644
index 0000000000000000000000000000000000000000..ecf6816df7bf147a34054fd3b13e01290f5662ad
--- /dev/null
+++ b/sources/docs/changelog/earlier.md
@@ -0,0 +1,309 @@
+---
+title: Earlier
+description: Changes in early, unversioned Typst
+---
+
+# Changes in early, unversioned Typst
+
+## 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]($terms): Does not include a colon
+ anymore and has a bit more indent
+
+- Command line interface
+ - Added `--font-path` argument for CLI
+ - Embedded default fonts in CLI binary
+ - Fixed build of CLI if `git` is not installed
+
+- Miscellaneous improvements
+ - 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`]($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`] type
+ - Added symbols for double, triple, and quadruple dot accent
+ - Added smart quotes for Norwegian Bokmål
+ - Added Nix flake
+ - Fixed bibliography ordering in IEEE style
+ - Fixed parsing of decimals in math: `[$1.2/3.4$]`
+ - 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`] 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
+
+
+
+## March 21, 2023
+- Reference and bibliography management
+ - [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 ]`
+ - `[$ A = pi r^2 $ ]`
+
+- Introspection system for interactions between different parts of the document
+ - [`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`] 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`] 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`] 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`] function
+ - Measure the layouted size of elements
+ - To be used in combination with the new `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`]
+ - 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`] 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`] 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`]($math.equation)
+ - Font family must be a named argument now: `[#set text(font: "..")]`
+ - 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`] list
+
+- Web app improvements
+ - Added template gallery
+ - Added buttons to insert headings, equations, raw blocks, and references
+ - Jump to the source of something by clicking on it in the preview panel
+ (works for text, equations, images, and more)
+ - You can now upload your own fonts and use them in your project
+ - Hover debugging and autocompletion now takes multiple files into account and
+ works in show rules
+ - Hover tooltips now automatically collapse multiple consecutive equal values
+ - The preview now automatically scrolls to the right place when you type
+ - Links are now clickable in the preview area
+ - Toolbar, preview, and editor can now all be hidden
+ - Added autocompletion for raw block language tags
+ - Added autocompletion in SVG files
+ - New back button instead of four-dots button
+ - Lots of bug fixes
+
+## 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`] function
+- Improved default spacing for headings
+- Added [`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 autocompletion for font families
+- Improved incremental compilation for user-defined functions
+
+## February 15, 2023
+- [Box]($box) and [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`] 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
+- Shapes, images, and transformations (move/rotate/scale/repeat) are now
+ block-level. To integrate them into a paragraph, use a [`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.
+- 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]($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`] 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`]($box.baseline) property on [`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`)
+- Fixed missing italic mappings
+- Math italics correction is now applied properly
+- Parentheses now scale in `[$zeta(x/2)$]`
+- Fixed placement of large root index
+- Fixed spacing in `[$abs(-x)$]`
+- Fixed inconsistency between text and identifiers in math
+- Accents are now ignored when positioning superscripts
+- Fixed vertical alignment in matrices
+- Fixed `text` set rule in `raw` show rule
+- Heading and list markers now parse consistently
+- Allow arbitrary math directly in content
+
+## 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 hash
+ - More expressions available with hash, 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 emoji: face, turtle]` to import from already bound module
+- New symbol handling
+ - Removed symbol notation
+ - Symbols are now in modules: `{sym}`, `{emoji}`, and `{math}`
+ - Math module also reexports all of `{sym}`
+ - Modified through field access, still order-independent
+ - Unknown modifiers are not allowed anymore
+ - Support for custom symbol definitions with `symbol` function
+ - Symbols now listed in documentation
+- New `{math}` module
+ - Contains all math-related functions
+ - Variables and function calls directly in math (without hash) access this
+ module instead of the global scope, but can also access local variables
+ - Can be explicitly used in code, e.g. `[#set math.vec(delim: "[")]`
+- Delimiter matching in math
+ - Any opening delimiters matches any closing one
+ - When matched, they automatically scale
+ - To prevent scaling, escape them
+ - 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
+- Multi-line math with alignment
+ - The `\` character inserts a line break
+ - The `&` character defines an alignment point
+ - Alignment points also work for underbraces, vectors, cases, and matrices
+ - Multiple alignment points are supported
+- More capable math function calls
+ - Function calls directly in math can now take code expressions with hash
+ - They can now also take named arguments
+ - Within math function calls, semicolons turn preceding arguments to arrays to
+ support matrices: `[$mat(1, 2; 3, 4)$]`
+- Arbitrary content in math
+ - Text, images, and other arbitrary content can now be embedded in math
+ - Math now also supports font fallback to support e.g. CJK and emoji
+- More math features
+ - New text operators: `op` function, `lim`, `max`, etc.
+ - New matrix function: `mat`
+ - New n-ary roots with `root` function: `[$root(3, x)$]`
+ - New under- and overbraces, -brackets, and -lines
+ - New `abs` and `norm` functions
+ - 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)$]`
+ - Added Fira Math font, removed Noto Sans Math font
+ - 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
+ - The `pairs` method on dictionaries now returns an array of length-2 arrays
+ instead of taking a closure
+ - The method call `{dict.at("key")}` now always fails if `"key"` doesn't exist
+ Previously, it was allowed in assignments. Alternatives are `{dict.key = x}`
+ and `{dict.insert("key", x)}`.
+- Smarter editor functionality
+ - Autocompletion for local variables
+ - Autocompletion for methods available on a value
+ - Autocompletion for symbols and modules
+ - Autocompletion for imports
+ - Hover over an identifier to see its value(s)
+- Further editor improvements
+ - New Font menu with previews
+ - Single projects may now be shared with share links
+ - New dashboard experience if projects are shared with you
+ - Keyboard Shortcuts are now listed in the menus and there are more of them
+ - New Offline indicator
+ - Tooltips for all buttons
+ - Improved account protection
+ - Moved Status indicator into the error list button
+- Further fixes
+ - Multiple bug fixes for incremental parser
+ - Fixed closure parameter capturing
+ - Fixed tons of math bugs
+ - Bugfixes for performance, file management, editing reliability
+ - Added redirection to the page originally navigated to after signin
diff --git a/sources/docs/changelog/welcome.md b/sources/docs/changelog/welcome.md
new file mode 100644
index 0000000000000000000000000000000000000000..7611f1c447d488c6fd35e99fcebbdbf2864e696c
--- /dev/null
+++ b/sources/docs/changelog/welcome.md
@@ -0,0 +1,28 @@
+---
+description: |
+ Learn what has changed in the latest Typst releases and move your documents
+ forward.
+---
+
+# Changelog
+Learn what has changed in the latest Typst releases and move your documents
+forward. This section documents all changes to Typst since its initial public
+release.
+
+## Versions
+- [Typst 0.13.1]($changelog/0.13.1)
+- [Typst 0.13.0]($changelog/0.13.0)
+- [Typst 0.12.0]($changelog/0.12.0)
+- [Typst 0.11.1]($changelog/0.11.1)
+- [Typst 0.11.0]($changelog/0.11.0)
+- [Typst 0.10.0]($changelog/0.10.0)
+- [Typst 0.9.0]($changelog/0.9.0)
+- [Typst 0.8.0]($changelog/0.8.0)
+- [Typst 0.7.0]($changelog/0.7.0)
+- [Typst 0.6.0]($changelog/0.6.0)
+- [Typst 0.5.0]($changelog/0.5.0)
+- [Typst 0.4.0]($changelog/0.4.0)
+- [Typst 0.3.0]($changelog/0.3.0)
+- [Typst 0.2.0]($changelog/0.2.0)
+- [Typst 0.1.0]($changelog/0.1.0)
+- [Earlier]($changelog/earlier)
diff --git a/sources/docs/dev/architecture.md b/sources/docs/dev/architecture.md
new file mode 100644
index 0000000000000000000000000000000000000000..bbae067923429a47e9da3d5b4c4979d41e94fd87
--- /dev/null
+++ b/sources/docs/dev/architecture.md
@@ -0,0 +1,199 @@
+# Typst Compiler Architecture
+Wondering how to contribute or just curious how Typst works? This document
+covers the general structure and architecture of Typst's compiler, so you get an
+understanding of what's where and how everything fits together.
+
+
+## Directories
+Let's start with a broad overview of the directories in this repository:
+
+- `crates/typst`: The main compiler crate which defines the complete language
+ and library.
+- `crates/typst-cli`: Typst's command line interface. This is a relatively small
+ layer on top of the compiler and the exporters.
+- `crates/typst-eval`: The interpreter for the Typst language.
+- `crates/typst-ide`: Exposes IDE functionality.
+- `crates/typst-kit`: Contains various default implementation of
+ functionality used in `typst-cli`.
+- `crates/typst-layout`: Typst's layout engine.
+- `crates/typst-library`: Typst's standard library.
+- `crates/typst-macros`: Procedural macros for the compiler.
+- `crates/typst-pdf`: The PDF exporter.
+- `crates/typst-realize`: Typst's realization subsystem.
+- `crates/typst-render`: A renderer for Typst frames.
+- `crates/typst-svg`: The SVG exporter.
+- `crates/typst-syntax`: Home to the parser and syntax tree definition.
+- `crates/typst-timing`: Performance timing for Typst.
+- `crates/typst-utils`: Utilities for Typst.
+- `docs`: Generates the content of the official
+ [documentation][docs] from markdown files and the inline
+ Rust documentation. Only generates the content and structure, not the concrete
+ HTML (that part is currently closed source).
+- `tests`: Integration tests for Typst compilation.
+- `tools`: Tooling for development.
+
+
+## Compilation
+The source-to-PDF compilation process of a Typst file proceeds in four phases.
+
+1. **Parsing:** Turns a source string into a syntax tree.
+2. **Evaluation:** Turns a syntax tree and its dependencies into content.
+3. **Layout:** Layouts content into frames.
+4. **Export:** Turns frames into an output format like PDF or a raster graphic.
+
+The Typst compiler is _incremental:_ Recompiling a document that was compiled
+previously is much faster than compiling from scratch. Most of the hard work is
+done by [`comemo`], an incremental compilation framework we have written for
+Typst. However, the compiler is still carefully written with incrementality in
+mind. Below we discuss the four phases and how incrementality affects each of
+them.
+
+
+## Parsing
+The syntax tree and parser are located in `crates/typst-syntax`. Parsing is
+a pure function `&str -> SyntaxNode` without any further dependencies. The
+result is a concrete syntax tree reflecting the whole file structure, including
+whitespace and comments. Parsing cannot fail. If there are syntactic errors, the
+returned syntax tree contains error nodes instead. It's important that the
+parser deals well with broken code because it is also used for syntax
+highlighting and IDE functionality.
+
+**Typedness:**
+The syntax tree is untyped, any node can have any `SyntaxKind`. This makes it
+very easy to (a) attach spans to each node (see below), (b) traverse the tree
+when doing highlighting or IDE analyses (no extra complications like a visitor
+pattern). The `typst::syntax::ast` module provides a typed API on top of
+the raw tree. This API resembles a more classical AST and is used by the
+interpreter.
+
+**Spans:**
+After parsing, the syntax tree is numbered with _span numbers._ These numbers
+are unique identifiers for syntax nodes that are used to trace back errors in
+later compilation phases to a piece of syntax. The span numbers are ordered so
+that the node corresponding to a number can be found quickly.
+
+**Incremental:**
+Typst has an incremental parser that can reparse a segment of markup or a
+code/content block. After incremental parsing, span numbers are reassigned
+locally. This way, span numbers further away from an edit stay mostly stable.
+This is important because they are used pervasively throughout the compiler,
+also as input to memoized functions. The less they change, the better for
+incremental compilation.
+
+
+## Evaluation
+The evaluation phase lives in `crates/typst/src/eval`. It takes a parsed
+`Source` file and evaluates it to a `Module`. A module consists of the `Content`
+that was written in it and a `Scope` with the bindings that were defined within
+it.
+
+A source file may depend on other files (imported sources, images, data files),
+which need to be resolved. Since Typst is deployed in different environments
+(CLI, web app, etc.) these system dependencies are resolved through a general
+interface called a `World`. Apart from files, the world also provides
+configuration and fonts.
+
+**Interpreter:**
+Typst implements a tree-walking interpreter. To evaluate a piece of source, you
+first create a `Vm` with a scope stack. Then, the AST is recursively evaluated
+through trait impls of the form `fn eval(&self, vm: &mut Vm) -> Result`.
+An interesting detail is how closures are dealt with: When the interpreter sees
+a closure / function definition, it walks the body of the closure and finds all
+accesses to variables that aren't defined within the closure. It then clones the
+values of all these variables (it _captures_ them) and stores them alongside the
+closure's syntactical definition in a closure value. When the closure is called,
+a fresh `Vm` is created and its scope stack is initialized with the captured
+variables.
+
+**Incremental:**
+In this phase, incremental compilation happens at the granularity of the module
+and the closure. Typst memoizes the result of evaluating a source file across
+compilations. Furthermore, it memoizes the result of calling a closure with a
+certain set of parameters. This is possible because Typst ensures that all
+functions are pure. The result of a closure call can be recycled if the closure
+has the same syntax and captures, even if the closure values stems from a
+different module evaluation (i.e. if a module is reevaluated, previous calls to
+closures defined in the module can still be reused).
+
+
+## Layout
+The layout phase takes `Content` and produces one `Frame` per page for it. To
+layout `Content`, we first have to _realize_ it by applying all relevant show
+rules to the content. Since show rules may be defined as Typst closures,
+realization can trigger closure evaluation, which in turn produces content that
+is recursively realized. Realization is a shallow process: While collecting list
+items into a list that we want to layout, we don't realize the content within
+the list items just yet. This only happens lazily once the list items are
+layouted.
+
+When we a have realized the content into a layoutable element, we can then
+layout it into _regions,_ which describe the space into which the content shall
+be layouted. Within these, an element is free to layout itself as it sees fit,
+returning one `Frame` per region it wants to occupy.
+
+**Introspection:**
+How content layouts (and realizes) may depend on how _it itself_ is layouted
+(e.g., through page numbers in the table of contents, counters, state, etc.).
+Typst resolves these inherently cyclical dependencies through the _introspection
+loop:_ The layout phase runs in a loop until the results stabilize. Most
+introspections stabilize after one or two iterations. However, some may never
+stabilize, so we give up after five attempts.
+
+**Incremental:**
+Layout caching happens at the granularity of the element. This is important
+because overall layout is the most expensive compilation phase, so we want to
+reuse as much as possible.
+
+
+## Export
+Exporters live in separate crates. They turn layouted frames into an output file
+format.
+
+- The PDF exporter takes layouted frames and turns them into a PDF file.
+- The SVG exporter takes a frame and turns it into an SVG.
+- The built-in renderer takes a frame and turns it into a pixel buffer.
+- HTML export does not exist yet, but will in the future. However, this requires
+ some complex compiler work because the export will start with `Content`
+ instead of `Frames` (layout is the browser's job).
+
+
+## IDE
+The `crates/typst-ide` crate implements IDE functionality for Typst. It
+builds heavily on the other modules (most importantly, `syntax` and `eval`).
+
+**Syntactic:**
+Basic IDE functionality is based on a file's syntax. However, the standard
+syntax node is a bit too limited for writing IDE tooling. It doesn't provide
+access to its parents or neighbours. This is fine for an evaluation-like
+recursive traversal, but impractical for IDE use cases. For this reason, there
+is an additional abstraction on top of a syntax node called a `LinkedNode`,
+which is used pervasively across the `ide` module.
+
+**Semantic:**
+More advanced functionality like autocompletion requires semantic analysis of
+the source. To gain semantic information for things like hover tooltips, we
+directly use other parts of the compiler. For instance, to find out the type of
+a variable, we evaluate and realize the full document equipped with a `Tracer`
+that emits the variable's value whenever it is visited. From the set of
+resulting values, we can then compute the set of types a value takes on. Thanks
+to incremental compilation, we can recycle large parts of the compilation that
+we had to do anyway to typeset the document.
+
+**Incremental:**
+Syntactic IDE stuff is relatively cheap for now, so there are no special
+incrementality concerns. Semantic analysis with a tracer is relatively
+expensive. However, large parts of a traced analysis compilation can reuse
+memoized results from a previous normal compilation. Only the module evaluation
+of the active file and layout code that somewhere within evaluates source code
+in the active file needs to re-run. This is all handled automatically by
+`comemo` because the tracer is wrapped in a `comemo::TrackedMut` container.
+
+
+## Tests
+Typst has an extensive suite of integration tests. These tests cover parsing,
+evaluation, realization, layout, and rendering. PDF output is sadly untested so
+far, but most bugs are in earlier phases of the compiler. For more details about
+testing, see the [tests directory](/tests) and its README.
+
+[docs]: https://typst.app/docs/
+[`comemo`]: https://github.com/typst/comemo/
diff --git a/sources/docs/guides/guide-for-latex-users.md b/sources/docs/guides/guide-for-latex-users.md
new file mode 100644
index 0000000000000000000000000000000000000000..fffa6c52129f41b1446168d8a8d6053333dcd263
--- /dev/null
+++ b/sources/docs/guides/guide-for-latex-users.md
@@ -0,0 +1,676 @@
+---
+description: |
+ Are you a LaTeX user? This guide explains the differences and
+ similarities between Typst and LaTeX so you can get started quickly.
+---
+
+# 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
+syntax, you will learn how to use your LaTeX skills to get a head start.
+
+Just like LaTeX, Typst is a markup-based typesetting system: You compose your
+document in a text file and mark it up with commands and other syntax. Then, you
+use a compiler to typeset the source file into a PDF. However, Typst also
+differs from LaTeX in several aspects: For one, Typst uses more dedicated syntax
+(like you may know from Markdown) for common tasks. Typst's commands are also
+more principled: They all work the same, so unlike in LaTeX, you just need to
+understand a few general concepts instead of learning different conventions for
+each package. Moreover Typst compiles faster than LaTeX: Compilation usually
+takes milliseconds, not seconds, so the web app and the compiler can both
+provide instant previews.
+
+In the following, we will cover some of the most common questions a user
+switching from LaTeX will have when composing a document in Typst. If you prefer
+a step-by-step introduction to Typst, check out our [tutorial].
+
+## Installation
+You have two ways to use Typst: In [our web app](https://typst.app/signup/) or
+by [installing the compiler](https://github.com/typst/typst/releases) on your
+computer. When you use the web app, we provide a batteries-included
+collaborative editor and run Typst in your browser, no installation required.
+
+If you choose to use Typst on your computer instead, you can download the
+compiler as a single, small binary which any user can run, no root privileges
+required. Unlike LaTeX, packages are downloaded when you first use them and
+then cached locally, keeping your Typst installation lean. You can use your own
+editor and decide where to store your files with the local compiler.
+
+## How do I create a new, empty document? { #getting-started }
+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]($parbreak) work just as they do in LaTeX, just use a
+blank line.
+
+```example
+Hey there!
+
+Here are two paragraphs. The
+output is shown to the right.
+```
+
+If you want to start from an preexisting LaTeX document instead, you can use
+[Pandoc](https://pandoc.org) to convert your source code to Typst markup. This
+conversion is also built into our web app, so you can upload your `.tex` file to
+start your project in Typst.
+
+## How do I create section headings, emphasis, ...? { #elements }
+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]($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.
+
+Emphasis (usually rendered as italic text) is expressed by enclosing text in
+`[_underscores_]` and strong emphasis (usually rendered in boldface) by using
+`[*stars*]` instead.
+
+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`] |
+| Emphasis | `\emph{emphasis}` | `[_emphasis_]` | [`emph`] |
+| Monospace / code | `\texttt{print(1)}` | ``[`print(1)`]`` | [`raw`] |
+| Link | `\url{https://typst.app}` | `[https://typst.app/]` | [`link`] |
+| Label | `\label{intro}` | `[]` | [`label`] |
+| Reference | `\ref{intro}` | `[@intro]` | [`ref`] |
+| Citation | `\cite{humphrey97}` | `[@humphrey97]` | [`cite`] |
+| Bullet list | `itemize` environment | `[- List]` | [`list`] |
+| Numbered list | `enumerate` environment | `[+ List]` | [`enum`] |
+| Term list | `description` environment | `[/ Term: List]` | [`terms`] |
+| Figure | `figure` environment | `figure` function | [`figure`] |
+| Table | `table` environment | `table` function | [`table`] |
+| Equation | `$x$`, `align` / `equation` environments | `[$x$]`, `[$ x = y $]` | [`equation`]($math.equation) |
+
+[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:
+
+````example
+To write this list in Typst...
+
+```latex
+\begin{itemize}
+ \item Fast
+ \item Flexible
+ \item Intuitive
+\end{itemize}
+```
+
+...just type this:
+
+- Fast
+- Flexible
+- Intuitive
+
+````
+
+Nesting lists works just by using proper indentation. Adding a blank line in
+between items results in a more [widely]($list.tight) spaced list.
+
+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
+_macros_ to affect the typesetting process and to insert and manipulate content.
+Some commands accept arguments, which are most frequently enclosed in curly
+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.
+
+Within Typst's markup, you can switch to code mode for a single command (or
+rather, _expression_) using a hash (`#`). 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_]($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:
+#rect()
+
+Let me show how to do
+#underline([_underlined_ text])
+
+We can also do some maths:
+#calc.max(3, 2 * 4)
+
+And finally a little loop:
+#for x in range(3) [
+ Hi #x.
+]
+```
+
+A function call always involves the name of the function ([`rect`],
+[`underline`], [`calc.max`]($calc.max), [`range`]($array.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].
+
+### 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
+arguments to increase legibility. For example, the dimensions and stroke of a
+rectangle are defined with named arguments:
+
+```example
+#rect(
+ width: 2cm,
+ height: 1cm,
+ stroke: red,
+)
+```
+
+You specify a named argument by first entering its name (above, it's `width`,
+`height`, and `stroke`), then a colon, followed by the value (`2cm`, `1cm`,
+`red`). You can find the available named arguments in the [reference
+page]($reference) for each function or in the autocomplete panel when typing.
+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] 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]. 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]
+to LaTeX.
+
+#rect(fill: aqua)[Get started here!]
+```
+
+### 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
+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]($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
+characters.
+
+Typst provides [control flow constructs]($scripting/#conditionals) and
+[operators]($scripting/#operators) such as `+` for adding things or `==` for
+checking equality between two variables.
+
+You can also store values, including functions, in your own
+[variables]($scripting/#bindings). This can be useful to perform computations on
+them, create reusable automations, or reference a value multiple times. The
+variable binding is accomplished with the let keyword, which works similar to
+`\newcommand`:
+
+```example
+// Store the integer `5`.
+#let five = 5
+
+// Define a function that
+// increments a value.
+#let inc(i) = i + 1
+
+// Reference the variables.
+I have #five fingers.
+
+If I had one more, I'd have
+#inc(five) fingers. Whoa!
+```
+
+### Commands to affect the remaining document { #rules }
+In LaTeX, some commands like `\textbf{bold text}` receive an argument in curly
+braces and only affect that argument. Other commands such as `\bfseries bold
+text` act as switches (LaTeX calls this a declaration), altering the appearance
+of all subsequent 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
+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)
+
+```example
+I am starting out with small text.
+
+#set text(14pt)
+
+This is a bit #text(18pt)[larger,]
+don't you think?
+```
+
+Set rules may appear anywhere in the document. They can be thought of as
+default argument values of their respective function:
+
+```example
+#set enum(numbering: "I.")
+
+Good results can only be obtained by
++ following best practices
++ being aware of current results
+ of other researchers
++ checking the data for biases
+```
+
+The `+` is syntactic sugar (think of it as an abbreviation) for a call to the
+[`{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`).
+
+You can achieve the effects of LaTeX commands like `\textbf`, `\textsf`,
+`\rmfamily`, `\mdseries`, and `\itshape` with the [`font`]($text.font),
+[`style`]($text.style), and [`weight`]($text.weight) arguments of the `text`
+function. The text function can be used in a set rule (declaration style) or
+with a content argument. To replace `\textsc`, you can use the [`smallcaps`]
+function, which renders its content argument as smallcaps. Should you want to
+use it declaration style (like `\scshape`), you can use an
+[_everything_ show rule]($styling/#show-rules) that applies the function to the
+rest of the scope:
+
+```example
+#show: smallcaps
+
+Boisterous Accusations
+```
+
+## How do I load a document class? { #templates }
+In LaTeX, you start your main `.tex` file with the `\documentclass{article}`
+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]($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
+[show rule]($styling/#show-rules) that wraps the following document in a given
+function. The following example illustrates how it works:
+
+```example:single
+>>> #let conf(
+>>> title: none,
+>>> authors: (),
+>>> abstract: [],
+>>> doc,
+>>> ) = {
+>>> set text(font: "Libertinus Serif", 11pt)
+>>> set par(justify: true)
+>>> set page(
+>>> "us-letter",
+>>> margin: auto,
+>>> header: align(
+>>> right + horizon,
+>>> title
+>>> ),
+>>> numbering: "1",
+>>> columns: 2
+>>> )
+>>>
+>>> show heading.where(
+>>> level: 1
+>>> ): it => block(
+>>> align(center,
+>>> text(
+>>> 13pt,
+>>> weight: "regular",
+>>> smallcaps(it.body),
+>>> )
+>>> ),
+>>> )
+>>> show heading.where(
+>>> level: 2
+>>> ): it => box(
+>>> text(
+>>> 11pt,
+>>> weight: "regular",
+>>> style: "italic",
+>>> it.body + [.],
+>>> )
+>>> )
+>>>
+>>> place(top, float: true, scope: "parent", {
+>>> set align(center)
+>>> text(17pt, title)
+>>>
+>>> let count = calc.min(authors.len(), 3)
+>>> grid(
+>>> columns: (1fr,) * count,
+>>> row-gutter: 24pt,
+>>> ..authors.map(author => [
+>>> #author.name \
+>>> #author.affiliation \
+>>> #link("mailto:" + author.email)
+>>> ]),
+>>> )
+>>>
+>>> par(justify: false)[
+>>> *Abstract* \
+>>> #abstract
+>>> ]
+>>> })
+>>>
+>>> set align(left)
+>>> doc
+>>> }
+<<< #import "conf.typ": conf
+#show: conf.with(
+ title: [
+ Towards Improved Modelling
+ ],
+ authors: (
+ (
+ name: "Theresa Tungsten",
+ affiliation: "Artos Institute",
+ email: "tung@artos.edu",
+ ),
+ (
+ name: "Eugene Deklan",
+ affiliation: "Honduras State",
+ email: "e.deklan@hstate.hn",
+ ),
+ ),
+ abstract: lorem(80),
+)
+
+Let's get started writing this
+article by putting insightful
+paragraphs right here!
+>>> #lorem(500)
+```
+
+The [`{import}`]($scripting/#modules) statement makes [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 applying the show rule, we can
+start writing our article right away!
+
+You can also use templates from Typst Universe (which is Typst's equivalent of
+CTAN) using an import statement like this: `[#import
+"@preview/elsearticle:0.2.1": elsearticle]`. Check the documentation of an
+individual template to learn the name of its template function. Templates and
+packages from Typst Universe are automatically downloaded when you first use
+them.
+
+In the web app, you can choose to create a project from a template on Typst
+Universe or even create your own using the template wizard. Locally, you can use
+the `typst init` CLI to create a new project from a template. Check out [the
+list of templates]($universe/search/?kind=templates) published on Typst
+Universe. You can also take a look at the [`awesome-typst`
+repository](https://github.com/qjcg/awesome-typst) to find community templates
+that aren't available through Universe.
+
+You can also [create your own, custom templates.]($tutorial/making-a-template)
+They are shorter and more readable than the corresponding LaTeX `.sty` files by
+orders of magnitude, so give it a try!
+
+
+
+Functions are Typst's "commands" and can transform their arguments to an output
+value, including document _content._ Functions are "pure", which means that they
+cannot have any effects beyond creating an output value / output content. This
+is in stark contrast to LaTeX macros that can have arbitrary effects on your
+document.
+
+To let a function style your whole document, the show rule processes everything
+that comes after it and calls the function specified after the colon with the
+result as an argument. The `.with` part is a _method_ that takes the `conf`
+function and pre-configures some of its arguments before passing it on to the
+show rule.
+
+
+## How do I load packages? { #packages }
+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`] function |
+| tabularx | [`table`], [`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`] function |
+| xcolor | [`text`]($text.fill) function: `[#set text(fill: rgb("#0178A4"))]` |
+| hyperref | [`link`] function |
+| bibtex, biblatex, natbib | [`cite`], [`bibliography`] functions |
+| lstlisting, minted | [`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`] function |
+| enumitem | [`list`], [`enum`], [`terms`] functions |
+
+Although _many_ things are built-in, not everything can be. That's why Typst has
+its own [package ecosystem]($universe) where the community share its creations
+and automations. Let's take, for instance, the _cetz_ package: This package
+allows you to create complex drawings and plots. To use cetz in your document,
+you can just write:
+
+```typ
+#import "@preview/cetz:0.2.1"
+```
+
+(The `@preview` is a _namespace_ that is used while the package manager is still
+in its early and experimental state. It will be replaced in the future.)
+
+Aside from the official package hub, you might also want to check out the
+[awesome-typst repository](https://github.com/qjcg/awesome-typst), which
+compiles a curated list of resources created for Typst.
+
+If you need to load functions and variables from another file within your
+project, for example to use a template, you can use the same
+[`import`]($scripting/#modules) statement with a file name rather than a
+package specification. To instead include the textual content of another file,
+you can use an [`include`]($scripting/#modules) statement. It will retrieve
+the content of the specified file and put it in your document.
+
+## How do I input maths? { #maths }
+To enter math mode in Typst, just enclose your equation in dollar signs. You can
+enter display mode by adding spaces or newlines between the equation's contents
+and its enclosing dollar signs.
+
+```example
+The sum of the numbers from
+$1$ to $n$ is:
+
+$ sum_(k=1)^n k = (n(n+1))/2 $
+```
+
+[Math mode]($category/math) works differently than regular markup or code mode.
+Numbers and single characters are displayed verbatim, while multiple consecutive
+(non-number) characters will be interpreted as Typst variables.
+
+Typst pre-defines a lot of useful variables in math mode. All Greek (`alpha`,
+`beta`, ...) and some Hebrew letters (`alef`, `bet`, ...) are available through
+their name. Some symbols are additionally available through shorthands, such as
+`<=`, `>=`, and `->`.
+
+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]($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:
+
+```example
+$ 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 behaviour 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
+honoring operator precedence. All round parentheses not made redundant by the
+fraction will appear in the output.
+
+```example
+$ f(x) = (x + 1) / x $
+```
+
+[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)$}`.
+
+Since variables in math mode do not need to be prepended with a `#` or a `/`,
+you can also call functions without these special characters:
+
+```example
+$ f(x, y) := cases(
+ 1 "if" (x dot y)/2 <= 0,
+ 2 "if" x "is even",
+ 3 "if" x in NN,
+ 4 "else",
+) $
+```
+
+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 `#`:
+
+```example
+$ (a + b)^2
+ = a^2
+ + text(fill: #maroon, 2 a b)
+ + b^2 $
+```
+
+You can use all Typst functions within math mode and insert any content. If you
+want them to work normally, with code mode in the argument list, you can prefix
+their call with a `#`. Nobody can stop you from using rectangles or emoji as
+your variables anymore:
+
+```example
+$ sum^10_(🥸=1)
+ #rect(width: 4mm, height: 2mm)/🥸
+ = 🧠 maltese $
+```
+
+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]($math.mat) that creates
+matrices:
+
+```example
+$ mat(
+ 1, 2, ..., 10;
+ 2, 2, ..., 10;
+ dots.v, dots.v, dots.down, dots.v;
+ 10, 10, ..., 10;
+) $
+```
+
+## How do I get the "LaTeX look?" { #latex-look }
+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]($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 derivative 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)
+#set par(leading: 0.55em, spacing: 0.55em, first-line-indent: 1.8em, justify: true)
+#set text(font: "New Computer Modern")
+#show raw: set text(font: "New Computer Modern Mono")
+#show heading: set block(above: 1.4em, below: 1em)
+```
+
+This should be a good starting point! If you want to go further, why not create
+a reusable template?
+
+## Bibliographies
+Typst includes a fully-featured bibliography system that is compatible with
+BibTeX files. You can continue to use your `.bib` literature libraries by
+loading them with the [`bibliography`] function. Another possibility is to use
+[Typst's YAML-based native format](https://github.com/typst/hayagriva/blob/main/docs/file-format.md).
+
+Typst uses the Citation Style Language to define and process citation and
+bibliography styles. You can compare CSL files to BibLaTeX's `.bbx` files.
+The compiler already includes [over 80 citation styles]($bibliography.style),
+but you can use any CSL-compliant style from the
+[CSL repository](https://github.com/citation-style-language/styles) or write
+your own.
+
+You can cite an entry in your bibliography or reference a label in your document
+with the same syntax: `[@key]` (this would reference an entry called `key`).
+Alternatively, you can use the [`cite`] function.
+
+Alternative forms for your citation, such as year only and citations for natural
+use in prose (cf. `\citet` and `\textcite`) are available with
+[`[#cite(, form: "prose")]`]($cite.form).
+
+You can find more information on the documentation page of the [`bibliography`]
+function.
+
+## What limitations does Typst currently have compared to LaTeX? { #limitations }
+Although Typst can be a LaTeX replacement for many today, there are still
+features that Typst does not (yet) support. Here is a list of them which, where
+applicable, contains possible workarounds.
+
+- **Well-established plotting ecosystem.** LaTeX users often create elaborate
+ charts along with their documents in PGF/TikZ. The Typst ecosystem does not
+ yet offer the same breadth of available options, but the ecosystem around the
+ [`cetz` package](https://typst.app/universe/package/cetz) is catching up
+ quickly.
+
+- **Change page margins without a pagebreak.** In LaTeX, margins can always be
+ adjusted, even without a pagebreak. To change margins in Typst, you use the
+ [`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.
+
+- **Include PDFs as images.** In LaTeX, it has become customary to insert vector
+ graphics as PDF or EPS files. Typst supports neither format as an image
+ format, but you can easily convert both into SVG files with [online
+ tools](https://cloudconvert.com/pdf-to-svg) or
+ [Inkscape](https://inkscape.org/). The web app will automatically convert PDF
+ files to SVG files upon uploading them. You can also use the
+ community-provided [`muchpdf` package](https://typst.app/universe/package/muchpdf)
+ to embed PDFs. It internally converts PDFs to SVGs on-the-fly.
diff --git a/sources/docs/guides/page-setup.md b/sources/docs/guides/page-setup.md
new file mode 100644
index 0000000000000000000000000000000000000000..36ed0fa23457f49a3c431010d55788254738b5f4
--- /dev/null
+++ b/sources/docs/guides/page-setup.md
@@ -0,0 +1,487 @@
+---
+description: |
+ An in-depth guide to setting page dimensions, margins, and page numbers in
+ Typst. Learn how to create appealing and clear layouts and get there quickly.
+---
+
+# Page setup guide
+Your page setup is a big part of the first impression your document gives. Line
+lengths, margins, and columns influence
+[appearance](https://practicaltypography.com/page-margins.html) and
+[legibility](https://designregression.com/article/line-length-revisited-following-the-research)
+while the right headers and footers will help your reader easily navigate your
+document. This guide will help you to customize pages, margins, headers,
+footers, and page numbers so that they are the right fit for your content and
+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}`]($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,
+)
+>>> #set text(6pt)
+>>> #set page(margin: auto)
+
+#set page(
+ paper: "iso-b7",
+ header: rect(fill: aqua)[Header],
+ footer: rect(fill: aqua)[Footer],
+ number-align: center,
+)
+
+#rect(fill: aqua.lighten(40%))
+```
+
+This example visualizes the dimensions for page content, headers, and footers.
+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`]($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}`]($page) set rule and passing it a string argument to use a common page
+size. Options include the complete ISO 216 series (e.g. `"a4"` and `"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`]($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
+[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`]($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
+this, you can pass a dictionary:
+
+```example
+#set page(margin: (
+ top: 3cm,
+ bottom: 2cm,
+ x: 1.5cm,
+))
+
+#lorem(100)
+```
+
+The page margin dictionary can have keys for each side (`top`, `bottom`, `left`,
+`right`), but you can also control left and right together by setting the `x`
+key of the margin dictionary, like in the example. Likewise, the top and bottom
+margins can be adjusted together by setting the `y` key.
+
+If you do not specify margins for all sides in the margin dictionary, the old
+margins will remain in effect for the unset sides. To prevent this and set all
+remaining margins to a common size, you can use the `rest` key. For example,
+`[#set page(margin: (left: 1.5in, rest: 1in))]` will set the left margin to 1.5
+inches and the remaining margins to one inch.
+
+### Different margins on alternating pages { #alternating-margins }
+Sometimes, you'll need to alternate horizontal margins for even and odd pages,
+for example, to have more room towards the spine of a book than on the outsides
+of its pages. Typst keeps track of whether a page is to the left or right of the
+binding. You can use this information and set the `inside` or `outside` keys of
+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))
+```
+
+Typst will assume that documents written in Left-to-Right scripts are bound on
+the left while books written in Right-to-Left scripts are bound on the right.
+However, you will need to change this in some cases: If your first page is
+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`]($page.binding) argument in the [`{page}`]($page) set rule.
+
+```typ
+// Produce a book bound on the right,
+// even though it is set in Spanish.
+#set text(lang: "es")
+#set page(binding: right)
+```
+
+If `binding` is `left`, `inside` margins will be on the left on odd pages, and
+vice versa.
+
+## Add headers and footers { #headers-and-footers }
+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`]($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))
+#set page(header: [
+ _Lisa Strassner's Thesis_
+ #h(1fr)
+ National Academy of Sciences
+])
+
+#lorem(150)
+```
+
+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}`]($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
+not want a header and footer on the title page. The example below shows how to
+conditionally remove the header on the first page:
+
+```typ
+>>> #set page("a5", margin: (x: 2.5cm, y: 3cm))
+#set page(header: context {
+ if counter(page).get().first() > 1 [
+ _Lisa Strassner's Thesis_
+ #h(1fr)
+ National Academy of Sciences
+ ]
+})
+
+#lorem(150)
+```
+
+This example may look intimidating, but let's break it down: By using the
+`{context}` keyword, we are telling Typst that the header depends on where we
+are in the document. We then ask Typst if the page [counter] is larger than one
+at our (context-dependent) 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.
+
+### Adapt headers and footers on pages with specific elements { #specific-elements }
+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
+`` [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))
+#set page(header: context {
+ let page-counter =
+ let matches = query()
+ let current = counter(page).get()
+ let has-table = matches.any(m =>
+ counter(page).at(m.location()) == current
+ )
+
+ if not has-table [
+ _Lisa Strassner's Thesis_
+ #h(1fr)
+ National Academy of Sciences
+ ]
+}))
+
+#lorem(100)
+#pagebreak()
+
+#table(
+ columns: 2 * (1fr,),
+ [A], [B],
+ [C], [D],
+)
+```
+
+Here, we query for all instances of the `` label. We then check that
+none of the tables are on the page at our current position. If so, we print the
+header. This example also uses variables to be more concise. Just as above, you
+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 page numbers 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)
+#set page(numbering: "1")
+
+This is a numbered page.
+```
+
+Above, you can check out the simplest conceivable example. It adds a single
+Arabic page number at the center of the footer. You can specify other characters
+than `"1"` to get other numerals. For example, `"i"` will yield lowercase Roman
+numerals. Any character that is not interpreted as a number will be output
+as-is. For example, put dashes around your page number by typing this:
+
+```example
+>>> #set page("iso-b6", margin: 1.75cm)
+#set page(numbering: "— 1 —")
+
+This is a — numbered — page.
+```
+
+You can add the total number of pages by entering a second number character in
+the string.
+
+```example
+>>> #set page("iso-b6", margin: 1.75cm)
+#set page(numbering: "1 of 1")
+
+This is one of many numbered pages.
+```
+
+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`]($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
+Sometimes, you need to add other content than a page number to your footer.
+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)
+#set page(footer: context [
+ *American Society of Proceedings*
+ #h(1fr)
+ #counter(page).display(
+ "1/1",
+ both: true,
+ )
+])
+
+This page has a custom footer.
+```
+
+First, we add some strongly emphasized text on the left and add free space to
+fill the line. Then, we call `counter(page)` to retrieve the page counter and
+use its `display` function to show its current value. We also set `both` to
+`{true}` so that our numbering pattern applies to the current _and_ final page
+number.
+
+We can also get more creative with the page number. For example, let's insert a
+circle for each page.
+
+```example
+>>> #set page("iso-b6", margin: 1.75cm)
+#set page(footer: context [
+ *Fun Typography Club*
+ #h(1fr)
+ #let (num,) = counter(page).get()
+ #let circles = num * (
+ box(circle(
+ radius: 2pt,
+ fill: navy,
+ )),
+ )
+ #box(
+ inset: (bottom: 1pt),
+ circles.join(h(1pt))
+ )
+])
+
+This page has a custom footer.
+```
+
+In this example, we use the number of pages to create an array of
+[circles]($circle). The circles are wrapped in a [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] 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
+[_join_]($scripting/#blocks) the different values of an array into a single
+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]($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
+want to start with the first page only after the title page. Or maybe you need
+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]. The
+simplest manipulation is to set the counter back to 1.
+
+```typ
+#counter(page).update(1)
+```
+
+This line will reset the page counter back to one. It should be placed at the
+start of a page because it will otherwise create a page break. You can also
+update the counter given its previous value by passing a function:
+
+```typ
+#counter(page).update(n => n + 5)
+```
+
+In this example, we skip five pages. `n` is the current value of the page
+counter and `n + 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`]($location.page) method on the return
+value of the [`here`] function:
+
+```example
+#counter(page).update(n => n + 5)
+
+// This returns one even though the
+// page counter was incremented by 5.
+#context here().page()
+```
+
+You can also obtain the page numbering pattern from the location returned by
+`here` with the [`page-numbering`]($location.page-numbering) method.
+
+## Add columns { #columns }
+Add columns to your document to fit more on a page while maintaining legible
+line lengths. Columns are vertical blocks of text which are separated by some
+whitespace. This space is called the gutter.
+
+To lay out your content in columns, just specify the desired number of columns
+in a [`{page}`]($page.columns) set rule. To adjust the amount of space between
+the columns, add a set rule on the [`columns` function]($columns), specifying
+the `gutter` parameter.
+
+```example
+>>> #set page(height: 120pt)
+#set page(columns: 2)
+#set columns(gutter: 12pt)
+
+#lorem(30)
+```
+
+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's [`place`
+function]($place) can temporarily escape the two-column layout by specifying
+`{float: true}` and `{scope: "parent"}`:
+
+```example:single
+>>> #set page(height: 180pt)
+#set page(columns: 2)
+#set par(justify: true)
+
+#place(
+ top + center,
+ float: true,
+ scope: "parent",
+ text(1.4em, weight: "bold")[
+ Impacts of Odobenidae
+ ],
+)
+
+== About seals in the wild
+#lorem(80)
+```
+
+_Floating placement_ refers to elements being pushed to the top or bottom of the
+column or page, with the remaining content flowing in between. It is also
+frequently used for [figures]($figure.placement).
+
+### Use columns anywhere in your document { #columns-anywhere }
+To create columns within a nested layout, e.g. within a rectangle, you can use
+the [`columns` function]($columns) directly. However, it really should only be
+used within nested layouts. At the page-level, the page set rule is preferable
+because it has better interactions with things like page-level floats,
+footnotes, and line numbers.
+
+```example
+#rect(
+ width: 6cm,
+ height: 3.5cm,
+ columns(2, gutter: 12pt)[
+ In the dimly lit gas station,
+ a solitary taxi stood silently,
+ its yellow paint fading with
+ time. Its windows were dark,
+ its engine idle, and its tires
+ rested on the cold concrete.
+ ]
+)
+```
+
+### 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()]`]($colbreak) at an
+appropriate spot in your markup, creating the desired column break manually.
+
+
+## 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}`]($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")
+#page(flipped: true)[
+ = Multiplication table
+
+ #table(
+ columns: 5 * (1fr,),
+ ..for x in range(1, 10) {
+ for y in range(1, 6) {
+ (str(x*y),)
+ }
+ }
+ )
+]
+```
diff --git a/sources/docs/guides/tables.md b/sources/docs/guides/tables.md
new file mode 100644
index 0000000000000000000000000000000000000000..5b7efdc486c3196c7ffaca12bf2ce2a3ddc7eafd
--- /dev/null
+++ b/sources/docs/guides/tables.md
@@ -0,0 +1,1343 @@
+---
+description: |
+ Not sure how to change table strokes? Need to rotate a table? This guide
+ explains all you need to know about tables in Typst.
+---
+
+# Table guide
+Tables are a great way to present data to your readers in an easily readable,
+compact, and organized manner. They are not only used for numerical values, but
+also survey responses, task planning, schedules, and more. Because of this wide
+set of possible applications, there is no single best way to lay out a table.
+Instead, think about the data you want to highlight, your document's overarching
+design, and ultimately how your table can best serve your readers.
+
+Typst can help you with your tables by automating styling, importing data from
+other applications, and more! This guide takes you through a few of the most
+common questions you may have when adding a table to your document with Typst.
+Feel free to skip to the section most relevant to you – we designed this guide
+to be read out of order.
+
+If you want to look up a detail of how tables work, you should also [check out
+their reference page]($table). And if you are looking for a table of contents
+rather than a normal table, the reference page of the [`outline`
+function]($outline) is the right place to learn more.
+
+## How to create a basic table? { #basic-tables }
+In order to create a table in Typst, use the [`table` function]($table). For a
+basic table, you need to tell the table function two things:
+
+- The number of columns
+- The content for each of the table cells
+
+So, let's say you want to create a table with two columns describing the
+ingredients for a cookie recipe:
+
+```example
+#table(
+ columns: 2,
+ [*Amount*], [*Ingredient*],
+ [360g], [Baking flour],
+ [250g], [Butter (room temp.)],
+ [150g], [Brown sugar],
+ [100g], [Cane sugar],
+ [100g], [70% cocoa chocolate],
+ [100g], [35-40% cocoa chocolate],
+ [2], [Eggs],
+ [Pinch], [Salt],
+ [Drizzle], [Vanilla extract],
+)
+```
+
+This example shows how to call, configure, and populate a table. Both the column
+count and cell contents are passed to the table as arguments. The [argument
+list]($function) is surrounded by round parentheses. In it, we first pass the
+column count as a named argument. Then, we pass multiple [content
+blocks]($content) as positional arguments. Each content block contains the
+contents for a single cell.
+
+To make the example more legible, we have placed two content block arguments on
+each line, mimicking how they would appear in the table. You could also write
+each cell on its own line. Typst does not care on which line you place the
+arguments. Instead, Typst will place the content cells from left to right (or
+right to left, if that is the writing direction of your language) and then from
+top to bottom. It will automatically add enough rows to your table so that it
+fits all of your content.
+
+It is best to wrap the header row of your table in the [`table.header`
+function]($table.header). This clarifies your intent and will also allow future
+versions of Typst to make the output more accessible to users with a screen
+reader:
+
+```example
+#table(
+ columns: 2,
+ table.header[*Amount*][*Ingredient*],
+ [360g], [Baking flour],
+<<< // ... the remaining cells
+>>> [250g], [Butter (room temp.)],
+>>> [150g], [Brown sugar],
+>>> [100g], [Cane sugar],
+>>> [100g], [70% cocoa chocolate],
+>>> [100g], [35-40% cocoa chocolate],
+>>> [2], [Eggs],
+>>> [Pinch], [Salt],
+>>> [Drizzle], [Vanilla extract],
+)
+```
+
+You could also write a show rule that automatically [strongly
+emphasizes]($strong) the contents of the first cells for all tables. This
+quickly becomes useful if your document contains multiple tables!
+
+```example
+#show table.cell.where(y: 0): strong
+
+#table(
+ columns: 2,
+ table.header[Amount][Ingredient],
+ [360g], [Baking flour],
+<<< // ... the remaining cells
+>>> [250g], [Butter (room temp.)],
+>>> [150g], [Brown sugar],
+>>> [100g], [Cane sugar],
+>>> [100g], [70% cocoa chocolate],
+>>> [100g], [35-40% cocoa chocolate],
+>>> [2], [Eggs],
+>>> [Pinch], [Salt],
+>>> [Drizzle], [Vanilla extract],
+)
+```
+
+We are using a show rule with a selector for cell coordinates here instead of
+applying our styles directly to `table.header`. This is due to a current
+limitation of Typst that will be fixed in a future release.
+
+Congratulations, you have created your first table! Now you can proceed to
+[change column sizes](#column-sizes), [adjust the strokes](#strokes), [add
+striped rows](#fills), and more!
+
+## How to change the column sizes? { #column-sizes }
+If you create a table and specify the number of columns, Typst will make each
+column large enough to fit its largest cell. Often, you want something
+different, for example, to make a table span the whole width of the page. You
+can provide a list, specifying how wide you want each column to be, through the
+`columns` argument. There are a few different ways to specify column widths:
+
+- First, there is `{auto}`. This is the default behavior and tells Typst to grow
+ the column to fit its contents. If there is not enough space, Typst will try
+ its best to distribute the space among the `{auto}`-sized columns.
+- [Lengths]($length) like `{6cm}`, `{0.7in}`, or `{120pt}`. As usual, you can
+ also use the font-dependent `em` unit. This is a multiple of your current font
+ size. It's useful if you want to size your table so that it always fits
+ about the same amount of text, independent of font size.
+- A [ratio in percent]($ratio) such as `{40%}`. This will make the column take
+ up 40% of the total horizontal space available to the table, so either the
+ inner width of the page or the table's container. You can also mix ratios and
+ lengths into [relative lengths]($relative). Be mindful that even if you
+ specify a list of column widths that sum up to 100%, your table could still
+ become larger than its container. This is because there can be
+ [gutter]($table.gutter) between columns that is not included in the column
+ widths. If you want to make a table fill the page, the next option is often
+ very useful.
+- A [fractional part of the free space]($fraction) using the `fr` unit, such as
+ `1fr`. This unit allows you to distribute the available space to columns. It
+ works as follows: First, Typst sums up the lengths of all columns that do not
+ use `fr`s. Then, it determines how much horizontal space is left. This
+ horizontal space then gets distributed to all columns denominated in `fr`s.
+ During this process, a `2fr` column will become twice as wide as a `1fr`
+ column. This is where the name comes from: The width of the column is its
+ fraction of the total fractionally sized columns.
+
+Let's put this to use with a table that contains the dates, numbers, and
+descriptions of some routine checks. The first two columns are `auto`-sized and
+the last column is `1fr` wide as to fill the whole page.
+
+```example
+#table(
+ columns: (auto, auto, 1fr),
+ table.header[Date][°No][Description],
+ [24/01/03], [813], [Filtered participant pool],
+ [24/01/03], [477], [Transitioned to sec. regimen],
+ [24/01/11], [051], [Cycled treatment substrate],
+)
+```
+
+Here, we have passed our list of column lengths as an [array], enclosed in round
+parentheses, with its elements separated by commas. The first two columns are
+automatically sized, so that they take on the size of their content and the
+third column is sized as `{1fr}` so that it fills up the remainder of the space
+on the page. If you wanted to instead change the second column to be a bit more
+spacious, you could replace its entry in the `columns` array with a value like
+`{6em}`.
+
+## How to caption and reference my table? { #captions-and-references }
+A table is just as valuable as the information your readers draw from it. You
+can enhance the effectiveness of both your prose and your table by making a
+clear connection between the two with a cross-reference. Typst can help you with
+automatic [references]($ref) and the [`figure` function]($figure).
+
+Just like with images, wrapping a table in the `figure` function allows you to
+add a caption and a label, so you can reference the figure elsewhere. Wrapping
+your table in a figure also lets you use the figure's `placement` parameter to
+float it to the top or bottom of a page.
+
+Let's take a look at a captioned table and how to reference it in prose:
+
+```example
+>>> #set page(width: 14cm)
+#show table.cell.where(y: 0): set text(weight: "bold")
+
+#figure(
+ table(
+ columns: 4,
+ stroke: none,
+
+ table.header[Test Item][Specification][Test Result][Compliance],
+ [Voltage], [220V ± 5%], [218V], [Pass],
+ [Current], [5A ± 0.5A], [4.2A], [Fail],
+ ),
+ caption: [Probe results for design A],
+)
+
+The results from @probe-a show that the design is not yet optimal.
+We will show how its performance can be improved in this section.
+```
+
+The example shows how to wrap a table in a figure, set a caption and a label,
+and how to reference that label. We start by using the `figure` function. It
+expects the contents of the figure as a positional argument. We just put the
+table function call in its argument list, omitting the `#` character because it
+is only needed when calling a function in markup mode. We also add the caption
+as a named argument (above or below) the table.
+
+After the figure call, we put a label in angle brackets (`[]`). This
+tells Typst to remember this element and make it referenceable under this name
+throughout your document. We can then reference it in prose by using the at sign
+and the label name `[@probe-a]`. Typst will print a nicely formatted reference
+and automatically update the label if the table's number changes.
+
+## How to get a striped table? { #fills }
+Many tables use striped rows or columns instead of strokes to differentiate
+between rows and columns. This effect is often called _zebra stripes._ Tables
+with zebra stripes are popular in Business and commercial Data Analytics
+applications, while academic applications tend to use strokes instead.
+
+To add zebra stripes to a table, we use the `table` function's `fill` argument.
+It can take three kinds of arguments:
+
+- A single color (this can also be a gradient or a tiling) to fill all cells
+ with. Because we want some cells to have another color, this is not useful if
+ we want to build zebra tables.
+- An array with colors which Typst cycles through for each column. We can use an
+ array with two elements to get striped columns.
+- A function that takes the horizontal coordinate `x` and the vertical
+ coordinate `y` of a cell and returns its fill. We can use this to create
+ horizontal stripes or [checkerboard patterns]($grid.cell).
+
+Let's start with an example of a horizontally striped table:
+
+```example
+>>> #set page(width: 16cm)
+#set text(font: "IBM Plex Sans")
+
+// Medium bold table header.
+#show table.cell.where(y: 0): set text(weight: "medium")
+
+// Bold titles.
+#show table.cell.where(x: 1): set text(weight: "bold")
+
+// See the strokes section for details on this!
+#let frame(stroke) = (x, y) => (
+ left: if x > 0 { 0pt } else { stroke },
+ right: stroke,
+ top: if y < 2 { stroke } else { 0pt },
+ bottom: stroke,
+)
+
+#set table(
+ fill: (rgb("EAF2F5"), none),
+ stroke: frame(rgb("21222C")),
+)
+
+#table(
+ columns: (0.4fr, 1fr, 1fr, 1fr),
+
+ table.header[Month][Title][Author][Genre],
+ [January], [The Great Gatsby], [F. Scott Fitzgerald], [Classic],
+ [February], [To Kill a Mockingbird], [Harper Lee], [Drama],
+ [March], [1984], [George Orwell], [Dystopian],
+ [April], [The Catcher in the Rye], [J.D. Salinger], [Coming-of-Age],
+)
+```
+
+This example shows a book club reading list. The line `{fill: (rgb("EAF2F5"),
+ none)}` in `table`'s set rule is all that is needed to add striped columns. It
+tells Typst to alternate between coloring columns with a light blue (in the
+[`rgb`]($color.rgb) function call) and nothing (`{none}`). Note that we
+extracted all of our styling from the `table` function call itself into set and
+show rules, so that we can automatically reuse it for multiple tables.
+
+Because setting the stripes itself is easy we also added some other styles to
+make it look nice. The other code in the example provides a dark blue
+[stroke](#stroke-functions) around the table and below the first line and
+emboldens the first row and the column with the book title. See the
+[strokes](#strokes) section for details on how we achieved this stroke
+configuration.
+
+Let's next take a look at how we can change only the set rule to achieve
+horizontal stripes instead:
+
+```example
+>>> #set page(width: 16cm)
+>>> #set text(font: "IBM Plex Sans")
+>>> #show table.cell.where(x: 1): set text(weight: "medium")
+>>> #show table.cell.where(y: 0): set text(weight: "bold")
+>>>
+>>> #let frame(stroke) = (x, y) => (
+>>> left: if x > 0 { 0pt } else { stroke },
+>>> right: stroke,
+>>> top: if y < 2 { stroke } else { 0pt },
+>>> bottom: stroke,
+>>> )
+>>>
+#set table(
+ fill: (_, y) => if calc.odd(y) { rgb("EAF2F5") },
+ stroke: frame(rgb("21222C")),
+)
+>>>
+>>> #table(
+>>> columns: (0.4fr, 1fr, 1fr, 1fr),
+>>>
+>>> table.header[Month][Title][Author][Genre],
+>>> [January], [The Great Gatsby],
+>>> [F. Scott Fitzgerald], [Classic],
+>>> [February], [To Kill a Mockingbird],
+>>> [Harper Lee], [Drama],
+>>> [March], [1984],
+>>> [George Orwell], [Dystopian],
+>>> [April], [The Catcher in the Rye],
+>>> [J.D. Salinger], [Coming-of-Age],
+>>> )
+```
+
+We just need to replace the set rule from the previous example with this one and
+get horizontal stripes instead. Here, we are passing a function to `fill`. It
+discards the horizontal coordinate with an underscore and then checks if the
+vertical coordinate `y` of the cell is odd. If so, the cell gets a light blue
+fill, otherwise, no fill is returned.
+
+Of course, you can make this function arbitrarily complex. For example, if you
+want to stripe the rows with a light and darker shade of blue, you could do
+something like this:
+
+```example
+>>> #set page(width: 16cm)
+>>> #set text(font: "IBM Plex Sans")
+>>> #show table.cell.where(x: 1): set text(weight: "medium")
+>>> #show table.cell.where(y: 0): set text(weight: "bold")
+>>>
+>>> #let frame(stroke) = (x, y) => (
+>>> left: if x > 0 { 0pt } else { stroke },
+>>> right: stroke,
+>>> top: if y < 2 { stroke } else { 0pt },
+>>> bottom: stroke,
+>>> )
+>>>
+#set table(
+ fill: (_, y) => (none, rgb("EAF2F5"), rgb("DDEAEF")).at(calc.rem(y, 3)),
+ stroke: frame(rgb("21222C")),
+)
+>>>
+>>> #table(
+>>> columns: (0.4fr, 1fr, 1fr, 1fr),
+>>>
+>>> table.header[Month][Title][Author][Genre],
+>>> [January], [The Great Gatsby],
+>>> [F. Scott Fitzgerald], [Classic],
+>>> [February], [To Kill a Mockingbird],
+>>> [Harper Lee], [Drama],
+>>> [March], [1984],
+>>> [George Orwell], [Dystopian],
+>>> [April], [The Catcher in the Rye],
+>>> [J.D. Salinger], [Coming-of-Age],
+>>> )
+```
+
+This example shows an alternative approach to write our fill function. The
+function uses an array with three colors and then cycles between its values for
+each row by indexing the array with the remainder of `y` divided by 3.
+
+Finally, here is a bonus example that uses the _stroke_ to achieve striped rows:
+
+```example
+>>> #set page(width: 16cm)
+>>> #set text(font: "IBM Plex Sans")
+>>> #show table.cell.where(x: 1): set text(weight: "medium")
+>>> #show table.cell.where(y: 0): set text(weight: "bold")
+>>>
+>>> #let frame(stroke) = (x, y) => (
+>>> left: if x > 0 { 0pt } else { stroke },
+>>> right: stroke,
+>>> top: if y < 2 { stroke } else { 0pt },
+>>> bottom: stroke,
+>>> )
+>>>
+#set table(
+ stroke: (x, y) => (
+ y: 1pt,
+ left: if x > 0 { 0pt } else if calc.even(y) { 1pt },
+ right: if calc.even(y) { 1pt },
+ ),
+)
+>>>
+>>> #table(
+>>> columns: (0.4fr, 1fr, 1fr, 1fr),
+>>>
+>>> table.header[Month][Title][Author][Genre],
+>>> [January], [The Great Gatsby],
+>>> [F. Scott Fitzgerald], [Classic],
+>>> [February], [To Kill a Mockingbird],
+>>> [Harper Lee], [Drama],
+>>> [March], [1984],
+>>> [George Orwell], [Dystopian],
+>>> [April], [The Catcher in the Rye],
+>>> [J.D. Salinger], [Coming-of-Age],
+>>> )
+```
+
+### Manually overriding a cell's fill color { #fill-override }
+Sometimes, the fill of a cell needs not to vary based on its position in the
+table, but rather based on its contents. We can use the [`table.cell`
+element]($table.cell) in the `table`'s parameter list to wrap a cell's content
+and override its fill.
+
+For example, here is a list of all German presidents, with the cell borders
+colored in the color of their party.
+
+```example
+>>> #set page(width: 10cm)
+#set text(font: "Roboto")
+
+#let cdu(name) = ([CDU], table.cell(fill: black, text(fill: white, name)))
+#let spd(name) = ([SPD], table.cell(fill: red, text(fill: white, name)))
+#let fdp(name) = ([FDP], table.cell(fill: yellow, name))
+
+#table(
+ columns: (auto, auto, 1fr),
+ stroke: (x: none),
+
+ table.header[Tenure][Party][President],
+ [1949-1959], ..fdp[Theodor Heuss],
+ [1959-1969], ..cdu[Heinrich Lübke],
+ [1969-1974], ..spd[Gustav Heinemann],
+ [1974-1979], ..fdp[Walter Scheel],
+ [1979-1984], ..cdu[Karl Carstens],
+ [1984-1994], ..cdu[Richard von Weizsäcker],
+ [1994-1999], ..cdu[Roman Herzog],
+ [1999-2004], ..spd[Johannes Rau],
+ [2004-2010], ..cdu[Horst Köhler],
+ [2010-2012], ..cdu[Christian Wulff],
+ [2012-2017], [n/a], [Joachim Gauck],
+ [2017-], ..spd[Frank-Walter-Steinmeier],
+)
+```
+
+In this example, we make use of variables because there only have been a total
+of three parties whose members have become president (and one unaffiliated
+president). Their colors will repeat multiple times, so we store a function that
+produces an array with their party's name and a table cell with that party's
+color and the president's name (`cdu`, `spd`, and `fdp`). We then use these
+functions in the `table` argument list instead of directly adding the name. We
+use the [spread operator]($arguments/#spreading) `..` to turn the items of the
+arrays into single cells. We could also write something like
+`{[FDP], table.cell(fill: yellow)[Theodor Heuss]}` for each cell directly in the
+`table`'s argument list, but that becomes unreadable, especially for the parties
+whose colors are dark so that they require white text. We also delete vertical
+strokes and set the font to Roboto.
+
+The party column and the cell color in this example communicate redundant
+information on purpose: Communicating important data using color only is a bad
+accessibility practice. It disadvantages users with vision impairment and is in
+violation of universal access standards, such as the
+[WCAG 2.1 Success Criterion 1.4.1](https://www.w3.org/WAI/WCAG21/Understanding/use-of-color.html).
+To improve this table, we added a column printing the party name. Alternatively,
+you could have made sure to choose a color-blindness friendly palette and mark
+up your cells with an additional label that screen readers can read out loud.
+The latter feature is not currently supported by Typst, but will be added in a
+future release. You can check how colors look for color-blind readers with
+[this Chrome extension](https://chromewebstore.google.com/detail/colorblindly/floniaahmccleoclneebhhmnjgdfijgg),
+[Photoshop](https://helpx.adobe.com/photoshop/using/proofing-colors.html), or
+[GIMP](https://docs.gimp.org/2.10/en/gimp-display-filter-dialog.html).
+
+## How to adjust the lines in a table? { #strokes }
+By default, Typst adds strokes between each row and column of a table. You can
+adjust these strokes in a variety of ways. Which one is the most practical,
+depends on the modification you want to make and your intent:
+
+- Do you want to style all tables in your document, irrespective of their size
+ and content? Use the `table` function's [stroke]($table.stroke) argument in a
+ set rule.
+- Do you want to customize all lines in a single table? Use the `table`
+ function's [stroke]($table.stroke) argument when calling the table function.
+- Do you want to change, add, or remove the stroke around a single cell? Use the
+ `table.cell` element in the argument list of your table call.
+- Do you want to change, add, or remove a single horizontal or vertical stroke
+ in a single table? Use the [`table.hline`] and [`table.vline`] elements in the
+ argument list of your table call.
+
+We will go over all of these options with examples next! First, we will tackle
+the `table` function's [stroke]($table.stroke) argument. Here, you can adjust
+both how the table's lines get drawn and configure which lines are drawn at all.
+
+Let's start by modifying the color and thickness of the stroke:
+
+```example
+#table(
+ columns: 4,
+ stroke: 0.5pt + rgb("666675"),
+ [*Monday*], [11.5], [13.0], [4.0],
+ [*Tuesday*], [8.0], [14.5], [5.0],
+ [*Wednesday*], [9.0], [18.5], [13.0],
+)
+```
+
+This makes the table lines a bit less wide and uses a bluish gray. You can see
+that we added a width in point to a color to achieve our customized stroke. This
+addition yields a value of the [stroke type]($stroke). Alternatively, you can
+use the dictionary representation for strokes which allows you to access
+advanced features such as dashed lines.
+
+The previous example showed how to use the stroke argument in the table
+function's invocation. Alternatively, you can specify the stroke argument in the
+`table`'s set rule. This will have exactly the same effect on all subsequent
+`table` calls as if the stroke argument was specified in the argument list. This
+is useful if you are writing a template or want to style your whole document.
+
+```typ
+// Renders the exact same as the last example
+#set table(stroke: 0.5pt + rgb("666675"))
+
+#table(
+ columns: 4,
+ [*Monday*], [11.5], [13.0], [4.0],
+ [*Tuesday*], [8.0], [14.5], [5.0],
+ [*Wednesday*], [9.0], [18.5], [13.0],
+)
+```
+
+For small tables, you sometimes want to suppress all strokes because they add
+too much visual noise. To do this, just set the stroke argument to `{none}`:
+
+```example
+#table(
+ columns: 4,
+ stroke: none,
+ [*Monday*], [11.5], [13.0], [4.0],
+ [*Tuesday*], [8.0], [14.5], [5.0],
+ [*Wednesday*], [9.0], [18.5], [13.0],
+)
+```
+
+If you want more fine-grained control of where lines get placed in your table,
+you can also pass a dictionary with the keys `top`, `left`, `right`, `bottom`
+(controlling the respective cell sides), `x`, `y` (controlling vertical and
+horizontal strokes), and `rest` (covers all strokes not styled by other
+dictionary entries). All keys are optional; omitted keys will be treated as if
+their value was the default value. For example, to get a table with only
+horizontal lines, you can do this:
+
+```example
+#table(
+ columns: 2,
+ stroke: (x: none),
+ align: horizon,
+ [☒], [Close cabin door],
+ [☐], [Start engines],
+ [☐], [Radio tower],
+ [☐], [Push back],
+)
+```
+
+This turns off all vertical strokes and leaves the horizontal strokes in place.
+To achieve the reverse effect (only horizontal strokes), set the stroke argument
+to `{(y: none)}` instead.
+
+[Further down in the guide](#stroke-functions), we cover how to use a function
+in the stroke argument to customize all strokes individually. This is how you
+achieve more complex stroking patterns.
+
+### Adding individual lines in the table { #individual-lines }
+If you want to add a single horizontal or vertical line in your table, for
+example to separate a group of rows, you can use the [`table.hline`] and
+[`table.vline`] elements for horizontal and vertical lines, respectively. Add
+them to the argument list of the `table` function just like you would add
+individual cells and a header.
+
+Let's take a look at the following example from the reference:
+
+```example
+#set table.hline(stroke: 0.6pt)
+
+#table(
+ stroke: none,
+ columns: (auto, 1fr),
+ // Morning schedule abridged.
+ [14:00], [Talk: Tracked Layout],
+ [15:00], [Talk: Automations],
+ [16:00], [Workshop: Tables],
+ table.hline(),
+ [19:00], [Day 1 Attendee Mixer],
+)
+```
+
+In this example, you can see that we have placed a call to `table.hline` between
+the cells, producing a horizontal line at that spot. We also used a set rule on
+the element to reduce its stroke width to make it fit better with the weight of
+the font.
+
+By default, Typst places horizontal and vertical lines after the current row or
+column, depending on their position in the argument list. You can also manually
+move them to a different position by adding the `y` (for `hline`) or `x` (for
+`vline`) argument. For example, the code below would produce the same result:
+
+```typ
+#set table.hline(stroke: 0.6pt)
+
+#table(
+ stroke: none,
+ columns: (auto, 1fr),
+ // Morning schedule abridged.
+ table.hline(y: 3),
+ [14:00], [Talk: Tracked Layout],
+ [15:00], [Talk: Automations],
+ [16:00], [Workshop: Tables],
+ [19:00], [Day 1 Attendee Mixer],
+)
+```
+
+Let's imagine you are working with a template that shows none of the table
+strokes except for one between the first and second row. Now, since you have one
+table that also has labels in the first column, you want to add an extra
+vertical line to it. However, you do not want this vertical line to cross into
+the top row. You can achieve this with the `start` argument:
+
+```example
+>>> #set page(width: 12cm)
+>>> #show table.cell.where(y: 0): strong
+>>> #set table(stroke: (_, y) => if y == 0 { (bottom: 1pt) })
+// Base template already configured tables, but we need some
+// extra configuration for this table.
+#{
+ set table(align: (x, _) => if x == 0 { left } else { right })
+ show table.cell.where(x: 0): smallcaps
+ table(
+ columns: (auto, 1fr, 1fr, 1fr),
+ table.vline(x: 1, start: 1),
+ table.header[Trainset][Top Speed][Length][Weight],
+ [TGV Réseau], [320 km/h], [200m], [383t],
+ [ICE 403], [330 km/h], [201m], [409t],
+ [Shinkansen N700], [300 km/h], [405m], [700t],
+ )
+}
+```
+
+In this example, we have added `table.vline` at the start of our positional
+argument list. But because the line is not supposed to go to the left of the
+first column, we specified the `x` argument as `{1}`. We also set the `start`
+argument to `{1}` so that the line does only start after the first row.
+
+The example also contains two more things: We use the align argument with a
+function to right-align the data in all but the first column and use a show rule
+to make the first column of table cells appear in small capitals. Because these
+styles are specific to this one table, we put everything into a [code
+block]($scripting/#blocks), so that the styling does not affect any further
+tables.
+
+### Overriding the strokes of a single cell { #stroke-override }
+Imagine you want to change the stroke around a single cell. Maybe your cell is
+very important and needs highlighting! For this scenario, there is the
+[`table.cell` function]($table.cell). Instead of adding your content directly in
+the argument list of the table, you wrap it in a `table.cell` call. Now, you can
+use `table.cell`'s argument list to override the table properties, such as the
+stroke, for this cell only.
+
+Here's an example with a matrix of two of the Big Five personality factors, with
+one intersection highlighted.
+
+```example
+>>> #set page(width: 16cm)
+#table(
+ columns: 3,
+ stroke: (x: none),
+
+ [], [*High Neuroticism*], [*Low Neuroticism*],
+
+ [*High Agreeableness*],
+ table.cell(stroke: orange + 2pt)[
+ _Sensitive_ \ Prone to emotional distress but very empathetic.
+ ],
+ [_Compassionate_ \ Caring and stable, often seen as a supportive figure.],
+
+ [*Low Agreeableness*],
+ [_Contentious_ \ Competitive and easily agitated.],
+ [_Detached_ \ Independent and calm, may appear aloof.],
+)
+```
+
+Above, you can see that we used the `table.cell` element in the table's argument
+list and passed the cell content to it. We have used its `stroke` argument to
+set a wider orange stroke. Despite the fact that we disabled vertical strokes on
+the table, the orange stroke appeared on all sides of the modified cell, showing
+that the table's stroke configuration is overwritten.
+
+### Complex document-wide stroke customization { #stroke-functions }
+This section explains how to customize all lines at once in one or multiple
+tables. This allows you to draw only the first horizontal line or omit the outer
+lines, without knowing how many cells the table has. This is achieved by
+providing a function to the table's `stroke` parameter. The function should
+return a stroke given the zero-indexed x and y position of the current cell. You
+should only need these functions if you are a template author, do not use a
+template, or need to heavily customize your tables. Otherwise, your template
+should set appropriate default table strokes.
+
+For example, this is a set rule that draws all horizontal lines except for the
+very first and last line.
+
+```example
+#show table.cell.where(x: 0): set text(style: "italic")
+#show table.cell.where(y: 0): set text(style: "normal", weight: "bold")
+#set table(stroke: (_, y) => if y > 0 { (top: 0.8pt) })
+
+#table(
+ columns: 3,
+ align: center + horizon,
+ table.header[Technique][Advantage][Drawback],
+ [Diegetic], [Immersive], [May be contrived],
+ [Extradiegetic], [Breaks immersion], [Obtrusive],
+ [Omitted], [Fosters engagement], [May fracture audience],
+)
+```
+
+In the set rule, we pass a function that receives two arguments, assigning the
+vertical coordinate to `y` and discarding the horizontal coordinate. It then
+returns a stroke dictionary with a `{0.8pt}` top stroke for all but the first
+line. The cells in the first line instead implicitly receive `{none}` as the
+return value. You can easily modify this function to just draw the inner
+vertical lines instead as `{(x, _) => if x > 0 { (left: 0.8pt) }}`.
+
+Let's try a few more stroking functions. The next function will only draw a line
+below the first row:
+
+```example
+>>> #show table.cell: it => if it.x == 0 and it.y > 0 {
+>>> set text(style: "italic")
+>>> it
+>>> } else {
+>>> it
+>>> }
+>>>
+>>> #show table.cell.where(y: 0): strong
+#set table(stroke: (_, y) => if y == 0 { (bottom: 1pt) })
+
+<<< // Table as seen above
+>>> #table(
+>>> columns: 3,
+>>> align: center + horizon,
+>>> table.header[Technique][Advantage][Drawback],
+>>> [Diegetic], [Immersive], [May be contrived],
+>>> [Extradiegetic], [Breaks immersion], [Obtrusive],
+>>> [Omitted], [Fosters engagement], [May fracture audience],
+>>> )
+```
+
+If you understood the first example, it becomes obvious what happens here. We
+check if we are in the first row. If so, we return a bottom stroke. Otherwise,
+we'll return `{none}` implicitly.
+
+The next example shows how to draw all but the outer lines:
+
+```example
+>>> #show table.cell: it => if it.x == 0 and it.y > 0 {
+>>> set text(style: "italic")
+>>> it
+>>> } else {
+>>> it
+>>> }
+>>>
+>>> #show table.cell.where(y: 0): strong
+#set table(stroke: (x, y) => (
+ left: if x > 0 { 0.8pt },
+ top: if y > 0 { 0.8pt },
+))
+
+<<< // Table as seen above
+>>> #table(
+>>> columns: 3,
+>>> align: center + horizon,
+>>> table.header[Technique][Advantage][Drawback],
+>>> [Diegetic], [Immersive], [May be contrived],
+>>> [Extradiegetic], [Breaks immersion], [Obtrusive],
+>>> [Omitted], [Fosters engagement], [May fracture audience],
+>>> )
+```
+
+This example uses both the `x` and `y` coordinates. It omits the left stroke in
+the first column and the top stroke in the first row. The right and bottom lines
+are not drawn.
+
+Finally, here is a table that draws all lines except for the vertical lines in
+the first row and horizontal lines in the table body. It looks a bit like a
+calendar.
+
+```example
+>>> #show table.cell: it => if it.x == 0 and it.y > 0 {
+>>> set text(style: "italic")
+>>> it
+>>> } else {
+>>> it
+>>> }
+>>>
+>>> #show table.cell.where(y: 0): strong
+#set table(stroke: (x, y) => (
+ left: if x == 0 or y > 0 { 1pt } else { 0pt },
+ right: 1pt,
+ top: if y <= 1 { 1pt } else { 0pt },
+ bottom: 1pt,
+))
+
+<<< // Table as seen above
+>>> #table(
+>>> columns: 3,
+>>> align: center + horizon,
+>>> table.header[Technique][Advantage][Drawback],
+>>> [Diegetic], [Immersive], [May be contrived],
+>>> [Extradiegetic], [Breaks immersion], [Obtrusive],
+>>> [Omitted], [Fosters engagement], [May fracture audience],
+>>> )
+```
+
+This example is a bit more complex. We start by drawing all the strokes on the
+right of the cells. But this means that we have drawn strokes in the top row,
+too, and we don't need those! We use the fact that `left` will override `right`
+and only draw the left line if we are not in the first row or if we are in the
+first column. In all other cases, we explicitly remove the left line. Finally,
+we draw the horizontal lines by first setting the bottom line and then for the
+first two rows with the `top` key, suppressing all other top lines. The last
+line appears because there is no `top` line that could suppress it.
+
+### How to achieve a double line? { #double-stroke }
+Typst does not yet have a native way to draw double strokes, but there are
+multiple ways to emulate them, for example with [tilings]($tiling). We will
+show a different workaround in this section: Table gutters.
+
+Tables can space their cells apart using the `gutter` argument. When a gutter is
+applied, a stroke is drawn on each of the now separated cells. We can
+selectively add gutter between the rows or columns for which we want to draw a
+double line. The `row-gutter` and `column-gutter` arguments allow us to do this.
+They accept arrays of gutter values. Let's take a look at an example:
+
+```example
+#table(
+ columns: 3,
+ stroke: (x: none),
+ row-gutter: (2.2pt, auto),
+ table.header[Date][Exercise Type][Calories Burned],
+ [2023-03-15], [Swimming], [400],
+ [2023-03-17], [Weightlifting], [250],
+ [2023-03-18], [Yoga], [200],
+)
+```
+
+We can see that we used an array for `row-gutter` that specifies a `{2.2pt}` gap
+between the first and second row. It then continues with `auto` (which is the
+default, in this case `{0pt}` gutter) which will be the gutter between all other
+rows, since it is the last entry in the array.
+
+## How to align the contents of the cells in my table? { #alignment }
+You can use multiple mechanisms to align the content in your table. You can
+either use the `table` function's `align` argument to set the alignment for your
+whole table (or use it in a set rule to set the alignment for tables throughout
+your document) or the [`align`] function (or `table.cell`'s `align` argument) to
+override the alignment of a single cell.
+
+When using the `table` function's align argument, you can choose between three
+methods to specify an [alignment]:
+
+- Just specify a single alignment like `right` (aligns in the top-right corner)
+ or `center + horizon` (centers all cell content). This changes the alignment
+ of all cells.
+- Provide an array. Typst will cycle through this array for each column.
+- Provide a function that is passed the horizontal `x` and vertical `y`
+ coordinate of a cell and returns an alignment.
+
+For example, this travel itinerary right-aligns the day column and left-aligns
+everything else by providing an array in the `align` argument:
+
+```example
+>>> #set page(width: 12cm)
+#set text(font: "IBM Plex Sans")
+#show table.cell.where(y: 0): set text(weight: "bold")
+
+#table(
+ columns: 4,
+ align: (right, left, left, left),
+ fill: (_, y) => if calc.odd(y) { green.lighten(90%) },
+ stroke: none,
+
+ table.header[Day][Location][Hotel or Apartment][Activities],
+ [1], [Paris, France], [Hôtel de l'Europe], [Arrival, Evening River Cruise],
+ [2], [Paris, France], [Hôtel de l'Europe], [Louvre Museum, Eiffel Tower],
+ [3], [Lyon, France], [Lyon City Hotel], [City Tour, Local Cuisine Tasting],
+ [4], [Geneva, Switzerland], [Lakeview Inn], [Lake Geneva, Red Cross Museum],
+ [5], [Zermatt, Switzerland], [Alpine Lodge], [Visit Matterhorn, Skiing],
+)
+```
+
+However, this example does not yet look perfect — the header cells should be
+bottom-aligned. Let's use a function instead to do so:
+
+```example
+>>> #set page(width: 12cm)
+#set text(font: "IBM Plex Sans")
+#show table.cell.where(y: 0): set text(weight: "bold")
+
+#table(
+ columns: 4,
+ align: (x, y) =>
+ if x == 0 { right } else { left } +
+ if y == 0 { bottom } else { top },
+ fill: (_, y) => if calc.odd(y) { green.lighten(90%) },
+ stroke: none,
+
+ table.header[Day][Location][Hotel or Apartment][Activities],
+ [1], [Paris, France], [Hôtel de l'Europe], [Arrival, Evening River Cruise],
+ [2], [Paris, France], [Hôtel de l'Europe], [Louvre Museum, Eiffel Tower],
+<<< // ... remaining days omitted
+>>> [3], [Lyon, France], [Lyon City Hotel], [City Tour, Local Cuisine Tasting],
+>>> [4], [Geneva, Switzerland], [Lakeview Inn], [Lake Geneva, Red Cross Museum],
+>>> [5], [Zermatt, Switzerland], [Alpine Lodge], [Visit Matterhorn, Skiing],
+)
+```
+
+In the function, we calculate a horizontal and vertical alignment based on
+whether we are in the first column (`{x == 0}`) or the first row (`{y == 0}`).
+We then make use of the fact that we can add horizontal and vertical alignments
+with `+` to receive a single, two-dimensional alignment.
+
+You can find an example of using `table.cell` to change a single cell's
+alignment on [its reference page]($table.cell).
+
+## How to merge cells? { #merge-cells }
+When a table contains logical groupings or the same data in multiple adjacent
+cells, merging multiple cells into a single, larger cell can be advantageous.
+Another use case for cell groups are table headers with multiple rows: That way,
+you can group for example a sales data table by quarter in the first row and by
+months in the second row.
+
+A merged cell spans multiple rows and/or columns. You can achieve it with the
+[`table.cell`] function's `rowspan` and `colspan` arguments: Just specify how
+many rows or columns you want your cell to span.
+
+The example below contains an attendance calendar for an office with in-person
+and remote days for each team member. To make the table more glanceable, we
+merge adjacent cells with the same value:
+
+```example
+>>> #set page(width: 22cm)
+#let ofi = [Office]
+#let rem = [_Remote_]
+#let lea = [*On leave*]
+
+#show table.cell.where(y: 0): set text(
+ fill: white,
+ weight: "bold",
+)
+
+#table(
+ columns: 6 * (1fr,),
+ align: (x, y) => if x == 0 or y == 0 { left } else { center },
+ stroke: (x, y) => (
+ // Separate black cells with white strokes.
+ left: if y == 0 and x > 0 { white } else { black },
+ rest: black,
+ ),
+ fill: (_, y) => if y == 0 { black },
+
+ table.header(
+ [Team member],
+ [Monday],
+ [Tuesday],
+ [Wednesday],
+ [Thursday],
+ [Friday]
+ ),
+ [Evelyn Archer],
+ table.cell(colspan: 2, ofi),
+ table.cell(colspan: 2, rem),
+ ofi,
+ [Lila Montgomery],
+ table.cell(colspan: 5, lea),
+ [Nolan Pearce],
+ rem,
+ table.cell(colspan: 2, ofi),
+ rem,
+ ofi,
+)
+```
+
+In the example, we first define variables with "Office", "Remote", and "On
+leave" so we don't have to write these labels out every time. We can then use
+these variables in the table body either directly or in a `table.cell` call if
+the team member spends multiple consecutive days in office, remote, or on leave.
+
+The example also contains a black header (created with `table`'s `fill`
+argument) with white strokes (`table`'s `stroke` argument) and white text (set
+by the `table.cell` set rule). Finally, we align all the content of all table
+cells in the body in the center. If you want to know more about the functions
+passed to `align`, `stroke`, and `fill`, you can check out the sections on
+[alignment], [strokes](#stroke-functions), and [striped
+tables](#fills).
+
+This table would be a great candidate for fully automated generation from an
+external data source! Check out the [section about importing
+data](#importing-data) to learn more about that.
+
+## How to rotate a table? { #rotate-table }
+When tables have many columns, a portrait paper orientation can quickly get
+cramped. Hence, you'll sometimes want to switch your tables to landscape
+orientation. There are two ways to accomplish this in Typst:
+
+- If you want to rotate only the table but not the other content of the page and
+ the page itself, use the [`rotate` function]($rotate) with the `reflow`
+ argument set to `{true}`.
+- If you want to rotate the whole page the table is on, you can use the [`page`
+ function]($page) with its `flipped` argument set to `{true}`. The header,
+ footer, and page number will now also appear on the long edge of the page.
+ This has the advantage that the table will appear right side up when read on a
+ computer, but it also means that a page in your document has different
+ dimensions than all the others, which can be jarring to your readers.
+
+Below, we will demonstrate both techniques with a student grade book table.
+
+First, we will rotate the table on the page. The example also places some text
+on the right of the table.
+
+```example
+#set page("a5", columns: 2, numbering: "— 1 —")
+>>> #set page(margin: auto)
+#show table.cell.where(y: 0): set text(weight: "bold")
+
+#rotate(
+ -90deg,
+ reflow: true,
+
+ table(
+ columns: (1fr,) + 5 * (auto,),
+ inset: (x: 0.6em,),
+ stroke: (_, y) => (
+ x: 1pt,
+ top: if y <= 1 { 1pt } else { 0pt },
+ bottom: 1pt,
+ ),
+ align: (left, right, right, right, right, left),
+
+ table.header(
+ [Student Name],
+ [Assignment 1], [Assignment 2],
+ [Mid-term], [Final Exam],
+ [Total Grade],
+ ),
+ [Jane Smith], [78%], [82%], [75%], [80%], [B],
+ [Alex Johnson], [90%], [95%], [94%], [96%], [A+],
+ [John Doe], [85%], [90%], [88%], [92%], [A],
+ [Maria Garcia], [88%], [84%], [89%], [85%], [B+],
+ [Zhang Wei], [93%], [89%], [90%], [91%], [A-],
+ [Marina Musterfrau], [96%], [91%], [74%], [69%], [B-],
+ ),
+)
+
+#lorem(80)
+```
+
+
+What we have here is a two-column document on ISO A5 paper with page numbers on
+the bottom. The table has six columns and contains a few customizations to
+[stroke](#strokes), alignment and spacing. But the most important part is that
+the table is wrapped in a call to the `rotate` function with the `reflow`
+argument being `{true}`. This will make the table rotate 90 degrees
+counterclockwise. The reflow argument is needed so that the table's rotation
+affects the layout. If it was omitted, Typst would lay out the page as if the
+table was not rotated (`{true}` might become the default in the future).
+
+The example also shows how to produce many columns of the same size: To the
+initial `{1fr}` column, we add an array with five `{auto}` items that we
+create by multiplying an array with one `{auto}` item by five. Note that arrays
+with just one item need a trailing comma to distinguish them from merely
+parenthesized expressions.
+
+The second example shows how to rotate the whole page, so that the table stays
+upright:
+
+```example
+#set page("a5", numbering: "— 1 —")
+>>> #set page(margin: auto)
+#show table.cell.where(y: 0): set text(weight: "bold")
+
+#page(flipped: true)[
+ #table(
+ columns: (1fr,) + 5 * (auto,),
+ inset: (x: 0.6em,),
+ stroke: (_, y) => (
+ x: 1pt,
+ top: if y <= 1 { 1pt } else { 0pt },
+ bottom: 1pt,
+ ),
+ align: (left, right, right, right, right, left),
+
+ table.header(
+ [Student Name],
+ [Assignment 1], [Assignment 2],
+ [Mid-term], [Final Exam],
+ [Total Grade],
+ ),
+ [Jane Smith], [78%], [82%], [75%], [80%], [B],
+ [Alex Johnson], [90%], [95%], [94%], [96%], [A+],
+ [John Doe], [85%], [90%], [88%], [92%], [A],
+ [Maria Garcia], [88%], [84%], [89%], [85%], [B+],
+ [Zhang Wei], [93%], [89%], [90%], [91%], [A-],
+ [Marina Musterfrau], [96%], [91%], [74%], [69%], [B-],
+ )
+
+ #pad(x: 15%, top: 1.5em)[
+ = Winter 2023/24 results
+ #lorem(80)
+ ]
+]
+```
+
+Here, we take the same table and the other content we want to set with it and
+put it into a call to the [`page`] function while supplying `{true}` to the
+`flipped` argument. This will instruct Typst to create new pages with width and
+height swapped and place the contents of the function call onto a new page.
+Notice how the page number is also on the long edge of the paper now. At the
+bottom of the page, we use the [`pad`] function to constrain the width of the
+paragraph to achieve a nice and legible line length.
+
+## How to break a table across pages? { #table-across-pages }
+It is best to contain a table on a single page. However, some tables just have
+many rows, so breaking them across pages becomes unavoidable. Fortunately, Typst
+supports breaking tables across pages out of the box. If you are using the
+[`table.header`] and [`table.footer`] functions, their contents will be repeated
+on each page as the first and last rows, respectively. If you want to disable
+this behavior, you can set `repeat` to `{false}` on either of them.
+
+If you have placed your table inside of a [figure], it becomes unable to break
+across pages by default. However, you can change this behavior. Let's take a
+look:
+
+```example
+#set page(width: 9cm, height: 6cm)
+#show table.cell.where(y: 0): set text(weight: "bold")
+#show figure: set block(breakable: true)
+
+#figure(
+ caption: [Training regimen for Marathon],
+ table(
+ columns: 3,
+ fill: (_, y) => if y == 0 { gray.lighten(75%) },
+
+ table.header[Week][Distance (km)][Time (hh:mm:ss)],
+ [1], [5], [00:30:00],
+ [2], [7], [00:45:00],
+ [3], [10], [01:00:00],
+ [4], [12], [01:10:00],
+ [5], [15], [01:25:00],
+ [6], [18], [01:40:00],
+ [7], [20], [01:50:00],
+ [8], [22], [02:00:00],
+ [...], [...], [...],
+ table.footer[_Goal_][_42.195_][_02:45:00_],
+ )
+)
+```
+
+A figure automatically produces a [block] which cannot break by default.
+However, we can reconfigure the block of the figure using a show rule to make it
+`breakable`. Now, the figure spans multiple pages with the headers and footers
+repeating.
+
+## How to import data into a table? { #importing-data }
+Often, you need to put data that you obtained elsewhere into a table. Sometimes,
+this is from Microsoft Excel or Google Sheets, sometimes it is from a dataset
+on the web or from your experiment. Fortunately, Typst can load many [common
+file formats]($category/data-loading), so you can use scripting to include their
+data in a table.
+
+The most common file format for tabular data is CSV. You can obtain a CSV file
+from Excel by choosing "Save as" in the _File_ menu and choosing the file format
+"CSV UTF-8 (Comma-delimited) (.csv)". Save the file and, if you are using the
+web app, upload it to your project.
+
+In our case, we will be building a table about Moore's Law. For this purpose, we
+are using a statistic with [how many transistors the average microprocessor
+consists of per year from Our World in
+Data](https://ourworldindata.org/grapher/transistors-per-microprocessor). Let's
+start by pressing the "Download" button to get a CSV file with the raw data.
+
+Be sure to move the file to your project or somewhere Typst can see it, if you
+are using the CLI. Once you did that, we can open the file to see how it is
+structured:
+
+```csv
+Entity,Code,Year,Transistors per microprocessor
+World,OWID_WRL,1971,2308.2417
+World,OWID_WRL,1972,3554.5222
+World,OWID_WRL,1974,6097.5625
+```
+
+The file starts with a header and contains four columns: Entity (which is to
+whom the metric applies), Code, the year, and the number of transistors per
+microprocessor. Only the last two columns change between each row, so we can
+disregard "Entity" and "Code".
+
+First, let's start by loading this file with the [`csv`] function. It accepts
+the file name of the file we want to load as a string argument:
+
+```typ
+#let moore = csv("moore.csv")
+```
+
+We have loaded our file (assuming we named it `moore.csv`) and [bound
+it]($scripting/#bindings) to the new variable `moore`. This will not produce any
+output, so there's nothing to see yet. If we want to examine what Typst loaded,
+we can either hover the name of the variable in the web app or print some items
+from the array:
+
+```example
+#let moore = csv("moore.csv")
+
+#moore.slice(0, 3)
+```
+
+With the arguments `{(0, 3)}`, the [`slice`]($array.slice) method returns the
+first three items in the array (with the indices 0, 1, and 2). We can see that
+each row is its own array with one item per cell.
+
+Now, let's write a loop that will transform this data into an array of cells
+that we can use with the table function.
+
+```example
+#let moore = csv("moore.csv")
+
+#table(
+ columns: 2,
+ ..for (.., year, count) in moore {
+ (year, count)
+ }
+)
+```
+
+The example above uses a for loop that iterates over the rows in our CSV file
+and returns an array for each iteration. We use the for loop's
+[destructuring]($scripting/#bindings) capability to discard all but the last two
+items of each row. We then create a new array with just these two. Because Typst
+will concatenate the array results of all the loop iterations, we get a
+one-dimensional array in which the year column and the number of transistors
+alternate. We can then insert the array as cells. For this we use the [spread
+operator]($arguments/#spreading) (`..`). By prefixing an array, or, in our case
+an expression that yields an array, with two dots, we tell Typst that the
+array's items should be used as positional arguments.
+
+Alternatively, we can also use the [`map`]($array.map), [`slice`]($array.slice),
+and [`flatten`]($array.flatten) array methods to write this in a more functional
+style:
+
+```typ
+#let moore = csv("moore.csv")
+
+#table(
+ columns: moore.first().len(),
+ ..moore.map(m => m.slice(2)).flatten(),
+)
+```
+
+This example renders the same as the previous one, but first uses the `map`
+function to change each row of the data. We pass a function to map that gets run
+on each row of the CSV and returns a new value to replace that row with. We use
+it to discard the first two columns with `slice`. Then, we spread the data into
+the `table` function. However, we need to pass a one-dimensional array and
+`moore`'s value is two-dimensional (that means that each of its row values
+contains an array with the cell data). That's why we call `flatten` which
+converts it to a one-dimensional array. We also extract the number of columns
+from the data itself.
+
+Now that we have nice code for our table, we should try to also make the table
+itself nice! The transistor counts go from millions in 1995 to trillions in 2021
+and changes are difficult to see with so many digits. We could try to present
+our data logarithmically to make it more digestible:
+
+```example
+#let moore = csv("moore.csv")
+#let moore-log = moore.slice(1).map(m => {
+ let (.., year, count) = m
+ let log = calc.log(float(count))
+ let rounded = str(calc.round(log, digits: 2))
+ (year, rounded)
+})
+
+#show table.cell.where(x: 0): strong
+
+#table(
+ columns: moore-log.first().len(),
+ align: right,
+ fill: (_, y) => if calc.odd(y) { rgb("D7D9E0") },
+ stroke: none,
+
+ table.header[Year][Transistor count ($log_10$)],
+ table.hline(stroke: rgb("4D4C5B")),
+ ..moore-log.flatten(),
+)
+```
+
+In this example, we first drop the header row from the data since we are adding
+our own. Then, we discard all but the last two columns as above. We do this by
+[destructuring]($scripting/#bindings) the array `m`, discarding all but the two
+last items. We then convert the string in `count` to a floating point number,
+calculate its logarithm and store it in the variable `log`. Finally, we round it
+to two digits, convert it to a string, and store it in the variable `rounded`.
+Then, we return an array with `year` and `rounded` that replaces the original
+row. In our table, we have added our custom header that tells the reader that
+we've applied a logarithm to the values. Then, we spread the flattened data as
+above.
+
+We also styled the table with [stripes](#fills), a
+[horizontal line](#individual-lines) below the first row, [aligned](#alignment)
+everything to the right, and emboldened the first column. Click on the links to
+go to the relevant guide sections and see how it's done!
+
+## What if I need the table function for something that isn't a table? { #table-and-grid }
+Tabular layouts of content can be useful not only for matrices of closely
+related data, like shown in the examples throughout this guide, but also for
+presentational purposes. Typst differentiates between grids that are for layout
+and presentational purposes only and tables, in which the arrangement of the
+cells itself conveys information.
+
+To make this difference clear to other software and allow templates to heavily
+style tables, Typst has two functions for grid and table layout:
+
+- The [`table`] function explained throughout this guide which is intended for
+ tabular data.
+- The [`grid`] function which is intended for presentational purposes and page
+ layout.
+
+Both elements work the same way and have the same arguments. You can apply
+everything you have learned about tables in this guide to grids. There are only
+three differences:
+
+- You'll need to use the [`grid.cell`], [`grid.vline`], and [`grid.hline`]
+ elements instead of [`table.cell`], [`table.vline`], and [`table.hline`].
+- The grid has different defaults: It draws no strokes by default and has no
+ spacing (`inset`) inside of its cells.
+- Elements like `figure` do not react to grids since they are supposed to have
+ no semantical bearing on the document structure.
diff --git a/sources/docs/guides/welcome.md b/sources/docs/guides/welcome.md
new file mode 100644
index 0000000000000000000000000000000000000000..c5c927828816ea223306f1321056241a2fed3136
--- /dev/null
+++ b/sources/docs/guides/welcome.md
@@ -0,0 +1,14 @@
+---
+description: Guides for Typst.
+---
+
+# Guides
+Welcome to the Guides section! Here, you'll find helpful material for specific
+user groups or use cases. Currently, two guides are available: An introduction
+to Typst for LaTeX users, and a detailed look at page setup. Feel free to
+propose other topics for guides!
+
+## List of Guides
+- [Guide for LaTeX users]($guides/guide-for-latex-users)
+- [Page setup guide]($guides/page-setup-guide)
+- [Table guide]($guides/table-guide)
diff --git a/sources/docs/overview.md b/sources/docs/overview.md
new file mode 100644
index 0000000000000000000000000000000000000000..bc7f14fc15f9cfc70f105076d768e265ec767ecb
--- /dev/null
+++ b/sources/docs/overview.md
@@ -0,0 +1,18 @@
+---
+description: |
+ Learn how to use Typst to compose documents faster. Get started with the
+ tutorial, or dive into the reference.
+---
+
+# Overview
+Welcome to Typst's documentation! Typst is a new markup-based typesetting system
+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.
+
+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.
diff --git a/sources/docs/reference/export/html.md b/sources/docs/reference/export/html.md
new file mode 100644
index 0000000000000000000000000000000000000000..330c2e13628a0dc03b1a1597ef5bfbc3f798330f
--- /dev/null
+++ b/sources/docs/reference/export/html.md
@@ -0,0 +1,61 @@
+
+
+Typst's HTML export is currently under active development. The feature is still
+very incomplete and only available for experimentation behind a feature flag. Do
+not use this feature for production use cases. In the CLI, you can experiment
+with HTML export by passing `--features html` or setting the `TYPST_FEATURES`
+environment variables to `html`. In the web app, HTML export is not available at
+this time. Visit the [tracking issue](https://github.com/typst/typst/issues/5512)
+to follow progress on HTML export and learn more about planned features.
+
+
+HTML files describe a document structurally. The aim of Typst's HTML export is
+to capture the structure of an input document and produce semantically rich HTML
+that retains this structure. The resulting HTML should be accessible,
+human-readable, and editable by hand and downstream tools.
+
+PDF, PNG, and SVG export, in contrast, all produce _visual_ representations of a
+fully-laid out document. This divergence in the formats' intents means that
+Typst cannot simply produce perfect HTML for your existing Typst documents. It
+cannot always know what the best semantic HTML representation of your content
+is.
+
+Instead, it gives _you_ full control: You can check the current export format
+through the [`target`] function and when it is set to HTML, generate [raw HTML
+elements]($html.elem). The primary intended use of these elements is in
+templates and show rules. This way, the document's contents can be fully
+agnostic to the export target and content can be shared between PDF and HTML
+export.
+
+Currently, Typst will always output a single HTML file. Support for outputting
+directories with multiple HTML documents and assets, as well as support for
+outputting fragments that can be integrated into other HTML documents is
+planned.
+
+Typst currently does not output CSS style sheets, instead focussing on emitting
+semantic markup. You can of course write your own CSS styles and still benefit
+from sharing your _content_ between PDF and HTML. For the future, we plan to
+give you the option of automatically emitting CSS, taking more of your existing
+set rules into account.
+
+# Exporting as HTML
+## Command Line
+Pass `--format html` to the `compile` or `watch` subcommand or provide an output
+file name that ends with `.html`. Note that you must also pass `--features html`
+or set `TYPST_FEATURES=html` to enable this experimental export target.
+
+When using `typst watch`, Typst will spin up a live-reloading HTTP server. You
+can configure it as follows:
+
+- Pass `--port` to change the port. (Defaults to the first free port in the
+ range 3000-3005.)
+- Pass `--no-reload` to disable injection of a live reload script. (The HTML
+ that is written to disk isn't affected either way.)
+- Pass `--no-serve` to disable the server altogether.
+
+## Web App
+Not currently available.
+
+# HTML-specific functionality
+Typst exposes HTML-specific functionality in the global `html` module. See below
+for the definitions it contains.
diff --git a/sources/docs/reference/export/pdf.md b/sources/docs/reference/export/pdf.md
new file mode 100644
index 0000000000000000000000000000000000000000..b220ae9469d10692546c2c710143d17e538f11cc
--- /dev/null
+++ b/sources/docs/reference/export/pdf.md
@@ -0,0 +1,71 @@
+PDF files focus on accurately describing documents visually, but also have
+facilities for annotating their structure. This hybrid approach makes
+them a good fit for document exchange: They render exactly the same on every
+device, but also support extraction of a document's content and structure (at
+least to an extent). Unlike PNG files, PDFs are not bound to a specific
+resolution. Hence, you can view them at any size without incurring a loss of
+quality.
+
+# PDF standards
+The International Standards Organization (ISO) has published the base PDF
+standard and various standards that extend it to make PDFs more suitable for
+specific use-cases. By default, Typst exports PDF 1.7 files. Adobe Acrobat 8 and
+later as well as all other commonly used PDF viewers are compatible with this
+PDF version.
+
+## PDF/A
+Typst optionally supports emitting PDF/A-conformant files. PDF/A files are
+geared towards maximum compatibility with current and future PDF tooling. They
+do not rely on difficult-to-implement or proprietary features and contain
+exhaustive metadata. This makes them suitable for long-term archival.
+
+The PDF/A Standard has multiple versions (_parts_ in ISO terminology) and most
+parts have multiple profiles that indicate the file's conformance level.
+Currently, Typst supports these PDF/A output profiles:
+
+- PDF/A-2b: The basic conformance level of ISO 19005-2. This version of PDF/A is
+ based on PDF 1.7 and results in self-contained, archivable PDF files.
+
+- PDF/A-3b: The basic conformance level of ISO 19005-3. This version of PDF/A is
+ based on PDF 1.7 and results in archivable PDF files that can contain
+ arbitrary other related files as [attachments]($pdf.embed). The only
+ difference between it and PDF/A-2b is the capability to embed
+ non-PDF/A-conformant files within.
+
+When choosing between exporting PDF/A and regular PDF, keep in mind that PDF/A
+files contain additional metadata, and that some readers will prevent the user
+from modifying a PDF/A file. Some features of Typst may be disabled depending on
+the PDF standard you choose.
+
+# Exporting as PDF
+## Command Line
+PDF is Typst's default export format. Running the `compile` or `watch`
+subcommand without specifying a format will create a PDF. When exporting to PDF,
+you have the following configuration options:
+
+- Which PDF standards Typst should enforce conformance with by specifying
+ `--pdf-standard` followed by one or multiple comma-separated standards. Valid
+ standards are `1.7`, `a-2b`, and `a-3b`. By default, Typst outputs
+ PDF-1.7-compliant files.
+
+- Which pages to export by specifying `--pages` followed by a comma-separated
+ list of numbers or dash-separated number ranges. Ranges can be half-open.
+ Example: `2,3,7-9,11-`.
+
+## Web App
+Click the quick download button at the top right to export a PDF with default
+settings. For further configuration, click "File" > "Export as" > "PDF" or click
+the downwards-facing arrow next to the quick download button and select "Export
+as PDF". When exporting to PDF, you have the following configuration options:
+
+- Which PDF standards Typst should enforce conformance with. By default, Typst
+ outputs PDF-1.7-compliant files. Valid additional standards are `A-2b` and
+ `A-3b`.
+
+- Which pages to export. Valid options are "All pages", "Current page", and
+ "Custom ranges". Custom ranges are a comma-separated list of numbers or
+ dash-separated number ranges. Ranges can be half-open. Example: `2,3,7-9,11-`.
+
+# PDF-specific functionality
+Typst exposes PDF-specific functionality in the global `pdf` module. See below
+for the definitions it contains.
diff --git a/sources/docs/reference/export/png.md b/sources/docs/reference/export/png.md
new file mode 100644
index 0000000000000000000000000000000000000000..0e817e0f1e11f2fc5dd0efc3cef507de223ad06c
--- /dev/null
+++ b/sources/docs/reference/export/png.md
@@ -0,0 +1,61 @@
+Instead of creating a PDF, Typst can also directly render pages to PNG raster
+graphics. PNGs are losslessly compressed images that can contain one page at a
+time. When exporting a multi-page document, Typst will emit multiple PNGs. PNGs
+are a good choice when you want to use Typst's output in an image editing
+software or when you can use none of Typst's other export formats.
+
+In contrast to Typst's other export formats, PNGs are bound to a specific
+resolution. When exporting to PNG, you can configure the resolution as pixels
+per inch (PPI). If the medium you view the PNG on has a finer resolution than
+the PNG you exported, you will notice a loss of quality. Typst calculates the
+resolution of your PNGs based on each page's physical dimensions and the PPI. If
+you need guidance for choosing a PPI value, consider the following:
+
+- A value of 300 or 600 is typical for desktop printing.
+- Professional prints of detailed graphics can go up to 1200 PPI.
+- If your document is only viewed at a distance, e.g. a poster, you may choose a
+ smaller value than 300.
+- If your document is viewed on screens, a typical PPI value for a smartphone is
+ 400-500.
+
+Because PNGs only contain a pixel raster, the text within cannot be extracted
+automatically (without OCR), for example by copy/paste or a screen reader. If
+you need the text to be accessible, export a PDF or HTML file instead.
+
+PNGs can have transparent backgrounds. By default, Typst will output a PNG with
+an opaque white background. You can make the background transparent using
+`[#set page(fill: none)]`. Learn more on the
+[`page` function's reference page]($page.fill).
+
+# Exporting as PNG
+## Command Line
+Pass `--format png` to the `compile` or `watch` subcommand or provide an output
+file name that ends with `.png`.
+
+If your document has more than one page, Typst will create multiple image files.
+The output file name must then be a template string containing at least one of
+- `[{p}]`, which will be replaced by the page number
+- `[{0p}]`, which will be replaced by the zero-padded page number (so that all
+ numbers have the same length)
+- `[{t}]`, which will be replaced by the total number of pages
+
+When exporting to PNG, you have the following configuration options:
+
+- Which resolution to render at by specifying `--ppi` followed by a number of
+ pixels per inch. The default is `144`.
+
+- Which pages to export by specifying `--pages` followed by a comma-separated
+ list of numbers or dash-separated number ranges. Ranges can be half-open.
+ Example: `2,3,7-9,11-`.
+
+## Web App
+Click "File" > "Export as" > "PNG" or click the downwards-facing arrow next to
+the quick download button and select "Export as PNG". When exporting to PNG, you
+have the following configuration options:
+
+- The resolution at which the pages should be rendered, as a number of pixels
+ per inch. The default is `144`.
+
+- Which pages to export. Valid options are "All pages", "Current page", and
+ "Custom ranges". Custom ranges are a comma-separated list of numbers or
+ dash-separated number ranges. Ranges can be half-open. Example: `2,3,7-9,11-`.
diff --git a/sources/docs/reference/export/svg.md b/sources/docs/reference/export/svg.md
new file mode 100644
index 0000000000000000000000000000000000000000..630ab845286ba43bb0248bed06d5ace63983cf9c
--- /dev/null
+++ b/sources/docs/reference/export/svg.md
@@ -0,0 +1,48 @@
+Instead of creating a PDF, Typst can also directly render pages to scalable
+vector graphics (SVGs), which are the preferred format for embedding vector
+graphics in web pages. Like PDF files, SVGs display your document exactly how
+you have laid it out in Typst. Likewise, they share the benefit of not being
+bound to a specific resolution. Hence, you can print or view SVG files on any
+device without incurring a loss of quality. (Note that font printing quality may
+be better with a PDF.) In contrast to a PDF, an SVG cannot contain multiple
+pages. When exporting a multi-page document, Typst will emit multiple SVGs.
+
+SVGs can represent text in two ways: By embedding the text itself and rendering
+it with the fonts available on the viewer's computer or by embedding the shapes
+of each glyph in the font used to create the document. To ensure that the SVG
+file looks the same across all devices it is viewed on, Typst chooses the latter
+method. This means that the text in the SVG cannot be extracted automatically,
+for example by copy/paste or a screen reader. If you need the text to be
+accessible, export a PDF or HTML file instead.
+
+SVGs can have transparent backgrounds. By default, Typst will output an SVG with
+an opaque white background. You can make the background transparent using
+`[#set page(fill: none)]`. Learn more on the
+[`page` function's reference page]($page.fill).
+
+# Exporting as SVG
+## Command Line
+Pass `--format svg` to the `compile` or `watch` subcommand or provide an output
+file name that ends with `.svg`.
+
+If your document has more than one page, Typst will create multiple image files.
+The output file name must then be a template string containing at least one of
+- `[{p}]`, which will be replaced by the page number
+- `[{0p}]`, which will be replaced by the zero-padded page number (so that all
+ numbers have the same length)
+- `[{t}]`, which will be replaced by the total number of pages
+
+When exporting to SVG, you have the following configuration options:
+
+- Which pages to export by specifying `--pages` followed by a comma-separated
+ list of numbers or dash-separated number ranges. Ranges can be half-open.
+ Example: `2,3,7-9,11-`.
+
+## Web App
+Click "File" > "Export as" > "SVG" or click the downwards-facing arrow next to
+the quick download button and select "Export as SVG". When exporting to SVG, you
+have the following configuration options:
+
+- Which pages to export. Valid options are "All pages", "Current page", and
+ "Custom ranges". Custom ranges are a comma-separated list of numbers or
+ dash-separated number ranges. Ranges can be half-open. Example: `2,3,7-9,11-`.
diff --git a/sources/docs/reference/language/context.md b/sources/docs/reference/language/context.md
new file mode 100644
index 0000000000000000000000000000000000000000..bdd520f5ddec34ceb36197037932f36b7e55bd23
--- /dev/null
+++ b/sources/docs/reference/language/context.md
@@ -0,0 +1,233 @@
+---
+description: |
+ How to deal with content that reacts to its location in the document.
+---
+
+# Context
+Sometimes, we want to create content that reacts to its location in the
+document. This could be a localized phrase that depends on the configured text
+language or something as simple as a heading number which prints the right
+value based on how many headings came before it. However, Typst code isn't
+directly aware of its location in the document. Some code at the beginning of
+the source text could yield content that ends up at the back of the document.
+
+To produce content that is reactive to its surroundings, we must thus
+specifically instruct Typst: We do this with the `{context}` keyword, which
+precedes an expression and ensures that it is computed with knowledge of its
+environment. In return, the context expression itself ends up opaque. We cannot
+directly access whatever results from it in our code, precisely because it is
+contextual: There is no one correct result, there may be multiple results in
+different places of the document. For this reason, everything that depends on
+the contextual data must happen inside of the context expression.
+
+Aside from explicit context expressions, context is also established implicitly
+in some places that are also aware of their location in the document:
+[Show rules]($styling/#show-rules) provide context[^1] and numberings in the
+outline, for instance, also provide the proper context to resolve counters.
+
+## Style context
+With set rules, we can adjust style properties for parts or the whole of our
+document. We cannot access these without a known context, as they may change
+throughout the course of the document. When context is available, we can
+retrieve them simply by accessing them as fields on the respective element
+function.
+
+```example
+#set text(lang: "de")
+#context text.lang
+```
+
+As explained above, a context expression is reactive to the different
+environments it is placed into. In the example below, we create a single context
+expression, store it in the `value` variable and use it multiple times. Each use
+properly reacts to the current surroundings.
+
+```example
+#let value = context text.lang
+#value
+
+#set text(lang: "de")
+#value
+
+#set text(lang: "fr")
+#value
+```
+
+Crucially, upon creation, `value` becomes opaque [content] that we cannot peek
+into. It can only be resolved when placed somewhere because only then the
+context is known. The body of a context expression may be evaluated zero, one,
+or multiple times, depending on how many different places it is put into.
+
+## Location context
+We've already seen that context gives us access to set rule values. But it can
+do more: It also lets us know _where_ in the document we currently are, relative
+to other elements, and absolutely on the pages. We can use this information to
+create very flexible interactions between different document parts. This
+underpins features like heading numbering, the table of contents, or page
+headers dependent on section headings.
+
+Some functions like [`counter.get`]($counter.get) implicitly access the current
+location. In the example below, we want to retrieve the value of the heading
+counter. Since it changes throughout the document, we need to first enter a
+context expression. Then, we use `get` to retrieve the counter's current value.
+This function accesses the current location from the context to resolve the
+counter value. Counters have multiple levels and `get` returns an array with the
+resolved numbers. Thus, we get the following result:
+
+```example
+#set heading(numbering: "1.")
+
+= Introduction
+#lorem(5)
+
+#context counter(heading).get()
+
+= Background
+#lorem(5)
+
+#context counter(heading).get()
+```
+
+For more flexibility, we can also use the [`here`] function to directly extract
+the current [location] from the context. The example below
+demonstrates this:
+
+- We first have `{counter(heading).get()}`, which resolves to `{(2,)}` as
+ before.
+- We then use the more powerful [`counter.at`] with [`here`], which in
+ combination is equivalent to `get`, and thus get `{(2,)}`.
+- Finally, we use `at` with a [label] to retrieve the value of the counter at a
+ _different_ location in the document, in our case that of the introduction
+ heading. This yields `{(1,)}`. Typst's context system gives us time travel
+ abilities and lets us retrieve the values of any counters and states at _any_
+ location in the document.
+
+```example
+#set heading(numbering: "1.")
+
+= Introduction
+#lorem(5)
+
+= Background
+#lorem(5)
+
+#context [
+ #counter(heading).get() \
+ #counter(heading).at(here()) \
+ #counter(heading).at()
+]
+```
+
+As mentioned before, we can also use context to get the physical position of
+elements on the pages. We do this with the [`locate`] function, which works
+similarly to `counter.at`: It takes a location or other [selector] that resolves
+to a unique element (could also be a label) and returns the position on the
+pages for that element.
+
+```example
+Background is at: \
+#context locate().position()
+
+= Introduction
+#lorem(5)
+#pagebreak()
+
+= Background
+#lorem(5)
+```
+
+There are other functions that make use of the location context, most
+prominently [`query`]. Take a look at the
+[introspection]($category/introspection) category for more details on those.
+
+## Nested contexts
+Context is also accessible from within function calls nested in context blocks.
+In the example below, `foo` itself becomes a contextual function, just like
+[`to-absolute`]($length.to-absolute) is.
+
+```example
+#let foo() = 1em.to-absolute()
+#context {
+ foo() == text.size
+}
+```
+
+Context blocks can be nested. Contextual code will then always access the
+innermost context. The example below demonstrates this: The first `text.lang`
+will access the outer context block's styles and as such, it will **not**
+see the effect of `{set text(lang: "fr")}`. The nested context block around the
+second `text.lang`, however, starts after the set rule and will thus show
+its effect.
+
+```example
+#set text(lang: "de")
+#context [
+ #set text(lang: "fr")
+ #text.lang \
+ #context text.lang
+]
+```
+
+You might wonder why Typst ignores the French set rule when computing the first
+`text.lang` in the example above. The reason is that, in the general case, Typst
+cannot know all the styles that will apply as set rules can be applied to
+content after it has been constructed. Below, `text.lang` is already computed
+when the template function is applied. As such, it cannot possibly be aware of
+the language change to French in the template.
+
+```example
+#let template(body) = {
+ set text(lang: "fr")
+ upper(body)
+}
+
+#set text(lang: "de")
+#context [
+ #show: template
+ #text.lang \
+ #context text.lang
+]
+```
+
+The second `text.lang`, however, _does_ react to the language change because
+evaluation of its surrounding context block is deferred until the styles for it
+are known. This illustrates the importance of picking the right insertion point for a context to get access to precisely the right styles.
+
+The same also holds true for the location context. Below, the first
+`{c.display()}` call will access the outer context block and will thus not see
+the effect of `{c.update(2)}` while the second `{c.display()}` accesses the inner context and will thus see it.
+
+```example
+#let c = counter("mycounter")
+#c.update(1)
+#context [
+ #c.update(2)
+ #c.display() \
+ #context c.display()
+]
+```
+
+## Compiler iterations
+To resolve contextual interactions, the Typst compiler processes your document
+multiple times. For instance, to resolve a `locate` call, Typst first provides a
+placeholder position, layouts your document and then recompiles with the known
+position from the finished layout. The same approach is taken to resolve
+counters, states, and queries. In certain cases, Typst may even need more than
+two iterations to resolve everything. While that's sometimes a necessity, it may
+also be a sign of misuse of contextual functions (e.g. of
+[state]($state/#caution)). If Typst cannot resolve everything within five
+attempts, it will stop and output the warning "layout did not converge within 5
+attempts."
+
+A very careful reader might have noticed that not all of the functions presented
+above actually make use of the current location. While
+`{counter(heading).get()}` definitely depends on it,
+`{counter(heading).at()}`, for instance, does not. However, it still
+requires context. While its value is always the same _within_ one compilation
+iteration, it may change over the course of multiple compiler iterations. If one
+could call it directly at the top level of a module, the whole module and its
+exports could change over the course of multiple compiler iterations, which
+would not be desirable.
+
+[^1]: Currently, all show rules provide styling context, but only show rules on
+ [locatable]($location/#locatable) elements provide a location context.
diff --git a/sources/docs/reference/language/scripting.md b/sources/docs/reference/language/scripting.md
new file mode 100644
index 0000000000000000000000000000000000000000..5e0f1555e4ade9ff401d13ffa17b42ca1e868a43
--- /dev/null
+++ b/sources/docs/reference/language/scripting.md
@@ -0,0 +1,373 @@
+---
+description: Automate your document with Typst's scripting capabilities.
+---
+
+# Scripting
+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
+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
+introduced with a hash (`#`) and normal markup parsing resumes after the
+expression is finished. If a character would continue the expression but should
+be interpreted as text, the expression can forcibly be ended with a semicolon
+(`;`).
+
+```example
+#emph[Hello] \
+#emoji.face \
+#"hello".len()
+```
+
+The example above shows a few of the available expressions, including
+[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 hash syntax (e.g. binary operator expressions). To embed
+these into markup, you can use parentheses, as in `[#(1 + 2)]`.
+
+## Blocks
+To structure your code and embed markup into it, Typst provides two kinds of
+_blocks:_
+
+- **Code block:** `{{ let x = 1; x + 2 }}` \
+ When writing code, you'll probably want to split up your computation into
+ multiple statements, create some intermediate variables and so on. Code blocks
+ let you write multiple expressions where one is expected. The individual
+ expressions in a code block should be separated by line breaks or semicolons.
+ The output values of the individual expressions in a code block are joined to
+ determine the block's value. Expressions without useful output, like `{let}`
+ bindings yield `{none}`, which can be joined with any value without effect.
+
+- **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]($function). Content
+ blocks are delimited by square brackets and can contain arbitrary markup. A
+ content block results in a value of type [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]}`.
+
+Content and code blocks can be nested arbitrarily. In the example below,
+`{[hello ]}` is joined with the output of `{a + [ the ] + b}` yielding
+`{[hello from the *world*]}`.
+
+```example
+#{
+ let a = [from]
+ let b = [*world*]
+ [hello ]
+ a + [ the ] + b
+}
+```
+
+## Bindings and Destructuring { #bindings }
+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]($function/#defining-functions). Variables can be
+accessed for the rest of the containing block (or the rest of the file if there
+is no containing block).
+
+```example
+#let name = "Typst"
+This is #name's documentation.
+It explains #name.
+
+#let add(x, y) = x + y
+Sum is #add(2, 3).
+```
+
+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.
+
+```example
+#let (x, y) = (1, 2)
+The coordinates are #x, #y.
+
+#let (a, .., b) = (1, 2, 3, 4)
+The first element is #a.
+The last element is #b.
+
+#let books = (
+ Shakespeare: "Hamlet",
+ Homer: "The Odyssey",
+ Austen: "Persuasion",
+)
+
+#let (Austen,) = books
+Austen wrote #Austen.
+
+#let (Homer: h) = books
+Homer wrote #h.
+
+#let (Homer, ..other) = books
+#for (author, title) in other [
+ #author wrote #title.
+]
+```
+
+You can use the underscore to discard elements in a destructuring pattern:
+
+```example
+#let (_, y, _) = (1, 2, 3)
+The y coordinate is #y.
+```
+
+Destructuring also works in argument lists of functions ...
+
+```example
+#let left = (2, 4, 5)
+#let right = (3, 2, 6)
+#left.zip(right).map(
+ ((a,b)) => a + b
+)
+```
+
+... and on the left-hand side of normal assignments. This can be useful to
+swap variables among other things.
+
+```example
+#{
+ let a = 1
+ let b = 2
+ (a, b) = (b, a)
+ [a = #a, b = #b]
+}
+```
+
+## 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}` expressions. When the condition evaluates to `{true}`, the conditional
+yields the value resulting from the if's body, otherwise yields the value
+resulting from the else's body.
+
+```example
+#if 1 < 2 [
+ This is shown
+] else [
+ This is not.
+]
+```
+
+Each branch can have a code or content block as its body.
+
+- `{if condition {..}}`
+- `{if condition [..]}`
+- `{if condition [..] else {..}}`
+- `{if condition [..] else if condition {..} else [..]}`
+
+## 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
+stays fulfilled. Just like blocks, loops _join_ the results from each iteration
+into one value.
+
+In the example below, the three sentences created by the for loop join together
+into a single content value and the length-1 arrays in the while loop join
+together into one larger array.
+
+```example
+#for c in "ABC" [
+ #c is a letter.
+]
+
+#let n = 2
+#while n < 10 {
+ n = (n * 2) - 1
+ (n,)
+}
+```
+
+For loops can iterate over a variety of collections:
+
+- `{for value in array {..}}` \
+ Iterates over the items in the [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]. The pairs can also be
+ destructured by using `{for (key, value) in dict {..}}`. It is more efficient
+ than `{for pair in dict.pairs() {..}}` because it doesn't create a temporary
+ array of all key-value pairs.
+
+- `{for letter in "abc" {..}}` \
+ Iterates over the characters of the [string]($str). Technically, it iterates
+ over the grapheme clusters of the string. Most of the time, a grapheme cluster
+ is just a single codepoint. However, a grapheme cluster could contain multiple
+ codepoints, like a flag emoji.
+
+- `{for byte in bytes("😀") {..}}` \
+ Iterates over the [bytes], which can be converted from a [string]($str) or
+ [read] from a file without encoding. Each byte value is an [integer]($int)
+ between `{0}` and `{255}`.
+
+To control the execution of the loop, Typst provides the `{break}` and
+`{continue}` statements. The former performs an early exit from the loop while
+the latter skips ahead to the next iteration of the loop.
+
+```example
+#for letter in "abc nope" {
+ if letter == " " {
+ break
+ }
+
+ letter
+}
+```
+
+The body of a loop can be a code or content block:
+
+- `{for .. in collection {..}}`
+- `{for .. in collection [..]}`
+- `{while condition {..}}`
+- `{while condition [..]}`
+
+## Fields
+You can use _dot notation_ to access fields on a value. For values of type
+[`content`], you can also use the [`fields`]($content.fields) function to list
+the fields.
+
+The value in question can be either:
+- a [dictionary] that has the specified key,
+- a [symbol] that has the specified modifier,
+- a [module] containing the specified definition,
+- [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 it = [= Heading]
+#it.body \
+#it.depth \
+#it.fields()
+
+#let dict = (greet: "Hello")
+#dict.greet \
+#emoji.face
+
+```
+
+## Methods
+A _method call_ is a convenient way to call a function that is scoped to a
+value's [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 its scoped functions. You cannot currently define your own
+methods.
+
+```example
+#let values = (1, 2, 3, 4)
+#values.pop() \
+#values.len() \
+
+#("a, b, c"
+ .split(", ")
+ .join[ --- ])
+
+#"abc".len() is the same as
+#str.len("abc")
+```
+
+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
+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].
+
+- **Import:** `{import "bar.typ"}` \
+ Evaluates the file at the path `bar.typ` and inserts the resulting [module]
+ into the current scope as `bar` (filename without extension). You can use the
+ `as` keyword to rename the imported module: `{import "bar.typ" as baz}`. You
+ can import nested items using dot notation: `{import "bar.typ": baz.a}`.
+
+- **Import items:** `{import "bar.typ": a, b}` \
+ Evaluates the file at the path `bar.typ`, extracts the values of the variables
+ `a` and `b` (that need to be defined in `bar.typ`, e.g. through `{let}`
+ bindings) and defines them in the current file. Replacing `a, b` with `*`
+ loads all variables defined in a module. You can use the `as` keyword to
+ rename the individual items: `{import "bar.typ": a as one, b as two}`
+
+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
+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.
+
+```example
+>>> #let add(x, y) = x + y
+<<< #import "@preview/example:0.1.0": add
+#add(2, 7)
+```
+
+The `preview` namespace contains packages shared by the community. You can find
+all available community packages on [Typst Universe]($universe).
+
+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
+The following table lists all available unary and binary operators with effect,
+arity (unary, binary) and precedence level (higher binds stronger). Some
+operations, such as [modulus]($calc.rem-euclid), do not have a special syntax
+and can be achieved using functions from the
+[`calc`]($category/foundations/calc) module.
+
+| Operator | Effect | Arity | Precedence |
+|:----------:|---------------------------------|:------:|:----------:|
+| `{-}` | Negation | Unary | 7 |
+| `{+}` | No effect (exists for symmetry) | Unary | 7 |
+| `{*}` | Multiplication | Binary | 6 |
+| `{/}` | Division | Binary | 6 |
+| `{+}` | Addition | Binary | 5 |
+| `{-}` | Subtraction | Binary | 5 |
+| `{==}` | Check equality | Binary | 4 |
+| `{!=}` | Check inequality | Binary | 4 |
+| `{<}` | Check less-than | Binary | 4 |
+| `{<=}` | Check less-than or equal | Binary | 4 |
+| `{>}` | Check greater-than | Binary | 4 |
+| `{>=}` | Check greater-than or equal | Binary | 4 |
+| `{in}` | Check if in collection | Binary | 4 |
+| `{not in}` | Check if not in collection | Binary | 4 |
+| `{not}` | Logical "not" | Unary | 3 |
+| `{and}` | Short-circuiting logical "and" | Binary | 3 |
+| `{or}` | Short-circuiting logical "or" | Binary | 2 |
+| `{=}` | Assignment | Binary | 1 |
+| `{+=}` | Add-Assignment | Binary | 1 |
+| `{-=}` | Subtraction-Assignment | Binary | 1 |
+| `{*=}` | Multiplication-Assignment | Binary | 1 |
+| `{/=}` | Division-Assignment | Binary | 1 |
+
+[semver]: https://semver.org/
diff --git a/sources/docs/reference/language/styling.md b/sources/docs/reference/language/styling.md
new file mode 100644
index 0000000000000000000000000000000000000000..b0b7ab7112e3583eb8f237e03e9f632657f112bb
--- /dev/null
+++ b/sources/docs/reference/language/styling.md
@@ -0,0 +1,145 @@
+---
+description: All concepts needed to style your document with Typst.
+---
+
+# Styling
+Typst includes a flexible styling system that automatically applies styling of
+your choice to your document. With _set rules,_ you can configure basic
+properties of elements. This way, you create most common styles. However, there
+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
+With set rules, you can customize the appearance of elements. They are written
+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.")
+#set text(
+ font: "New Computer Modern"
+)
+
+= Introduction
+With set rules, you can style
+your document.
+```
+
+A top level set rule stays in effect until the end of the file. When nested
+inside of a block, it is only in effect until the end of that block. With a
+block, you can thus restrict the effect of a rule to a particular segment of
+your document. Below, we use a content block to scope the list styling to one
+particular list.
+
+```example
+This list is affected: #[
+ #set list(marker: [--])
+ - Dash
+]
+
+This one is not:
+- Bullet
+```
+
+Sometimes, you'll want to apply a set rule conditionally. For this, you can use
+a _set-if_ rule.
+
+```example
+#let task(body, critical: false) = {
+ set text(red) if critical
+ [- #body]
+}
+
+#task(critical: true)[Food today?]
+#task(critical: false)[Work deadline]
+```
+
+## 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], 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)
+
+= This is navy-blue
+But this stays black.
+```
+
+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]. This function
+receives the element in question and can return arbitrary content. The available
+[fields]($scripting/#fields) on the element passed to the function again match
+the parameters of the respective element function. Below, we define a show rule
+that formats headings for a fantasy encyclopedia.
+
+```example
+#set heading(numbering: "(I)")
+#show heading: it => [
+ #set align(center)
+ #set text(font: "Inria Serif")
+ \~ #emph(it.body)
+ #counter(heading).display(
+ it.numbering
+ ) \~
+]
+
+= Dragon
+With a base health of 15, the
+dragon is the most powerful
+creature.
+
+= Manticore
+While less powerful than the
+dragon, the manticore gets
+extra style points.
+```
+
+Like set rules, show rules are in effect until the end of the current block or
+file.
+
+Instead of a function, the right-hand side of a show rule can also take a
+literal string or content block that should be directly substituted for the
+element. And apart from a function, the left-hand side of a show rule can also
+take a number of other _selectors_ that define what to apply the transformation
+to:
+
+- **Everything:** `{show: rest => ..}` \
+ Transform everything after the show rule. This is useful to apply a more
+ complex layout to your whole document without wrapping everything in a giant
+ function call.
+
+- **Text:** `{show "Text": ..}` \
+ Style, transform or replace text.
+
+- **Regex:** `{show regex("\w+"): ..}` \
+ Select and transform text with a regular expression for even more flexibility.
+ 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 : ..}` \
+ Select and transform elements that have the specified label. See the
+ documentation of the [`label` type]($label) for more details.
+
+```example
+#show "Project": smallcaps
+#show "badly": "great"
+
+We started Project in 2019
+and are still working on it.
+Project is progressing badly.
+```
diff --git a/sources/docs/reference/language/syntax.md b/sources/docs/reference/language/syntax.md
new file mode 100644
index 0000000000000000000000000000000000000000..fdc4d154aacfe70829f0b2d9cbd678c2a5aa87d7
--- /dev/null
+++ b/sources/docs/reference/language/syntax.md
@@ -0,0 +1,215 @@
+---
+description: |
+ A compact reference for Typst's syntax. Learn more about the language within
+ markup, math, and code mode.
+---
+
+# Syntax
+Typst is a markup language. This means that you can use simple syntax to
+accomplish common layout tasks. The lightweight markup syntax is complemented by
+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.
+
+## Modes
+Typst has three syntactical modes: Markup, math, and code. Markup mode is the
+default in a Typst document, math mode lets you write mathematical formulas, and
+code mode lets you use Typst's scripting features.
+
+You can switch to a specific mode at any point by referring to the following
+table:
+
+| New mode | Syntax | Example |
+|----------|---------------------------------|---------------------------------|
+| Code | Prefix the code with `#` | `[Number: #(1 + 2)]` |
+| Math | Surround equation with `[$..$]` | `[$-x$ is the opposite of $x$]` |
+| Markup | Surround markup with `[[..]]` | `{let name = [*Typst!*]}` |
+
+Once you have entered code mode with `#`, you don't need to use further hashes
+unless you switched back to markup or math mode in between.
+
+## 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
+more about their syntax and usage.
+
+| Name | Example | See |
+| ------------------ | ---------------------------- | ------------------------ |
+| Paragraph break | Blank line | [`parbreak`] |
+| Strong emphasis | `[*strong*]` | [`strong`] |
+| Emphasis | `[_emphasis_]` | [`emph`] |
+| Raw text | ``[`print(1)`]`` | [`raw`] |
+| Link | `[https://typst.app/]` | [`link`] |
+| Label | `[]` | [`label`] |
+| Reference | `[@intro]` | [`ref`] |
+| Heading | `[= Heading]` | [`heading`] |
+| Bullet list | `[- item]` | [`list`] |
+| Numbered list | `[+ item]` | [`enum`] |
+| Term list | `[/ Term: description]` | [`terms`] |
+| Math | `[$x^2$]` | [Math]($category/math) |
+| Line break | `[\]` | [`linebreak`] |
+| Smart quote | `['single' or "double"]` | [`smartquote`] |
+| Symbol shorthand | `[~]`, `[---]` | [Symbols]($category/symbols/sym) |
+| Code expression | `[#rect(width: 1cm)]` | [Scripting]($scripting/#expressions) |
+| Character escape | `[Tweet at us \#ad]` | [Below](#escapes) |
+| Comment | `[/* block */]`, `[// line]` | [Below](#comments) |
+
+## Math mode { #math }
+Math mode is a special markup mode that is used to typeset mathematical
+formulas. It is entered by wrapping an equation in `[$]` characters. This works
+both in markup and code. The equation will be typeset into its own block if it
+starts and ends with at least one space (e.g. `[$ x^2 $]`). Inline math can be
+produced by omitting the whitespace (e.g. `[$x^2$]`). An overview over the
+syntax specific to math mode follows:
+
+| Name | Example | See |
+| ---------------------- | ------------------------ | ------------------------ |
+| Inline math | `[$x^2$]` | [Math]($category/math) |
+| 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`]($math.frac) |
+| Line break | `[$x \ y$]` | [`linebreak`] |
+| Alignment point | `[$x &= 2 \ &= 3$]` | [Math]($category/math) |
+| Variable access | `[$#x$, $pi$]` | [Math]($category/math) |
+| Field access | `[$arrow.r.long$]` | [Scripting]($scripting/#fields) |
+| Implied multiplication | `[$x y$]` | [Math]($category/math) |
+| Symbol shorthand | `[$->$]`, `[$!=$]` | [Symbols]($category/symbols/sym) |
+| Text/string in math | `[$a "is natural"$]` | [Math]($category/math) |
+| Math function call | `[$floor(x)$]` | [Math]($category/math) |
+| Code expression | `[$#rect(width: 1cm)$]` | [Scripting]($scripting/#expressions) |
+| Character escape | `[$x\^2$]` | [Below](#escapes) |
+| Comment | `[$/* comment */$]` | [Below](#comments) |
+
+## Code mode { #code }
+Within code blocks and expressions, new expressions can start without a leading
+`#` character. Many syntactic elements are specific to expressions. Below is
+a table listing all syntax that is available in code mode:
+
+| Name | Example | See |
+| ------------------------ | ----------------------------- | ---------------------------------- |
+| None | `{none}` | [`none`] |
+| Auto | `{auto}` | [`auto`] |
+| Boolean | `{false}`, `{true}` | [`bool`] |
+| Integer | `{10}`, `{0xff}` | [`int`] |
+| Floating-point number | `{3.14}`, `{1e5}` | [`float`] |
+| Length | `{2pt}`, `{3mm}`, `{1em}`, .. | [`length`] |
+| Angle | `{90deg}`, `{1rad}` | [`angle`] |
+| Fraction | `{2fr}` | [`fraction`] |
+| Ratio | `{50%}` | [`ratio`] |
+| String | `{"hello"}` | [`str`] |
+| Label | `{}` | [`label`] |
+| Math | `[$x^2$]` | [Math]($category/math) |
+| Raw text | ``[`print(1)`]`` | [`raw`] |
+| Variable access | `{x}` | [Scripting]($scripting/#blocks) |
+| 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]($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]($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]($function) |
+| Set rule | `{set text(14pt)}` | [Styling]($styling/#set-rules) |
+| Set-if rule | `{set text(..) if .. }` | [Styling]($styling/#set-rules) |
+| Show-set rule | `{show heading: set block(..)}` | [Styling]($styling/#show-rules) |
+| Show rule with function | `{show raw: it => {..}}` | [Styling]($styling/#show-rules) |
+| Show-everything rule | `{show: template}` | [Styling]($styling/#show-rules) |
+| Context expression | `{context text.lang}` | [Context]($context) |
+| Conditional | `{if x == 1 {..} else {..}}` | [Scripting]($scripting/#conditionals) |
+| 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]($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 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
+
+We show with $p < 0.05$
+that the difference is
+significant.
+```
+
+Comments can also be wrapped between `/*` and `*/`. In this case, the comment
+can span over multiple lines:
+```example
+Our study design is as follows:
+/* Somebody write this up:
+ - 1000 participants.
+ - 2x2 data design. */
+```
+
+## 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]($str).
+
+```example
+I got an ice cream for
+\$1.50! \u{1f600}
+```
+
+## Paths
+Typst has various features that require a file path to reference external
+resources such as images, Typst files, or data files. Paths are represented as
+[strings]($str). There are two kinds of paths: Relative and absolute.
+
+- A **relative path** searches from the location of the Typst file where the
+ feature is invoked. It is the default:
+ ```typ
+ #image("images/logo.png")
+ ```
+
+- An **absolute path** searches from the _root_ of the project. It starts with a
+ leading `/`:
+ ```typ
+ #image("/assets/logo.png")
+ ```
+
+### Project root
+By default, the project root is the parent directory of the main Typst file.
+For security reasons, you cannot read any files outside of the root directory.
+
+If you want to set a specific folder as the root of your project, you can use
+the CLI's `--root` flag. Make sure that the main file is contained in the
+folder's subtree!
+```bash
+typst compile --root .. file.typ
+```
+
+In the web app, the project itself is the root directory. You can always read
+all files within it, no matter which one is previewed (via the eye toggle next
+to each Typst file in the file panel).
+
+### Paths and packages
+A package can only load files from its own directory. Within it, absolute paths
+point to the package root, rather than the project root. For this reason, it
+cannot directly load files from the project directory. If a package needs
+resources from the project (such as a logo image), you must pass the already
+loaded image, e.g. as a named parameter `{logo: image("mylogo.svg")}`. Note that
+you can then still customize the image's appearance with a set rule within the
+package.
+
+In the future, paths might become a
+[distinct type from strings](https://github.com/typst/typst/issues/971), so that
+they can retain knowledge of where they were constructed. This way, resources
+could be loaded from a different root.
diff --git a/sources/docs/reference/library/data-loading.md b/sources/docs/reference/library/data-loading.md
new file mode 100644
index 0000000000000000000000000000000000000000..659a8cccc4aaba19bf5c9a336ae7f0e0e1c7ef10
--- /dev/null
+++ b/sources/docs/reference/library/data-loading.md
@@ -0,0 +1,4 @@
+Data loading from external files.
+
+These functions help you with loading and embedding data, for example from the
+results of an experiment.
diff --git a/sources/docs/reference/library/foundations.md b/sources/docs/reference/library/foundations.md
new file mode 100644
index 0000000000000000000000000000000000000000..738c3789db4f2a89818755702ff00c20fa597bff
--- /dev/null
+++ b/sources/docs/reference/library/foundations.md
@@ -0,0 +1,4 @@
+Foundational types and functions.
+
+Here, you'll find documentation for basic data types like [integers]($int) and
+[strings]($str) as well as details about core computational functions.
diff --git a/sources/docs/reference/library/introspection.md b/sources/docs/reference/library/introspection.md
new file mode 100644
index 0000000000000000000000000000000000000000..f48a9937c73014709d0ab994eb9f674715d4ad11
--- /dev/null
+++ b/sources/docs/reference/library/introspection.md
@@ -0,0 +1,10 @@
+Interactions between document parts.
+
+This category is home to Typst's introspection capabilities: With the `counter`
+function, you can access and manipulate page, section, figure, and equation
+counters or create custom ones. Meanwhile, the `query` function lets you search
+for elements in the document to construct things like a list of figures or
+headers which show the current chapter title.
+
+Most of the functions are _contextual._ It is recommended to read the chapter on
+[context] before continuing here.
diff --git a/sources/docs/reference/library/layout.md b/sources/docs/reference/library/layout.md
new file mode 100644
index 0000000000000000000000000000000000000000..450058d4ce08bad24de7ad75c12fd025d5f5177d
--- /dev/null
+++ b/sources/docs/reference/library/layout.md
@@ -0,0 +1,3 @@
+Arranging elements on the page in different ways.
+
+By combining layout functions, you can create complex and automatic layouts.
diff --git a/sources/docs/reference/library/math.md b/sources/docs/reference/library/math.md
new file mode 100644
index 0000000000000000000000000000000000000000..61f2bb58fd7b775c49f8366f753b529c8fc83424
--- /dev/null
+++ b/sources/docs/reference/library/math.md
@@ -0,0 +1,101 @@
+Typst has special [syntax]($syntax/#math) and library functions to typeset
+mathematical formulas. Math formulas can be displayed inline with text or as
+separate blocks. They will be typeset into their own block if they start and end
+with at least one space (e.g. `[$ x^2 $]`).
+
+# Variables
+In math, single letters are always displayed as is. Multiple letters, however,
+are interpreted as variables and functions. To display multiple letters
+verbatim, you can place them into quotes and to access single letter variables,
+you can use the [hash syntax]($scripting/#expressions).
+
+```example
+$ A = pi r^2 $
+$ "area" = pi dot "radius"^2 $
+$ cal(A) :=
+ { x in RR | x "is natural" } $
+#let x = 5
+$ #x < 17 $
+```
+
+# Symbols
+Math mode makes a wide selection of [symbols]($category/symbols/sym) like `pi`,
+`dot`, or `RR` available. Many mathematical symbols are available in different
+variants. You can select between different variants by applying
+[modifiers]($symbol) to the symbol. Typst further recognizes a number of
+shorthand sequences like `=>` that approximate a symbol. When such a shorthand
+exists, the symbol's documentation lists it.
+
+```example
+$ x < y => x gt.eq.not y $
+```
+
+# Line Breaks
+Formulas can also contain line breaks. Each line can contain one or multiple
+_alignment points_ (`&`) which are then aligned.
+
+```example
+$ sum_(k=0)^n k
+ &= 1 + ... + n \
+ &= (n(n+1)) / 2 $
+```
+
+# Function calls
+Math mode supports special function calls without the hash prefix. In these
+"math calls", the argument list works a little differently than in code:
+
+- Within them, Typst is still in "math mode". Thus, you can write math directly
+ into them, but need to use hash syntax to pass code expressions (except for
+ strings, which are available in the math syntax).
+- They support positional and named arguments, as well as argument spreading.
+- They don't support trailing content blocks.
+- They provide additional syntax for 2-dimensional argument lists. The semicolon
+ (`;`) merges preceding arguments separated by commas into an array argument.
+
+```example
+$ frac(a^2, 2) $
+$ vec(1, 2, delim: "[") $
+$ mat(1, 2; 3, 4) $
+$ mat(..#range(1, 5).chunks(2)) $
+$ lim_x =
+ op("lim", limits: #true)_x $
+```
+
+To write a verbatim comma or semicolon in a math call, escape it with a
+backslash. The colon on the other hand is only recognized in a special way if
+directly preceded by an identifier, so to display it verbatim in those cases,
+you can just insert a space before it.
+
+Functions calls preceded by a hash are normal code function calls and not
+affected by these rules.
+
+# Alignment
+When equations include multiple _alignment points_ (`&`), this creates blocks of
+alternatingly right- and left-aligned columns. In the example below, the
+expression `(3x + y) / 7` is right-aligned and `= 9` is left-aligned. The word
+"given" is also left-aligned because `&&` creates two alignment points in a row,
+alternating the alignment twice. `& &` and `&&` behave exactly the same way.
+Meanwhile, "multiply by 7" is right-aligned because just one `&` precedes it.
+Each alignment point simply alternates between right-aligned/left-aligned.
+
+```example
+$ (3x + y) / 7 &= 9 && "given" \
+ 3x + y &= 63 & "multiply by 7" \
+ 3x &= 63 - y && "subtract y" \
+ x &= 21 - y/3 & "divide by 3" $
+```
+
+# Math fonts
+You can set the math font by with a [show-set rule]($styling/#show-rules) as
+demonstrated below. Note that only special OpenType math fonts are suitable for
+typesetting maths.
+
+```example
+#show math.equation: set text(font: "Fira Math")
+$ sum_(i in NN) 1 + i $
+```
+
+# Math module
+All math functions are part of the `math` [module]($scripting/#modules), which
+is available by default in equations. Outside of equations, they can be accessed
+with the `math.` prefix.
diff --git a/sources/docs/reference/library/model.md b/sources/docs/reference/library/model.md
new file mode 100644
index 0000000000000000000000000000000000000000..e433ed53b24cf155cf9c61d17927b4d196a4fa66
--- /dev/null
+++ b/sources/docs/reference/library/model.md
@@ -0,0 +1,5 @@
+Document structuring.
+
+Here, you can find functions to structure your document and interact with that
+structure. This includes section headings, figures, bibliography management,
+cross-referencing and more.
diff --git a/sources/docs/reference/library/symbols.md b/sources/docs/reference/library/symbols.md
new file mode 100644
index 0000000000000000000000000000000000000000..2e6f48cdb1e22e216ee6a47aaccd40bb7cca01fd
--- /dev/null
+++ b/sources/docs/reference/library/symbols.md
@@ -0,0 +1,5 @@
+These two modules give names to symbols and emoji to make them easy to insert
+with a normal keyboard. Alternatively, you can also always directly enter
+Unicode symbols into your text and formulas. In addition to the symbols listed
+below, math mode defines `dif` and `Dif`. These are not normal symbol values
+because they also affect spacing and font style.
diff --git a/sources/docs/reference/library/text.md b/sources/docs/reference/library/text.md
new file mode 100644
index 0000000000000000000000000000000000000000..239c0b265dfe73a4e77f63d7d39b5c8cdfeaf456
--- /dev/null
+++ b/sources/docs/reference/library/text.md
@@ -0,0 +1,3 @@
+Text styling.
+
+The [text function]($text) is of particular interest.
diff --git a/sources/docs/reference/library/visualize.md b/sources/docs/reference/library/visualize.md
new file mode 100644
index 0000000000000000000000000000000000000000..9259401f853e441362aaf59d4abc0e4d64f9b5c1
--- /dev/null
+++ b/sources/docs/reference/library/visualize.md
@@ -0,0 +1,5 @@
+Drawing and data visualization.
+
+If you want to create more advanced drawings or plots, also have a look at the
+[CetZ](https://github.com/johannes-wolf/cetz) package as well as more
+specialized [packages]($universe) for your use case.
diff --git a/sources/docs/reference/welcome.md b/sources/docs/reference/welcome.md
new file mode 100644
index 0000000000000000000000000000000000000000..1154cc5205cf371e3b14d21a8b468b3bb934cfd0
--- /dev/null
+++ b/sources/docs/reference/welcome.md
@@ -0,0 +1,28 @@
+---
+description: |
+ The Typst reference is a systematic and comprehensive guide to the Typst
+ typesetting language.
+---
+
+# Reference
+This reference documentation is a comprehensive guide to all of Typst's syntax,
+concepts, types, and functions. If you are completely new to Typst, we recommend
+starting with the [tutorial] and then coming back to the reference to learn more
+about Typst's features as you need them.
+
+## 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)
+
+## 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
+it.
+
+The final part of the reference explains all functions that are used within
+Typst's code mode to manipulate and transform data. Just as in the previous
+part, each function is documented with a description of its purpose, a list of
+its parameters, and examples of how to use it.
diff --git a/sources/docs/tutorial/1-writing.md b/sources/docs/tutorial/1-writing.md
new file mode 100644
index 0000000000000000000000000000000000000000..acc257830fad48598cafc6760a81e6f972653cba
--- /dev/null
+++ b/sources/docs/tutorial/1-writing.md
@@ -0,0 +1,308 @@
+---
+description: Typst's tutorial.
+---
+
+# Writing in Typst
+Let's get started! Suppose you got assigned to write a technical report for
+university. It will contain prose, maths, headings, and figures. To get started,
+you create a new project on the Typst app. You'll be taken to the editor where
+you see two panels: A source panel where you compose your document and a
+preview panel where you see the rendered document.
+
+
+
+You already have a good angle for your report in mind. So let's start by writing
+the introduction. Enter some text in the editor panel. You'll notice that the
+text immediately appears on the previewed page.
+
+```example
+In this report, we will explore the
+various factors that influence fluid
+dynamics in glaciers and how they
+contribute to the formation and
+behaviour of these natural structures.
+```
+
+_Throughout this tutorial, we'll show code examples like this one. Just like in the app, the first panel contains markup and the second panel shows a preview. We shrunk the page to fit the examples so you can see what's going on._
+
+The next step is to add a heading and emphasize some text. Typst uses simple
+markup for the most common formatting tasks. To add a heading, enter the `=`
+character and to emphasize some text with italics, enclose it in
+`[_underscores_]`.
+
+```example
+= Introduction
+In this report, we will explore the
+various factors that influence _fluid
+dynamics_ in glaciers and how they
+contribute to the formation and
+behaviour of these natural structures.
+```
+
+That was easy! To add a new paragraph, just add a blank line in between two
+lines of text. If that paragraph needs a subheading, produce it by typing `==`
+instead of `=`. The number of `=` characters determines the nesting level of the
+heading.
+
+Now we want to list a few of the circumstances that influence glacier dynamics.
+To do that, we use a numbered list. For each item of the list, we type a `+`
+character at the beginning of the line. Typst will automatically number the
+items.
+
+```example
++ The climate
++ The topography
++ The geology
+```
+
+If we wanted to add a bulleted list, we would use the `-` character instead of
+the `+` character. We can also nest lists: For example, we can add a sub-list to
+the first item of the list above by indenting it.
+
+```example
++ The climate
+ - Temperature
+ - Precipitation
++ The topography
++ The geology
+```
+
+## Adding a figure { #figure }
+You think that your report would benefit from a figure. Let's add one. Typst
+supports images in the formats PNG, JPEG, GIF, and SVG. To add an image file to
+your project, first open the _file panel_ by clicking the box icon in the left
+sidebar. Here, you can see a list of all files in your project. Currently, there
+is only one: The main Typst file you are writing in. To upload another file,
+click the button with the arrow in the top-right corner. This opens the upload
+dialog, in which you can pick files to upload from your computer. Select an
+image file for your report.
+
+
+
+We have seen before that specific symbols (called _markup_) have specific
+meaning in Typst. We can use `=`, `-`, `+`, and `_` to create headings, lists
+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`] function.
+
+```example
+#image("glacier.jpg")
+```
+
+In general, a function produces some output for a set of _arguments_. When you
+_call_ a function within markup, you provide the arguments and Typst inserts the
+result (the function's _return value_) into the document. In our case, the
+`image` function takes one argument: The path to the image file. To call a
+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]($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
+therefore specified as a `name: value` pair. If there are multiple arguments,
+they are separated by commas, so we first need to put a comma behind the path.
+
+```example
+#image("glacier.jpg", width: 70%)
+```
+
+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]
+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 now have to remove the hash before the image function call.
+The hash is only needed directly in markup (to disambiguate text from function
+calls).
+
+The caption consists of arbitrary markup. To give markup to a function, we
+enclose it in square brackets. This construct is called a _content block._
+
+```example
+#figure(
+ image("glacier.jpg", width: 70%),
+ caption: [
+ _Glaciers_ form an important part
+ of the earth's climate system.
+ ],
+)
+```
+
+You continue to write your report and now want to reference the figure. To do
+that, first attach a label to figure. A label uniquely identifies an element in
+your document. Add one after the figure by enclosing some name in angle
+brackets. You can then reference the figure in your text by writing an `[@]`
+symbol followed by that name. Headings and equations can also be labelled to
+make them referenceable.
+
+```example
+Glaciers as the one shown in
+@glaciers will cease to exist if
+we don't take action soon!
+
+#figure(
+ image("glacier.jpg", width: 70%),
+ caption: [
+ _Glaciers_ form an important part
+ of the earth's climate system.
+ ],
+)
+```
+
+
+
+So far, we've passed content blocks (markup in square brackets) and strings
+(text in double quotes) to our functions. Both seem to contain text. What's the
+difference?
+
+A content block can contain text, but also any other kind of markup, function
+calls, and more, whereas a string is really just a _sequence of characters_ and
+nothing else.
+
+For example, the image function expects a path to an image file.
+It would not make sense to pass, e.g., a paragraph of text or another image as
+the image's path parameter. That's why only strings are allowed here.
+In contrast, strings work wherever content is expected because text is a
+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`] 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),
+but for compatibility you can also use BibLaTeX files. As your classmate has
+already done a literature survey and sent you a `.bib` file, you'll use that
+one. Upload the file through the file panel to access it in Typst.
+
+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]($bibliography.style) for more details.
+
+```example
+= Methods
+We follow the glacier melting models
+established in @glacier-melt.
+
+#bibliography("works.bib")
+```
+
+## 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
+to let Typst know it should expect a mathematical expression:
+
+```example
+The equation $Q = rho A v + C$
+defines the glacial flow rate.
+```
+
+The equation is typeset inline, on the same line as the surrounding text. If you
+want to have it on its own line instead, you should insert a single space at its
+start and end:
+
+```example
+The flow rate of a glacier is
+defined by the following equation:
+
+$ Q = rho A v + C $
+```
+
+We can see that Typst displayed the single letters `Q`, `A`, `v`, and `C` as-is,
+while it translated `rho` into a Greek letter. Math mode will always show single
+letters verbatim. Multiple letters, however, are interpreted as symbols,
+variables, or function names. To imply a multiplication between single letters,
+put spaces between them.
+
+If you want to have a variable that consists of multiple letters, you can
+enclose it in quotes:
+
+```example
+The flow rate of a glacier is given
+by the following equation:
+
+$ Q = rho A v + "time offset" $
+```
+
+You'll also need a sum formula in your paper. We can use the `sum` symbol and
+then specify the range of the summation in sub- and superscripts:
+
+```example
+Total displaced soil by glacial flow:
+
+$ 7.32 beta +
+ sum_(i=0)^nabla Q_i / 2 $
+```
+
+To add a subscript to a symbol or variable, type a `_` character and then the
+subscript. Similarly, use the `^` character for a superscript. If your
+sub- or superscript consists of multiple things, you must enclose them
+in round parentheses.
+
+The above example also showed us how to insert fractions: Simply put a `/`
+character between the numerator and the denominator and Typst will automatically
+turn it into a fraction. Parentheses are smartly resolved, so you can enter your
+expression as you would into a calculator and Typst will replace parenthesized
+sub-expressions with the appropriate notation.
+
+```example
+Total displaced soil by glacial flow:
+
+$ 7.32 beta +
+ sum_(i=0)^nabla
+ (Q_i (a_i - epsilon)) / 2 $
+```
+
+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`]($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`]($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
+name:
+
+```example
+$ a arrow.squiggly b $
+```
+
+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
+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]($table), [shapes]($category/visualize), and [code blocks]($raw). You
+can peruse the [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
+think the report could look a bit less plain. In the next section, we'll learn
+how to customize the look of our document.
diff --git a/sources/docs/tutorial/2-formatting.md b/sources/docs/tutorial/2-formatting.md
new file mode 100644
index 0000000000000000000000000000000000000000..a8c72cefe02ed1d01d320fb7a6a61651c702f3c6
--- /dev/null
+++ b/sources/docs/tutorial/2-formatting.md
@@ -0,0 +1,280 @@
+---
+description: Typst's tutorial.
+---
+
+# Formatting
+So far, you have written a report with some text, a few equations and images.
+However, it still looks very plain. Your teaching assistant does not yet know
+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
+As we have seen in the previous chapter, Typst has functions that _insert_
+content (e.g. the [`image`] function) and others that _manipulate_ content that
+they received as arguments (e.g. the [`align`] function). The first impulse you
+might have when you want, for example, to change the font, could be to look
+for a function that does that and wrap the complete document in it.
+
+```example
+#text(font: "New Computer Modern")[
+ = Background
+ In the case of glaciers, fluid
+ dynamics principles can be used
+ to understand how the movement
+ and behaviour of the ice is
+ influenced by factors such as
+ temperature, pressure, and the
+ presence of other fluids (such as
+ water).
+]
+```
+
+Wait, shouldn't all arguments of a function be specified within parentheses? Why
+is there a second set of square brackets with content _after_ the parentheses?
+The answer is that, as passing content to a function is such a common thing to
+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. With the [`text`] function, we can adjust the font
+for all text 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
+rule by entering the `{set}` keyword, followed by the name of the function whose
+properties you want to set, and a list of arguments in parentheses.
+
+```example
+#set text(
+ font: "New Computer Modern"
+)
+
+= Background
+In the case of glaciers, fluid
+dynamics principles can be used
+to understand how the movement
+and behaviour of the ice is
+influenced by factors such as
+temperature, pressure, and the
+presence of other fluids (such as
+water).
+```
+
+
+
+Want to know in more technical terms what is happening here?
+
+Set rules can be conceptualized as setting default values
+for some of the parameters of a function for all future
+uses of that function.
+
+
+## The autocomplete panel { #autocomplete }
+If you followed along and tried a few things in the app, you might have noticed
+that always after you enter a `#` character, a panel pops up to show you the
+available functions, and, within an argument list, the available parameters.
+That's the autocomplete panel. It can be very useful while you are writing your
+document: You can apply its suggestions by hitting the Return key or navigate to
+the desired completion with the arrow keys. The panel can be dismissed by
+hitting the Escape key and opened again by typing `#` or hitting
+Ctrl + Space. Use the autocomplete panel to discover the
+right arguments for functions. Most suggestions come with a small description of
+what they do.
+
+
+
+## Set up the page { #page-setup }
+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`] to set font family, size, color, and other properties of text
+- [`page`] to set the page size, margins, headers, enable columns, and footers
+- [`par`] to justify paragraphs, set line spacing, and more
+- [`heading`] to set the appearance of headings and enable numbering
+- [`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
+do it with. The function reference pages indicate which parameters are settable.
+
+Let's add a few more styles to our document. We want larger margins and a serif
+font. For the purposes of the example, we'll also set another page size.
+
+```example
+#set page(
+ paper: "a6",
+ margin: (x: 1.8cm, y: 1.5cm),
+)
+#set text(
+ font: "New Computer Modern",
+ size: 10pt
+)
+#set par(
+ justify: true,
+ leading: 0.52em,
+)
+
+= Introduction
+In this report, we will explore the
+various factors that influence fluid
+dynamics in glaciers and how they
+contribute to the formation and
+behaviour of these natural structures.
+
+>>> Glacier displacement is influenced
+>>> by a number of factors, including
+>>> + The climate
+>>> + The topography
+>>> + The geology
+>>>
+>>> This report will present a physical
+>>> model of glacier displacement and
+>>> dynamics, and will explore the
+>>> influence of these factors on the
+>>> movement of large bodies of ice.
+<<< ...
+
+#align(center + bottom)[
+ #image("glacier.jpg", width: 70%)
+
+ *Glaciers form an important
+ part of the earth's climate
+ system.*
+]
+```
+
+There are a few things of note here.
+
+First is the [`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`] 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] 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}`).
+
+Finally, we have bottom aligned our image by adding a vertical alignment to our
+center alignment. Vertical and horizontal alignments can be combined with the
+`{+}` operator to yield a 2D alignment.
+
+## 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`] function.
+
+```example
+>>> #set text(font: "New Computer Modern")
+#set heading(numbering: "1.")
+
+= Introduction
+#lorem(10)
+
+== Background
+#lorem(12)
+
+== Methods
+#lorem(15)
+```
+
+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]($numbering)
+for our headings:
+
+```example
+>>> #set text(font: "New Computer Modern")
+#set heading(numbering: "1.a")
+
+= Introduction
+#lorem(10)
+
+== Background
+#lorem(12)
+
+== Methods
+#lorem(15)
+```
+
+This example also uses the [`lorem`] function to generate some placeholder text.
+This function takes a number as an argument and generates that 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.
+
+
+## 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.
+
+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]($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.
+Show rules can be applied to instances of text, many functions, and even the
+whole document.
+
+```example
+#show "ArtosFlow": name => box[
+ #box(image(
+ "logo.svg",
+ height: 0.7em,
+ ))
+ #name
+]
+
+This report is embedded in the
+ArtosFlow project. ArtosFlow is a
+project of the Artos Institute.
+```
+
+There is a lot of new syntax in this example: We write the `{show}` keyword,
+followed by a string of text we want to show differently and a colon. Then, we
+write a function that takes the content that shall be shown as an argument.
+Here, we called that argument `name`. We can now use the `name` variable in the
+function's body to print the ArtosFlow name. Our show rule adds the logo image
+in front of the name and puts the result into a box to prevent linebreaks from
+occurring between logo and name. The image is also put inside of a box, so that
+it does not appear in its own paragraph.
+
+The calls to the first box function and the image function did not require a
+leading `#` because they were not embedded directly in markup. When Typst
+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
+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
+basic show rule to change how text appears throughout your document.
+
+You have handed in your report. Your supervisor was so happy with it that they
+want to adapt it into a conference paper! In the next section, we will learn how
+to format your document as a paper using more advanced show rules and functions.
diff --git a/sources/docs/tutorial/3-advanced.md b/sources/docs/tutorial/3-advanced.md
new file mode 100644
index 0000000000000000000000000000000000000000..b7f338db589a2fcaeb8f18047568f6798ad014c4
--- /dev/null
+++ b/sources/docs/tutorial/3-advanced.md
@@ -0,0 +1,546 @@
+---
+description: Typst's tutorial.
+---
+
+# Advanced Styling
+In the previous two chapters of this tutorial, you have learned how to write a
+document in Typst and how to change its formatting. The report you wrote
+throughout the last two chapters got a straight A and your supervisor wants to
+base a conference paper on it! The report will of course have to comply with the
+conference's style guide. Let's see how we can achieve that.
+
+Before we start, let's create a team, invite your supervisor and add them to the
+team. You can do this by going back to the app dashboard with the back icon in
+the top left corner of the editor. Then, choose the plus icon in the left
+toolbar and create a team. Finally, click on the new team and go to its settings
+by clicking 'manage team' next to the team name. Now you can invite your
+supervisor by email.
+
+
+
+Next, move your project into the team: Open it, going to its settings by
+choosing the gear icon in the left toolbar and selecting your new team from the
+owners dropdown. Don't forget to save your changes!
+
+Now, your supervisor can also edit the project and you can both see the changes
+in real time. You can join our [Discord server](https://discord.gg/2uDybryKPe)
+to find other users and try teams with them!
+
+## The conference guidelines { #guidelines }
+The layout guidelines are available on the conference website. Let's take a look
+at them:
+
+- The font should be an 11pt serif font
+- The title should be in 17pt and bold
+- The paper contains a single-column abstract and two-column main text
+- The abstract should be centered
+- The main text should be justified
+- First level section headings should be 13pt, centered, and rendered in small
+ capitals
+- Second level headings are run-ins, italicized and have the same size as the
+ body text
+- Finally, the pages should be US letter sized, numbered in the center of the
+ footer and the top right corner of each page should contain the title of the
+ paper
+
+We already know how to do many of these things, but for some of them, we'll need
+to learn some new tricks.
+
+## Writing the right set rules { #set-rules }
+Let's start by writing some set rules for the document.
+
+```example
+#set page(
+>>> margin: auto,
+ paper: "us-letter",
+ header: align(right)[
+ A fluid dynamic model for
+ glacier flow
+ ],
+ numbering: "1",
+)
+#set par(justify: true)
+#set text(
+ font: "Libertinus Serif",
+ size: 11pt,
+)
+
+#lorem(600)
+```
+
+You are already familiar with most of what is going on here. We set the text
+size to `{11pt}` and the font to Libertinus Serif. We also enable paragraph
+justification and set the page size to US letter.
+
+The `header` argument is new: With it, we can provide content to fill the top
+margin of every page. In the header, we specify our paper's title as requested
+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]($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
+function here to format things to our liking.
+
+## Creating a title and abstract { #title-and-abstract }
+Now, let's add a title and an abstract. We'll start with the title. We center
+align it and increase its font weight by enclosing it in `[*stars*]`.
+
+```example
+>>> #set page(width: 300pt, margin: 30pt)
+>>> #set text(font: "Libertinus Serif", 11pt)
+#align(center, text(17pt)[
+ *A fluid dynamic model
+ for glacier flow*
+])
+```
+
+This looks right. We used the `text` function to override the previous text
+set rule locally, increasing the size to 17pt for the function's argument. Let's
+also add the author list: Since we are writing this paper together with our
+supervisor, we'll add our own and their name.
+
+```example
+>>> #set page(width: 300pt, margin: 30pt)
+>>> #set text(font: "Libertinus Serif", 11pt)
+>>>
+>>> #align(center, text(17pt)[
+>>> *A fluid dynamic model
+>>> for glacier flow*
+>>> ])
+#grid(
+ columns: (1fr, 1fr),
+ align(center)[
+ Therese Tungsten \
+ Artos Institute \
+ #link("mailto:tung@artos.edu")
+ ],
+ align(center)[
+ Dr. John Doe \
+ Artos Institute \
+ #link("mailto:doe@artos.edu")
+ ]
+)
+```
+
+The two author blocks are laid out next to each other. We use the [`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]($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.
+
+```example:0,0,612,317.5
+>>> #set text(font: "Libertinus Serif", 11pt)
+>>> #set par(justify: true)
+>>> #set page(
+>>> "us-letter",
+>>> margin: auto,
+>>> header: align(right + horizon)[
+>>> A fluid dynamic model for
+>>> glacier flow
+>>> ],
+>>> numbering: "1",
+>>> )
+>>>
+>>> #align(center, text(17pt)[
+>>> *A fluid dynamic model
+>>> for glacier flow*
+>>> ])
+>>>
+>>> #grid(
+>>> columns: (1fr, 1fr),
+>>> align(center)[
+>>> Therese Tungsten \
+>>> Artos Institute \
+>>> #link("mailto:tung@artos.edu")
+>>> ],
+>>> align(center)[
+>>> Dr. John Doe \
+>>> Artos Institute \
+>>> #link("mailto:doe@artos.edu")
+>>> ]
+>>> )
+>>>
+<<< ...
+
+#align(center)[
+ #set par(justify: false)
+ *Abstract* \
+ #lorem(80)
+]
+>>> #lorem(600)
+```
+
+Well done! One notable thing is that we used a set rule within the content
+argument of `align` to turn off justification for the abstract. This does not
+affect the remainder of the document even though it was specified after the
+first set rule because content blocks _scope_ styling. Anything set within a
+content block will only affect the content within that block.
+
+Another tweak could be to save the paper title in a variable, so that we do not
+have to type it twice, for header and title. We can do that with the `{let}`
+keyword:
+
+```example:single
+#let title = [
+ A fluid dynamic model
+ for glacier flow
+]
+
+<<< ...
+
+>>> #set text(font: "Libertinus Serif", 11pt)
+>>> #set par(justify: true)
+#set page(
+>>> "us-letter",
+>>> margin: auto,
+ header: align(
+ right + horizon,
+ title
+ ),
+<<< ...
+>>> numbering: "1",
+)
+
+#align(center, text(17pt)[
+ *#title*
+])
+
+<<< ...
+
+>>> #grid(
+>>> columns: (1fr, 1fr),
+>>> align(center)[
+>>> Therese Tungsten \
+>>> Artos Institute \
+>>> #link("mailto:tung@artos.edu")
+>>> ],
+>>> align(center)[
+>>> Dr. John Doe \
+>>> Artos Institute \
+>>> #link("mailto:doe@artos.edu")
+>>> ]
+>>> )
+>>>
+>>> #align(center)[
+>>> #set par(justify: false)
+>>> *Abstract* \
+>>> #lorem(80)
+>>> ]
+>>>
+>>> #lorem(600)
+```
+
+After we bound the content to the `title` variable, we can use it in functions
+and also within markup (prefixed by `#`, like functions). This way, if we decide
+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. Fortunately, that's
+easy to do: We just need to amend our `page` set rule with the `columns`
+argument.
+
+By adding `{columns: 2}` to the argument list, we have wrapped the whole
+document in two columns. However, that would also affect the title and authors
+overview. To keep them spanning the whole page, we can wrap them in a function
+call to [`{place}`]($place). Place expects an alignment and the content it
+should place as positional arguments. Using the named `{scope}` argument, we can
+decide if the items should be placed relative to the current column or its
+parent (the page). There is one more thing to configure: If no other arguments
+are provided, `{place}` takes its content out of the flow of the document and
+positions it over the other content without affecting the layout of other
+content in its container:
+
+```example
+#place(
+ top + center,
+ rect(fill: black),
+)
+#lorem(30)
+```
+
+If we hadn't used `{place}` here, the square would be in its own line, but here
+it overlaps the few lines of text following it. Likewise, that text acts like as
+if there was no square. To change this behavior, we can pass the argument
+`{float: true}` to ensure that the space taken up by the placed item at the top
+or bottom of the page is not occupied by any other content.
+
+```example:single
+>>> #let title = [
+>>> A fluid dynamic model
+>>> for glacier flow
+>>> ]
+>>>
+>>> #set text(font: "Libertinus Serif", 11pt)
+>>> #set par(justify: true)
+>>>
+#set page(
+>>> margin: auto,
+ paper: "us-letter",
+ header: align(
+ right + horizon,
+ title
+ ),
+ numbering: "1",
+ columns: 2,
+)
+
+#place(
+ top + center,
+ float: true,
+ scope: "parent",
+ clearance: 2em,
+)[
+>>> #text(
+>>> 17pt,
+>>> weight: "bold",
+>>> title,
+>>> )
+>>>
+>>> #grid(
+>>> columns: (1fr, 1fr),
+>>> [
+>>> Therese Tungsten \
+>>> Artos Institute \
+>>> #link("mailto:tung@artos.edu")
+>>> ],
+>>> [
+>>> Dr. John Doe \
+>>> Artos Institute \
+>>> #link("mailto:doe@artos.edu")
+>>> ]
+>>> )
+<<< ...
+
+ #par(justify: false)[
+ *Abstract* \
+ #lorem(80)
+ ]
+]
+
+= Introduction
+#lorem(300)
+
+= Related Work
+#lorem(200)
+```
+
+In this example, we also used the `clearance` argument of the `{place}` function
+to provide the space between it and the body instead of using the [`{v}`]($v)
+function. We can also remove the explicit `{align(center, ..)}` calls around the
+various parts since they inherit the center alignment from the placement.
+
+Now there is only one thing left to do: Style our headings. We need to make them
+centered and use small capitals. Because the `heading` function does not offer
+a way to set any of that, we need to write our own heading show rule.
+
+```example:50,250,265,270
+>>> #let title = [
+>>> A fluid dynamic model
+>>> for glacier flow
+>>> ]
+>>>
+>>> #set text(font: "Libertinus Serif", 11pt)
+>>> #set par(justify: true)
+>>> #set page(
+>>> "us-letter",
+>>> margin: auto,
+>>> header: align(
+>>> right + horizon,
+>>> title
+>>> ),
+>>> numbering: "1",
+>>> columns: 2,
+>>> )
+#show heading: it => [
+ #set align(center)
+ #set text(13pt, weight: "regular")
+ #block(smallcaps(it.body))
+]
+
+<<< ...
+>>>
+>>> #place(
+>>> top + center,
+>>> float: true,
+>>> scope: "parent",
+>>> clearance: 2em,
+>>> )[
+>>> #text(
+>>> 17pt,
+>>> weight: "bold",
+>>> title,
+>>> )
+>>>
+>>> #grid(
+>>> columns: (1fr, 1fr),
+>>> [
+>>> Therese Tungsten \
+>>> Artos Institute \
+>>> #link("mailto:tung@artos.edu")
+>>> ],
+>>> [
+>>> Dr. John Doe \
+>>> Artos Institute \
+>>> #link("mailto:doe@artos.edu")
+>>> ]
+>>> )
+>>>
+>>> #par(justify: false)[
+>>> *Abstract* \
+>>> #lorem(80)
+>>> ]
+>>> ]
+>>>
+>>> = Introduction
+>>> #lorem(35)
+>>>
+>>> == Motivation
+>>> #lorem(45)
+```
+
+This looks great! We used a show rule that applies to all headings. We give it a
+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`] 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
+headers, but right now, they look indistinguishable from the section headings. We
+can fix that by using a `where` selector on our set rule: This is a
+[method]($scripting/#methods) we can call on headings (and other
+elements) that allows us to filter them by their level. We can use it to
+differentiate between section and subsection headings:
+
+```example:50,250,265,245
+>>> #let title = [
+>>> A fluid dynamic model
+>>> for glacier flow
+>>> ]
+>>>
+>>> #set text(font: "Libertinus Serif", 11pt)
+>>> #set par(justify: true)
+>>> #set page(
+>>> "us-letter",
+>>> margin: auto,
+>>> header: align(
+>>> right + horizon,
+>>> title
+>>> ),
+>>> numbering: "1",
+>>> columns: 2,
+>>> )
+>>>
+#show heading.where(
+ level: 1
+): it => block(width: 100%)[
+ #set align(center)
+ #set text(13pt, weight: "regular")
+ #smallcaps(it.body)
+]
+
+#show heading.where(
+ level: 2
+): it => text(
+ size: 11pt,
+ weight: "regular",
+ style: "italic",
+ it.body + [.],
+)
+>>>
+>>> #place(
+>>> top + center,
+>>> float: true,
+>>> scope: "parent",
+>>> clearance: 2em,
+>>> )[
+>>> #text(
+>>> 17pt,
+>>> weight: "bold",
+>>> title,
+>>> )
+>>>
+>>> #grid(
+>>> columns: (1fr, 1fr),
+>>> [
+>>> Therese Tungsten \
+>>> Artos Institute \
+>>> #link("mailto:tung@artos.edu")
+>>> ],
+>>> [
+>>> Dr. John Doe \
+>>> Artos Institute \
+>>> #link("mailto:doe@artos.edu")
+>>> ]
+>>> )
+>>>
+>>> #par(justify: false)[
+>>> *Abstract* \
+>>> #lorem(80)
+>>> ]
+>>> ]
+>>>
+>>> = Introduction
+>>> #lorem(35)
+>>>
+>>> == Motivation
+>>> #lorem(45)
+```
+
+This looks great! We wrote two show rules that each selectively apply to the
+first and second level headings. We used a `where` selector to filter the
+headings by their level. We then rendered the subsection headings as run-ins. We
+also automatically add a period to the end of the subsection headings.
+
+Let's review the conference's style guide:
+- The font should be an 11pt serif font ✓
+- The title should be in 17pt and bold ✓
+- The paper contains a single-column abstract and two-column main text ✓
+- The abstract should be centered ✓
+- The main text should be justified ✓
+- First level section headings should be centered, rendered in small caps and in
+ 13pt ✓
+- Second level headings are run-ins, italicized and have the same size as the
+ body text ✓
+- Finally, the pages should be US letter sized, numbered in the center and the
+ top right corner of each page should contain the title of the paper ✓
+
+We are now in compliance with all of these styles and can submit the paper to
+the conference! The finished paper looks like this:
+
+
+
+## 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`] 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
+the conference and are planning a project which you hope to publish at the same
+venue next year. You'll need to write a new paper using the same style guide
+though, so maybe now you want to create a time-saving template for you and your
+team?
+
+In the next section, we will learn how to create templates that can be reused in
+multiple documents. This is a more advanced topic, so feel free to come back
+to it later if you don't feel up to it right now.
diff --git a/sources/docs/tutorial/4-template.md b/sources/docs/tutorial/4-template.md
new file mode 100644
index 0000000000000000000000000000000000000000..7542cd6e48184e6836311ed5b4696a577b02e3cf
--- /dev/null
+++ b/sources/docs/tutorial/4-template.md
@@ -0,0 +1,406 @@
+---
+description: Typst's tutorial.
+---
+
+# Making a Template
+In the previous three chapters of this tutorial, you have learned how to write a
+document in Typst, apply basic styles, and customize its appearance in-depth to
+comply with a publisher's style guide. Because the paper you wrote in the
+previous chapter was a tremendous success, you have been asked to write a
+follow-up article for the same conference. This time, you want to take the style
+you created in the previous chapter and turn it into a reusable template. In
+this chapter you will learn how to create a template that you and your team can
+use with just one show rule. Let's get started!
+
+## A toy template { #toy-template }
+In Typst, templates are functions in which you can wrap your whole document. To
+learn how to do that, let's first review how to write your very own functions.
+They can do anything you want them to, so why not go a bit crazy?
+
+```example
+#let amazed(term) = box[✨ #term ✨]
+
+You are #amazed[beautiful]!
+```
+
+This function takes a single argument, `term`, and returns a content block with
+the `term` surrounded by sparkles. We also put the whole thing in a box so that
+the term we are amazed by cannot be separated from its sparkles by a line break.
+
+Many functions that come with Typst have optional named parameters. Our
+functions can also have them. Let's add a parameter to our function that lets us
+choose the color of the text. We need to provide a default color in case the
+parameter isn't given.
+
+```example
+#let amazed(term, color: blue) = {
+ text(color, box[✨ #term ✨])
+}
+
+You are #amazed[beautiful]!
+I am #amazed(color: purple)[amazed]!
+```
+
+Templates now work by wrapping our whole document in a custom function like
+`amazed`. But wrapping a whole document in a giant function call would be
+cumbersome! Instead, we can use an "everything" show rule to achieve the same
+with cleaner code. To write such a show rule, put a colon directly after the
+show keyword and then provide a function. This function is given the rest of the
+document as a parameter. The function can then do anything with this content.
+Since the `amazed` function can be called with a single content argument, we can
+just pass it by name to the show rule. Let's try it:
+
+```example
+>>> #let amazed(term, color: blue) = {
+>>> text(color, box[✨ #term ✨])
+>>> }
+#show: amazed
+I choose to focus on the good
+in my life and let go of any
+negative thoughts or beliefs.
+In fact, I am amazing!
+```
+
+Our whole document will now be passed to the `amazed` function, as if we wrapped
+it around it. Of course, this is not especially useful with this particular
+function, but when combined with set rules and named arguments, it can be very
+powerful.
+
+## Embedding set and show rules { #set-and-show-rules }
+To apply some set and show rules to our template, we can use `set` and `show`
+within a content block in our function and then insert the document into
+that content block.
+
+```example
+#let template(doc) = [
+ #set text(font: "Inria Serif")
+ #show "something cool": [Typst]
+ #doc
+]
+
+#show: template
+I am learning something cool today.
+It's going great so far!
+```
+
+Just like we already discovered in the previous chapter, set rules will apply to
+everything within their content block. Since the everything show rule passes our
+whole document to the `template` function, the text set rule and string show
+rule in our template will apply to the whole document. Let's use this knowledge
+to create a template that reproduces the body style of the paper we wrote in the
+previous chapter.
+
+```example
+#let conf(title, doc) = {
+ set page(
+ paper: "us-letter",
+>>> margin: auto,
+ header: align(
+ right + horizon,
+ title
+ ),
+ columns: 2,
+<<< ...
+ )
+ set par(justify: true)
+ set text(
+ font: "Libertinus Serif",
+ size: 11pt,
+ )
+
+ // Heading show rules.
+<<< ...
+>>> show heading.where(
+>>> level: 1
+>>> ): it => block(
+>>> align(center,
+>>> text(
+>>> 13pt,
+>>> weight: "regular",
+>>> smallcaps(it.body),
+>>> )
+>>> ),
+>>> )
+>>> show heading.where(
+>>> level: 2
+>>> ): it => box(
+>>> text(
+>>> 11pt,
+>>> weight: "regular",
+>>> style: "italic",
+>>> it.body + [.],
+>>> )
+>>> )
+
+ doc
+}
+
+#show: doc => conf(
+ [Paper title],
+ doc,
+)
+
+= Introduction
+#lorem(90)
+
+<<< ...
+>>> == Motivation
+>>> #lorem(140)
+>>>
+>>> == Problem Statement
+>>> #lorem(50)
+>>>
+>>> = Related Work
+>>> #lorem(200)
+```
+
+We copy-pasted most of that code from the previous chapter. The two differences
+are this:
+
+1. We wrapped everything in the function `conf` using an everything show rule.
+ The function applies a few set and show rules and echoes the content it has
+ been passed at the end.
+
+2. Moreover, we used a curly-braced code block instead of a content block. This
+ way, we don't need to prefix all set rules and function calls with a `#`. In
+ exchange, we cannot write markup directly in the code block anymore.
+
+Also note where the title comes from: We previously had it inside of a variable.
+Now, we are receiving it as the first parameter of the template function. To do
+so, we passed a closure (that's a function without a name that is used right
+away) to the everything show rule. We did that because the `conf` function
+expects two positional arguments, the title and the body, but the show rule will
+only pass the body. Therefore, we add a new function definition that allows us
+to set a paper title and use the single parameter from the show rule.
+
+## Templates with named arguments { #named-arguments }
+Our paper in the previous chapter had a title and an author list. Let's add
+these things to our template. In addition to the title, we want our template to
+accept a list of authors with their affiliations and the paper's abstract. To
+keep things readable, we'll add those as named arguments. In the end, we want it
+to work like this:
+
+```typ
+#show: doc => conf(
+ title: [Towards Improved Modelling],
+ authors: (
+ (
+ name: "Theresa Tungsten",
+ affiliation: "Artos Institute",
+ email: "tung@artos.edu",
+ ),
+ (
+ name: "Eugene Deklan",
+ affiliation: "Honduras State",
+ email: "e.deklan@hstate.hn",
+ ),
+ ),
+ abstract: lorem(80),
+ doc,
+)
+
+...
+```
+
+Let's build this new template function. First, we add a default value to the
+`title` argument. This way, we can call the template without specifying a title.
+We also add the named `authors` and `abstract` parameters with empty defaults.
+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] 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]($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:
+
+```typ
+#let conf(
+ title: none,
+ authors: (),
+ abstract: [],
+ doc,
+) = {
+ // Set and show rules from before.
+>>> #set page(columns: 2)
+<<< ...
+
+ set align(center)
+ text(17pt, title)
+
+ let count = authors.len()
+ let ncols = calc.min(count, 3)
+ grid(
+ columns: (1fr,) * ncols,
+ row-gutter: 24pt,
+ ..authors.map(author => [
+ #author.name \
+ #author.affiliation \
+ #link("mailto:" + author.email)
+ ]),
+ )
+
+ par(justify: false)[
+ *Abstract* \
+ #abstract
+ ]
+
+ set align(left)
+ doc
+}
+```
+
+## A separate file { #separate-file }
+Most of the time, a template is specified in a different file and then imported
+into the document. This way, the main file you write in is kept clutter free and
+your template is easily reused. Create a new text file in the file panel by
+clicking the plus button and name it `conf.typ`. Move the `conf` function
+definition inside of that new file. Now you can access it from your main file by
+adding an import before the show rule. Specify the path of the file between the
+`{import}` keyword and a colon, then name the function that you want to import.
+
+Another thing that you can do to make applying templates just a bit more elegant
+is to use the [`.with`]($function.with) method on functions to pre-populate all
+the named arguments. This way, you can avoid spelling out a closure and
+appending the content argument at the bottom of your template list. Templates on
+[Typst Universe]($universe) are designed to work with this style of function
+call.
+
+```example:single
+>>> #let conf(
+>>> title: none,
+>>> authors: (),
+>>> abstract: [],
+>>> doc,
+>>> ) = {
+>>> set text(font: "Libertinus Serif", 11pt)
+>>> set par(justify: true)
+>>> set page(
+>>> "us-letter",
+>>> margin: auto,
+>>> header: align(
+>>> right + horizon,
+>>> title
+>>> ),
+>>> numbering: "1",
+>>> columns: 2,
+>>> )
+>>>
+>>> show heading.where(
+>>> level: 1
+>>> ): it => block(
+>>> align(center,
+>>> text(
+>>> 13pt,
+>>> weight: "regular",
+>>> smallcaps(it.body),
+>>> )
+>>> ),
+>>> )
+>>> show heading.where(
+>>> level: 2
+>>> ): it => box(
+>>> text(
+>>> 11pt,
+>>> weight: "regular",
+>>> style: "italic",
+>>> it.body + [.],
+>>> )
+>>> )
+>>>
+>>> place(
+>>> top,
+>>> float: true,
+>>> scope: "parent",
+>>> clearance: 2em,
+>>> {
+>>> set align(center)
+>>> text(17pt, title)
+>>> let count = calc.min(authors.len(), 3)
+>>> grid(
+>>> columns: (1fr,) * count,
+>>> row-gutter: 24pt,
+>>> ..authors.map(author => [
+>>> #author.name \
+>>> #author.affiliation \
+>>> #link("mailto:" + author.email)
+>>> ]),
+>>> )
+>>> par(justify: false)[
+>>> *Abstract* \
+>>> #abstract
+>>> ]
+>>> },
+>>> )
+>>> doc
+>>>}
+<<< #import "conf.typ": conf
+#show: conf.with(
+ title: [
+ Towards Improved Modelling
+ ],
+ authors: (
+ (
+ name: "Theresa Tungsten",
+ affiliation: "Artos Institute",
+ email: "tung@artos.edu",
+ ),
+ (
+ name: "Eugene Deklan",
+ affiliation: "Honduras State",
+ email: "e.deklan@hstate.hn",
+ ),
+ ),
+ abstract: lorem(80),
+)
+
+= Introduction
+#lorem(90)
+
+== Motivation
+#lorem(140)
+
+== Problem Statement
+#lorem(50)
+
+= Related Work
+#lorem(200)
+```
+
+We have now converted the conference paper into a reusable template for that
+conference! Why not share it in the [Forum](https://forum.typst.app/) or on
+[Typst's Discord server](https://discord.gg/2uDybryKPe) so that others can use
+it too?
+
+## 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
+can now use Typst to write your own documents and share them with others.
+
+We are still a super young project and are looking for feedback. If you have any
+questions, suggestions or you found a bug, please let us know
+in the [Forum](https://forum.typst.app/),
+on our [Discord server](https://discord.gg/2uDybryKPe),
+on [GitHub](https://github.com/typst/typst/),
+or via the web app's feedback form (always available in the Help menu).
+
+So what are you waiting for? [Sign up](https://typst.app) and write something!
diff --git a/sources/docs/tutorial/welcome.md b/sources/docs/tutorial/welcome.md
new file mode 100644
index 0000000000000000000000000000000000000000..18b65aef76b8d9aa79a321a4abd5048c6ae1c140
--- /dev/null
+++ b/sources/docs/tutorial/welcome.md
@@ -0,0 +1,44 @@
+---
+description: Typst's tutorial.
+---
+
+# Tutorial
+Welcome to Typst's tutorial! In this tutorial, you will learn how to write and
+format documents in Typst. We will start with everyday tasks and gradually
+introduce more advanced features. This tutorial does not assume prior knowledge
+of Typst, other markup languages, or programming. We do assume that you know how
+to edit a text file.
+
+The best way to start is to sign up to the Typst app for free and follow along
+with the steps below. The app gives you instant preview, syntax highlighting and
+helpful autocompletions. Alternatively, you can follow along in your local text
+editor with the [open-source CLI](https://github.com/typst/typst).
+
+## When to use Typst { #when-typst }
+Before we get started, let's check what Typst is and when to use it. Typst is a
+markup language for typesetting documents. It is designed to be easy to learn,
+fast, and versatile. Typst takes text files with markup in them and outputs
+PDFs.
+
+Typst is a good choice for writing any long form text such as essays, articles,
+scientific papers, books, reports, and homework assignments. Moreover, Typst is
+a great fit for any documents containing mathematical notation, such as papers
+in the math, physics, and engineering fields. Finally, due to its strong styling
+and automation features, it is an excellent choice for any set of documents that
+share a common style, such as a book series.
+
+## What you will learn { #learnings }
+This tutorial has four chapters. Each chapter builds on the previous one. Here
+is what you will learn in each of them:
+
+1. [Writing in Typst:]($tutorial/writing-in-typst) Learn how to write text and
+ insert images, equations, and other elements.
+2. [Formatting:]($tutorial/formatting) Learn how to adjust the formatting
+ of your document, including font size, heading styles, and more.
+3. [Advanced Styling:]($tutorial/advanced-styling) Create a complex page
+ layout for a scientific paper with typographic features such as an author
+ list and run-in headings.
+4. [Making a Template:]($tutorial/making-a-template) Build a reusable template
+ from the paper you created in the previous chapter.
+
+We hope you'll enjoy Typst!
diff --git a/sources/tests/README.md b/sources/tests/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..e625581a3f61418fdfd11bce8a85ff30fa49d127
--- /dev/null
+++ b/sources/tests/README.md
@@ -0,0 +1,150 @@
+# Tests
+
+## Directory structure
+Top level directory structure:
+- `src`: Testing code.
+- `suite`: Input files. Mostly organized in parallel to the code. Each file can
+ contain multiple tests, each of which is a section of Typst code
+ following `--- {name} ---`.
+- `ref`: References which the output is compared with to determine whether a
+ test passed or failed.
+- `store`: Store for PNG, PDF, and SVG output files produced by the tests.
+
+## Running the tests
+Running all tests (including unit tests):
+```bash
+cargo test --workspace
+```
+
+Running just the integration tests (the tests in this directory):
+```bash
+cargo test --workspace --test tests
+```
+
+You may want to [make yourself an alias](#making-an-alias) `testit` so that you can
+write shorter commands. In the examples below, we will use this alias.
+
+Running all tests with the given name pattern. You can use
+[regular expression](https://docs.rs/regex/latest/regex/)s.
+```bash
+testit math # The name has "math" anywhere
+testit math page # The name has "math" or "page" anywhere
+testit "^math" "^page" # The name begins with "math" or "page"
+testit "^(math|page)" # Same as above.
+```
+
+Running all tests discovered under given paths:
+```bash
+testit -p tests/suite/math/attach.typ
+testit -p tests/suite/model -p tests/suite/text
+```
+
+Running tests that begin with `issue` under a given path:
+```bash
+testit "^issue" -p tests/suite/model
+```
+
+Running a test with the exact test name `math-attach-mixed`.
+```bash
+testit --exact math-attach-mixed
+```
+
+You may find more options in the help message:
+```bash
+testit --help
+```
+
+To make the integration tests go faster they don't generate PDFs or SVGs by
+default. Pass the `--pdf` or `--svg` flag to generate those. Mind that PDFs and
+SVGs are **not** tested automatically at the moment, so you should always check
+the output manually when making changes.
+```bash
+testit --pdf
+```
+
+## Writing tests
+The syntax for an individual test is `--- {name} {attr}* ---` followed by some
+Typst code that should be tested. The name must be globally unique in the test
+suite, so that tests can be easily migrated across files. A test name can be
+followed by space-separated attributes. For instance, `--- my-test html ---`
+adds the `html` modifier to `my-test`, instructing the test runner to also
+test HTML output. The following attributes are currently defined:
+
+- `render`: Tests paged output against a reference image (the default, only
+ needs to be specified when `html` is also specified to enable both at the
+ same)
+- `html`: Tests HTML output against a reference HTML file. Disables the `render`
+ default.
+- `large`: Permits a reference image size exceeding 20 KiB. Should be used
+ sparingly.
+
+There are, broadly speaking, three kinds of tests:
+
+- Tests that just ensure that the code runs successfully: Those typically make
+ use of `test` or `assert.eq` (both are very similar, `test` is just shorter)
+ to ensure certain properties hold when executing the Typst code.
+
+- Tests that ensure the code emits particular diagnostic messages: Those have
+ inline annotations like `// Error: 2-7 thing was wrong`. An annotation can
+ start with either "Error", "Warning", or "Hint". The range designates the
+ code span the diagnostic message refers to in the first non-comment line
+ below. If the code span is in a line further below, you can write ranges
+ like `3:2-3:7` to indicate the 2-7 column in the 3rd non-comment line.
+
+- Tests that ensure certain output is produced:
+
+ - Visual output: By default, the compiler produces paged output, renders it
+ with the `typst-render` crate, and compares it against a reference image
+ stored in the repository. The test runner automatically detects whether a
+ test has visual output and requires a reference image in this case.
+
+ To prevent bloat, it is important that the test images are kept as small as
+ possible. To that effect, the test runner enforces a maximum size of 20 KiB.
+ If you're updating a test and hit `reference output size exceeds`, see the
+ section on "Updating reference images" below. If truly necessary, the size
+ limit can be lifted by adding a `large` attribute after the test name, but
+ this should be the case very rarely.
+
+ - HTML output: When a test has the `html` attribute, the compiler produces
+ HTML output and compares it against a reference file stored in the
+ repository. By default, this enables testing of paged output, but you can
+ test both at once by passing both `render` and `html` as attributes.
+
+If you have the choice between writing a test using assertions or using
+reference images, prefer assertions. This makes the test easier to understand
+in isolation and prevents bloat due to images.
+
+## Updating reference images
+If you created a new test or fixed a bug in an existing test, you may need to
+update the reference output used for comparison. For this, you can use the
+`--update` flag:
+```bash
+testit --exact my-test-name --update
+```
+
+For visual tests, this will generally generate compressed reference images (to
+remain within the size limit).
+
+If you use the VS Code test helper extension (see the `tools` folder), you can
+alternatively use the save button to update the reference output.
+
+## Making an alias
+If you want to have a quicker way to run the tests, consider adding a shortcut
+to your shell profile so that you can simply write something like:
+```bash
+testit --exact my-test-name
+```
+
+### Bash
+Open your Bash configuration by executing `nano ~/.bashrc`.
+```bash
+alias testit="cargo test --workspace --test tests --"
+```
+
+### PowerShell
+Open your PowerShell profile by executing `notepad $profile`.
+```ps
+function testit {
+ cargo test --workspace --test tests -- $args
+}
+```
diff --git a/sources/tools/support/README.md b/sources/tools/support/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..e83978de6125e444ae5af7ac91005b32d226907b
--- /dev/null
+++ b/sources/tools/support/README.md
@@ -0,0 +1,13 @@
+# Language support
+This VS Code extension provides minimal language support for Typst. It contains
+a syntax definition and a language configuration for comment toggling,
+autoclosing etc.
+
+The extension was created for development purposes only. It is not maintained
+and its grammar is buggy. For a more actively developed extension see the
+third-party [Tinymist extension](https://github.com/Myriad-Dreamin/tinymist).
+
+## Installation
+The simplest way to install this extension (and keep it up-to-date) is to add a
+symlink from `~/.vscode/extensions/typst-support` to
+`path/to/typst/tools/support`.
diff --git a/sources/tools/test-helper/README.md b/sources/tools/test-helper/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..3ecc1d4f4137ee0158578fd3f9c163f3180e5a4f
--- /dev/null
+++ b/sources/tools/test-helper/README.md
@@ -0,0 +1,34 @@
+# Test helper
+
+This is a small VS Code extension that helps with managing Typst's test suite.
+When installed, for all `.typ` files in the `tests` directory, the following
+Code Lens buttons will appear above every test's name:
+
+- View: Opens the output and reference image of a test to the side.
+- Run: Runs the test and shows the results to the side.
+- Save: Runs the test with `--update` to save the reference output.
+- Terminal: Runs the test in the integrated terminal.
+
+In the side panel opened by the Code Lens buttons, there are a few menu buttons
+at the top right:
+
+- Refresh: Reloads the panel to reflect changes to the images.
+- Run: Runs the test and shows the results.
+- Save: Runs the test with `--update` to save the reference output.
+
+## Installation
+In order for VS Code to run the extension with its built-in
+[Node](https://nodejs.org) engine, you need to first build it from source.
+Navigate to `test-helper` directory and build the extension:
+```bash
+npm install # Install the dependencies.
+npm run build # Build the extension from source.
+```
+
+Then, you can easily install it (and keep it up-to-date) via VS Code's UI:
+- Go to View > Command Palette or press Cmd/Ctrl+P,
+- In the drop down list, pick command "Developer: Install Extension from
+ Location",
+- Select this `test-helper` directory in the file explorer dialogue box. VS Code
+ will add the extension's path to `~/.vscode/extensions/extensions.json` (or
+ `%USERPROFILE%\.vscode\extensions\extensions.json` on Windows).