diff options
author | Qrius <[email protected]> | 2024-09-26 00:11:05 +0200 |
---|---|---|
committer | Qrius <[email protected]> | 2024-09-26 00:11:05 +0200 |
commit | 4eaf1f1327d0b88a6a5f937bb646753e639d4be7 (patch) | |
tree | 121c79510bf5f26b569c2f789130cb06b0398b27 | |
parent | eb2a8c1ac8db20d176b1af6a2ea26a5b27b996d9 (diff) | |
download | skaldpress-4eaf1f1327d0b88a6a5f937bb646753e639d4be7.tar.gz skaldpress-4eaf1f1327d0b88a6a5f937bb646753e639d4be7.zip |
Add ability to nest templates, improve a bunch of other things
-rw-r--r-- | src/skaldpress/error.rs | 4 | ||||
-rw-r--r-- | src/skaldpress/main.rs | 105 | ||||
-rw-r--r-- | src/skaldpress/metadata_parser.rs | 23 |
3 files changed, 110 insertions, 22 deletions
diff --git a/src/skaldpress/error.rs b/src/skaldpress/error.rs index 9c84dd1..83b5253 100644 --- a/src/skaldpress/error.rs +++ b/src/skaldpress/error.rs @@ -15,6 +15,7 @@ pub enum SkaldpressError { DirectoryReadError(u8, std::io::Error, String), PathOperationError(u8, Option<Box<dyn Error>>), DirectoryCreateError(u8, std::io::Error, String), + MetadataError(u8, std::io::Error), SMPError(u8, SMPError), } @@ -36,6 +37,9 @@ impl fmt::Display for SkaldpressError { SkaldpressError::DirectoryCreateError(code, _, dir) => { write!(f, "[SP{}] Directory create error \"{}\"", code, dir) } + SkaldpressError::MetadataError(code, e) => { + write!(f, "[SP{}] Invalid metadata! \"{:#?}\"", code, e) + } SkaldpressError::SMPError(code, e) => { write!(f, "[SP{}] Macro processing error \"{:#?}\"", code, e) } diff --git a/src/skaldpress/main.rs b/src/skaldpress/main.rs index 1664272..84a4285 100644 --- a/src/skaldpress/main.rs +++ b/src/skaldpress/main.rs @@ -105,6 +105,55 @@ fn macro_processor( macro_processor } +fn get_template_path(template: &str, opts: &Opts) -> String { + format!("{}{}", opts.template_dir, template) +} + +fn wrap_template( + macro_processor: &mut MacroProcessor, + template_file: &str, + file_content: &str, + opts: &Opts, +) -> Result<(String, String), SkaldpressError> { + let template = fs::read_to_string(&template_file).map_err(|e| { + SkaldpressError::TemplateReadError( + SP_COMPILE_FILE_TEMPLATE_READ_ERROR, + e, + template_file.to_string(), + ) + })?; + let template_extension = Path::new(&template_file) + .extension() + .unwrap_or(std::ffi::OsStr::new("")); + + let (template_metadata, template_content) = match extract_parse_yaml_metadata(&template) { + Some((map, file_content)) => (map, file_content), + None => (HashMap::new(), template.as_str()), + }; + + macro_processor.define_macro_string(String::from("CONTENT"), file_content.to_string()); + let content = macro_processor + .process_input(&template_content) + .map_err(|e| SkaldpressError::SMPError(SP_COMPILE_TEMPLATE_MACRO_PROCESS_ERROR, e))?; + + let Some(template_parent) = &template_metadata.get("template") else { + return Ok(( + content, + template_extension.to_str().unwrap_or("").to_string(), + )); + }; + let template_parent = &TryInto::<String>::try_into(*template_parent) + .map_err(|e| SkaldpressError::MetadataError(12, std::io::Error::other(e)))?; + + println!("Wrapping in template {}", template_parent); + wrap_template( + macro_processor, + &get_template_path(template_parent, opts), + &content, + opts, + ) +} + /// Will attempt to compile a specific file, potentially storing some state about the file fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, SkaldpressError> { let extension = file_path.extension().unwrap_or(std::ffi::OsStr::new("")); @@ -116,7 +165,10 @@ fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, Skaldpres file_path.to_str().unwrap_or("unknown file").to_string(), ) })?; - let (map, file_content) = extract_parse_yaml_metadata(&file_content); + let (map, file_content) = match extract_parse_yaml_metadata(&file_content) { + Some((map, file_content)) => (map, file_content), + None => (HashMap::new(), file_content.as_str()), + }; let file_content = match extension .to_str() .ok_or(SkaldpressError::PathOperationError( @@ -127,6 +179,19 @@ fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, Skaldpres _ => file_content.to_string(), }; + if let Some(skip_smp) = &map.get("skip_smp") { + if let YamlValue::Scalar(skip_smp) = skip_smp { + if skip_smp.to_lowercase() == "true" { + return Ok(CompiledFile { + content: file_content, + metadata: map, + extension: String::from(extension.to_str().unwrap_or("")), + source_path: String::from(file_path.to_str().unwrap_or("")), + }); + } + } + } + let mut macro_processor = macro_processor(&map, None); let Some(template) = &map.get("template") else { @@ -141,26 +206,19 @@ fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, Skaldpres }); }; - let template_file = format!("{}{}", opts.template_dir, template); - let template = fs::read_to_string(&template_file).map_err(|e| { - SkaldpressError::TemplateReadError( - SP_COMPILE_FILE_TEMPLATE_READ_ERROR, - e, - template_file.clone(), - ) - })?; - let template_extension = Path::new(&template_file) - .extension() - .unwrap_or(std::ffi::OsStr::new("")); + let template_file = get_template_path( + &TryInto::<String>::try_into(*template) + .map_err(|e| SkaldpressError::MetadataError(12, std::io::Error::other(e)))?, + opts, + ); + + let (content, template_extension) = + wrap_template(&mut macro_processor, &template_file, &file_content, opts)?; - macro_processor.define_macro_string(String::from("CONTENT"), file_content); - let content = macro_processor - .process_input(&template) - .map_err(|e| SkaldpressError::SMPError(SP_COMPILE_TEMPLATE_MACRO_PROCESS_ERROR, e))?; Ok(CompiledFile { content, metadata: map, - extension: String::from(template_extension.to_str().unwrap_or("")), + extension: String::from(template_extension), source_path: String::from(file_path.to_str().unwrap_or("")), }) } @@ -228,7 +286,7 @@ fn compile_file_and_write( } } - let dest_file_path = Path::new(&opts.build_dir) + let mut dest_file_path = Path::new(&opts.build_dir) .join( source_file_path .strip_prefix(&opts.content_dir) @@ -241,6 +299,17 @@ fn compile_file_and_write( ) .with_extension(&cfile.extension); + if let Some(target_filename) = cfile.metadata.get("target_filename") { + match target_filename { + YamlValue::Scalar(filename) => { + dest_file_path = dest_file_path + .with_file_name(filename) + .with_extension(&cfile.extension) + } + _ => (), + } + } + let dest_dir = &dest_file_path .parent() .ok_or(SkaldpressError::PathOperationError(5, None))?; diff --git a/src/skaldpress/metadata_parser.rs b/src/skaldpress/metadata_parser.rs index 77ee7b8..4d6e352 100644 --- a/src/skaldpress/metadata_parser.rs +++ b/src/skaldpress/metadata_parser.rs @@ -16,10 +16,21 @@ impl fmt::Display for YamlValue { } } +impl TryFrom<&YamlValue> for String { + type Error = String; + + fn try_from(s: &YamlValue) -> Result<String, String> { + match s { + YamlValue::Scalar(s) => Ok(String::from(s)), + YamlValue::List(_) => Err(String::from("List value cannot be turned into string")), + } + } +} + /// Extract a beginning YAML block of a input-string into a HashMap -/// -/// Currently, all files MUST have a metadata block, or this will fail completely -pub fn extract_parse_yaml_metadata<'a>(markdown: &'a str) -> (HashMap<String, YamlValue>, &'a str) { +pub fn extract_parse_yaml_metadata<'a>( + markdown: &'a str, +) -> Option<(HashMap<String, YamlValue>, &'a str)> { let mut yaml_map = HashMap::new(); let lines = markdown.lines(); let mut yaml_started = false; @@ -28,6 +39,10 @@ pub fn extract_parse_yaml_metadata<'a>(markdown: &'a str) -> (HashMap<String, Ya let mut current_key: Option<String> = None; let mut current_list: Vec<String> = Vec::new(); + if lines.clone().next().unwrap_or("").trim() != "---" { + return None; + } + for (i, line) in lines.enumerate() { if line.trim() == "---" { if yaml_started { @@ -69,5 +84,5 @@ pub fn extract_parse_yaml_metadata<'a>(markdown: &'a str) -> (HashMap<String, Ya end_index = markdown.len(); } - (yaml_map, &markdown[end_index..]) + Some((yaml_map, &markdown[end_index..])) } |