@@ -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() {
@@ -1,4 +1,5 @@
use globset::{Glob, GlobSet, GlobSetBuilder};
+use itertools::Itertools;
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
@@ -60,6 +61,7 @@ pub trait PathExt {
}
}
fn local_to_wsl(&self) -> Option<PathBuf>;
+ fn multiple_extensions(&self) -> Option<String>;
}
impl<T: AsRef<Path>> PathExt for T {
@@ -130,6 +132,27 @@ impl<T: AsRef<Path>> PathExt for T {
Some(new_path.into())
}
+
+ /// 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("."))
+ }
}
/// In memory, this is identical to `Path`. On non-Windows conversions to this type are no-ops. On
@@ -1727,4 +1750,23 @@ mod tests {
assert_eq!(natural_sort("file-1.2", "file-1.10"), Ordering::Less);
assert_eq!(natural_sort("file-1.10", "file-1.2"), Ordering::Greater);
}
+
+ #[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()));
+ }
}