From ddfc43512c02716d6444a42eb16109375aaab248 Mon Sep 17 00:00:00 2001 From: syui Date: Fri, 11 Jul 2025 08:52:34 +0900 Subject: [PATCH] add md msg --- src/shortcode.rs | 72 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/src/shortcode.rs b/src/shortcode.rs index 7844eb2..0c588d5 100644 --- a/src/shortcode.rs +++ b/src/shortcode.rs @@ -13,6 +13,7 @@ impl ShortcodeProcessor { // Register built-in shortcodes processor.register_img_compare(); + processor.register_message(); processor } @@ -24,14 +25,21 @@ impl ShortcodeProcessor { ); } + fn register_message(&mut self) { + self.shortcodes.insert( + "msg".to_string(), + Box::new(|attrs| Self::parse_message_shortcode(attrs)), + ); + } + pub fn process(&self, content: &str) -> String { let mut processed = content.to_string(); // Process {{< shortcode >}} format (Hugo-style) - let hugo_regex = Regex::new(r#"\{\{\<\s*(\w+(?:-\w+)*)\s+([^>]*)\s*\>\}\}"#).unwrap(); + let hugo_regex = Regex::new(r#"\{\{<\s*(\w+(?:-\w+)*)\s*([^>]*)\s*>\}\}"#).unwrap(); processed = hugo_regex.replace_all(&processed, |caps: ®ex::Captures| { let shortcode_name = &caps[1]; - let attrs = &caps[2]; + let attrs = caps.get(2).map(|m| m.as_str()).unwrap_or(""); if let Some(handler) = self.shortcodes.get(shortcode_name) { handler(attrs) @@ -41,10 +49,10 @@ impl ShortcodeProcessor { }).to_string(); // Process [shortcode] format (Bracket-style) - let bracket_regex = Regex::new(r#"\[(\w+(?:-\w+)*)\s+([^\]]*)\]"#).unwrap(); + let bracket_regex = Regex::new(r#"\[(\w+(?:-\w+)*)\s*([^\]]*)\]"#).unwrap(); processed = bracket_regex.replace_all(&processed, |caps: ®ex::Captures| { let shortcode_name = &caps[1]; - let attrs = &caps[2]; + let attrs = caps.get(2).map(|m| m.as_str()).unwrap_or(""); if let Some(handler) = self.shortcodes.get(shortcode_name) { handler(attrs) @@ -113,6 +121,29 @@ impl ShortcodeProcessor { ) } + fn parse_message_shortcode(attrs: &str) -> String { + let attributes = Self::parse_attributes(attrs); + + let msg_type = attributes.get("type").map(|s| s.as_str()).unwrap_or("info"); + let content = attributes.get("content").map(|s| s.as_str()).unwrap_or(""); + + let (symbol, class_suffix) = match msg_type { + "info" => ("!", "message"), + "warning" => ("⚠", "warning"), + "error" => ("✖", "error"), + "success" => ("✓", "success"), + "note" => ("📝", "note"), + _ => ("!", "message"), + }; + + format!(r#" +"#, + class_suffix, symbol, content + ) + } + /// Register a custom shortcode handler #[allow(dead_code)] pub fn register_shortcode(&mut self, name: &str, handler: F) @@ -189,4 +220,37 @@ mod tests { assert_eq!(attributes.get("after").unwrap(), "test2.jpg"); assert_eq!(attributes.get("width").unwrap(), "800"); } + + #[test] + fn test_message_shortcode_info() { + let processor = ShortcodeProcessor::new(); + let input = r#"[msg type="info" content="This is an info message"]"#; + let result = processor.process(input); + + assert!(result.contains("msg message")); + assert!(result.contains("This is an info message")); + assert!(result.contains("!")); + } + + #[test] + fn test_message_shortcode_warning() { + let processor = ShortcodeProcessor::new(); + let input = r#"{{< msg type="warning" content="This is a warning" >}}"#; + let result = processor.process(input); + + assert!(result.contains("msg warning")); + assert!(result.contains("This is a warning")); + assert!(result.contains("⚠")); + } + + #[test] + fn test_message_shortcode_default() { + let processor = ShortcodeProcessor::new(); + let input = r#"[msg content="Default message"]"#; + let result = processor.process(input); + + assert!(result.contains("msg message")); + assert!(result.contains("Default message")); + assert!(result.contains("!")); + } } \ No newline at end of file