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 | 40c4bb30c16f52fd9ec4944482dbbb929386ab78 (patch) | |
tree | caaae9b3380f0fd81b2ef8d1cfbaa747488729fb /src | |
parent | 6af9f573fce9c167487e10c7327feff357327d6a (diff) | |
download | skaldpress-40c4bb30c16f52fd9ec4944482dbbb929386ab78.tar.gz skaldpress-40c4bb30c16f52fd9ec4944482dbbb929386ab78.zip |
Fix a bunch of things, add diferent syntax for strings
Diffstat (limited to 'src')
-rw-r--r-- | src/macro_processor/error.rs | 8 | ||||
-rw-r--r-- | src/macro_processor/macro_processor.rs | 88 | ||||
-rw-r--r-- | src/skaldpress/main.rs | 48 |
3 files changed, 104 insertions, 40 deletions
diff --git a/src/macro_processor/error.rs b/src/macro_processor/error.rs index cd94c4d..7661156 100644 --- a/src/macro_processor/error.rs +++ b/src/macro_processor/error.rs @@ -5,6 +5,7 @@ use std::fmt; pub enum SMPError { IncludeError(u8, std::io::Error, String), ShellCommandError(u8, Box<dyn Error>), + MarkdownError(u8, markdown::message::Message), UnknownError(u8, Option<Box<dyn Error>>), } @@ -17,6 +18,13 @@ impl fmt::Display for SMPError { SMPError::ShellCommandError(code, e) => { write!(f, "[SMP{}] Error running shell command \"{:#?}\"", code, e) } + SMPError::MarkdownError(code, message) => { + write!( + f, + "[SMP{}] Error converting markdown \"{:#?}\"", + code, message + ) + } SMPError::UnknownError(code, e) => { write!( f, diff --git a/src/macro_processor/macro_processor.rs b/src/macro_processor/macro_processor.rs index ee7e269..ba28b15 100644 --- a/src/macro_processor/macro_processor.rs +++ b/src/macro_processor/macro_processor.rs @@ -443,6 +443,36 @@ fn smp_builtin_format_time( Ok(format!("{}", dt.format(&args[0]))) } +fn smp_builtin_html_from_markdown( + smp: &mut MacroProcessor, + macro_name: &str, + args: &mut [String], +) -> Result<String, SMPError> { + if args.len() < 1 { + smp.warnings + .push(MacroProcessorWarning::from_macro_invocation( + macro_name, + args, + format!("Wrong number of arguments, expected 1"), + )); + return Ok(macro_name.to_string()); + } + let content = smp.process_input(&args[0])?; + let content = smp.process_input(&content)?; + markdown::to_html_with_options( + &content, + &markdown::Options { + parse: markdown::ParseOptions::gfm(), + compile: markdown::CompileOptions { + allow_dangerous_html: true, + allow_dangerous_protocol: true, + ..markdown::CompileOptions::default() + }, + }, + ) + .map_err(|e| SMPError::MarkdownError(15, e)) +} + fn macro_is_whitespace_deleting(s: &str) -> bool { s.chars().nth(s.len() - 1) == Some('_') } @@ -607,6 +637,11 @@ impl MacroProcessor { String::from("format_time"), MacroType::Function(smp_builtin_format_time), ); + #[cfg(feature = "markdown")] + self.define_macro( + String::from("html_from_markdown"), + MacroType::Function(smp_builtin_html_from_markdown), + ); #[cfg(feature = "webring")] self.define_macro( String::from("webring_rss"), @@ -687,9 +722,6 @@ impl MacroProcessor { match macro_body { MacroType::String(body) => { let mut expanded = body.clone(); - // The expanded macro, should _probably_ be expanded again - // The below is a okay _idea_, but I am not sure if I want to have this syntax for - // functions defined in normal smp code for (i, arg) in args.iter().enumerate() { let placeholder = format!("${}", i); expanded = expanded.replace(&placeholder, arg); @@ -724,16 +756,22 @@ impl MacroProcessor { let mut skip_next_line_ending = false; - let mut in_quote_single = false; - let mut in_quote_double = false; + //let mut current_indent = 0; + //let mut line_text_seen = false; + + // We should keep track of filename, linenumber, and character number on line here + // So we can give sensible error messages - const QUOTE_START: char = '`'; - const QUOTE_END: char = '\''; let mut quote_level = 0; let mut parens_level = 0; - for (i, c) in input.char_indices() { + let mut chars = input.char_indices().peekable(); + while let Some((i, c)) = chars.next() { highlight_debug!(input, macro_name_start, i); + let peek = match chars.peek() { + Some((_, c)) => Some(c), + None => None, + }; match state { ParserState::DNL => { @@ -749,28 +787,31 @@ impl MacroProcessor { continue; } - if c.is_alphanumeric() { - state = ParserState::InMacro; - macro_name.push(c); - } else if c == QUOTE_START { + if c == '%' && peek == Some(&'"') { state = ParserState::InQuotes; quote_level += 1; + chars.next(); + } else if c.is_alphanumeric() { + state = ParserState::InMacro; + macro_name.push(c); } else { output.push(c); } } ParserState::InQuotes => match c { - QUOTE_START => { + '%' if peek == Some(&'"') => { quote_level += 1; - output.push(c); + chars.next(); + output.push_str(r#"%""#); } - QUOTE_END => { + '"' if peek == Some(&'%') => { quote_level -= 1; if quote_level == 0 { state = ParserState::Normal; } else { - output.push(c); + output.push_str(r#""%"#); } + chars.next(); } _ => { output.push(c); @@ -810,6 +851,21 @@ impl MacroProcessor { } } ParserState::InMacroArgs => { + if c == '%' && peek == Some(&'"') { + quote_level += 1; + chars.next(); + argument.push_str(r#"%""#); + continue; + } else if c == '"' && peek == Some(&'%') { + quote_level -= 1; + chars.next(); + argument.push_str(r#""%"#); + continue; + } else if quote_level > 0 { + argument.push(c); + continue; + } + if (c == ')') && (parens_level == 1) { if macro_is_whitespace_deleting(¯o_name) { if output.chars().last() == Some(' ') { diff --git a/src/skaldpress/main.rs b/src/skaldpress/main.rs index 69f934a..284ad88 100644 --- a/src/skaldpress/main.rs +++ b/src/skaldpress/main.rs @@ -280,7 +280,14 @@ fn extract_requested_macro_processor_state( /// 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("")); + let extension = file_path + .extension() + .unwrap_or(std::ffi::OsStr::new("")) + .to_str() + .ok_or(SkaldpressError::PathOperationError( + SP_COMPILE_FILE_EXTENSION_ERROR_2, + None, + ))?; let file_content = fs::read_to_string(file_path).map_err(|e| { SkaldpressError::FileReadError( @@ -293,34 +300,14 @@ fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, Skaldpres 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( - SP_COMPILE_FILE_EXTENSION_ERROR_2, - None, - ))? { - "md" => markdown::to_html_with_options( - file_content, - &markdown::Options { - parse: markdown::ParseOptions::gfm(), - compile: markdown::CompileOptions { - allow_dangerous_html: true, - allow_dangerous_protocol: true, - ..markdown::CompileOptions::default() - }, - }, - ) - .map_err(|_e| SkaldpressError::MarkdownError(15))?, - _ => 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, + content: file_content.to_string(), metadata: map, - extension: String::from(extension.to_str().unwrap_or("")), + extension: String::from(extension), source_path: String::from(file_path.to_str().unwrap_or("")), needs_recompilation: false, stored_smp_state: HashMap::new(), @@ -339,6 +326,19 @@ fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, Skaldpres let mut macro_processor = MacroProcessor::new(); macro_processor_initialize(&map, &mut macro_processor, stored_smp_state); + //let file_content = macro_processor + // .process_input(&file_content) + // .map_err(|e| SkaldpressError::SMPError(SP_COMPILE_FILE_MACRO_PROCESS_ERROR, e))?; + //let file_content = do_content_conversion(&file_content, extension)?; + // This didn't work properly, + // Maybe we should instead make a macro which can convert from markdown, and wrap this in a + // macro like that if it is a markdown-file? + + let file_content = match extension { + "md" => format!(r#"html_from_markdown(%"{}"%)"#, file_content), + content => content.to_string(), + }; + let Some(template) = &map.get("template") else { let file_content = macro_processor .process_input(&file_content) @@ -348,7 +348,7 @@ fn compile_file(file_path: &Path, opts: &Opts) -> Result<CompiledFile, Skaldpres content: file_content, stored_smp_state: extract_requested_macro_processor_state(&mut macro_processor, &map), metadata: map, - extension: String::from(extension.to_str().unwrap_or("")), + extension: String::from(extension), source_path: String::from(file_path.to_str().unwrap_or("")), needs_recompilation: needs_recompilation(¯o_processor), }); |