use pest::{ iterators::{Pair, Pairs}, Parser, }; use pest_derive::Parser; use crate::{html::escape, syntax_highlight::syntax_highlight}; #[derive(Parser)] #[grammar = "src/markdown/parser.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) -> String { p.map(|p| render_ast(p)).collect::>().join("") } pub fn render_ast(p: Pair) -> String { match p.as_rule() { Rule::block => render_pairs(p.into_inner()), Rule::header => { let mut level = 0; while p.as_str()[level..].starts_with("#") { level += 1 } format!("{}", render_pairs(p.into_inner())) } Rule::paragraph => format!("

{}

", render_pairs(p.into_inner())), Rule::style_italic => format!("{}", render_pairs(p.into_inner())), Rule::style_bold => format!("{}", render_pairs(p.into_inner())), Rule::style_code => format!("{}", p.into_inner().next().unwrap().as_str()), Rule::unordered_list => format!("
    {}
", render_pairs(p.into_inner())), Rule::ordered_list => format!("
    {}
", render_pairs(p.into_inner())), Rule::unordered_list_item | Rule::ordered_list_item => { format!("
  • {}
  • ", render_pairs(p.into_inner())) } Rule::hyperlink => { let k = p.into_inner().collect::>(); let label = k[0].as_str(); let target = k[1].as_str(); format!("{}", escape(target), escape(label)) } Rule::span => render_pairs(p.into_inner()), Rule::EOI => "".to_string(), Rule::code_block => { let k = p.into_inner().collect::>(); let lang = k[0].as_str(); let inner = k[1].as_str(); format!( "
    {}
    ", syntax_highlight(lang, &inner).unwrap_or_else(|| escape(&inner)) ) } Rule::inline_latex => fix_katex( &katex::render_with_opts( &p.into_inner().as_str(), &katex::OptsBuilder::default().build().unwrap(), ) .unwrap(), ), Rule::latex_block => fix_katex( &katex::render_with_opts( &p.into_inner().as_str(), &katex::OptsBuilder::default() .display_mode(true) .build() .unwrap(), ) .unwrap(), ), Rule::text => escape(p.as_str()), _ => todo!("{:?}", p.as_rule()), } } // TODO this is *really* bad fix fn fix_katex<'a>(s: &str) -> String { let e = s.find("", "", ) }