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
}
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),
}
#[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]
);
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"),
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]
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]
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]
);
// 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]
>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()),
+ ]
+ );
}
}