diff --git a/src/compiler/compiler.rs b/src/compiler/compiler.rs index 3d30b39..095e346 100644 --- a/src/compiler/compiler.rs +++ b/src/compiler/compiler.rs @@ -74,8 +74,8 @@ impl Compiler { self.cache.as_ref().map(RefCell::borrow_mut) } - pub fn sanitize>(&self, str: S) -> String { - match self.target { + pub fn sanitize>(target: Target, str: S) -> String { + match target { Target::HTML => str .as_ref() .replace("&", "&") @@ -109,14 +109,14 @@ impl Compiler { result += ""; result += ""; if let Some(page_title) = get_variable_or_error(document, "html.page_title") { - result += format!("{}", self.sanitize(page_title.to_string())) + result += format!("{}", Compiler::sanitize(self.target(), page_title.to_string())) .as_str(); } if let Some(css) = document.get_variable("html.css") { result += format!( "", - self.sanitize(css.to_string()) + Compiler::sanitize(self.target(), css.to_string()) ) .as_str(); } diff --git a/src/compiler/navigation.rs b/src/compiler/navigation.rs index 43dd8a8..cc424ea 100644 --- a/src/compiler/navigation.rs +++ b/src/compiler/navigation.rs @@ -1,47 +1,73 @@ use std::collections::HashMap; +use crate::compiler::compiler::Compiler; + use super::compiler::CompiledDocument; use super::compiler::Target; -#[derive(Debug)] +#[derive(Debug, Default)] pub struct NavEntry { - pub(crate) name: String, - pub(crate) path: Option, - pub(crate) children: Option>, + pub(self) entries: Vec<(String, String)>, + pub(self) children: HashMap, } -#[derive(Debug)] -pub struct Navigation { - pub(crate) entries: HashMap, -} +impl NavEntry { + // FIXME: Sanitize + pub fn compile(&self, target: Target, doc: &CompiledDocument) -> String { + let categories = vec![ + doc.get_variable("nav.category").map_or("", |s| s.as_str()), + doc.get_variable("nav.subcategory") + .map_or("", |s| s.as_str()), + ]; -impl Navigation { - pub fn compile(&self, target: Target) -> String { let mut result = String::new(); match target { Target::HTML => { result += r#""); } } - for (name, ent) in &self.entries { - process(&mut result, name, ent, 0); - } + process(target, &categories, true, &mut result, self, 0); result += r#""#; } @@ -51,9 +77,10 @@ impl Navigation { } } -pub fn create_navigation(docs: &Vec) -> Result { - let mut nav = Navigation { - entries: HashMap::new(), +pub fn create_navigation(docs: &Vec) -> Result { + let mut nav = NavEntry { + entries: vec![], + children: HashMap::new(), }; for doc in docs { @@ -64,71 +91,60 @@ pub fn create_navigation(docs: &Vec) -> Result (cat, title, path), + let (title, path) = match (title, path) { + (Some(title), Some(path)) => (title, path), _ => { - println!("Skipping navigation generation for `{}`", doc.input); + eprintln!("Skipping navigation generation for `{}`, must have a defined `@nav.title` and `@compiler.output`", doc.input); continue; } }; - if let Some(subcat) = subcat { - // Get parent entry - let mut pent = match nav.entries.get_mut(cat.as_str()) { - Some(pent) => pent, + let pent = if let Some(subcat) = subcat { + let cat = match cat { + Some(cat) => cat, None => { - // Create parent entry - nav.entries.insert( - cat.clone(), - NavEntry { - name: cat.clone(), - path: None, - children: Some(HashMap::new()), - }, + eprintln!( + "Skipping `{}`: No `@nav.category`, but `@nav.subcategory` is set", + doc.input ); - nav.entries.get_mut(cat.as_str()).unwrap() + continue; } }; - // Insert into parent - if let Some(previous) = pent.children.as_mut().unwrap().insert( - subcat.clone(), - NavEntry { - name: subcat.clone(), - path: Some(path.to_string()), - children: None, - }, - ) { - return Err(format!( - "Duplicate subcategory:\n{subcat}\nclashes with:\n{previous:#?}" - )); + let mut cat_ent = match nav.children.get_mut(cat.as_str()) { + Some(cat_ent) => cat_ent, + None => { + // Insert + nav.children.insert(cat.clone(), NavEntry::default()); + nav.children.get_mut(cat.as_str()).unwrap() + } + }; + + match cat_ent.children.get_mut(subcat.as_str()) { + Some(subcat_ent) => subcat_ent, + None => { + // Insert + cat_ent.children.insert(subcat.clone(), NavEntry::default()); + cat_ent.children.get_mut(subcat.as_str()).unwrap() + } + } + } else if let Some(cat) = cat { + match nav.children.get_mut(cat.as_str()) { + Some(cat_ent) => cat_ent, + None => { + // Insert + nav.children.insert(cat.clone(), NavEntry::default()); + nav.children.get_mut(cat.as_str()).unwrap() + } } } else { - // Get entry - let mut ent = match nav.entries.get_mut(cat.as_str()) { - Some(ent) => ent, - None => { - // Create parent entry - nav.entries.insert( - cat.clone(), - NavEntry { - name: cat.clone(), - path: None, - children: Some(HashMap::new()), - }, - ); - nav.entries.get_mut(cat.as_str()).unwrap() - } - }; + &mut nav + }; - if let Some(path) = ent.path.as_ref() { - return Err(format!( - "Duplicate category:\n{subcat:#?}\nwith previous path:\n{path}" - )); - } - ent.path = Some(path.to_string()); - } + pent.entries.push((title.clone(), path.clone())) } + println!("{nav:#?}"); + Ok(nav) } diff --git a/src/elements/code.rs b/src/elements/code.rs index 1ee9274..09eceed 100644 --- a/src/elements/code.rs +++ b/src/elements/code.rs @@ -117,7 +117,7 @@ impl Code { if let Some(name) = &self.name { result += format!( "
{}
", - compiler.sanitize(name.as_str()) + Compiler::sanitize(compiler.target(), name.as_str()) ) .as_str(); } @@ -612,7 +612,13 @@ impl RegexRule for CodeRule { bindings.push(( "push_block".to_string(), lua.create_function( - |_, (language, name, content, line_offset): (String, Option, String, Option)| { + |_, + (language, name, content, line_offset): ( + String, + Option, + String, + Option, + )| { CTX.with_borrow(|ctx| { ctx.as_ref().map(|ctx| { let theme = ctx diff --git a/src/elements/link.rs b/src/elements/link.rs index 3e79f0e..6869c63 100644 --- a/src/elements/link.rs +++ b/src/elements/link.rs @@ -45,13 +45,13 @@ impl Element for Link { match compiler.target() { Target::HTML => Ok(format!( "{}", - compiler.sanitize(self.url.as_str()), - compiler.sanitize(self.name.as_str()), + Compiler::sanitize(compiler.target(), self.url.as_str()), + Compiler::sanitize(compiler.target(), self.name.as_str()), )), Target::LATEX => Ok(format!( "\\href{{{}}}{{{}}}", - compiler.sanitize(self.url.as_str()), - compiler.sanitize(self.name.as_str()), + Compiler::sanitize(compiler.target(), self.url.as_str()), + Compiler::sanitize(compiler.target(), self.name.as_str()), )), } } diff --git a/src/elements/media.rs b/src/elements/media.rs index c1a7d9c..3499d65 100644 --- a/src/elements/media.rs +++ b/src/elements/media.rs @@ -150,18 +150,26 @@ impl Element for Medium { .map_or(String::new(), |w| format!(r#" style="width:{w};""#)); result.push_str(format!(r#"
"#).as_str()); result += match self.media_type { - MediaType::IMAGE => - format!(r#""#, self.uri), - MediaType::VIDEO => - format!(r#""#, self.uri), - MediaType::AUDIO => - format!(r#""#, self.uri), - }.as_str(); + MediaType::IMAGE => format!(r#""#, self.uri), + MediaType::VIDEO => format!( + r#""#, + self.uri + ), + MediaType::AUDIO => { + format!(r#""#, self.uri) + } + } + .as_str(); let caption = self .caption .as_ref() - .and_then(|cap| Some(format!(" {}", compiler.sanitize(cap.as_str())))) + .and_then(|cap| { + Some(format!( + " {}", + Compiler::sanitize(compiler.target(), cap.as_str()) + )) + }) .unwrap_or(String::new()); // Reference diff --git a/src/elements/section.rs b/src/elements/section.rs index 7638610..a319866 100644 --- a/src/elements/section.rs +++ b/src/elements/section.rs @@ -41,7 +41,7 @@ impl Element for Section { Target::HTML => Ok(format!( "{1}", self.depth, - compiler.sanitize(self.title.as_str()) + Compiler::sanitize(compiler.target(), self.title.as_str()) )), Target::LATEX => Err("Unimplemented compiler".to_string()), } diff --git a/src/elements/text.rs b/src/elements/text.rs index 2f4f04a..cf0a2ac 100644 --- a/src/elements/text.rs +++ b/src/elements/text.rs @@ -39,7 +39,7 @@ impl Element for Text { fn to_string(&self) -> String { format!("{self:#?}") } fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result { - Ok(compiler.sanitize(self.content.as_str())) + Ok(Compiler::sanitize(compiler.target(), self.content.as_str())) } } diff --git a/src/main.rs b/src/main.rs index 02be5b3..6a7f824 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,6 @@ mod lua; mod parser; use std::env; -use std::fs::OpenOptions; use std::io::BufWriter; use std::io::Write; use std::process::ExitCode; @@ -18,7 +17,6 @@ use compiler::compiler::CompiledDocument; use compiler::compiler::Compiler; use compiler::compiler::Target; use compiler::navigation::create_navigation; -use compiler::navigation::Navigation; use document::document::Document; use getopts::Options; use parser::langparser::LangParser; @@ -275,7 +273,6 @@ fn main() -> ExitCode { return ExitCode::FAILURE; } }; - let compiled_navigation = navigation.compile(Target::HTML); // Output for doc in compiled { @@ -290,15 +287,17 @@ fn main() -> ExitCode { } }; + let nav = navigation.compile(Target::HTML, &doc); + let file = std::fs::File::create(output.clone() + "/" + out_path.as_str()).unwrap(); let mut writer = BufWriter::new(file); write!( writer, "{}{}{}{}", - doc.header, compiled_navigation, doc.body, doc.footer - ); - writer.flush(); + doc.header, nav, doc.body, doc.footer + ).unwrap(); + writer.flush().unwrap(); } return ExitCode::SUCCESS;