]> git.r.bdr.sh - rbdr/page/blobdiff - src/gemini_parser.rs
Use gema_texto for gemini parsing
[rbdr/page] / src / gemini_parser.rs
index 418b758b2206bfc294373e0f4e18e9e8d5d25662..f7aa0cc70b640794b9664f6314beb12685f80608 100644 (file)
@@ -5,36 +5,34 @@ pub enum GeminiLine {
     Heading(u8, String),
     Link(String, String),
     Quote(String),
-    ListItem(String)
+    ListItem(String),
 }
 
-/// Parses gemtext source code into a vector of GeminiLine elements.
-/// 
+/// Parses gemtext source code into a vector of `GeminiLine` elements.
+///
 /// # Arguments
 /// * `source` - A string slice that contains the gemtext
-/// 
+///
 /// # Returns
 /// A `Vec<GeminiLine>` containing the rendered HTML.
 pub fn parse(source: &str) -> Vec<GeminiLine> {
-    source.lines()
-        .fold(
-            (Vec::new(), false),
-            |(mut lines, is_preformatted), line| {
-                let parsed = if is_preformatted {
-                    parse_preformatted_line(line)
-                } else {
-                    parse_line(line)
-                };
-
-                let new_is_preformatted = match parsed {
-                    GeminiLine::PreformattedToggle(x, _) => x,
-                    _ => is_preformatted
-                };
-
-                lines.push(parsed);
-                (lines, new_is_preformatted)
-            }
-        )
+    source
+        .lines()
+        .fold((Vec::new(), false), |(mut lines, is_preformatted), line| {
+            let parsed = if is_preformatted {
+                parse_preformatted_line(line)
+            } else {
+                parse_line(line)
+            };
+
+            let new_is_preformatted = match parsed {
+                GeminiLine::PreformattedToggle(x, _) => x,
+                _ => is_preformatted,
+            };
+
+            lines.push(parsed);
+            (lines, new_is_preformatted)
+        })
         .0
 }
 
@@ -49,16 +47,18 @@ fn parse_line(line: &str) -> GeminiLine {
     match line {
         s if s.starts_with("###") => GeminiLine::Heading(3, s[3..].to_string()),
         s if s.starts_with("##") => GeminiLine::Heading(2, s[2..].to_string()),
-        s if s.starts_with("#") => GeminiLine::Heading(1, s[1..].to_string()),
+        s if s.starts_with('#') => GeminiLine::Heading(1, s[1..].to_string()),
         s if s.starts_with("=>") => {
             let content = s[2..].trim();
             match content.split_once(char::is_whitespace) {
-                Some((url, text)) => GeminiLine::Link(url.trim().to_string(), text.trim().to_string()),
+                Some((url, text)) => {
+                    GeminiLine::Link(url.trim().to_string(), text.trim().to_string())
+                }
                 None => GeminiLine::Link(content.trim().to_string(), String::new()),
             }
-        },
+        }
         s if s.starts_with("* ") => GeminiLine::ListItem(s[2..].to_string()),
-        s if s.starts_with(">") => GeminiLine::Quote(s[1..].to_string()),
+        s if s.starts_with('>') => GeminiLine::Quote(s[1..].to_string()),
         s if s.starts_with("```") => GeminiLine::PreformattedToggle(true, s[3..].to_string()),
         _ => GeminiLine::Text(line.to_string(), false),
     }
@@ -70,16 +70,37 @@ mod tests {
 
     #[test]
     fn test_headings() {
-        assert_eq!(parse_line("### Heading"), GeminiLine::Heading(3, " Heading".to_string()));
-        assert_eq!(parse_line("## Heading"), GeminiLine::Heading(2, " Heading".to_string()));
-        assert_eq!(parse_line("# Heading"), GeminiLine::Heading(1, " Heading".to_string()));
-        assert_eq!(parse_line("###"), GeminiLine::Heading(3, "".to_string()));
-        assert_eq!(parse_line("#####"), GeminiLine::Heading(3, "##".to_string()));
+        assert_eq!(
+            parse_line("### Heading"),
+            GeminiLine::Heading(3, " Heading".to_string())
+        );
+        assert_eq!(
+            parse_line("## Heading"),
+            GeminiLine::Heading(2, " Heading".to_string())
+        );
+        assert_eq!(
+            parse_line("# Heading"),
+            GeminiLine::Heading(1, " Heading".to_string())
+        );
+        assert_eq!(parse_line("###"), GeminiLine::Heading(3, String::new()));
+        assert_eq!(
+            parse_line("#####"),
+            GeminiLine::Heading(3, "##".to_string())
+        );
         assert_eq!(parse_line("# "), GeminiLine::Heading(1, " ".to_string()));
 
-        assert_eq!(parse_preformatted_line("### Heading"), GeminiLine::Text("### Heading".to_string(), true));
-        assert_eq!(parse_preformatted_line("## Heading"), GeminiLine::Text("## Heading".to_string(), true));
-        assert_eq!(parse_preformatted_line("# Heading"), GeminiLine::Text("# Heading".to_string(), true));
+        assert_eq!(
+            parse_preformatted_line("### Heading"),
+            GeminiLine::Text("### Heading".to_string(), true)
+        );
+        assert_eq!(
+            parse_preformatted_line("## Heading"),
+            GeminiLine::Text("## Heading".to_string(), true)
+        );
+        assert_eq!(
+            parse_preformatted_line("# Heading"),
+            GeminiLine::Text("# Heading".to_string(), true)
+        );
     }
 
     #[test]
@@ -90,16 +111,16 @@ mod tests {
         );
         assert_eq!(
             parse_line("=> /local/path"),
-            GeminiLine::Link("/local/path".to_string(), "".to_string())
+            GeminiLine::Link("/local/path".to_string(), String::new())
         );
 
         assert_eq!(
             parse_line("=>"),
-            GeminiLine::Link("".to_string(), "".to_string())
+            GeminiLine::Link(String::new(), String::new())
         );
         assert_eq!(
             parse_line("=> "),
-            GeminiLine::Link("".to_string(), "".to_string())
+            GeminiLine::Link(String::new(), String::new())
         );
         assert_eq!(
             parse_line("=>  multiple    spaces  in   text"),
@@ -119,10 +140,16 @@ mod tests {
             GeminiLine::ListItem("List item".to_string())
         );
 
-        assert_eq!(parse_line("* "), GeminiLine::ListItem("".to_string()));
+        assert_eq!(parse_line("* "), GeminiLine::ListItem(String::new()));
         assert_eq!(parse_line("*"), GeminiLine::Text("*".to_string(), false));
-        assert_eq!(parse_line("*WithText"), GeminiLine::Text("*WithText".to_string(), false));
-        assert_eq!(parse_line("*  Multiple spaces"), GeminiLine::ListItem(" Multiple spaces".to_string()));
+        assert_eq!(
+            parse_line("*WithText"),
+            GeminiLine::Text("*WithText".to_string(), false)
+        );
+        assert_eq!(
+            parse_line("*  Multiple spaces"),
+            GeminiLine::ListItem(" Multiple spaces".to_string())
+        );
     }
 
     #[test]
@@ -132,9 +159,12 @@ mod tests {
             GeminiLine::Quote("Quote text".to_string())
         );
 
-        assert_eq!(parse_line(">"), GeminiLine::Quote("".to_string()));
+        assert_eq!(parse_line(">"), GeminiLine::Quote(String::new()));
         assert_eq!(parse_line("> "), GeminiLine::Quote(" ".to_string()));
-        assert_eq!(parse_line(">>Nested"), GeminiLine::Quote(">Nested".to_string()));
+        assert_eq!(
+            parse_line(">>Nested"),
+            GeminiLine::Quote(">Nested".to_string())
+        );
     }
 
     #[test]
@@ -144,19 +174,27 @@ mod tests {
             GeminiLine::PreformattedToggle(true, "alt-text".to_string())
         );
 
-        assert_eq!(parse_line("```"), GeminiLine::PreformattedToggle(true, "".to_string()));
-        assert_eq!(parse_line("``` "), GeminiLine::PreformattedToggle(true, " ".to_string()));
-        assert_eq!(parse_line("````"), GeminiLine::PreformattedToggle(true, "`".to_string()));
+        assert_eq!(
+            parse_line("```"),
+            GeminiLine::PreformattedToggle(true, String::new())
+        );
+        assert_eq!(
+            parse_line("``` "),
+            GeminiLine::PreformattedToggle(true, " ".to_string())
+        );
+        assert_eq!(
+            parse_line("````"),
+            GeminiLine::PreformattedToggle(true, "`".to_string())
+        );
 
         assert_eq!(
             parse_preformatted_line("```alt-text"),
-            GeminiLine::PreformattedToggle(false, "".to_string())
+            GeminiLine::PreformattedToggle(false, String::new())
         );
         assert_eq!(
             parse_preformatted_line("```"),
-            GeminiLine::PreformattedToggle(false, "".to_string())
+            GeminiLine::PreformattedToggle(false, String::new())
         );
-
     }
 
     #[test]
@@ -168,16 +206,25 @@ mod tests {
         );
 
         // Edge cases
-        assert_eq!(parse_line(""), GeminiLine::Text("".to_string(), false));
+        assert_eq!(parse_line(""), GeminiLine::Text(String::new(), false));
         assert_eq!(parse_line(" "), GeminiLine::Text(" ".to_string(), false));
         assert_eq!(parse_line("  "), GeminiLine::Text("  ".to_string(), false));
     }
 
     #[test]
     fn test_malformed_input() {
-        assert_eq!(parse_line("= >Not a link"), GeminiLine::Text("= >Not a link".to_string(), false));
-        assert_eq!(parse_line("``Not preformatted"), GeminiLine::Text("``Not preformatted".to_string(), false));
-        assert_eq!(parse_line("** Not a list"), GeminiLine::Text("** Not a list".to_string(), false));
+        assert_eq!(
+            parse_line("= >Not a link"),
+            GeminiLine::Text("= >Not a link".to_string(), false)
+        );
+        assert_eq!(
+            parse_line("``Not preformatted"),
+            GeminiLine::Text("``Not preformatted".to_string(), false)
+        );
+        assert_eq!(
+            parse_line("** Not a list"),
+            GeminiLine::Text("** Not a list".to_string(), false)
+        );
     }
 
     #[test]
@@ -200,23 +247,26 @@ code
 >Quote
 ```trailing alt";
         let result = parse(input);
-        assert_eq!(result, vec![
-            GeminiLine::Heading(1, " Heading 1".to_string()),
-            GeminiLine::Heading(2, " Heading 2".to_string()),
-            GeminiLine::Heading(3, " Heading 3".to_string()),
-            GeminiLine::Text("Regular text".to_string(), false),
-            GeminiLine::Link("https://example.com".to_string(), "Link text".to_string()),
-            GeminiLine::ListItem("List item".to_string()),
-            GeminiLine::Quote("Quote".to_string()),
-            GeminiLine::PreformattedToggle(true, "alt".to_string()),
-            GeminiLine::Text("code".to_string(), true),
-            GeminiLine::Text("# Heading 1".to_string(), true),
-            GeminiLine::Text("## Heading 2".to_string(), true),
-            GeminiLine::Text("### Heading 3".to_string(), true),
-            GeminiLine::Text("=> https://example.com Link text".to_string(), true),
-            GeminiLine::Text("* List item".to_string(), true),
-            GeminiLine::Text(">Quote".to_string(), true),
-            GeminiLine::PreformattedToggle(false, "".to_string()),
-        ]);
+        assert_eq!(
+            result,
+            vec![
+                GeminiLine::Heading(1, " Heading 1".to_string()),
+                GeminiLine::Heading(2, " Heading 2".to_string()),
+                GeminiLine::Heading(3, " Heading 3".to_string()),
+                GeminiLine::Text("Regular text".to_string(), false),
+                GeminiLine::Link("https://example.com".to_string(), "Link text".to_string()),
+                GeminiLine::ListItem("List item".to_string()),
+                GeminiLine::Quote("Quote".to_string()),
+                GeminiLine::PreformattedToggle(true, "alt".to_string()),
+                GeminiLine::Text("code".to_string(), true),
+                GeminiLine::Text("# Heading 1".to_string(), true),
+                GeminiLine::Text("## Heading 2".to_string(), true),
+                GeminiLine::Text("### Heading 3".to_string(), true),
+                GeminiLine::Text("=> https://example.com Link text".to_string(), true),
+                GeminiLine::Text("* List item".to_string(), true),
+                GeminiLine::Text(">Quote".to_string(), true),
+                GeminiLine::PreformattedToggle(false, String::new()),
+            ]
+        );
     }
 }