typst-bake 0.1.9

Bake Typst templates, fonts, and packages into your Rust binary — use Typst as a self-contained, embedded library
Documentation
#![cfg_attr(docsrs, feature(doc_cfg))]

//! # typst-bake
//!
//! Bake Typst templates, fonts, and packages into your Rust binary — use Typst
//! as a self-contained, embedded library.
//!
//! ## Cargo Features
//!
//! - **`pdf`** (default) - Enable PDF generation via [`Document::to_pdf`]
//! - **`svg`** - Enable SVG generation via [`Document::to_svg`]
//! - **`png`** - Enable PNG rasterization via [`Document::to_png`]
//! - **`full`** - Enable all output formats
//!
//! ## Features
//!
//! - **Multiple Output Formats** - Generate PDF, SVG, or PNG from the same template
//! - **File Embedding** - All files in `template-dir` are embedded and accessible from `.typ` files
//! - **Font Embedding** - Fonts (TTF, OTF, TTC) in `fonts-dir` are automatically bundled
//! - **Package Bundling** - Scans for package imports and recursively resolves all dependencies
//! - **Optimized Binary Size** - Resources are compressed with zstd and decompressed lazily at runtime
//! - **Runtime Inputs** - Pass dynamic data from Rust structs to Typst via [`IntoValue`] / [`IntoDict`] derive macros
//! - **Page Selection** - Select specific pages for output via [`Document::select_pages`]
//!
//! ## Quick Start
//!
//! Add to your `Cargo.toml`:
//! ```toml
//! [package.metadata.typst-bake]
//! template-dir = "./templates"
//! fonts-dir = "./fonts"
//!
//! [dependencies]
//! typst-bake = "0.1"
//! ```
//!
//! Then use the [`document!`] macro:
//! ```rust,ignore
//! // Generate PDF
//! let pdf = typst_bake::document!("main.typ").to_pdf()?;
//!
//! // Generate SVG (one per page)
//! let svgs = typst_bake::document!("main.typ").to_svg()?;
//!
//! // Generate PNG at 144 DPI (Retina)
//! let pngs = typst_bake::document!("main.typ").to_png(144.0)?;
//! ```

mod build;
mod document;
mod error;
mod resolver;
mod stats;
mod util;

pub use build::rebuild_if_changed;
pub use document::{Document, Pages};
pub use error::{Error, Result};
pub use stats::{
    CategoryStats, DedupStats, EmbedStats, HasCompressionRatio, PackageInfo, PackageStats,
};
/// Creates a [`Document`] with embedded templates, fonts, and packages.
///
/// # Usage
///
/// ```rust,ignore
/// // Generate PDF
/// let pdf = typst_bake::document!("main.typ").to_pdf()?;
///
/// // Generate SVG (one per page)
/// let svgs = typst_bake::document!("main.typ").to_svg()?;
///
/// // Generate PNG at 144 DPI (Retina)
/// let pngs = typst_bake::document!("main.typ").to_png(144.0)?;
/// ```
///
/// # Configuration
///
/// Add to your `Cargo.toml`:
/// ```toml
/// [package.metadata.typst-bake]
/// template-dir = "./templates"
/// fonts-dir = "./fonts"
/// ```
///
/// # What Gets Embedded
///
/// - **Templates**: All files in `template-dir` are embedded and accessible from `.typ` files.
///   Paths resolve relative to the referring `.typ` file.
/// - **Fonts**: Only supported font formats (TTF, OTF, TTC) are embedded. At least one font
///   is required; without fonts, Typst produces invisible text.
/// - **Packages**: Using packages requires no manual setup. Just use `#import "@preview/..."`
///   or `#import "@local/..."` as you normally would in Typst. The macro scans for package
///   imports and recursively resolves all dependencies at compile time. Shares Typst's own
///   package directories, so locally installed packages are picked up automatically.
pub use typst_bake_macros::document;

/// Derive macro for converting a struct to a Typst value.
///
/// All structs that will be passed to Typst templates (directly or nested) must derive this.
///
/// - **Top-level struct**: Use both [`IntoValue`] and [`IntoDict`]
/// - **Nested structs**: Use [`IntoValue`] only
///
/// # Example
///
/// ```rust,ignore
/// use typst_bake::{IntoValue, IntoDict};
///
/// #[derive(IntoValue, IntoDict)]  // Top-level: both macros
/// struct Inputs {
///     title: String,
///     products: Vec<Product>,
/// }
///
/// #[derive(IntoValue)]  // Nested: IntoValue only
/// struct Product {
///     name: String,
///     price: f64,
/// }
/// ```
///
/// In `.typ` files, nested structs are accessed as dictionaries:
/// ```typ
/// #for product in inputs.products [
///   - #product.name: $#product.price
/// ]
/// ```
pub use typst_bake_macros::IntoValue;

/// Derive macro for converting a struct to a Typst dictionary.
///
/// Only the top-level struct passed to [`Document::with_inputs`] needs this.
/// Nested structs should only derive [`IntoValue`].
///
/// # Example
///
/// ```rust,ignore
/// use typst_bake::{IntoValue, IntoDict};
///
/// #[derive(IntoValue, IntoDict)]  // Top-level: both macros
/// struct Inputs {
///     title: String,
///     items: Vec<Item>,
/// }
///
/// #[derive(IntoValue)]  // Nested: IntoValue only
/// struct Item {
///     name: String,
///     price: f64,
/// }
///
/// let pdf = typst_bake::document!("main.typ")
///     .with_inputs(Inputs { /* ... */ })
///     .to_pdf()?;
/// ```
pub use typst_bake_macros::IntoDict;

/// Re-export include_dir for macro-generated code.
#[doc(hidden)]
pub use include_dir;

/// Internal module for macro-generated code.
/// Do not use directly.
#[doc(hidden)]
pub mod __internal {
    pub use super::document::Document;
    pub use include_dir::Dir;
    // Re-export include_dir crate for direct struct construction
    pub use include_dir;
    // Re-export typst crate for derive macros
    pub use typst;
}