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#"
Mermaid Diagram
{escaped_code}
"# ); } 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#"
{lang_escaped}
{highlighted_html}
"# ) } fn escape_html(text: &str) -> String { text.replace('&', "&") .replace('<', "<") .replace('>', ">") .replace('"', """) .replace('\'', "'") }