mirror of https://github.com/w4/bin.git
50 lines
1.6 KiB
Rust
50 lines
1.6 KiB
Rust
use bat::assets::HighlightingAssets;
|
|
use once_cell::sync::Lazy;
|
|
use syntect::{
|
|
html::{ClassStyle, ClassedHTMLGenerator},
|
|
parsing::SyntaxSet,
|
|
};
|
|
|
|
thread_local!(pub static BAT_ASSETS: HighlightingAssets = HighlightingAssets::from_binary());
|
|
|
|
/// Takes the content of a paste and the extension passed in by the viewer and will return the content
|
|
/// highlighted in the appropriate format in HTML.
|
|
///
|
|
/// Returns `None` if the extension isn't supported.
|
|
pub fn highlight(content: &str, ext: &str) -> Option<String> {
|
|
static SS: Lazy<SyntaxSet> = Lazy::new(SyntaxSet::load_defaults_newlines);
|
|
|
|
BAT_ASSETS
|
|
.with(|f| {
|
|
let ss = f.get_syntax_set().ok().unwrap_or(&SS);
|
|
let Some(syntax) = ss.find_syntax_by_extension(ext) else {
|
|
return Ok(None);
|
|
};
|
|
let mut html_generator =
|
|
ClassedHTMLGenerator::new_with_class_style(syntax, ss, ClassStyle::Spaced);
|
|
for line in LinesWithEndings(content.trim()) {
|
|
html_generator.parse_html_for_line_which_includes_newline(line)?;
|
|
}
|
|
Ok::<_, syntect::Error>(Some(html_generator.finalize()))
|
|
})
|
|
.unwrap_or_else(|_| Some(content.to_string()))
|
|
}
|
|
|
|
pub struct LinesWithEndings<'a>(&'a str);
|
|
|
|
impl<'a> Iterator for LinesWithEndings<'a> {
|
|
type Item = &'a str;
|
|
|
|
#[inline]
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
if self.0.is_empty() {
|
|
None
|
|
} else {
|
|
let split = self.0.find('\n').map_or(self.0.len(), |i| i + 1);
|
|
let (line, rest) = self.0.split_at(split);
|
|
self.0 = rest;
|
|
Some(line)
|
|
}
|
|
}
|
|
}
|