Skip to main content

typst_bake/
error.rs

1//! Error types for typst-bake.
2
3use std::fmt;
4
5use thiserror::Error;
6
7/// A source location (file, line, column) within a Typst source file.
8///
9/// Line and column are 1-based; the column counts characters from the start of
10/// the line, matching the Typst CLI's reporting.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct SourceLocation {
13    /// Path of the source file, e.g. `reports/event_report/report.typ`.
14    pub file: String,
15    /// 1-based line number.
16    pub line: usize,
17    /// 1-based column number (character count within the line).
18    pub column: usize,
19}
20
21impl fmt::Display for SourceLocation {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        write!(f, "{}:{}:{}", self.file, self.line, self.column)
24    }
25}
26
27/// A single Typst compilation diagnostic with resolved source location.
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub struct Diagnostic {
30    /// Where the error occurred, if it points into a source file.
31    pub location: Option<SourceLocation>,
32    /// The diagnostic message.
33    pub message: String,
34    /// Additional hints the compiler provided.
35    pub hints: Vec<String>,
36    /// The chain of call/import sites leading to the error (may be empty).
37    pub trace: Vec<SourceLocation>,
38}
39
40impl fmt::Display for Diagnostic {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        match &self.location {
43            Some(loc) => write!(f, "{loc}: error: {}", self.message)?,
44            None => write!(f, "error: {}", self.message)?,
45        }
46        for hint in &self.hints {
47            write!(f, "\n  hint: {hint}")?;
48        }
49        for site in &self.trace {
50            write!(f, "\n  called from: {site}")?;
51        }
52        Ok(())
53    }
54}
55
56/// Format a list of diagnostics, one per line, for the `Compilation` error.
57fn format_diagnostics(diagnostics: &[Diagnostic]) -> String {
58    diagnostics
59        .iter()
60        .map(|d| d.to_string())
61        .collect::<Vec<_>>()
62        .join("\n")
63}
64
65/// Errors that can occur during document compilation and rendering.
66#[derive(Error, Debug)]
67pub enum Error {
68    /// Entry file was not found in the embedded templates.
69    #[error("entry file not found: {0}")]
70    EntryNotFound(&'static str),
71
72    /// Entry file content is not valid UTF-8.
73    #[error("entry file is not valid UTF-8")]
74    InvalidUtf8,
75
76    /// Typst compilation failed.
77    #[error("compilation failed:\n{}", format_diagnostics(.0))]
78    Compilation(Vec<Diagnostic>),
79
80    /// PDF generation failed.
81    #[error("PDF generation failed: {0}")]
82    PdfGeneration(String),
83
84    /// PNG encoding failed.
85    #[error("PNG encoding failed: {0}")]
86    PngEncoding(String),
87
88    /// Invalid file path provided for runtime file injection.
89    #[error("invalid file path: {0}")]
90    InvalidFilePath(String),
91
92    /// Invalid page selection (empty or out of range).
93    #[error("invalid page selection: {0}")]
94    InvalidPageSelection(String),
95
96    /// Invalid PDF configuration (e.g. a standard/tagging conflict or bad timestamp).
97    #[error("invalid PDF config: {0}")]
98    InvalidPdfConfig(String),
99
100    /// Decompression of embedded content failed.
101    #[error("decompression failed")]
102    Decompression(#[from] std::io::Error),
103}
104
105/// A specialized Result type for typst-bake operations.
106pub type Result<T> = std::result::Result<T, Error>;