Skip to content

Commit 200aaee

Browse files
Nemo157syphar
authored andcommitted
Support highlighting Cargo.lock and Cargo.toml.orig
This requires passing the full filename into the highlighter so that if specific files have an overridden syntax definition they will be chosen. We also need to edit the syntax definition we load so that it includes all the filenames we need.
1 parent bdb17de commit 200aaee

File tree

4 files changed

+80
-24
lines changed

4 files changed

+80
-24
lines changed

build.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,10 @@ fn write_known_targets(out_dir: &Path) -> Result<()> {
186186
}
187187

188188
fn compile_syntax(out_dir: &Path) -> Result<()> {
189-
use syntect::{dumps::dump_to_uncompressed_file, parsing::SyntaxSetBuilder};
189+
use syntect::{
190+
dumps::dump_to_uncompressed_file,
191+
parsing::{SyntaxDefinition, SyntaxSetBuilder},
192+
};
190193

191194
fn tracked_add_from_folder(
192195
builder: &mut SyntaxSetBuilder,
@@ -207,7 +210,16 @@ fn compile_syntax(out_dir: &Path) -> Result<()> {
207210
&mut builder,
208211
"assets/syntaxes/Packages/Markdown/Markdown.sublime-syntax",
209212
)?;
210-
tracked_add_from_folder(&mut builder, "assets/syntaxes/Extras/TOML/")?;
213+
214+
// The TOML syntax already includes `Cargo.lock` in its alternative file extensions, but we
215+
// also want to support `Cargo.toml.orig` files.
216+
let mut toml = SyntaxDefinition::load_from_str(
217+
&tracked::read_to_string("assets/syntaxes/Extras/TOML/TOML.sublime-syntax")?,
218+
true,
219+
Some("TOML"),
220+
)?;
221+
toml.file_extensions.push("Cargo.toml.orig".into());
222+
builder.add(toml);
211223

212224
dump_to_uncompressed_file(&builder.build(), out_dir.join("syntect.packdump"))?;
213225

src/web/highlight.rs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::error::Result;
22
use once_cell::sync::Lazy;
33
use syntect::{
44
html::{ClassStyle, ClassedHTMLGenerator},
5-
parsing::SyntaxSet,
5+
parsing::{SyntaxReference, SyntaxSet},
66
util::LinesWithEndings,
77
};
88

@@ -21,14 +21,7 @@ static SYNTAXES: Lazy<SyntaxSet> = Lazy::new(|| {
2121
syntaxes
2222
});
2323

24-
pub fn try_with_lang(lang: Option<&str>, code: &str) -> Result<String> {
25-
let syntax = lang
26-
.and_then(|lang| SYNTAXES.find_syntax_by_token(lang))
27-
.or_else(|| SYNTAXES.find_syntax_by_first_line(code))
28-
.unwrap_or_else(|| SYNTAXES.find_syntax_plain_text());
29-
30-
log::trace!("Using syntax {:?} for language {lang:?}", syntax.name);
31-
24+
fn try_with_syntax(syntax: &SyntaxReference, code: &str) -> Result<String> {
3225
let mut html_generator = ClassedHTMLGenerator::new_with_class_style(
3326
syntax,
3427
&SYNTAXES,
@@ -42,6 +35,25 @@ pub fn try_with_lang(lang: Option<&str>, code: &str) -> Result<String> {
4235
Ok(html_generator.finalize())
4336
}
4437

38+
fn select_syntax(name: Option<&str>, code: &str) -> &'static SyntaxReference {
39+
name.and_then(|name| {
40+
SYNTAXES.find_syntax_by_token(name).or_else(|| {
41+
if name.starts_with('.') {
42+
None
43+
} else {
44+
name.rsplit_once('.')
45+
.and_then(|(_, ext)| SYNTAXES.find_syntax_by_token(ext))
46+
}
47+
})
48+
})
49+
.or_else(|| SYNTAXES.find_syntax_by_first_line(code))
50+
.unwrap_or_else(|| SYNTAXES.find_syntax_plain_text())
51+
}
52+
53+
pub fn try_with_lang(lang: Option<&str>, code: &str) -> Result<String> {
54+
try_with_syntax(select_syntax(lang, code), code)
55+
}
56+
4557
pub fn with_lang(lang: Option<&str>, code: &str) -> String {
4658
match try_with_lang(lang, code) {
4759
Ok(highlighted) => highlighted,
@@ -51,3 +63,16 @@ pub fn with_lang(lang: Option<&str>, code: &str) -> String {
5163
}
5264
}
5365
}
66+
67+
#[cfg(test)]
68+
mod tests {
69+
use super::select_syntax;
70+
71+
#[test]
72+
fn custom_filetypes() {
73+
let toml = select_syntax(Some("toml"), "");
74+
75+
assert_eq!(select_syntax(Some("Cargo.toml.orig"), "").name, toml.name);
76+
assert_eq!(select_syntax(Some("Cargo.lock"), "").name, toml.name);
77+
}
78+
}

src/web/source.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,19 @@ struct File {
2424
name: String,
2525
/// The mime type of the file
2626
mime: String,
27-
/// The extension of the file, if it has one
28-
extension: Option<String>,
2927
}
3028

3129
impl File {
3230
fn from_path_and_mime(path: &str, mime: &str) -> File {
33-
let (name, mime, extension) = if let Some((dir, _)) = path.split_once('/') {
34-
(dir, "dir", None)
31+
let (name, mime) = if let Some((dir, _)) = path.split_once('/') {
32+
(dir, "dir")
3533
} else {
36-
let extension = if path.starts_with('.') {
37-
None
38-
} else {
39-
path.rsplit_once('.').map(|(_, ext)| ext)
40-
};
41-
42-
(path, mime, extension)
34+
(path, mime)
4335
};
4436

4537
Self {
4638
name: name.to_owned(),
4739
mime: mime.to_owned(),
48-
extension: extension.map(|s| s.to_owned()),
4940
}
5041
}
5142
}
@@ -438,4 +429,32 @@ mod tests {
438429
Ok(())
439430
})
440431
}
432+
433+
#[test]
434+
fn cargo_special_filetypes_are_highlighted() {
435+
wrapper(|env| {
436+
env.fake_release()
437+
.name("fake")
438+
.version("0.1.0")
439+
.source_file("Cargo.toml.orig", b"[package]")
440+
.source_file("Cargo.lock", b"[dependencies]")
441+
.create()?;
442+
443+
let web = env.frontend();
444+
445+
let response = web
446+
.get("/crate/fake/0.1.0/source/Cargo.toml.orig")
447+
.send()?
448+
.text()?;
449+
assert!(response.contains(r#"<span class="syntax-source syntax-toml">"#));
450+
451+
let response = web
452+
.get("/crate/fake/0.1.0/source/Cargo.lock")
453+
.send()?
454+
.text()?;
455+
assert!(response.contains(r#"<span class="syntax-source syntax-toml">"#));
456+
457+
Ok(())
458+
});
459+
}
441460
}

templates/crate/source.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
{# If the file has content, then display it in a codeblock #}
114114
{%- if file_content -%}
115115
<div id="source-code" class="pure-u-1 pure-u-sm-17-24 pure-u-md-19-24">
116-
{{- file_content | highlight(lang=file.extension) -}}
116+
{{- file_content | highlight(lang=file.name) -}}
117117
</div>
118118
{%- endif -%}
119119
</div>

0 commit comments

Comments
 (0)