From: Ruben Beltran del Rio Date: Thu, 9 Jan 2025 21:02:19 +0000 (+0100) Subject: Remove no longer necessary code X-Git-Tag: 1.4.2~1 X-Git-Url: https://git.r.bdr.sh/rbdr/page/commitdiff_plain/f5ac7b8efb4e0d1dd197ddecbad2b46fd19f5ddb?ds=inline Remove no longer necessary code --- diff --git a/src/file_finder.rs b/src/file_finder.rs index a834bd9..ef57950 100644 --- a/src/file_finder.rs +++ b/src/file_finder.rs @@ -78,6 +78,7 @@ mod tests { create_dir_all(test_dir.join("nested")).expect("Could not create nested test directory"); create_dir_all(test_dir.join("assets")).expect("Could not create assets test directory"); create_test_file(&test_dir.join("_layout.html"), ""); + create_test_file(&test_dir.join("notalayout.html"), ""); create_test_file(&test_dir.join("nested/nested.gmi"), ""); create_test_file(&test_dir.join("assets/style.css"), ""); create_test_file(&test_dir.join("image.png"), ""); diff --git a/src/file_handler/mod.rs b/src/file_handler/mod.rs index e8a446b..4e4bed9 100644 --- a/src/file_handler/mod.rs +++ b/src/file_handler/mod.rs @@ -208,11 +208,16 @@ mod tests { let handler = FileHandler { strategies: vec![Box::new(mock_strategy)], - layout: None, + layout: Some("None".to_string()), }; let path = PathBuf::from("test.whatever"); + let file = File{ + path: path.clone(), + file_type: FileType::Gemini + }; assert!(matches!(handler.identify(&path), FileType::Gemini)); + handler.handle(&path, &path, &path, &file); } #[test] 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` containing the rendered HTML. -pub fn parse(source: &str) -> Vec { - 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()), - ] - ); - } -} diff --git a/src/html_renderer.rs b/src/html_renderer.rs deleted file mode 100644 index 6b9ce38..0000000 --- a/src/html_renderer.rs +++ /dev/null @@ -1,256 +0,0 @@ -use crate::gemini_parser::GeminiLine; - -/// Renders HTML from a vector of `GeminiLine` elements. -/// -/// # Arguments -/// * `lines` - Vector of `GeminiLine` elements to render -/// -/// # Returns -/// A String containing the rendered HTML. -pub fn render_html(lines: &[GeminiLine]) -> String { - let mut heading_stack = Vec::new(); - let mut last_line: Option<&GeminiLine> = None; - let mut result = String::new(); - - for line in lines { - result.push_str(&line_preamble(line, last_line, &mut heading_stack)); - result.push_str(&line_content(line)); - result.push('\n'); - last_line = Some(line); - } - - result.push_str(&finalize_html(&heading_stack, last_line)); - result -} - -fn line_preamble( - line: &GeminiLine, - last_line: Option<&GeminiLine>, - heading_stack: &mut Vec, -) -> String { - let mut html = String::new(); - - if let Some(last_line) = last_line { - match last_line { - GeminiLine::ListItem(_) => match line { - GeminiLine::ListItem(_) => {} - _ => html.push_str("\n"), - }, - GeminiLine::Quote(_) => match line { - GeminiLine::Quote(_) => {} - _ => html.push_str("\n"), - }, - _ => {} - } - } - - match line { - GeminiLine::Heading(level, _) => { - while let Some(open_heading) = heading_stack.pop() { - // You just encountered a more important heading. - // Put it back. Desist. - if open_heading < *level { - heading_stack.push(open_heading); - break; - } - - html.push_str("\n"); - - if open_heading == *level { - break; - } - } - heading_stack.push(*level); - html.push_str(&format!("
\n")); - } - GeminiLine::ListItem(_) => match last_line { - Some(GeminiLine::ListItem(_)) => {} - _ => html.push_str("
    \n"), - }, - GeminiLine::Quote(_) => match last_line { - Some(GeminiLine::Quote(_)) => {} - _ => html.push_str("
    \n"), - }, - _ => {} - } - - html -} - -fn line_content(line: &GeminiLine) -> String { - match line { - GeminiLine::Text(content, false) => format!("

    {content}

    "), - GeminiLine::Link(url, text) => { - let display = if text.is_empty() { url } else { text }; - format!("

    {display}

    ") - } - GeminiLine::Heading(level, content) => format!("{content}"), - GeminiLine::ListItem(content) => format!("
  • {content}
  • "), - GeminiLine::PreformattedToggle(true, alt_text) => { - format!("
    ")
    -        }
    -        GeminiLine::PreformattedToggle(false, _) => "
    ".to_string(), - GeminiLine::Text(content, true) | GeminiLine::Quote(content) => content.to_string(), - } -} - -fn finalize_html(heading_stack: &[u8], last_line: Option<&GeminiLine>) -> String { - let mut html = String::new(); - - match last_line { - Some(GeminiLine::ListItem(_)) => html.push_str("
\n"), - Some(GeminiLine::Quote(_)) => html.push_str("\n"), - _ => {} - } - - for _ in heading_stack { - html.push_str("
\n"); - } - - html -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_simple_text() { - let input = vec![GeminiLine::Text("Hello world".to_string(), false)]; - assert_eq!(render_html(&input), "

Hello world

\n"); - } - - #[test] - fn test_heading_nesting() { - let input = vec![ - GeminiLine::Heading(1, "Top".to_string()), - GeminiLine::Heading(2, "Sub".to_string()), - GeminiLine::Heading(3, "SubSub".to_string()), - GeminiLine::Heading(2, "Another Sub".to_string()), - ]; - assert_eq!( - render_html(&input), - "
\n\ -

Top

\n\ -
\n\ -

Sub

\n\ -
\n\ -

SubSub

\n\ -
\n\ -
\n\ -
\n\ -

Another Sub

\n\ -
\n\ -
\n" - ); - } - - #[test] - fn test_list_transitions() { - let input = vec![ - GeminiLine::ListItem("First".to_string()), - GeminiLine::ListItem("Second".to_string()), - GeminiLine::Text("Break".to_string(), false), - GeminiLine::ListItem("New list".to_string()), - ]; - assert_eq!( - render_html(&input), - "
    \n\ -
  • First
  • \n\ -
  • Second
  • \n\ -
\n\ -

Break

\n\ -
    \n\ -
  • New list
  • \n\ -
\n" - ); - } - - #[test] - fn test_quote_transitions() { - let input = vec![ - GeminiLine::Quote("First quote".to_string()), - GeminiLine::Quote("Still quoting".to_string()), - GeminiLine::Text("Normal text".to_string(), false), - GeminiLine::Quote("New quote".to_string()), - ]; - assert_eq!( - render_html(&input), - "
\n\ - First quote\n\ - Still quoting\n\ -
\n\ -

Normal text

\n\ -
\n\ - New quote\n\ -
\n" - ); - } - - #[test] - fn test_preformatted() { - let input = vec![ - GeminiLine::PreformattedToggle(true, "code".to_string()), - GeminiLine::Text("let x = 42;".to_string(), true), - GeminiLine::PreformattedToggle(false, String::new()), - ]; - assert_eq!( - render_html(&input), - "
\n\
-             let x = 42;\n\
-             
\n" - ); - } - - #[test] - fn test_links() { - let input = vec![ - GeminiLine::Link("https://example.com".to_string(), "Example".to_string()), - GeminiLine::Link("https://rust-lang.org".to_string(), String::new()), - ]; - assert_eq!( - render_html(&input), - "

Example

\n\ -

https://rust-lang.org

\n" - ); - } - - #[test] - fn test_complex_nesting() { - let input = vec![ - GeminiLine::Heading(1, "Title".to_string()), - GeminiLine::Text("Intro".to_string(), false), - GeminiLine::Heading(2, "Section".to_string()), - GeminiLine::ListItem("Point 1".to_string()), - GeminiLine::ListItem("Point 2".to_string()), - GeminiLine::Quote("Important quote".to_string()), - GeminiLine::Heading(2, "Another Section".to_string()), - ]; - assert_eq!( - render_html(&input), - "
\n\ -

Title

\n\ -

Intro

\n\ -
\n\ -

Section

\n\ -
    \n\ -
  • Point 1
  • \n\ -
  • Point 2
  • \n\ -
\n\ -
\n\ - Important quote\n\ -
\n\ -
\n\ -
\n\ -

Another Section

\n\ -
\n\ -
\n" - ); - } - - #[test] - fn test_empty_input() { - let input = Vec::new(); - assert_eq!(render_html(&input), ""); - } -}