{r2typ} allows you to generate Typst markup using R and makes you much more efficient in creating PDF reports. It supports all of the following:
- ✅ almost all Typst functions (+ an option to add yours)
- ✅ conversions from R to Typst (
NULL->none,TRUE->true, etc.) - ✅ Typst colors, alignment, units and direction natively
- ✅
setand (simple)showrules - ✅ works well with Quarto
- ✅ extremely simple syntax
- ✅ very lightweight (no required dependencies)
Check out the documentation.
Warning
The project is still early stage and likely contains a few bugs.
# install.packages("pak")
pak::pkg_install("y-sunflower/r2typ")Typst is a powerful typesetting system, but writing its markup programmatically from R can be cumbersome when you need to automate reports, generate dynamic documents, or integrate Typst output into data workflows. {r2typ} fills this gap by offering a light, consistent interface that turns R expressions directly into valid Typst markup.
It streamlines the creation of complex layouts, ensures reliable type conversions, and makes it easy to embed Typst generation into pipelines, scripts, and Quarto projects.
The main thing to understand is that {r2typ} essentially does one thing: generate text. And that's it!
library(r2typ)
heading(level = 2, numbering = "1.1", "Hello world")
#> #heading(level: 2, numbering: "1.1")[Hello world]
text(size = pt(12), baseline = em(1.2), overhang = FALSE, "hey there")
#> #text(size: 12pt, baseline: 1.2em, overhang: false)[hey there]
image(width = percent(80), height = auto, "link.svg")
#> #image(width: 80%, height: auto, "link.svg")
circle(fill = blue, "hey")
#> #circle(fill: blue)[hey]
circle(radius = pt(100), "hey", linebreak(), "there")
#> #circle(radius: 100pt)[hey #linebreak() there]
place(top + left, dy = pt(15), square(size = pt(35), fill = red))
#> #place(top + left, dy: 15pt)[#square(size: 35pt, fill: red)]{r2typ} converts some R types into Typst types:
NULLbecomesnone
image("image.png", width = percent(80), alt = NULL)
#> #image(width: 80%, alt: none, \"image.png\")TRUE/FALSEbecometrue/false
list_(tight = FALSE, "hey", "you")
#> #list(tight: false, [hey], [you])c()vectors and unnamedlist()(such aslist("a", "b") become arrays:
text(`stylistic-set` = c(1, 2, 3), "10 years ago")
#> #text(stylistic-set: (1, 2, 3))[10 years ago]
text(`stylistic-set` = list(1, 2, 3), "10 years ago") # equivalent
#> #text(stylistic-set: (1, 2, 3))[10 years ago]- Named
list()(such aslist(a = "hello", b = "world")) become dictionnaries:
text(costs = list(hyphenation = percent(100), runt = percent(100)))
#> #text(costs: (hyphenation: 100%, runt: 100%))set_text(red, size = pt(20))
#> #set text(size: 20pt, red)
show_heading(set_text(fill = red))
#> #show heading: set text(fill: red, size: 20pt)Functions in {r2typ} accept all positional and named arguments! This means that you're responsible of making sure the arguments you're using are valid!
But to help you in that process, there is a is_valid_typst() function that will return either TRUE or FALSE depending on whether your Typst can be compiled successfully.
place(
top + left,
dy = pt(15),
square(size = pt(35), fill = red)
) |>
is_valid_typst()
#> TRUEAlso note that all examples in the
{r2typ}documentation are valid Typst examples.
hello <- function(...) typst_function("hello", ...)
hello(fill = red, size = pt(10), other_arg = "world")
#> #hello(fill: red, size: 10pt, other_arg: "world")A complete example that generates a PDF using R only:
c(
set_page(height = pt(400)),
set_text(purple),
set_circle(width = percent(50)),
align(
center + horizon,
circle(
fill = aqua,
stroke = pt(5) + red,
align(
right,
text(
font = "Roboto",
size = em(1.2),
"My favorite food is cookies!"
)
)
)
)
) |>
typst_write() |>
typst_compile(output = "example.pdf")Learn more in the get started vignette.
{r2typ} generates Typst markup, not Typst code. Most people, when writing native Typst, rely primarily on markup mode. Code mode is mainly used to add logic or create functions.
This is an important distinction to keep in mind, but the core difference is that function calls start with a # (e.g., #text("hey") VS text("hey")).
You can learn more about it here.
- ✅ Text
- ✅ Foundations
- ✅ Model, everything except:
cite,link,numbering,ref,terms - ✅ Layout, everything except:
columns,layout,measure,repeat,rotate - ✅ Visualize, everything except:
curve,gradient,path,stroke,polygon,tiling
something's missing? Please open an issue!
