raw
1use crate::ast::{CodeBlock, CodeBlockKind};
2
3
5#[cfg(feature = "highlighting-inkjet")]
6pub(super) fn highlight(block: &CodeBlock) -> String {
7 use std::cell::RefCell;
8
9 use inkjet::{Highlighter, Language, formatter::Html};
10
11 let language = match &block.kind {
12 CodeBlockKind::Indented => Language::Plaintext,
13 CodeBlockKind::Fenced { info } => info
14 .as_deref()
15 .and_then(Language::from_token)
16 .unwrap_or(Language::Plaintext),
17 };
18
19 let mut buf = String::new();
20
21 thread_local! {
22 static HIGHLIGHTER: RefCell<Highlighter> = RefCell::new(Highlighter::new());
23 }
24
25 HIGHLIGHTER.with(|this| {
27 this.borrow_mut()
28 .highlight_to_fmt(language, &Html, &block.literal, &mut buf)
29 .expect("failed to write highlighted code");
30 });
31
32 buf
33}
34
35#[cfg(feature = "highlighting-syntect")]
36pub fn highlight(block: &CodeBlock) -> String {
37 use std::sync::LazyLock;
38
39 use syntect::{
40 html::{ClassStyle, ClassedHTMLGenerator},
41 parsing::SyntaxSet,
42 util::LinesWithEndings,
43 };
44
45 static SET: LazyLock<SyntaxSet> = LazyLock::new(SyntaxSet::load_defaults_newlines);
46
47 let syntax_ref = match &block.kind {
48 CodeBlockKind::Indented => SET.find_syntax_plain_text(),
49 CodeBlockKind::Fenced { info } => info
50 .as_deref()
51 .and_then(|token| SET.find_syntax_by_token(token))
52 .unwrap_or_else(|| SET.find_syntax_plain_text()),
53 };
54
55 let mut rs_html_generator =
56 ClassedHTMLGenerator::new_with_class_style(syntax_ref, &SET, ClassStyle::Spaced);
57
58 for line in LinesWithEndings::from(&block.literal) {
59 rs_html_generator
60 .parse_html_for_line_which_includes_newline(line)
61 .unwrap();
62 }
63
64 rs_html_generator.finalize()
65}
66
67#[cfg(not(any(feature = "highlighting-inkjet", feature = "highlighting-syntect")))]
68pub fn highlight(block: &CodeBlock) -> String {
69 crate::util::escape(&block.literal)
70}
71