From 5a3b0ba94a5a2f3697abb09675483b187194b811 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 21 Jan 2025 22:16:34 +0100 Subject: [PATCH] Make default syntax for highlighting optional --- src/web/highlight.rs | 38 ++++++++++++++++++++++++------------ src/web/markdown.rs | 20 ++++++++++++------- src/web/page/templates.rs | 3 ++- templates/crate/details.html | 2 +- 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/web/highlight.rs b/src/web/highlight.rs index d20b44b72..cc0250d64 100644 --- a/src/web/highlight.rs +++ b/src/web/highlight.rs @@ -49,10 +49,16 @@ fn try_with_syntax(syntax: &SyntaxReference, code: &str) -> Result { Ok(html_generator.finalize()) } -fn select_syntax(name: Option<&str>, code: &str) -> &'static SyntaxReference { +fn select_syntax( + name: Option<&str>, + code: &str, + default: Option<&str>, +) -> &'static SyntaxReference { name.and_then(|name| { if name.is_empty() { - return SYNTAXES.find_syntax_by_token("rust"); + if let Some(default) = default { + return SYNTAXES.find_syntax_by_token(default); + } } SYNTAXES.find_syntax_by_token(name).or_else(|| { name.rsplit_once('.') @@ -63,12 +69,12 @@ fn select_syntax(name: Option<&str>, code: &str) -> &'static SyntaxReference { .unwrap_or_else(|| SYNTAXES.find_syntax_plain_text()) } -pub fn try_with_lang(lang: Option<&str>, code: &str) -> Result { - try_with_syntax(select_syntax(lang, code), code) +pub fn try_with_lang(lang: Option<&str>, code: &str, default: Option<&str>) -> Result { + try_with_syntax(select_syntax(lang, code, default), code) } -pub fn with_lang(lang: Option<&str>, code: &str) -> String { - match try_with_lang(lang, code) { +pub fn with_lang(lang: Option<&str>, code: &str, default: Option<&str>) -> String { + match try_with_lang(lang, code, default) { Ok(highlighted) => highlighted, Err(err) => { if err.is::() { @@ -92,23 +98,29 @@ mod tests { #[test] fn custom_filetypes() { - let toml = select_syntax(Some("toml"), ""); + let toml = select_syntax(Some("toml"), "", None); - assert_eq!(select_syntax(Some("Cargo.toml.orig"), "").name, toml.name); - assert_eq!(select_syntax(Some("Cargo.lock"), "").name, toml.name); + assert_eq!( + select_syntax(Some("Cargo.toml.orig"), "", None).name, + toml.name + ); + assert_eq!(select_syntax(Some("Cargo.lock"), "", None).name, toml.name); } #[test] fn dotfile_with_extension() { - let toml = select_syntax(Some("toml"), ""); + let toml = select_syntax(Some("toml"), "", None); - assert_eq!(select_syntax(Some(".rustfmt.toml"), "").name, toml.name); + assert_eq!( + select_syntax(Some(".rustfmt.toml"), "", None).name, + toml.name + ); } #[test] fn limits() { let is_limited = |s: String| { - try_with_lang(Some("toml"), &s) + try_with_lang(Some("toml"), &s, None) .unwrap_err() .is::() }; @@ -119,7 +131,7 @@ mod tests { #[test] fn limited_escaped() { let text = "

\n".to_string() + "aa".repeat(PER_LINE_BYTE_LENGTH_LIMIT).as_str(); - let highlighted = with_lang(Some("toml"), &text); + let highlighted = with_lang(Some("toml"), &text, None); assert!(highlighted.starts_with("<p>\n")); } } diff --git a/src/web/markdown.rs b/src/web/markdown.rs index c3cdcaae3..2242bcd63 100644 --- a/src/web/markdown.rs +++ b/src/web/markdown.rs @@ -5,9 +5,9 @@ use comrak::{ use std::collections::HashMap; #[derive(Debug)] -struct CodeAdapter(F); +struct CodeAdapter(F, Option<&'static str>); -impl, &str) -> String + Send + Sync> SyntaxHighlighterAdapter +impl, &str, Option<&str>) -> String + Send + Sync> SyntaxHighlighterAdapter for CodeAdapter { fn write_highlighted( @@ -19,7 +19,7 @@ impl, &str) -> String + Send + Sync> SyntaxHighlighterAdapter // comrak does not treat `,` as an info-string delimiter, so we do that here // TODO: https://github.com/kivikakk/comrak/issues/246 let lang = lang.and_then(|lang| lang.split(',').next()); - write!(output, "{}", (self.0)(lang, code)) + write!(output, "{}", (self.0)(lang, code, self.1)) } fn write_pre_tag( @@ -67,9 +67,10 @@ fn write_opening_tag( fn render_with_highlighter( text: &str, - highlighter: impl Fn(Option<&str>, &str) -> String + Send + Sync, + default_syntax: Option<&'static str>, + highlighter: impl Fn(Option<&str>, &str, Option<&str>) -> String + Send + Sync, ) -> String { - let code_adapter = CodeAdapter(highlighter); + let code_adapter = CodeAdapter(highlighter, default_syntax); comrak::markdown_to_html_with_plugins( text, @@ -95,7 +96,11 @@ fn render_with_highlighter( /// Wrapper around the Markdown parser and renderer to render markdown pub fn render(text: &str) -> String { - render_with_highlighter(text, highlight::with_lang) + render_with_highlighter(text, None, highlight::with_lang) +} + +pub fn render_with_default(text: &str, default: &'static str) -> String { + render_with_highlighter(text, Some(default), highlight::with_lang) } #[cfg(test)] @@ -118,7 +123,8 @@ mod test { ignore::spaces(); ``` "}, - |lang, code| { + None, + |lang, code, _| { let mut highlighted = highlighted.lock().unwrap(); highlighted.push((lang.map(str::to_owned), code.to_owned())); code.to_owned() diff --git a/src/web/page/templates.rs b/src/web/page/templates.rs index a39d705da..252e945ab 100644 --- a/src/web/page/templates.rs +++ b/src/web/page/templates.rs @@ -201,7 +201,8 @@ pub mod filters { } pub fn highlight(code: impl std::fmt::Display, lang: &str) -> rinja::Result> { - let highlighted_code = crate::web::highlight::with_lang(Some(lang), &code.to_string()); + let highlighted_code = + crate::web::highlight::with_lang(Some(lang), &code.to_string(), None); Ok(Safe(format!( "

{}
", highlighted_code diff --git a/templates/crate/details.html b/templates/crate/details.html index 6e4318941..35b4e6be7 100644 --- a/templates/crate/details.html +++ b/templates/crate/details.html @@ -198,7 +198,7 @@ {# If there's not a readme then attempt to display the long description #} {%- elif let Some(rustdoc) = rustdoc -%} - {{ crate::web::markdown::render(rustdoc)|safe }} + {{ crate::web::markdown::render_with_default(rustdoc, "rust")|safe }} {%- endif -%}