iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
📝

An Early Deep Dive into Typst 0.14.0

に公開

Introduction

In this article, I will introduce the new features and changes in Typst 0.14.0, which was released on 2025/10/24.

Release Notes & Deep Dive Articles List

Release Date Version Official Release Notes Deep Dive Article
2024/10/18 0.12.0 Official Release Notes Deep Dive into Typst 0.12.0 Updates
2025/02/19 0.13.0 Official Release Notes Deep Dive into Typst 0.13.0 Updates
2025/10/24 0.14.0 Official Release Notes Deep Dive into Typst 0.14.0 Updates

Pickups

This section highlights features that have a significant impact or that I personally found interesting. In particular, breaking changes are marked with the 💥 symbol.

Inserting PDF files as images with image() is now supported

From v0.14, PDF files can be inserted as images. Usage is exactly the same as for images like JPEG or SVG, using the image() function.

// Simply doing this will insert the first page
#image("./example.pdf")

// If explicitly specifying the format (usually auto-detected)
#image("./example.pdf", format: "pdf")

// Insert by specifying the page number
#image("./example.pdf", page: 3)

Considering that it was previously necessary to convert files to SVG or similar formats first, this is a very welcome addition. However, there are some limitations to keep in mind.

  • When exporting to PDF, the version of the PDF file being read must be less than or equal to the export version.
    • The PDF specification has versions like PDF 1.7 and PDF 2.0.
    • The default format supported by Typst is PDF 1.7. When exporting to PDF with default settings, the version of the PDF file you can read is up to 1.7.
    • Typst supports exporting to PDF 2.0, so if you want to insert a PDF 2.0 figure, you should change the export settings. In the Typst CLI, this is possible with the --pdf-standard 2.0 option.
  • This cannot be used when exporting to specific PDF standards such as PDF/A-3 or PDF/UA-1.
  • Password-protected PDF files cannot be read.
  • Tags within the PDF image are not preserved. To improve accessibility, you need to use the alt field.

Note that PDF files inserted with image() are processed as follows depending on the export format during Typst compilation:

Export Format Processing
PDF Directly embedded
PNG Rasterized
SVG, HTML Converted to SVG and embedded

Element function title() added

An element function title() for inserting the title of the entire document has been added. From now on, you should use title() instead of things like heading() for parts of the document where you display the title.

#set document(title: [Deep Dive into Typst 0.14.0 Updates])

#title()  // If no argument is provided, the value of the document.title property is referenced

While you can embed an arbitrary title by using #title[... title ...], it is recommended to use the title field of document(), which provides benefits such as being recognizable by PDF viewers.

Fraction display styles are now configurable

In Typst, a slash inside a formula like $a / b$ is treated as a fraction. By default, the numerator and denominator are displayed vertically according to general fraction notation, but in cases like inline equations, you might want to display them side-by-side with a slash. Starting from v0.14, you can now choose from three types of fraction notations.


Three notation styles available starting from v0.14

To specify it explicitly, use the math.frac syntax. Inside a formula, it can be called simply as frac().

$ frac(x, y, style: "vertical") $
$ frac(x, y, style: "skewed") $
$ frac(x, y, style: "horizontal") $

Like other syntax, you can use set or show rules to change the behavior of the slash notation itself. For example, it is useful in cases such as:

  • Adopting a specific notation uniformly for all $a / b$ formatted syntax.
  • Applying "horizontal" to $a / b$ formatted syntax only for inline equations.

Refer to the following example for the actual configuration method.

Code Example
#let Res = math.op("Res")
#let example(title, body) = block(stroke: 1pt, width: 100%, inset: 10pt)[
  = #title

  #body
]
#page(
  width: 500pt,
  height: auto,
  margin: 20pt,
)[
  #grid(
    columns: (1fr, 1fr), column-gutter: 10pt, row-gutter: 10pt,

    example["vertical" style][
      #set math.frac(style: "vertical")  // default
      The coefficient of $1 / (z - a)$ in Laurent expansion
      $
        c_(-1) = 1/(2 pi i) integral.cont_C f(z) d z
      $
      is called the residue and denoted as $Res(f, a)$.
    ],

    example["skewed" style][
      #set math.frac(style: "skewed")
      The coefficient of $1 / (z - a)$ in Laurent expansion
      $
        c_(-1) = 1/(2 pi i) integral.cont_C f(z) d z
      $
      is called the residue and denoted as $Res(f, a)$.
    ],

    example["horizontal" style][
      #set math.frac(style: "horizontal")
      The coefficient of $1 / (z - a)$ in Laurent expansion
      $
        c_(-1) = 1/(2 pi i) integral.cont_C f(z) d z
      $
      is called the residue and denoted as $Res(f, a)$.
    ],

    example["horizontal" + "vertical" style][
      // Set horizontal as default for inline equations only
      #show math.equation.where(block: false): set math.frac(style: "horizontal")
      The coefficient of $1 / (z - a)$ in Laurent expansion
      $
        c_(-1) = 1/(2 pi i) integral.cont_C f(z) d z
      $
      is called the residue and denoted as $Res(f, a)$.
    ],
  )
]

From this example, you can also see that the presence or absence of parentheses changes depending on the style. In "vertical" and "skewed" styles, where there is no risk of misunderstanding, parentheses are omitted; conversely, in "horizontal", parentheses are displayed.

Ability to adjust inter-character spacing during justification

Previously, Typst performed justification through word spacing adjustments and hyphenation. However, in narrow columns, these adjustments were sometimes insufficient, leading to sparse lines that looked poor. In v0.14, a parameter for adjusting inter-character spacing has been added alongside word spacing, making it easier to refine the appearance. You can adjust inter-character spacing by specifying the par.justification-limits property as follows:

#set par(justification-limits: (tracking: (min: -0.01em, max: 0.02em)))

This means "allowing inter-character spacing to be adjusted between -0.01em and 0.02em." The actual character width is automatically adjusted by Typst's justification algorithm. Looking at the official examples, providing even a small amount of leeway—just 2% of the character width—in the inter-character spacing results in a significant difference in the typesetting outcome.


Difference in typesetting results due to justification-limits (Left: Default, Right: Example with width in tracking)

Comparing "Anne Christine Bayley" in the first line or "she returned to England," in the sixth line from the bottom makes the pure effect of the adjustment via character width easy to understand.

New features added to HTML export

Various features have also been added to the HTML export, which was introduced experimentally in v0.13.

  • Various elements such as image() and footnote() can now be exported to HTML. Everything listed on the Model page is now exportable to HTML, meaning the core functions for document structure are mostly covered.

  • The behavior when converting code blocks to HTML has been improved.

    • The entire code is now wrapped in a <code> tag, and if a language is specified, a data-lang attribute is added.
    • Syntax highlighting is now applied. The highlighting uses <span> tags for coloring, and it seems that themes set in Typst are reflected.
  • Under the html module, functions like html.div corresponding to HTML tags have been added individually.

    • For example, html.a corresponds to the <a> tag and takes a keyword argument called href.
  • References using labels can now be used as internal document links (intra-doc links).

Creating web pages and blogs using Typst is likely to become even more efficient in the future.

By the way, regarding mathematical formulas, HTML export is not yet officially supported. However, it is already possible to convert formulas to SVG images and embed them in HTML. If you are interested, you might find useful insights by referring to this issue comment.

Added features for generating accessible PDFs

"Accessible PDF" refers to a PDF that can be accessed and understood by a wide variety of people. When thinking about accessibility, people with visual impairments might come to mind first, but it is not limited to them. It includes everyone: "people who print and read PDFs," "people who use text-to-speech features," "people who have AI read and summarize content," and so on. In that sense, it is not a feature for just a few people, but rather a concept that can relate to almost everyone.

PDF has a standard for accessibility called "PDF/UA," and you can improve accessibility by creating documents that comply with this standard. In v0.14, the following accessibility-related features have been added:

  • Added functionality to generate PDFs compliant with the PDF/UA-1 standard.

  • Accessibility-related information is now included by default during PDF output.

    • Document structures like headings are now tagged, etc.
  • An Accessibility Guide has been added to the official documentation.

To generate a PDF compliant with the PDF/UA-1 standard using the Typst CLI, specify the --pdf-standard ua-1 option during compilation.

typst compile [input_file] --pdf-standard ua-1

As a result, compilation errors will occur for documents that do not comply with PDF/UA-1. For example, the following simple file would normally compile without issues, but it is not permitted under PDF/UA-1.

= PDF/UA-1 Test

This is a test for PDF/UA-1.

$ a^2 + b^2 = c^2 $

Actually compiling this results in the following errors:

error: PDF/UA-1 error: missing alt text
   ┌─ pdfua1a.typ:16:0

16 │ $ a^2 + b^2 = c^2 $
   │ ^^^^^^^^^^^^^^^^^^^

   = hint: make sure your images and equations have alt text

error: PDF/UA-1 error: missing document title
 = hint: set the title of the document

In other words, it is flagging two issues:

  • The math equation lacks "alt text" (supplementary text used for environments where images or equations cannot be displayed or for people who cannot see them).

  • No document title is set.

Fixing these would look like this:

// The document.title property is mandatory for the document
#set document(title: [PDF/UA-1 Test])

// Element function added in v0.14. Displays the document title.
#title()

This is a test for PDF/UA-1.

// Equations without alt text are not allowed
#math.equation(
  alt: "a squared plus b squared equals c squared",
  $ a^2 + b^2 = c^2 $,
)

Now the compilation will succeed.

Additionally, several other features related to accessibility have been added:

  • pdf.artifact(): Manually tag a portion of the document as an "Artifact" to tell screen readers that the element is a decoration with no semantic meaning.

  • pdf.header-cell(), etc.: Can be used to improve the accessibility of complex tables.

  • Sequential numbering has been added to heading information in PDFs.

Important Notes

We have summarized the points to check when updating to Typst v0.14 and notes that might have an impact in future changes.

  • From v0.14, the following descriptions will cause compilation errors. Although these are mostly intended to reject semantically invalid descriptions, they may prevent existing documents from compiling.

    • Specifying an invalid mime property in the pdf.attach (formerly pdf.embed) function.

    • Specifying an empty string as the argument for a URL in the link() function.

    • Specifying an empty list for the text.font property.

    • Defining an empty label (#label("")).

  • The following features are deprecated:

    • pdf.embed: Renamed to pdf.attach.

    • Renaming of some styles in bibliography():

      • "chicago-fullnotes""chicago-notes" or "chicago-shortened-notes"

      • "modern-humanities-research-association""modern-humanities-research-association-notes"

  • Some symbol names are also deprecated. Here are some excerpts that are likely to be used frequently:

    Glyph Old notation (Deprecated) Alternative notation
    \aleph alef aleph
    \oplus plus.circle plus.o
    \bigotimes times.circle.big times.o.big
    \circledcirc circle.nested compose.o
    \langle / \rangle angle.l / angle.r chevron.l / chevron.r
    \partial diff partial
    h planck h
    \hslash planck.reduce planck

    Refer to the CHANGELOG for all deprecations.

List of Other Changes

  • Added support for loading images in WebP format.
  • Supported multi-line table.header in tables, allowing headers to have a hierarchical structure.

  • 💥 The default value of the enum.item property has changed from none to auto.

  • The sub() and super() functions now utilize OpenType subs / sups font features.

  • raw() function:

    • Improved visibility of the default syntax highlighting for plain text.

    • Changed JSON highlighting so that keys and values are colored differently.

  • Added translations for headings, figures, etc., to multiple languages (refer to the documentation for the list of languages).

  • Display a warning when using variable fonts (which are currently unsupported).

  • Multiple fonts can now be used within a single equation.

  • Glyph layout within equations is now more appropriate, referencing Unicode features.

  • show rules now apply to some "generated characters" as well.

    • For example, the radical sign in sqrt() or parentheses enclosing large matrices correspond to "generated characters."
  • Handwriting (script) fonts can now be specified with scr().

    • While cal() was equivalent to \mathcal{} in LaTeX, scr() is equivalent to \mathscr{}.
  • Added dotless property to the accent() function.

    • Controls whether to keep the original dot when adding an accent to i or j.
  • Added augment property to matrix(), allowing lines to be drawn to indicate augmented matrices.

    • This is useful for completing linear algebra reports.
  • Improved parsing priority for fraction notation and some shorthand notations.

  • The in operator can now be used to check if something is defined within a module.

  • Added a default argument to the array.first(), array.last(), array.join(), str.first(), and str.last() methods.

    • These return the specified value when an empty array or string is provided. For example, "".first(default: "x") returns "x".
  • Added a by argument to the array.sorted() method.

    • This allows you to customize the function used for comparison.
  • Added the str.normalize() method for Unicode normalization.

    • You can select from four types of normalization (NFC, NFD, NFKC, NFKD) via the form argument.
  • Added direction.from() and direction.to() functions, as well as the direction.sign() method.

    • The direction type represents the direction in which glyphs or blocks are arranged, consisting of the following four types:

      • ltr (left-to-right)

      • rtl (right-to-left)

      • ttb (top-to-bottom)

      • btt (bottom-to-top)

    • For example, direction.from(left) returns ltr, which is the direction flowing from the left.

    • The direction.sign() method returns 1 or -1 based on whether ltr / ttb is considered positive. For example, ltr.sign() returns 1, and rtl.sign() returns -1.

  • Updated the WASM runtime used for plugins to support SIMD operations.

  • Integer values used for numbering headings or counters now use 64-bit integer types (like u64 in Rust) regardless of the platform.

  • The behavior when reading numbers that cannot be represented by 64-bit integers in data loading functions such as json() or yaml() has become more consistent.

    • For JSON, YAML, and CBOR, the behavior has been unified to "convert to float and read."
    • However, it results in an error in TOML (as specified by the TOML specification).
  • All PDF/A standards are now supported.

    • By specifying a specific standard during compilation, a PDF compliant with that standard will be output.
  • You can now choose the output PDF version from 1.4, 1.5, 1.6, 1.7, and 2.0.

    • The default is PDF 1.7.
  • Improved behavior for text extraction from PDFs.

    • Related to accessibility, the behavior when copying and pasting text from a PDF viewer has been improved.
      • Cases where multiple characters are contained in a single glyph are now handled correctly.
      • Spaces inserted during natural line breaks in paragraphs are now correctly preserved.
    • Although the actual text extraction behavior varies by viewer, I obtained text closer to what I intuitively expected in my own environment (macOS Preview, Skim, Adobe Acrobat Reader). Benefits include selecting two-column text in the correct order and removing hyphens used for justification.
  • Values for document.authors and document.keywords properties are now output as <meta> tags.

  • The html.elem() function can now accept custom HTML element names.

  • When an empty attribute value is specified, it is now output using shorthand syntax.

    • Example: The hidden attribute in <div hidden></div>.

Related Materials

Discussion