56 lines
1.6 KiB
Rust
56 lines
1.6 KiB
Rust
|
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<String> {
|
||
|
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)
|
||
|
}
|