aboutsummaryrefslogtreecommitdiff
path: root/code/src/markdown
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2022-09-26 15:16:05 +0200
committermetamuffin <metamuffin@disroot.org>2022-09-26 15:16:05 +0200
commita5ee9b1edd25f698813ebdc52404ec19fa479718 (patch)
tree7d428ca9b2b0059e39f78bc096bf57b94f1d8a3d /code/src/markdown
parent15d78464ba9a717a71e1dc47a4101c8b13ec6581 (diff)
downloadmetamuffin-blog-a5ee9b1edd25f698813ebdc52404ec19fa479718.tar
metamuffin-blog-a5ee9b1edd25f698813ebdc52404ec19fa479718.tar.bz2
metamuffin-blog-a5ee9b1edd25f698813ebdc52404ec19fa479718.tar.zst
new renderer
Diffstat (limited to 'code/src/markdown')
-rw-r--r--code/src/markdown/mod.rs41
-rw-r--r--code/src/markdown/parser.rs167
-rw-r--r--code/src/markdown/render.rs8
3 files changed, 42 insertions, 174 deletions
diff --git a/code/src/markdown/mod.rs b/code/src/markdown/mod.rs
index 7bdf323..b6dfb55 100644
--- a/code/src/markdown/mod.rs
+++ b/code/src/markdown/mod.rs
@@ -1,2 +1,39 @@
-pub mod parser;
-pub mod render;
+use pest::{
+ iterators::{Pair, Pairs},
+ Parser,
+};
+use pest_derive::Parser;
+
+use crate::html::escape;
+
+#[derive(Parser)]
+#[grammar = "grammar/markdown.pest"]
+struct Grammar;
+
+pub fn render(s: &str) -> String {
+ match Grammar::parse(Rule::file, s) {
+ Ok(pairs) => {
+ eprintln!("{pairs:#?}");
+ render_pairs(pairs)
+ }
+ Err(e) => panic!("{e}"),
+ }
+}
+
+pub fn render_pairs(p: Pairs<Rule>) -> String {
+ p.map(|p| render_ast(p)).collect::<Vec<_>>().join("")
+}
+
+pub fn render_ast(p: Pair<Rule>) -> String {
+ match p.as_rule() {
+ Rule::block => render_pairs(p.into_inner()),
+ Rule::header => format!("<h1>{}</h1>", render_pairs(p.into_inner())),
+ Rule::paragraph => format!("<p>{}</p>", render_pairs(p.into_inner())),
+ Rule::list => format!("<ul>{}</ul>", render_pairs(p.into_inner())),
+ Rule::list_item => format!("<li>{}</li>", render_pairs(p.into_inner())),
+ Rule::span => render_pairs(p.into_inner()),
+ Rule::text => escape(p.as_str()),
+ Rule::EOI => "".to_string(),
+ _ => todo!("{:?}", p.as_rule()),
+ }
+}
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
- }
-}
diff --git a/code/src/markdown/render.rs b/code/src/markdown/render.rs
index 7962561..75ebe43 100644
--- a/code/src/markdown/render.rs
+++ b/code/src/markdown/render.rs
@@ -74,14 +74,6 @@ pub fn blocks_to_html(blocks: Vec<Block>) -> String {
out
}
-pub fn escape(text: &str) -> String {
- text.replace("&", "&amp;")
- .replace("<", "&lt;")
- .replace(">", "&gt;")
- .replace("'", "&#8217;")
- .replace("\"", "&quot;")
-}
-
// TODO this is *really* bad fix
fn fix_katex<'a>(s: &str) -> String {
let e = s.find("<span class=\"katex-html\"").unwrap();