diff options
Diffstat (limited to 'src/gemini_parser.rs')
| -rw-r--r-- | src/gemini_parser.rs | 272 |
1 files changed, 0 insertions, 272 deletions
diff --git a/src/gemini_parser.rs b/src/gemini_parser.rs deleted file mode 100644 index f7aa0cc..0000000 --- a/src/gemini_parser.rs +++ /dev/null @@ -1,272 +0,0 @@ -#[derive(PartialEq, Eq, Debug)] -pub enum GeminiLine { - Text(String, bool), - PreformattedToggle(bool, String), - Heading(u8, String), - Link(String, String), - Quote(String), - ListItem(String), -} - -/// 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) - }) - .0 -} - -fn parse_preformatted_line(line: &str) -> GeminiLine { - match line { - s if s.starts_with("```") => GeminiLine::PreformattedToggle(false, String::new()), - _ => GeminiLine::Text(line.to_string(), true), - } -} - -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("=>") => { - 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()) - } - 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::PreformattedToggle(true, s[3..].to_string()), - _ => GeminiLine::Text(line.to_string(), false), - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[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, 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) - ); - } - - #[test] - fn test_links() { - assert_eq!( - parse_line("=> https://example.com Link text"), - GeminiLine::Link("https://example.com".to_string(), "Link text".to_string()) - ); - assert_eq!( - parse_line("=> /local/path"), - GeminiLine::Link("/local/path".to_string(), String::new()) - ); - - assert_eq!( - parse_line("=>"), - GeminiLine::Link(String::new(), String::new()) - ); - assert_eq!( - parse_line("=> "), - GeminiLine::Link(String::new(), String::new()) - ); - assert_eq!( - parse_line("=> multiple spaces in text"), - GeminiLine::Link("multiple".to_string(), "spaces in text".to_string()) - ); - - assert_eq!( - parse_preformatted_line("=> https://example.com Link text"), - GeminiLine::Text("=> https://example.com Link text".to_string(), true) - ); - } - - #[test] - fn test_list_items() { - assert_eq!( - parse_line("* List item"), - GeminiLine::ListItem("List item".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()) - ); - } - - #[test] - fn test_quotes() { - assert_eq!( - parse_line(">Quote text"), - GeminiLine::Quote("Quote text".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()) - ); - } - - #[test] - fn test_preformatted() { - assert_eq!( - parse_line("```alt-text"), - GeminiLine::PreformattedToggle(true, "alt-text".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, String::new()) - ); - assert_eq!( - parse_preformatted_line("```"), - GeminiLine::PreformattedToggle(false, String::new()) - ); - } - - #[test] - fn test_text() { - // Normal case - assert_eq!( - parse_line("Regular text"), - GeminiLine::Text("Regular text".to_string(), false) - ); - - // Edge cases - 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) - ); - } - - #[test] - fn test_full_document() { - let input = "\ -# Heading 1 -## Heading 2 -### Heading 3 -Regular text -=> https://example.com Link text -* List item ->Quote -```alt -code -# Heading 1 -## Heading 2 -### Heading 3 -=> https://example.com Link text -* List item ->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, String::new()), - ] - ); - } -} |