diff --git a/ImageDescriber.Test/ScanTests.cs b/ImageDescriber.Test/ScanTests.cs index ddea4bf..eaaa0ca 100644 --- a/ImageDescriber.Test/ScanTests.cs +++ b/ImageDescriber.Test/ScanTests.cs @@ -181,6 +181,45 @@ public void SanitizeFileNameStripsUpperCaseImageExtension() Assert.AreEqual("photo.png", result.WeakString); } + [TestMethod] + [DataRow("sunset-over-the-lake.", "sunset-over-the-lake.jpg")] + [DataRow("Sunset over the lake.", "Sunset over the lake.jpg")] + [DataRow("sunset-over-the-lake. ", "sunset-over-the-lake.jpg")] + [DataRow("\"sunset-over-the-lake.\"", "sunset-over-the-lake.jpg")] + public void SanitizeFileNameDropsTrailingPeriod(string suggestion, string expected) + { + FileName result = Scan.SanitizeFileName(suggestion, ".jpg".As()); + + Assert.AreEqual(expected, result.WeakString); + } + + [TestMethod] + public void SanitizeFileNameStripsImageExtensionFollowedByPeriod() + { + FileName result = Scan.SanitizeFileName("photo.jpg.", ".png".As()); + + Assert.AreEqual("photo.png", result.WeakString); + } + + [TestMethod] + [DataRow("...")] + [DataRow(". . .")] + [DataRow("-.-")] + public void SanitizeFileNameReturnsUnnamedForOnlyPeriods(string suggestion) + { + FileName result = Scan.SanitizeFileName(suggestion, ".jpg".As()); + + Assert.AreEqual("unnamed.jpg", result.WeakString); + } + + [TestMethod] + public void SanitizeFileNameDropsPeriodLeftBeforeTrimmedHyphen() + { + FileName result = Scan.SanitizeFileName("sunset.-", ".jpg".As()); + + Assert.AreEqual("sunset.jpg", result.WeakString); + } + [TestMethod] public void HashFilesSkipsFilesThatCannotBeRead() { diff --git a/ImageDescriber/Verbs/Scan.cs b/ImageDescriber/Verbs/Scan.cs index 8c58f49..f2e860c 100644 --- a/ImageDescriber/Verbs/Scan.cs +++ b/ImageDescriber/Verbs/Scan.cs @@ -263,7 +263,9 @@ internal static FileName SanitizeFileName(string rawSuggestion, FileExtension ex .Split('\n') .Select(line => line.Trim()) .FirstOrDefault(line => line.Length > 0 && !IsCodeFence(line)) ?? string.Empty; - name = name.Trim('"', '\'', '`').Trim(); + // Models often end the answer with a full stop. Drop it before the extension check, so + // "photo.jpg." still loses its extension and "sunset." does not become "sunset..jpg" + name = name.Trim('"', '\'', '`').Trim().TrimEnd('.', ' '); // Strip an image extension the model may have included. A suggestion normally has no // extension, so any other dot is part of the name ("st.-louis-arch", "sunset-at-5.30pm") @@ -283,7 +285,7 @@ internal static FileName SanitizeFileName(string rawSuggestion, FileExtension ex name = name.Replace("--", "-", StringComparison.Ordinal); } - name = name.Trim('-', ' '); + name = name.Trim('-', ' ', '.'); if (string.IsNullOrEmpty(name)) {