use crate::safety::html::unsafe_string;
use synoptic::TokOpt;
pub const TAB_WIDTH: usize = 2;
pub fn convert_code_to_html(kind: &str, code: &str) -> Option<String> {
let kind = match kind {
"rust" => "rs",
"python" => "py",
"javascript" => "js",
"typescript" => "ts",
_ => kind,
};
let mut clip = 0;
for character in code.chars().rev() {
match character {
'\n' | ' ' => clip += 1,
_ => {
break;
}
}
}
let (code, trailing_whitespace) = code.split_at(code.len() - clip);
let trailing_whitespace = trailing_whitespace.replace('\n', " ");
let Some(mut highlighter) = synoptic::from_extension(kind, TAB_WIDTH) else {
return None;
};
let lines = code
.lines()
.map(|line| line.to_owned())
.collect::<Vec<String>>();
highlighter.run(&lines);
let highlighted = Some(
lines
.iter()
.enumerate()
.map(|(line_number, line)| {
highlighter
.line(line_number, line)
.into_iter()
.map(|token| match token {
TokOpt::Some(text, kind) => {
format!("<span class=\"{kind}\">{}</span>", unsafe_string(&text))
}
TokOpt::None(text) => unsafe_string(&text).to_string(),
})
.collect::<Vec<String>>()
.concat()
})
.collect::<Vec<String>>()
.join(" ")
+ &format!("{trailing_whitespace}"),
);
highlighted
}