aboutsummaryrefslogtreecommitdiff
path: root/code/src/markdown/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'code/src/markdown/parser.rs')
-rw-r--r--code/src/markdown/parser.rs167
1 files changed, 3 insertions, 164 deletions
diff --git a/code/src/markdown/parser.rs b/code/src/markdown/parser.rs
index 94eab49..8876335 100644
--- a/code/src/markdown/parser.rs
+++ b/code/src/markdown/parser.rs
@@ -1,3 +1,6 @@
+use pest::Parser;
+use pest_derive::Parser;
+
#[derive(Debug, Clone)]
pub enum Block {
Header(usize, Vec<Span>),
@@ -21,167 +24,3 @@ pub enum Span {
Strong(Vec<Span>),
Latex(String),
}
-
-pub fn parse(mut s: &str) -> Vec<Block> {
- let mut blocks = Vec::new();
- while s.len() != 0 {
- if s.starts_with("\n") {
- s = &s[1..];
- continue;
- }
- // TODO bad code here
- if let Some((block, rest)) = try_header(s) {
- s = rest;
- blocks.push(block);
- continue;
- }
- if let Some((block, rest)) = try_latex_block(s) {
- s = rest;
- blocks.push(block);
- continue;
- }
- if let Some((block, rest)) = try_code_block(s) {
- s = rest;
- blocks.push(block);
- continue;
- }
- if let Some((block, rest)) = try_list(s) {
- s = rest;
- blocks.push(block);
- continue;
- }
- let lf = [s.find("\n\n"), s.find("\n-")]
- .iter()
- .filter_map(|e| *e)
- .min()
- .unwrap_or(s.len());
- let span = Span::parse(&s[..lf]);
- blocks.push(Block::Paragraph(span));
- if lf >= s.len() {
- break;
- }
- s = &s[lf + 1..];
- }
- blocks
-}
-
-fn try_code_block(mut s: &str) -> Option<(Block, &str)> {
- if !s.starts_with("```") {
- return None;
- }
- s = &s[3..];
- let lf = s.find('\n')?;
- let syntax = if lf != 0 {
- Some(String::from(&s[0..lf]))
- } else {
- None
- };
- s = &s[lf..];
- let end = s.find("\n```\n")?;
- Some((
- Block::CodeBlock(syntax, String::from(&s[..end])),
- &s[end + 4..],
- ))
-}
-fn try_latex_block(mut s: &str) -> Option<(Block, &str)> {
- if !s.starts_with("$$") {
- return None;
- }
- s = &s[2..];
- let end = s.find("$$")?;
- Some((Block::LatexBlock(String::from(&s[..end])), &s[end + 2..]))
-}
-fn try_list(mut s: &str) -> Option<(Block, &str)> {
- if !s.starts_with("-") {
- return None;
- };
- let mut blocks = vec![];
- loop {
- if !s.starts_with("-") || s.len() == 0 {
- break Some((Block::UnorderedList(blocks), s));
- }
- s = &s[1..];
- let mut lf = s.find("\n").unwrap();
- while s[lf + 1..].starts_with(" ") {
- lf += 2 + s[lf + 2..].find("\n").unwrap();
- }
- let mut k = s[..lf]
- .split("\n")
- .map(|l| if l.starts_with(" ") { &l[2..] } else { &l })
- .collect::<Vec<_>>()
- .join("\n");
- k.push('\n');
- blocks.push(parse(&k));
- s = &s[lf + 1..];
- }
-}
-fn try_header(s: &str) -> Option<(Block, &str)> {
- if s.starts_with("#") {
- let mut u = 0;
- while s.chars().nth(u)? == '#' {
- u += 1;
- }
- let lf = s.find('\n')?;
- Some((Block::Header(u, Span::parse(&s[u..lf])), &s[lf + 1..]))
- } else {
- None
- }
-}
-
-impl Span {
- pub fn parse(mut s: &str) -> Vec<Span> {
- let mut spans = Vec::new();
- while s.len() != 0 {
- let nt = s.find(&['*', '_', '`', '[', '$']);
-
- if let Some(nt) = nt {
- spans.push(Span::Text(String::from(&s[..nt])));
- s = &s[nt..];
- if s.starts_with("**") {
- s = &s[2..];
- let end = s.find("**").expect("** not ended");
- spans.push(Span::Strong(Span::parse(&s[..end])));
- s = &s[end + 2..];
- continue;
- }
- if s.starts_with("_") {
- s = &s[1..];
- let end = s.find("_").expect("_ not ended");
- spans.push(Span::Emphasis(Span::parse(&s[..end])));
- s = &s[end + 1..];
- continue;
- }
- if s.starts_with("`") {
- s = &s[1..];
- let end = s.find("`").expect("` not ended");
- spans.push(Span::Code(String::from(&s[..end])));
- s = &s[end + 1..];
- continue;
- }
- if s.starts_with("$") {
- s = &s[1..];
- let end = s.find("$").expect("$ not ended");
- spans.push(Span::Latex(String::from(&s[..end])));
- s = &s[end + 1..];
- continue;
- }
- if s.starts_with("[") {
- s = &s[1..];
- let del = s.find("](").expect("]( expected");
- let end = del + s[del..].find(")").expect(") expected");
- spans.push(Span::Link(
- String::from(&s[..del]),
- String::from(&s[del + 2..end]),
- ));
- s = &s[end + 1..];
- continue;
- }
- panic!("{s:?}")
- } else {
- spans.push(Span::Text(String::from(s)));
- break;
- }
- }
- spans
- }
-}