use pest::{ iterators::{Pair, Pairs}, Parser, }; use pest_derive::Parser; use crate::{html::escape, syntax_highlight::syntax_highlight}; #[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) -> 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 => format!("

{}

", render_pairs(p.into_inner())), Rule::paragraph => format!("

{}

", render_pairs(p.into_inner())), 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::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::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 => format!("TODO: Inline latex"), Rule::latex_block => format!("

    TODO: Latex block

    "), Rule::text => escape(p.as_str()), _ => todo!("{:?}", p.as_rule()), } }