Created
May 3, 2020 14:29
-
-
Save dustinknopoff/b67a1082eae29c0c63f88dcdf64175d5 to your computer and use it in GitHub Desktop.
A bare minimum pulldown_cmark highlighting using syntect based off of conversation in: https://github.com/raphlinus/pulldown-cmark/issues/167
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use syntect::highlighting::ThemeSet; | |
use syntect::html::highlighted_html_for_string; | |
use syntect::parsing::SyntaxSet; | |
use pulldown_cmark::{html, CodeBlockKind, CowStr, Event, Options, Parser, Tag}; | |
fn main() { | |
// Setup for pulldown_cmark to read (only) from stdin | |
let opts = Options::all(); | |
let input = String::from( | |
r#"Test | |
```bash | |
sh install.sh && echo "true" | |
``` | |
Test"#, | |
); | |
let mut s = String::with_capacity(&input.len() * 3 / 2); | |
let p = Parser::new_ext(&input, opts); | |
// Setup for syntect to highlight (specifically) Rust code | |
let ss = SyntaxSet::load_defaults_newlines(); | |
let ts = ThemeSet::load_defaults(); | |
let theme = &ts.themes["Solarized (light)"]; | |
// We'll build a new vector of events since we can only consume the parser once | |
let mut new_p = Vec::new(); | |
// As we go along, we'll want to highlight code in bundles, not lines | |
let mut to_highlight = String::new(); | |
// And track a little bit of state | |
let mut in_code_block = false; | |
p.for_each(|event| match event { | |
Event::Start(Tag::CodeBlock(_)) => { | |
in_code_block = true; | |
} | |
Event::End(Tag::CodeBlock(ref token)) => { | |
if in_code_block { | |
let syntax = if let CodeBlockKind::Fenced(val) = token { | |
ss.find_syntax_by_extension(&val.clone().into_string()) | |
.unwrap_or_else(|| ss.find_syntax_plain_text()) | |
} else { | |
ss.find_syntax_plain_text() | |
}; | |
// Format the whole multi-line code block as HTML all at once | |
let html = highlighted_html_for_string(&to_highlight, &ss, &syntax, &theme); | |
// And put it into the vector | |
new_p.push(Event::Html(CowStr::Boxed(html.into_boxed_str()))); | |
to_highlight = String::new(); | |
in_code_block = false; | |
} | |
} | |
Event::Text(t) => { | |
if in_code_block { | |
// If we're in a code block, build up the string of text | |
to_highlight.push_str(&t); | |
} else { | |
new_p.push(Event::Text(t)) | |
} | |
} | |
e => { | |
new_p.push(e); | |
} | |
}); | |
// Now we send this new vector of events off to be transformed into HTML | |
html::push_html(&mut s, new_p.into_iter()); | |
print!("{}", s); | |
} |
Author
dustinknopoff
commented
May 3, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment