This commit is contained in:
Jacob 2025-08-27 00:41:03 +08:00 committed by GitHub
commit 45bba9f3af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 52 additions and 0 deletions

View file

@ -52,6 +52,15 @@ impl FileIcons {
}
}
// handle cases where the file extension is made up of multiple important
// parts (e.g Component.stories.tsx) that refer to an alternative icon style
if let Some(suffix) = path.multiple_extensions() {
let maybe_path = get_icon_from_suffix(suffix.as_str());
if maybe_path.is_some() {
return maybe_path;
}
}
// primary case: check if the files extension or the hidden file name
// matches some icon path
if let Some(suffix) = path.extension_or_hidden_file_name() {
@ -72,6 +81,7 @@ impl FileIcons {
return maybe_path;
}
}
this.get_icon_for_type("default", cx)
}

View file

@ -1,4 +1,5 @@
use globset::{Glob, GlobSet, GlobSetBuilder};
use itertools::Itertools;
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
@ -20,6 +21,7 @@ pub fn home_dir() -> &'static PathBuf {
pub trait PathExt {
fn compact(&self) -> PathBuf;
fn extension_or_hidden_file_name(&self) -> Option<&str>;
fn multiple_extensions(&self) -> Option<String>;
fn to_sanitized_string(&self) -> String;
fn try_from_bytes<'a>(bytes: &'a [u8]) -> anyhow::Result<Self>
where
@ -84,6 +86,27 @@ impl<T: AsRef<Path>> PathExt for T {
.or_else(|| path.file_stem()?.to_str())
}
/// Returns a file's "full" joined collection of extensions, in the case where a file does not
/// just have a singular extension but instead has multiple (e.g File.tar.gz, Component.stories.tsx)
///
/// Will provide back the extensions joined together such as tar.gz or stories.tsx
fn multiple_extensions(&self) -> Option<String> {
let path = self.as_ref();
let file_name = path.file_name()?.to_str()?;
let parts: Vec<&str> = file_name
.split('.')
// Skip the part with the file name extension
.skip(1)
.collect();
if parts.len() < 2 {
return None;
}
Some(parts.into_iter().join("."))
}
/// Returns a sanitized string representation of the path.
/// Note, on Windows, this assumes that the path is a valid UTF-8 string and
/// is not a UNC path.
@ -1171,6 +1194,25 @@ mod tests {
assert_eq!(path.extension_or_hidden_file_name(), Some("eslintrc.js"));
}
#[test]
fn test_multiple_extensions() {
// No extensions
let path = Path::new("/a/b/c/file_name");
assert_eq!(path.multiple_extensions(), None);
// Only one extension
let path = Path::new("/a/b/c/file_name.tsx");
assert_eq!(path.multiple_extensions(), None);
// Stories sample extension
let path = Path::new("/a/b/c/file_name.stories.tsx");
assert_eq!(path.multiple_extensions(), Some("stories.tsx".to_string()));
// Longer sample extension
let path = Path::new("/a/b/c/long.app.tar.gz");
assert_eq!(path.multiple_extensions(), Some("app.tar.gz".to_string()));
}
#[test]
fn edge_of_glob() {
let path = Path::new("/work/node_modules");