typst-as-lib 0.2.0

Small wrapper for typst that makes it easier to use it as a templating engine
Documentation
typst-as-lib-0.2.0 has been yanked.

typst-as-lib

Small wrapper for typst that makes it easier to use it as a templating engine. Maybe useful for someone...

Usage

rust code

// main.rs
use derive_typst_intoval::{IntoDict, IntoValue};
use std::fs;
use typst::foundations::{Bytes, Dict, IntoValue, Smart};
use typst::text::Font;
use typst_as_lib::TypstTemplate;

static TEMPLATE_FILE: &str = include_str!(
    "./templates/template.typ"
);

static FONT: &[u8] = include_bytes!(
    "./fonts/texgyrecursor-regular.otf"
);

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

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

    // optionally pass in some additional source files.
    // template = template.add_other_sources_from_strings(other_sources);

    // optionally pass in some additional binary files.
    // template = template.add_binary_files(files);

    // Some dummy content. We use `derive_typst_intoval` to easily 
    // create `Dict`s from structs by deriving `IntoDict`;
    let content = Content {
        v: vec![
            ContentElement {
                heading: "Heading".to_owned(),
                text: Some("Text".to_owned()),
                num1: 1,
                num2: Some(2),
            },
            ContentElement {
                heading: "Heading2".to_owned(),
                num1: 2,
                ..Default::default()
            },
        ],
    };

    let mut tracer = Default::default();

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

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

// Implement Into<Dict> manually, so we can just pass the struct
// to the compile function.
impl From<Content> for Dict {
    fn from(value: Content) -> Self {
        value.into_dict()
    }
}

#[derive(Debug, Clone, IntoValue, IntoDict)]
struct Content {
    v: Vec<ContentElement>,
}

#[derive(Debug, Clone, Default, IntoValue, IntoDict)]
struct ContentElement {
    heading: String,
    text: Option<String>,
    num1: i32,
    num2: Option<i32>,
}

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 i < last_index [
    #pagebreak()
  ]
]

Run example with cargo r --example small_example.

Some links, idk