Skip to main content

mdbook_typstpdf/config/
mod.rs

1use std::{collections::HashMap, path::PathBuf};
2
3pub mod book;
4pub mod chapter;
5pub mod renderer;
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Debug, Serialize, Deserialize)]
9#[serde(rename_all = "kebab-case")]
10pub struct Config {
11    /// the typst template directory that holds all templates you can reference
12    #[serde(rename = "template_dir", default = "get_default_template_dir")]
13    pub template_dir: String, // the directory of the templates, default is "./typst-template"
14
15    /// the list of template name and template file name.
16    /// this tool will generate a pdf file for each template
17    /// if no template is provided, it will generate a default pdf file without template.
18    #[serde(rename = "templates", default = "Default::default")]
19    pub templates: HashMap<String, String>, // template name -> template path, the template name will be the name for pdf output
20
21    /// whether the intermidate typst files for each chapter should be kept or not.
22    #[serde(rename = "keep_typst_files", default = "Default::default")]
23    pub keep_typst_files: bool, // whether to keep the preprocessed files, typst files
24
25    /// parameter and value pairs for template use.
26    /// you can define your value pair that match your template definition.
27    #[serde(
28        rename = "template_parameters",
29        default = "get_default_template_parameters"
30    )]
31    pub template_parameters: HashMap<String, String>, // the parameters for the template, default is empty
32
33    /// option multi-lines string that can be imported at the beginning of each chapter.
34    /// it's very useful when you want to add the import statements for popular typst external functions.
35    #[serde(rename = "chapter_imports")]
36    pub chapter_imports: Option<String>, // it will be a multi-lines string
37
38    /// max_width in a floating number between 0.0 and 1.0 (include).
39    /// this constraint will only be applied when the max height already meets the requirement.
40    #[serde(rename = "max_width", default = "Default::default")]
41    pub max_width: Option<f64>,
42
43    /// max_height in a floating number between 0.0 and 1.0 (include).
44    #[serde(rename = "max_height", default = "Default::default")]
45    pub max_height: Option<f64>,
46}
47
48impl Default for Config {
49    fn default() -> Self {
50        Self {
51            // output_dir: get_default_output_dir(),
52            template_dir: get_default_template_dir(),
53            templates: HashMap::new(),
54            keep_typst_files: false,
55            template_parameters: get_default_template_parameters(),
56            chapter_imports: None,
57            max_width: None,
58            max_height: None,
59        }
60    }
61}
62pub const TARGET_TEMPLATE_DIR: &str = "templates";
63pub const TARGET_CHAPTERS_DIR: &str = "chapters";
64pub const TARGET_TYPST_DIR: &str = "typst";
65pub const TARGET_PDF_DIR: &str = "pdf";
66pub const BEST_PRACTICE_TEMPLATE: &str = "best_practice_template";
67
68pub const IMAGE_DIR: &str = "__images";
69
70impl Config {
71    pub fn get_book_name(
72        &self,
73        template_name: Option<&str>,
74        ctx: &mdbook_renderer::RenderContext,
75    ) -> String {
76        // doesn't include the extension
77        // it can be typ or pdf
78        let root_name = ctx.root.file_name().unwrap().to_str().unwrap();
79        let root_name = if root_name.is_empty() {
80            "book"
81        } else {
82            root_name
83        };
84        match template_name {
85            Some(template_name) => format!("{}-{}", root_name, template_name),
86            None => root_name.to_string(),
87        }
88    }
89    pub fn get_template_dir(&self, ctx: &mdbook_renderer::RenderContext) -> PathBuf {
90        // this is the directory of the source templates
91        let template_path = std::path::Path::new(&self.template_dir);
92
93        if template_path.is_absolute() {
94            PathBuf::from(&self.template_dir)
95        } else {
96            ctx.root.clone().join(&self.template_dir)
97        }
98    }
99
100    pub fn get_typst_dir(&self, ctx: &mdbook_renderer::RenderContext) -> PathBuf {
101        let typst_pdf_dir = self.get_output_dir(ctx);
102
103        typst_pdf_dir.join(TARGET_TYPST_DIR)
104    }
105
106    pub fn get_pdf_dir(&self, ctx: &mdbook_renderer::RenderContext) -> PathBuf {
107        let typst_dir = self.get_output_dir(ctx);
108        typst_dir.join(TARGET_PDF_DIR)
109    }
110
111    pub fn get_typst_templates_dir(&self, ctx: &mdbook_renderer::RenderContext) -> PathBuf {
112        // this is the directory of templates to support final typst outputs
113        let typst_dir = self.get_typst_dir(ctx);
114        typst_dir.join(TARGET_TEMPLATE_DIR)
115    }
116
117    pub fn get_chapters_dir(&self, ctx: &mdbook_renderer::RenderContext) -> PathBuf {
118        let typst_dir = self.get_typst_dir(ctx);
119        typst_dir.join(TARGET_CHAPTERS_DIR)
120    }
121
122    pub fn get_output_dir(&self, ctx: &mdbook_renderer::RenderContext) -> PathBuf {
123        ctx.destination.clone()
124    }
125}
126// fn get_default_output_dir() -> Vec<String> {
127//     vec!["book".to_string(),"pdf-output".to_string()]
128// }
129
130fn get_default_template_parameters() -> HashMap<String, String> {
131    let mut result = HashMap::new();
132    // doc_title: "Document Title",
133    // doc_version: "1.0",
134    // abstract: "Document abstract",
135    // doc_author: "Author Name",
136    // author_email: "author@example.com",
137    // doc_date: "January 1, 2023",
138    // software_tested: "Software v1.0",
139    // feedback_email: "feedback@example.com",
140    // reviewers: "Reviewer Names",
141    result.insert("doc_title".to_string(), "Document Title".to_string());
142    result.insert("doc_version".to_string(), "1.0".to_string());
143    result.insert("abstract".to_string(), "Document abstract".to_string());
144    result.insert("doc_author".to_string(), "Author Name".to_string());
145    result.insert("author_email".to_string(), "author@example.com".to_string());
146    result.insert("doc_date".to_string(), "January 1, 2023".to_string());
147    result.insert("software_tested".to_string(), "Software v1.0".to_string());
148    result.insert(
149        "feedback_email".to_string(),
150        "feedback@example.com".to_string(),
151    );
152    result.insert("reviewers".to_string(), "Reviewer Names".to_string());
153    result
154}
155
156fn get_default_template_dir() -> String {
157    "./typst-template".to_string()
158}