use std::path::Path; use syntect::highlighting::ThemeSet; use syntect::html::highlighted_html_for_string; use syntect::parsing::SyntaxSet; const THEME: &str = "InspiredGitHub"; const STYLE: &str = "html,body{margin:0;background:#fff}\ pre{margin:0;padding:1rem;font:14px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;overflow:auto}"; pub fn page(path: &Path, text: &str) -> String { let title = path .file_name() .and_then(|n| n.to_str()) .unwrap_or("paste"); let body = highlight(path, text); let mut out = String::with_capacity(body.len() + 256); out.push_str("\n\n\n\n"); push_escaped(&mut out, title); out.push_str("\n\n\n\n"); out.push_str(&body); out.push_str("\n\n\n"); out } fn highlight(path: &Path, text: &str) -> String { let syntaxes = SyntaxSet::load_defaults_newlines(); let themes = ThemeSet::load_defaults(); let syntax = path .extension() .and_then(|e| e.to_str()) .and_then(|e| syntaxes.find_syntax_by_extension(e)) .or_else(|| syntaxes.find_syntax_by_first_line(text)) .unwrap_or_else(|| syntaxes.find_syntax_plain_text()); let Some(theme) = themes.themes.get(THEME) else { return fallback_pre(text); }; match highlighted_html_for_string(text, &syntaxes, syntax, theme) { Ok(html) => html, Err(_) => fallback_pre(text), } } fn fallback_pre(text: &str) -> String { let mut out = String::with_capacity(text.len() + 16); out.push_str("
");
    push_escaped(&mut out, text);
    out.push_str("
"); out } fn push_escaped(out: &mut String, s: &str) { for c in s.chars() { match c { '&' => out.push_str("&"), '<' => out.push_str("<"), '>' => out.push_str(">"), '"' => out.push_str("""), '\'' => out.push_str("'"), other => out.push(other), } } } #[cfg(test)] mod tests { use super::*; #[test] fn page_contains_filename_in_title() { let html = page(Path::new("/srv/x.rs"), "fn main() {}\n"); assert!(html.contains("x.rs")); } #[test] fn page_escapes_filename() { let html = page(Path::new("/srv/