79 lines
2.5 KiB
Rust
79 lines
2.5 KiB
Rust
use super::Highlighter;
|
|
use pulldown_cmark::escape::escape_html;
|
|
use std::fmt::Write;
|
|
use tree_sitter_highlight::{Highlight as TSHighlight, HighlightConfiguration, HighlightEvent};
|
|
|
|
pub struct TreeSitterHighlighter {
|
|
config: &'static HighlightConfiguration,
|
|
}
|
|
|
|
// SAFETY: the only thing we store is a HighlightConfiguration, which is thread safe
|
|
// unsafe impl Sync for TreeSitterHighlighter {}
|
|
|
|
impl TreeSitterHighlighter {
|
|
pub fn new(config: &'static HighlightConfiguration) -> Self {
|
|
Self { config }
|
|
}
|
|
}
|
|
|
|
impl Highlighter for TreeSitterHighlighter {
|
|
fn highlight(&self, code: &str) -> String {
|
|
let mut highlighter = tree_sitter_highlight::Highlighter::new();
|
|
let highlights = highlighter
|
|
.highlight(self.config, code.as_bytes(), None, |_| None)
|
|
.unwrap();
|
|
let mut buf = String::new();
|
|
for highlight in highlights {
|
|
let event = highlight.unwrap();
|
|
match event {
|
|
HighlightEvent::Source { start, end } => {
|
|
escape_html(
|
|
&mut buf,
|
|
std::str::from_utf8(&code.as_bytes()[start..end]).unwrap(),
|
|
)
|
|
.unwrap();
|
|
}
|
|
HighlightEvent::HighlightStart(TSHighlight(idx)) => {
|
|
write!(
|
|
&mut buf,
|
|
"<span class=\"hl-{}\">",
|
|
HIGHLIGHT_CLASS_NAMES[idx]
|
|
)
|
|
.unwrap();
|
|
}
|
|
HighlightEvent::HighlightEnd => {
|
|
buf.push_str("</span>");
|
|
}
|
|
}
|
|
}
|
|
buf
|
|
}
|
|
}
|
|
|
|
pub const HIGHLIGHT_NAMES: &[&str] = &[
|
|
"attribute",
|
|
"comment",
|
|
"constant",
|
|
"embedded", // something inside a string, e.g., the foo in `${foo}` in js
|
|
"function",
|
|
"function.builtin",
|
|
"keyword",
|
|
"module", // e.g., atoms in elixir
|
|
"number",
|
|
"operator",
|
|
"property",
|
|
"punctuation.special", // e.g., in js the dollar sign and curly braces in `${foo}`
|
|
"string",
|
|
"string.special.key", // e.g., json keys
|
|
"tag", // e.g., html tags, css class/id selectors
|
|
"type",
|
|
"type.builtin",
|
|
"variable",
|
|
"variable.builtin",
|
|
];
|
|
|
|
const HIGHLIGHT_CLASS_NAMES: &[&str] = &[
|
|
"attr", "cmt", "const", "emb", "fn", "builtin", "kw", "mod", "num", "op", "prop", "punct-sp",
|
|
"str", "key", "tag", "type", "builtin", "var", "builtin",
|
|
];
|