#typst #template #source-file #templating #engine #resolver

typst-as-lib

Small wrapper for typst that makes it easier to use it as a templating engine

12 releases (7 breaking)

0.8.0 Jul 22, 2024
0.7.2 Jul 22, 2024
0.6.1 Jul 20, 2024
0.5.1 Jul 17, 2024
0.1.4 Jul 13, 2024

#61 in Template engine

MIT license

38KB
760 lines

Typst as lib

Small wrapper around Typst that makes it easier to use it as a templating engine. This API is currently not really stable, although I try to implement the features with as little change to the API as possible.

Usage

rust code

// main.rs
static TEMPLATE_FILE: &str = include_str!("./templates/template.typ");
static FONT: &[u8] = include_bytes!("./fonts/texgyrecursor-regular.otf");
static OUTPUT: &str = "./examples/output.pdf";
static IMAGE: &[u8] = include_bytes!("./templates/images/typst.png");

fn main() {
    let font = Font::new(Bytes::from(FONT), 0).expect("Could not parse font!");

    // Read in fonts and the main source file.
    // We can use this template more than once, if needed (Possibly
    // with different input each time).
    let template = TypstTemplate::new(vec![font], TEMPLATE_FILE);

    let mut tracer = Tracer::new();

    // Run it
    // Run `template.compile(&mut tracer)` to run typst script
    // without any input.
    let doc = template
        .compile_with_input(&mut tracer, dummy_data())
        .expect("typst::compile() returned an error!");

    // Create pdf
    let pdf = typst_pdf::pdf(&doc, Smart::Auto, None);
    fs::write(OUTPUT, pdf).expect("Could not write pdf.");
}

Full example file

Typst code

// template.typ
#import sys: inputs

#set page(paper: "a4")
#set text(font: "TeX Gyre Cursor", 11pt)

#let content = inputs.v
#let last_index = content.len() - 1

#for (i, elem) in content.enumerate() [
  == #elem.heading
  Text: #elem.text \
  Num1: #elem.num1 \
  Num2: #elem.num2 \
  #if elem.image != none [#image.decode(elem.image, height: 40pt)]
  #if i < last_index [
    #pagebreak()
  ]
]

Run example with:

cargo r --example=small_example

Resolving files

Binaries

Use TypstTemplate::with_static_file_resolver and add the binaries as key value pairs ((file_name, &[u8])).

Sources

Use TypstTemplate::with_static_source_file_resolver and add the sources as key value pairs ((file_name, String)).

Local files

Resolving local files can be enabled with TypstTemplate::with_file_system_resolver. The root should be the template folder. Files cannot be resolved, if they are outside of root.

Remote Packages

Resolving packages can be enabled with TypstTemplate::with_package_file_resolver. The package feature needs to be enabled.

Examples

Static binaries and sources

See example which uses the static file resolvers.

cargo r --example=resolve_static

Local files and remote packages

See example which uses the file and the package resolver.

cargo r --example=resolve_files --features=package

Custom file resolver

You can also write your own file resolver. You need to implement the Trait FileResolver and pass it to the TypstTemplate::add_file_resolver function.

TypstTemplateCollection

If you want to compile multiple typst (main) source files you might want to use the TypstTemplateCollection, which allows you to specify the source file, when calling TypstTemplateCollection::compile, instead of passing it to new. The source file has to be added with TypstTemplateCollection::add_static_file_resolver first. TypstTemplate is just a wrapper around TypstTemplateCollection, that also saves a FileId for the main source file.

Loading fonts

Loading fonts is not in the scope of this library (yet?). If you are interested in that, write an issue.

  • This is how the typst-cli loads system fonts.
  • Here is an example of loading fonts from a folder.

TODO

  • allow usage of reqwest instead of ureq with a feature flag
  • fonts
  • have option to cache packages on the hard drive for PackageResolver

Dependencies

~62MB
~1M SLoC