Project

typst

0.01
A long-lived project that still receives updates
Ruby binding to typst, a new markup-based typesetting system that is powerful and easy to learn.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 1.1
~> 0.3
~> 1.5
~> 3.6

Runtime

~> 3.2
~> 0.9, >= 0.9.124
 Project Readme

typst-rb

Ruby binding to typst, a new markup-based typesetting system that is powerful and easy to learn.

Installation

gem install typst

Usage

require "typst"

# Compile a typst file and write the output to a PDF file
Typst("readme.typ").compile(:pdf).write("readme.pdf")

Use a typst file readme.typ

t = Typst("readme.typ")

Use a typst string

t = Typst(body: %{hello world})

Use a typst file in a zip file

t = Typst(zip: "test/main.typ.zip")

Compile to PDF

doc = t.compile(:pdf)

Compile to PDF selecting the typst supported PdfStandard

doc = t.compile(:pdf, pdf_standards: ["2.0"])

Compile to SVG

doc = t.compile(:svg)

Compile to PNG

doc = t.compile(:png)

Compile to PNG and set PPI

doc = t.compile(:png, ppi: 72)

Compile to HTML (using Typst expirmental HTML)

doc = t.compile(:html_experimental)

Or return content as an array of bytes

pdf_bytes = Typst("readme.typ").compile(:pdf).bytes
# => [37, 80, 68, 70, 45, 49, 46, 55, 10, 37, 128 ...]

Write the output to a file

Note: for multi-page documents using formats other than PDF and HTML, pages write to multiple files, e.g. readme_0.png, readme_1.png

doc.write("filename.pdf")

Return PDF, SVG, PNG or HTML content as an array of pages

Typst("readme.typ").compile(:pdf).pages
# => ["%PDF-1.7\n%\x80\x80\x80\x80\n\n1 0 obj\n<<\n  /Type /Pages\n  /Count 3\n  /Kids [160 0 R 162 ...

Typst("readme.typ").compile(:svg).pages
# => ["<svg class=\"typst-doc\" viewBox=\"0 0 595.2764999999999 841.89105\" ...

Typst("readme.typ").compile(:png).pages
# => ["\x89PNG\r\n\x1A\n\x00\x00\x00\rIHDR\x00\x00\x04\xA7\x00\x00\x06\x94\b\ ...

Typst("readme.typ").compile(:html_experimental).pages
# => ["<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" ...

Pass values into typst using sys_inputs

sys_inputs_example = %{
#let persons = json(bytes(sys.inputs.persons))

#for person in persons [
  #person.name is #person.age years old.\\
]
}
people = [{"name" => "John", "age" => 35}, {"name" => "Xoliswa", "age" => 45}]
data = { "persons" => people.to_json }
Typst(body: sys_inputs_example, sys_inputs: data).compile(:pdf).write("sys_inputs_example.pdf")

Apply inputs to typst to product multiple PDFs

t = Typst(body: sys_inputs_example)
people.each do |person|
  t.with_inputs({ "persons" => [person].to_json }).compile(:pdf).write("#{person['name']}.pdf")
end

A more complex example of compiling from string using other dependency typst template, svg and font resources all in memory

main = %{
#import "template.typ": *

#show: template.with()

#lorem(50)

#image("icon.svg")
}

template = %{
#let template(body) = {
  set text(12pt, font: "Example")
  body
}
}

icon = File.read("icon.svg")
font_bytes = File.read("Example.ttf")

Typst(body: main, dependencies: { "template.typ" => template, "icon.svg" => icon }, fonts: { "Example.ttf" => font_bytes }).compile(:pdf)

From a zip with a named main typst file

Typst(zip: "test/main.typ.zip", main_file: "hello.typ").compile(:pdf)

Use a package from the Typst Universe

Your package_example.typ file...

#import "@preview/wordometer:0.1.5": word-count, total-words
#show: word-count

In this document, there are #total-words words all up.

#word-count(total => [
  The number of words in this block is #total.words
  and there are #total.characters letters.
])

...compiles just like anything else

Typst("package_example.typ").compile(:pdf).write("package_example.pdf")

Query a typst document

Typst("readme.typ").query("heading").result
# => 
# [{"func" => "heading",
#   "level" => 1,
#   "depth" => 1,
# ...

Typst("readme.typ").query("heading", format: "json").result(raw: true)
# => "[\n  {\n    \"func\": \"heading\",\n    \"level\": 1,\n    \"depth\": ..."

Typst("readme.typ").query("heading", format: "yaml").result(raw: true)
# => "- func: heading\n  level: 1\n  depth: 1\n  offset: 0\n  numbering: ..."

# Query results as JSON string
Typst("test/test.typ").query("heading").to_s
# => "[\n  {\n    \"func\": \"heading\",\n    \"level\": 1,\n    \"depth\": 1,\n    \"offset\": 0,\n ...

# Query results as YAML string
Typst("test/test.typ").query("heading", format: "yaml").to_s
# => "- func: heading\n  level: 1\n  depth: 1\n  offset: 0\n  numbering: null\n  supplement:\n    ...

clear the compilation cache

# Evict all entries whose age is larger than or equal to `max_age`
max_age = 10
Typst::clear_cache(max_age)

Contributors & Acknowledgements

typst-rb is based on typst-py by messense
clear_cache was contributed by NRicciVestmark

License

This work is released under the Apache-2.0 license. A copy of the license is provided in the LICENSE file.