summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorQrius <[email protected]>2024-09-26 00:11:05 +0200
committerQrius <[email protected]>2024-09-26 00:11:05 +0200
commit40c4bb30c16f52fd9ec4944482dbbb929386ab78 (patch)
treecaaae9b3380f0fd81b2ef8d1cfbaa747488729fb /src
parent6af9f573fce9c167487e10c7327feff357327d6a (diff)
downloadskaldpress-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.rs8
-rw-r--r--src/macro_processor/macro_processor.rs88
-rw-r--r--src/skaldpress/main.rs48
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(&macro_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(&macro_processor),
});