feat: gemtext parser, pre tag

This commit is contained in:
Artemy Egorov 2024-08-02 19:49:10 +03:00
parent 856534c22f
commit 6265701499
9 changed files with 258 additions and 1 deletions

View file

@ -36,6 +36,7 @@ pub enum Tag {
Bl(NotNullBody, AlignArgument),
Carousel(Vec<Tag>),
Code(String, TextOrNullArgument),
Pre(String),
}
pub trait ToDaletl {
@ -78,6 +79,7 @@ impl ToDaletlTag for Tag {
Tag::Bl(b, a) => t_new(Tid::Bl, b.to_daletl_body(), a.to_daletl_argument()),
Tag::Carousel(b) => t_new(Tid::Carousel, b.to_daletl_body(), NA),
Tag::Code(s, a) => t_new(Tid::Code, s.to_daletl_body(), a.to_daletl_argument()),
Tag::Pre(s) => t_new(Tid::Pre, s.to_daletl_body(), NA),
}
}
}

View file

@ -92,4 +92,5 @@ pub enum Tid {
Bl,
Carousel,
Code,
Pre,
}

View file

@ -6,3 +6,6 @@ pub mod abstractions;
#[cfg(feature = "daletpack")]
pub mod daletpack;
#[cfg(feature = "parsers")]
pub mod parsers;

68
src/parsers/gemtext.rs Normal file
View file

@ -0,0 +1,68 @@
use crate::abstractions::{Body, HeadingLevel, NotNullBody, Tag};
#[derive(Debug)]
pub enum GemTextParseError {
InvalidLink,
}
pub fn parse_gemtext(s: String) -> Result<Vec<Tag>, GemTextParseError> {
let mut page: Vec<Tag> = Vec::new();
let mut preformatted = false;
let mut preformatted_text = String::new();
let mut before_is_ordered_list = false;
let mut ordered_list: Vec<Tag> = Vec::new();
for line in s.lines() {
let mut line = line.trim().to_owned();
if before_is_ordered_list && !line.starts_with("* ") {
page.push(Tag::Ul(ordered_list.clone()));
before_is_ordered_list = false;
ordered_list.clear();
} else if preformatted && !line.starts_with("```") {
preformatted_text.push_str(&line);
preformatted_text.push('\n');
} else if line.starts_with("=>") {
let body = line.split_off(2);
let mut body = body.trim().splitn(2, " ");
let url = body.next().ok_or(GemTextParseError::InvalidLink)?.trim();
match body.next() {
Some(label) => page.push(Tag::Link(
Body::Text(label.trim().to_owned()),
url.to_owned(),
)),
None => page.push(Tag::Link(Body::Null, url.to_owned())),
};
} else if line.starts_with("# ") {
let body = line.split_off(2);
page.push(Tag::H(body.trim().to_owned(), HeadingLevel::One));
} else if line.starts_with("## ") {
let body = line.split_off(3);
page.push(Tag::H(body.trim().to_owned(), HeadingLevel::Two));
} else if line.starts_with("### ") {
let body = line.split_off(4);
page.push(Tag::H(body.trim().to_owned(), HeadingLevel::Three));
} else if line.starts_with("* ") {
before_is_ordered_list = true;
let body = line.split_off(2);
ordered_list.push(Tag::El(NotNullBody::Text(body)));
} else if line.starts_with("> ") {
let body = line.split_off(2);
page.push(Tag::Bq(NotNullBody::Text(body)));
} else if line.starts_with("```") {
if preformatted {
page.push(Tag::Pre(preformatted_text.clone()));
preformatted_text.clear();
}
preformatted = !preformatted;
} else if !line.is_empty() {
page.push(Tag::P(NotNullBody::Text(line)));
}
}
Ok(page)
}

1
src/parsers/mod.rs Normal file
View file

@ -0,0 +1 @@
pub mod gemtext;