use color_eyre::Result; use pulldown_cmark::Event; use pulldown_cmark::Tag; use pulldown_cmark::{Options, Parser}; use crate::hilighting; pub fn render_markdown_to_html(markdown: &str) -> Result { let options = Options::all(); let mut content_html = String::new(); let parser = Parser::new_ext(markdown, options); let mut code_block = false; let mut code_lang = None; let mut code_accumulator = String::new(); let mut events = Vec::new(); for event in parser { match event { Event::Text(text) => { if code_block { code_accumulator.push_str(&text); } else { events.push(Event::Text(text)); } } Event::Start(Tag::CodeBlock(kind)) => { code_block = true; if let pulldown_cmark::CodeBlockKind::Fenced(lang) = kind { code_lang = Some(lang); } } Event::End(Tag::CodeBlock(_)) => { code_block = false; let lang = code_lang.take().unwrap_or("".into()); let res = hilighting::hilight(&code_accumulator, &lang).unwrap(); events.push(Event::Html(res.into())); code_accumulator.clear(); } _ => events.push(event), } } events.retain(|e| match e { Event::Text(t) | Event::Html(t) => !t.is_empty(), _ => true, }); pulldown_cmark::html::push_html(&mut content_html, events.into_iter()); Ok(content_html) }