diff --git a/crates/catalog/src/model.rs b/crates/catalog/src/model.rs index f03772a3..153c715e 100644 --- a/crates/catalog/src/model.rs +++ b/crates/catalog/src/model.rs @@ -377,9 +377,9 @@ impl Photo { d } /// The file name's extension without the dot, as written (`CR2` for `IMG_0042.CR2`); empty - /// when the name has none. + /// when the name has none (`README`, a dot file such as `.hidden`). pub fn extension(&self) -> &str { - self.file_name.rsplit_once('.').map_or("", |(_, ext)| ext) + self.file_name.rsplit_once('.').filter(|(stem, _)| !stem.is_empty()).map_or("", |(_, ext)| ext) } /// Width and height in pixels as the photo is shown: turned by its orientation and cut by its /// crop. Straightening and Constrain Crop shrink the crop without changing its shape, so the @@ -394,7 +394,7 @@ impl Photo { } /// Cropped or straightened. pub fn is_cropped(&self) -> bool { - self.develop.crop.geometry != lightcraft_develop::Crop::default().geometry + !self.develop.crop.geometry.is_identity() } /// How many keywords the photo has: a hierarchical keyword (`travel|italy|rome`) is one, and /// the same keyword in different case or with stray spaces counts once; blank ones don't count. diff --git a/crates/catalog/src/rules.rs b/crates/catalog/src/rules.rs index 8975ce3b..cb2f1981 100644 --- a/crates/catalog/src/rules.rs +++ b/crates/catalog/src/rules.rs @@ -727,6 +727,8 @@ mod tests { assert!(m(&p, "extension", "isEmpty", json!(null)), "no dot, no extension"); p.file_name = "archive.tar.gz".into(); assert!(m(&p, "extension", "is", json!("gz"))); + p.file_name = ".hidden".into(); + assert!(m(&p, "extension", "isEmpty", json!(null)), "a dot file has no extension"); assert!(m(&p, "copyName", "isEmpty", json!(null))); p.copy_name = Some("Black and white".into()); assert!(m(&p, "copyName", "contains", json!("black")));