Skip to content

Commit

Permalink
Make default syntax for highlighting optional
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeGomez committed Jan 21, 2025
1 parent 406eb57 commit 3930e4b
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 22 deletions.
38 changes: 25 additions & 13 deletions src/web/highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,16 @@ fn try_with_syntax(syntax: &SyntaxReference, code: &str) -> Result<String> {
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('.')
Expand All @@ -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<String> {
try_with_syntax(select_syntax(lang, code), code)
pub fn try_with_lang(lang: Option<&str>, code: &str, default: Option<&str>) -> Result<String> {
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::<LimitsExceeded>() {
Expand All @@ -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::<LimitsExceeded>()
};
Expand All @@ -119,7 +131,7 @@ mod tests {
#[test]
fn limited_escaped() {
let text = "<p>\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("&lt;p&gt;\n"));
}
}
20 changes: 13 additions & 7 deletions src/web/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use comrak::{
use std::collections::HashMap;

#[derive(Debug)]
struct CodeAdapter<F>(F);
struct CodeAdapter<F>(F, Option<&'static str>);

impl<F: Fn(Option<&str>, &str) -> String + Send + Sync> SyntaxHighlighterAdapter
impl<F: Fn(Option<&str>, &str, Option<&str>) -> String + Send + Sync> SyntaxHighlighterAdapter
for CodeAdapter<F>
{
fn write_highlighted(
Expand All @@ -19,7 +19,7 @@ impl<F: Fn(Option<&str>, &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(
Expand Down Expand Up @@ -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,
Expand All @@ -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)]
Expand All @@ -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()
Expand Down
3 changes: 2 additions & 1 deletion src/web/page/templates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ pub mod filters {
}

pub fn highlight(code: impl std::fmt::Display, lang: &str) -> rinja::Result<Safe<String>> {
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!(
"<pre><code>{}</code></pre>",
highlighted_code
Expand Down
2 changes: 1 addition & 1 deletion templates/crate/details.html
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@

{# If there's a readme, display it #}
{%- if let Some(readme) = readme -%}
{{ crate::web::markdown::render(readme)|safe }}
{{ crate::web::markdown::render_with_default(readme, "rust")|safe }}

{# If there's not a readme then attempt to display the long description #}
{%- elif let Some(rustdoc) = rustdoc -%}
Expand Down

0 comments on commit 3930e4b

Please sign in to comment.