pub mod config;
pub mod error;
mod world;
#[cfg(feature = "wasm")]
pub mod wasm;
pub use config::Config;
pub use error::{Error, Result};
use std::path::Path;
use typst::diag::{Severity, SourceDiagnostic};
use typst::{World, WorldExt};
pub fn compile(input: &Path, config: &Config) -> Result<Vec<u8>> {
compile_with_warnings(input, config).map(|output| output.pdf)
}
#[derive(Debug, Clone)]
pub struct Output {
pub pdf: Vec<u8>,
pub warnings: Vec<String>,
}
pub fn compile_with_warnings(input: &Path, config: &Config) -> Result<Output> {
if !input.exists() {
return Err(Error::InputNotFound(input.to_path_buf()));
}
let world = world::TypstWorld::from_file(input, config)?;
compile_world(&world)
}
fn compile_world(world: &world::TypstWorld) -> Result<Output> {
let warned = typst::compile(world);
let warnings: Vec<String> = warned
.warnings
.iter()
.map(|warning| format_diagnostic(world, warning))
.collect();
let fail = |errors: typst::ecow::EcoVec<SourceDiagnostic>| {
let mut lines: Vec<String> = errors
.iter()
.map(|error| format_diagnostic(world, error))
.collect();
lines.extend(warnings.iter().cloned());
Error::Compile(lines.join("\n"))
};
let document = warned.output.map_err(fail)?;
let pdf = typst_pdf::pdf(&document, &typst_pdf::PdfOptions::default()).map_err(fail)?;
Ok(Output { pdf, warnings })
}
fn format_diagnostic(world: &world::TypstWorld, diagnostic: &SourceDiagnostic) -> String {
let severity = match diagnostic.severity {
Severity::Error => "error",
Severity::Warning => "warning",
};
let location = diagnostic
.span
.id()
.map(|id| {
let path = world.display_path(id);
let line_column = world.range(diagnostic.span).and_then(|range| {
world
.source(id)
.ok()?
.lines()
.byte_to_line_column(range.start)
});
match line_column {
Some((line, column)) => format!("{path}:{}:{}: ", line + 1, column + 1),
None => format!("{path}: "),
}
})
.unwrap_or_default();
let hints: String = diagnostic
.hints
.iter()
.map(|hint| format!("\n hint: {}", hint.v))
.collect();
format!("{location}{severity}: {}{hints}", diagnostic.message)
}