diff --git a/src/IIIF/IIIF.Tests/Presentation/HtmlSanitiserTests.cs b/src/IIIF/IIIF.Tests/Presentation/HtmlSanitiserTests.cs
index 37b3d23..f9049f7 100644
--- a/src/IIIF/IIIF.Tests/Presentation/HtmlSanitiserTests.cs
+++ b/src/IIIF/IIIF.Tests/Presentation/HtmlSanitiserTests.cs
@@ -11,6 +11,19 @@ public class HtmlSanitiserTests
public void SanitiseHtml_ReturnsGivenString_IfNullOrEmpty(string val)
=> val.SanitiseHtml().Should().Be(val);
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void SanitiseHtml_ReturnsEmptyString_IfGivenInvalidHtml(bool ignoreNonHtml)
+ {
+ const string input = "
invalid html
";
+ const string expected = "";
+
+ var actual = input.SanitiseHtml(ignoreNonHtml);
+
+ actual.Should().Be(expected);
+ }
+
[Fact]
public void SanitiseHtml_Trims_Whitespace_FromBeginningAndEnd_IfIgnoreNonHtmlFalse()
{
diff --git a/src/IIIF/IIIF.Tests/Presentation/V3/LabelValuePairXTests.cs b/src/IIIF/IIIF.Tests/Presentation/V3/LabelValuePairXTests.cs
new file mode 100644
index 0000000..41bea6c
--- /dev/null
+++ b/src/IIIF/IIIF.Tests/Presentation/V3/LabelValuePairXTests.cs
@@ -0,0 +1,64 @@
+using System.Collections.Generic;
+using IIIF.Presentation.V3;
+using IIIF.Presentation.V3.Strings;
+
+namespace IIIF.Tests.Presentation.V3;
+
+public class LabelValuePairXTests
+{
+ [Fact]
+ public void TryGetValue_False_NullList()
+ {
+ List metadata = null;
+
+ var result = metadata.TryGetValue("en", "bar", out var languageMap);
+
+ result.Should().BeFalse();
+ languageMap.Should().BeNull();
+ }
+
+ [Fact]
+ public void TryGetValue_False_EmptyList()
+ {
+ var metadata = new List();
+
+ var result = metadata.TryGetValue("en", "bar", out var languageMap);
+
+ result.Should().BeFalse();
+ languageMap.Should().BeNull();
+ }
+
+ [Fact]
+ public void TryGetValue_True_ReturnsCorrect_IfFound()
+ {
+ var metadata = new List { new("en", "foo", "bar", "baz") };
+ var expected = new LanguageMap("en", new[] { "bar", "baz" });
+
+ var result = metadata.TryGetValue("en", "foo", out var languageMap);
+
+ result.Should().BeTrue();
+ languageMap.Should().BeEquivalentTo(expected);
+ }
+
+ [Fact]
+ public void TryGetValue_False_IfNotFoundForLanguage()
+ {
+ var metadata = new List { new("en", "foo", "bar", "baz") };
+
+ var result = metadata.TryGetValue("en", "bar", out var languageMap);
+
+ result.Should().BeFalse();
+ languageMap.Should().BeNull();
+ }
+
+ [Fact]
+ public void TryGetValue_False_IfLabelForDifferentLanguage()
+ {
+ var metadata = new List { new("en", "foo", "bar", "baz") };
+
+ var result = metadata.TryGetValue("fr", "bar", out var languageMap);
+
+ result.Should().BeFalse();
+ languageMap.Should().BeNull();
+ }
+}
\ No newline at end of file
diff --git a/src/IIIF/IIIF/Presentation/HtmlSanitiser.cs b/src/IIIF/IIIF/Presentation/HtmlSanitiser.cs
index a4ab7b6..0470b0b 100644
--- a/src/IIIF/IIIF/Presentation/HtmlSanitiser.cs
+++ b/src/IIIF/IIIF/Presentation/HtmlSanitiser.cs
@@ -72,6 +72,7 @@ public static string SanitiseHtml(this string propertyValue, bool ignoreNonHtml
var workingString = Sanitizer.Sanitize(propertyValue.Trim());
+ if (string.IsNullOrEmpty(workingString)) return workingString;
if (IsHtmlString(workingString)) return workingString;
if (!HtmlSanitizerOptions.AllowedTags.Contains(nonHtmlWrappingTag))
@@ -85,5 +86,6 @@ public static string SanitiseHtml(this string propertyValue, bool ignoreNonHtml
return Sanitizer.Sanitize(workingString);
}
- private static bool IsHtmlString(string candidate) => candidate[0] == '<' && candidate[^1] == '>';
+ private static bool IsHtmlString(string candidate)
+ => candidate[0] == '<' && candidate[^1] == '>';
}
\ No newline at end of file
diff --git a/src/IIIF/IIIF/Presentation/V3/LabelValuePairX.cs b/src/IIIF/IIIF/Presentation/V3/LabelValuePairX.cs
new file mode 100644
index 0000000..788bbd2
--- /dev/null
+++ b/src/IIIF/IIIF/Presentation/V3/LabelValuePairX.cs
@@ -0,0 +1,39 @@
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using IIIF.Presentation.V3.Strings;
+using IIIF.Utils;
+
+namespace IIIF.Presentation.V3;
+
+public static class LabelValuePairX
+{
+ ///
+ /// Try get values associated with specified language and label.
+ ///
+ /// Collection of to search
+ /// Language to get values for
+ /// Label to get values for
+ /// Found
+ /// true if matching value found, else false
+ public static bool TryGetValue(
+ this List? labelValuePairs,
+ string language,
+ string label,
+ [NotNullWhen(true)] out LanguageMap? languageMap)
+ {
+ languageMap = null;
+ if (labelValuePairs.IsNullOrEmpty()) return false;
+
+ foreach (var langValues in labelValuePairs.Where(lvp => lvp.Label.ContainsKey(language)))
+ {
+ if (langValues.Label.Any(l => l.Value.Contains(label)))
+ {
+ languageMap = langValues.Value;
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/IIIF/IIIF/Presentation/V3/ResourceBase.cs b/src/IIIF/IIIF/Presentation/V3/ResourceBase.cs
index 801f164..725acc1 100644
--- a/src/IIIF/IIIF/Presentation/V3/ResourceBase.cs
+++ b/src/IIIF/IIIF/Presentation/V3/ResourceBase.cs
@@ -119,4 +119,4 @@ public abstract class ResourceBase : JsonLdBase, IResource
///
[JsonProperty(Order = 1000)]
public List? PartOf { get; set; }
-}
\ No newline at end of file
+}
diff --git a/src/IIIF/IIIF/Presentation/V3/Strings/LabelValuePair.cs b/src/IIIF/IIIF/Presentation/V3/Strings/LabelValuePair.cs
index 58ee501..ede598a 100644
--- a/src/IIIF/IIIF/Presentation/V3/Strings/LabelValuePair.cs
+++ b/src/IIIF/IIIF/Presentation/V3/Strings/LabelValuePair.cs
@@ -1,5 +1,4 @@
using System.Linq;
-using Newtonsoft.Json;
namespace IIIF.Presentation.V3.Strings;
diff --git a/src/IIIF/IIIF/Utils/CollectionX.cs b/src/IIIF/IIIF/Utils/CollectionX.cs
index 174dce0..42e40ac 100644
--- a/src/IIIF/IIIF/Utils/CollectionX.cs
+++ b/src/IIIF/IIIF/Utils/CollectionX.cs
@@ -1,10 +1,11 @@
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
namespace IIIF.Utils;
internal static class CollectionX
{
- public static bool IsNullOrEmpty(this List collection)
+ public static bool IsNullOrEmpty([NotNullWhen(false)] this List? collection)
{
return collection == null || collection.Count == 0;
}