diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/skaldpress/main.rs | 34 | ||||
-rw-r--r-- | src/skaldpress/metadata_parser.rs | 56 |
2 files changed, 84 insertions, 6 deletions
diff --git a/src/skaldpress/main.rs b/src/skaldpress/main.rs index 84a4285..45d0a78 100644 --- a/src/skaldpress/main.rs +++ b/src/skaldpress/main.rs @@ -33,6 +33,13 @@ struct CompiledFile { source_path: String, } +/// SMP Macro for processing input with a template +/// +/// This will keep state of the macro_processor from the document which invokes the macro. +/// No additional metadata will be added. +/// +/// Usage in files: +/// template(<template>, <content>) fn sp_template( smp: &mut MacroProcessor, macro_name: &str, @@ -50,6 +57,10 @@ fn sp_template( smp.process_input(&template) } +/// SMP Macro for getting all files with specific tag, this is only _really_ effective the second run +/// +/// Usage in files: +/// all_tagged_by(<tag name>, <template> [, <field to sort by>] [, reversed]) fn sp_all_tagged_by( smp: &mut MacroProcessor, macro_name: &str, @@ -72,8 +83,29 @@ fn sp_all_tagged_by( let mut out = String::new(); + let mut tagged_files = tagged_files.clone(); + if args.len() > 2 { + if args.len() > 3 && args[3] == "reversed" { + tagged_files.sort_by(|a, b| { + *(&compiled_files[*b] + .metadata + .get(&args[2]) + .unwrap() + .cmp(&compiled_files[*a].metadata.get(&args[2]).unwrap())) + }); + } else { + tagged_files.sort_by(|a, b| { + *(&compiled_files[*a] + .metadata + .get(&args[2]) + .unwrap() + .cmp(&compiled_files[*b].metadata.get(&args[2]).unwrap())) + }); + } + } + for doc_i in tagged_files { - let file = &compiled_files[*doc_i]; + let file = &compiled_files[doc_i]; let mut smp_local = macro_processor(&file.metadata, Some(smp)); out.push_str(&sp_template( &mut smp_local, diff --git a/src/skaldpress/metadata_parser.rs b/src/skaldpress/metadata_parser.rs index 4d6e352..a2abcc2 100644 --- a/src/skaldpress/metadata_parser.rs +++ b/src/skaldpress/metadata_parser.rs @@ -1,9 +1,14 @@ +#[cfg(feature = "time")] +use chrono::DateTime; +use std::cmp::Ordering; use std::collections::HashMap; use std::fmt; -#[derive(Debug)] +#[derive(Eq, PartialEq, Debug)] pub enum YamlValue { Scalar(String), + Integer(i64), + Date(String, i64), List(Vec<String>), } @@ -11,6 +16,8 @@ impl fmt::Display for YamlValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { YamlValue::Scalar(x) => write!(f, "{}", x), + YamlValue::Integer(x) => write!(f, "{}", x), + YamlValue::Date(x, _) => write!(f, "{}", x), YamlValue::List(_l) => write!(f, "List<String>"), } } @@ -22,11 +29,53 @@ impl TryFrom<&YamlValue> for String { fn try_from(s: &YamlValue) -> Result<String, String> { match s { YamlValue::Scalar(s) => Ok(String::from(s)), + YamlValue::Integer(s) => Ok(s.to_string()), + YamlValue::Date(s, _) => Ok(s.to_string()), YamlValue::List(_) => Err(String::from("List value cannot be turned into string")), } } } +impl PartialOrd for YamlValue { + fn partial_cmp(&self, other: &YamlValue) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Ord for YamlValue { + fn cmp(&self, other: &YamlValue) -> Ordering { + if let YamlValue::Integer(a_int) = self { + if let YamlValue::Integer(b_int) = other { + return a_int.cmp(b_int); + } + } + if let YamlValue::Scalar(a_str) = self { + if let YamlValue::Scalar(b_str) = other { + return a_str.cmp(b_str); + } + } + if let YamlValue::Date(_, a_timestamp) = self { + if let YamlValue::Date(_, b_timestamp) = other { + return a_timestamp.cmp(b_timestamp); + } + } + self.to_string().cmp(&other.to_string()) + } +} + +fn str_to_yaml_value(in_str: &str) -> YamlValue { + let in_str = in_str.trim(); + if let Ok(int) = in_str.parse::<i64>() { + return YamlValue::Integer(int); + } + #[cfg(feature = "time")] + if let Ok(dt) = DateTime::parse_from_rfc3339(in_str) { + return YamlValue::Date(in_str.to_string(), dt.timestamp()); + } + + YamlValue::Scalar(in_str.to_string()) +} + /// Extract a beginning YAML block of a input-string into a HashMap pub fn extract_parse_yaml_metadata<'a>( markdown: &'a str, @@ -64,10 +113,7 @@ pub fn extract_parse_yaml_metadata<'a>( } current_key = Some(key.trim().to_string()); if !value.trim().is_empty() { - yaml_map.insert( - current_key.clone().unwrap(), - YamlValue::Scalar(value.trim().to_string()), - ); + yaml_map.insert(current_key.clone().unwrap(), str_to_yaml_value(value)); current_key = None; } } |