cdoc/
parser.rs

1use cdoc_parser::ast::Ast;
2use cdoc_parser::document::Document;
3use serde::{Deserialize, Serialize};
4use thiserror::Error;
5
6use crate::preprocessors::{AstPreprocessor, AstPreprocessorConfig, PreprocessorContext};
7
8#[derive(Serialize, Deserialize, Debug, Clone, Default)]
9pub struct Parser {
10    #[serde(default = "default_preprocessors")]
11    pub preprocessors: Vec<Box<dyn AstPreprocessorConfig>>,
12    #[serde(default, flatten)]
13    pub settings: ParserSettings,
14}
15
16fn default_preprocessors() -> Vec<Box<dyn AstPreprocessorConfig>> {
17    vec![]
18}
19
20/// Additional parser configuration.
21#[derive(Serialize, Deserialize, Debug, Clone, Default)]
22pub struct ParserSettings {
23    /// Include solutions for the [crate::preprocessors::exercises::Exercises] preprocessor.
24    #[serde(default)]
25    pub solutions: bool,
26}
27
28impl Parser {
29    pub fn parse(
30        &self,
31        doc: Document<Ast>,
32        ctx: &PreprocessorContext,
33    ) -> Result<Document<Ast>, anyhow::Error> {
34        let doc_ast = self.run_ast_processors(doc.clone(), ctx)?;
35
36        Ok(doc_ast)
37    }
38
39    pub fn run_ast_processors(
40        &self,
41        doc: Document<Ast>,
42        ctx: &PreprocessorContext,
43    ) -> Result<Document<Ast>, anyhow::Error> {
44        let mut built = self
45            .preprocessors
46            .iter()
47            .map(|p| p.build(ctx, &self.settings))
48            .collect::<anyhow::Result<Vec<Box<dyn AstPreprocessor>>>>()?;
49
50        let doc = built
51            .iter_mut()
52            .try_fold(doc, |c, ast_processor| ast_processor.process(c))?;
53
54        Ok(doc)
55    }
56}
57
58#[allow(unused)]
59struct HeadingNode {
60    id: String,
61    children: Vec<HeadingNode>,
62}
63
64#[derive(Error, Debug)]
65pub enum ParserError {
66    #[error("IO Error: ")]
67    IoError(#[from] std::io::Error),
68
69    #[error("Error in template")]
70    TemplateError(#[from] tera::Error),
71
72    #[error("JSON Error: ")]
73    JSONError(#[from] serde_json::error::Error),
74
75    #[error("Error parsing frontmatter: ")]
76    FrontMatter(#[from] serde_yaml::Error),
77
78    #[error(transparent)]
79    ExtensionError(#[from] crate::preprocessors::Error),
80
81    #[cfg(feature = "katex")]
82    #[error(transparent)]
83    KaTeX(#[from] katex::Error),
84
85    #[error(transparent)]
86    Std(#[from] Box<dyn std::error::Error>),
87
88    #[error(transparent)]
89    Anyhow(#[from] anyhow::Error),
90}
91
92#[cfg(test)]
93mod tests {
94
95    // #[test]
96    // fn test_deserialization() {
97    //     let config = r#"
98    //         {
99    //             "preprocessors": [
100    //                 {
101    //                     "type": "shortcodes",
102    //                     "template": "tp/**",
103    //                     "file_ext": ".html"
104    //                 }
105    //             ],
106    //             "event_processors": []
107    //         }
108    //     "#;
109    //
110    //     let p: Parser = serde_json::from_str(config).unwrap();
111    // }
112}