From 994da996bcfea9c8b0d44bb7306101dfa83378a8 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sat, 18 Apr 2020 16:05:34 +0800 Subject: [PATCH] blog: refactor: apply highlight via idomatic Iterator operations --- src/blog.rs | 70 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/src/blog.rs b/src/blog.rs index 6ee1c43..7a36492 100644 --- a/src/blog.rs +++ b/src/blog.rs @@ -231,6 +231,43 @@ impl PostContentCache { } } + fn transform_code_block_highlight<'iter, 'ev>( + parser: impl Iterator> + ) -> impl Iterator> { + let mut in_code_block = false; + let mut code_block_lang = None; + parser.map(move |ev| { + match &ev { + Event::Start(Tag::CodeBlock(block)) => { + in_code_block = true; + match block { + CodeBlockKind::Fenced(lang) => code_block_lang = Some(lang.to_string()), + CodeBlockKind::Indented => code_block_lang = None + } + }, + Event::End(Tag::CodeBlock(_)) => { + in_code_block = false; + code_block_lang = None; + }, + Event::Text(text) => { + if in_code_block { + let highlighted = if let Some(ref code_block_lang) = code_block_lang { + crate::hljs::highlight(&code_block_lang, text) + } else { + crate::hljs::highlight_auto(text) + }; + + return Event::Html( + highlighted.into()); + } + } + _ => () + } + + ev + }) + } + // Do some HTML-level transformations to the compiled result // Because the Markdown parser doesn't always allow us to do // everything, like adding `id` attributes to tags @@ -276,41 +313,22 @@ impl PostContentCache { // because we need to asynchronously transform the events // which could not be done through mapping on iterators let mut parser: Vec = Parser::new_ext(&post.content, Options::all()).collect(); - let mut in_code_block = false; - let mut code_block_lang = ""; for ev in parser.iter_mut() { match ev { - Event::Start(Tag::CodeBlock(block)) => { - in_code_block = true; - match block { - CodeBlockKind::Fenced(lang) => code_block_lang = lang, - CodeBlockKind::Indented => code_block_lang = "" - } - }, - Event::End(Tag::CodeBlock(_)) => { - in_code_block = false; - code_block_lang = ""; - }, Event::Start(tag) | Event::End(tag) => { Self::transform_tag(tag).await; }, - Event::Text(text) => { - if in_code_block { - let highlighted = if code_block_lang != "" { - crate::hljs::highlight(code_block_lang, text) - } else { - crate::hljs::highlight_auto(text) - }; - - *ev = Event::Html( - highlighted.into()); - } - } _ => () }; } + + // Now some pure iterator operations + let parser = parser.into_iter(); + // Apply code highlighting via Highlight.js + let parser = Self::transform_code_block_highlight(parser); + let mut html_output = String::new(); - html::push_html(&mut html_output, parser.into_iter()); + html::push_html(&mut html_output, parser); html_output = Self::transform_html(html_output); PostContentCache { uuid: post.uuid.clone(),