use syntect::easy::HighlightLines;
use syntect::highlighting::ThemeSet;
use syntect::html::{IncludeBackground, styled_line_to_highlighted_html};
use syntect::parsing::SyntaxSet;
/// Преобразует исходный код и его язык в подсвеченный HTML.
///
/// # Аргументы
/// * `code` - Исходный код как строка.
/// * `lang` - Идентификатор языка (например, "rust", "python", "mermaid").
/// * `ss` - Набор синтаксисов (SyntaxSet).
/// * `ts` - Набор тем (ThemeSet).
///
/// # Возвращает
/// Строку HTML, содержащую обертку блока кода с заголовком и кнопкой копирования.
pub fn code_to_html(code: &str, lang: &str, ss: &SyntaxSet, ts: &ThemeSet) -> String {
let theme = &ts.themes["base16-ocean.dark"];
if lang == "mermaid" {
let escaped_code = escape_html(code);
return format!(
r#"
"#
);
}
let lang_display = if lang.is_empty() { "text" } else { lang };
let lang_escaped = escape_html(lang_display);
let highlighted_html = if !lang.is_empty() {
if let Some(syntax) = ss.find_syntax_by_token(lang) {
let mut h = HighlightLines::new(syntax, theme);
let mut result_html = String::new();
for line in code.lines() {
let line_with_newline = format!("{line}\n");
match h.highlight_line(&line_with_newline, ss) {
Ok(regions) => {
match styled_line_to_highlighted_html(®ions[..], IncludeBackground::No) {
Ok(html_line) => result_html.push_str(&html_line),
Err(_) => result_html.push_str(&escape_html(&line_with_newline)),
}
}
Err(_) => {
result_html.push_str(&escape_html(&line_with_newline));
}
}
}
result_html
} else {
escape_html(code)
}
} else {
escape_html(code)
};
format!(
r#""#
)
}
fn escape_html(text: &str) -> String {
text.replace('&', "&")
.replace('<', "<")
.replace('>', ">")
.replace('"', """)
.replace('\'', "'")
}