const ALIASES: [(&str, &str); 24] = [
("json", "json"),
("jsonc", "json"),
("yaml", "yaml"),
("yml", "yaml"),
("csv", "csv"),
("tsv", "csv"),
("xml", "xml"),
("log", "log"),
("txt", "plaintext"),
("text", "plaintext"),
("plaintext", "plaintext"),
("javascript", "javascript"),
("js", "javascript"),
("jsx", "javascript"),
("mjs", "javascript"),
("cjs", "javascript"),
("javascriptreact", "javascript"),
("typescript", "typescript"),
("ts", "typescript"),
("tsx", "typescript"),
("mts", "typescript"),
("cts", "typescript"),
("typescriptreact", "typescript"),
("html", "html"),
];
const EXTENSION_ONLY: [(&str, &str); 2] = [("htm", "html"), ("xhtml", "html")];
pub(crate) const SUPPORTED_FORMATS: [&str; 9] = [
"json",
"yaml",
"csv",
"xml",
"log",
"plaintext",
"javascript",
"typescript",
"html",
];
fn normalise(value: &str) -> String {
value
.trim()
.to_lowercase()
.trim_start_matches('.')
.to_string()
}
fn lookup(name: &str) -> Option<&'static str> {
let name = normalise(name);
ALIASES
.iter()
.chain(EXTENSION_ONLY.iter())
.find(|(alias, _)| *alias == name)
.map(|(_, language)| *language)
}
pub(crate) fn resolve_format(format: Option<&str>, filename: Option<&str>) -> Option<&'static str> {
if let Some(language) = format.and_then(lookup) {
return Some(language);
}
let extension = filename?.rsplit_once('.')?.1;
lookup(extension)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn an_explicit_format_wins() {
assert_eq!(resolve_format(Some("yml"), None), Some("yaml"));
assert_eq!(resolve_format(Some(".TS"), None), Some("typescript"));
}
#[test]
fn a_filename_is_the_fallback() {
assert_eq!(resolve_format(None, Some("app.log")), Some("log"));
assert_eq!(resolve_format(Some("rust"), Some("a.json")), Some("json"));
}
#[test]
fn typescript_and_plaintext_are_their_own_keys() {
assert_eq!(resolve_format(Some("typescript"), None), Some("typescript"));
assert_eq!(resolve_format(Some("plaintext"), None), Some("plaintext"));
assert_eq!(resolve_format(Some("tsx"), None), Some("typescript"));
}
#[test]
fn an_unknown_name_resolves_to_nothing() {
assert_eq!(resolve_format(Some("rust"), None), None);
assert_eq!(resolve_format(None, Some("main.rs")), None);
assert_eq!(resolve_format(None, Some("noextension")), None);
assert_eq!(resolve_format(None, None), None);
}
#[test]
fn every_supported_name_resolves() {
for name in SUPPORTED_FORMATS {
assert_eq!(resolve_format(Some(name), None), Some(name), "{name}");
}
}
}