diff --git a/src/AngleSharp.Diffing.Tests/DiffBuilderTest.cs b/src/AngleSharp.Diffing.Tests/DiffBuilderTest.cs
index 9769990..e9ad09d 100644
--- a/src/AngleSharp.Diffing.Tests/DiffBuilderTest.cs
+++ b/src/AngleSharp.Diffing.Tests/DiffBuilderTest.cs
@@ -1,3 +1,8 @@
+using AngleSharp.Diffing.Strategies;
+using AngleSharp.Diffing.Strategies.AttributeStrategies;
+using AngleSharp.Diffing.Strategies.TextNodeStrategies;
+using AngleSharp.Diffing.TestData;
+
namespace AngleSharp.Diffing;
@@ -116,4 +121,38 @@ public void Test006(string control, string test)
diffs.ShouldBeEmpty();
}
-}
+
+ [Theory(DisplayName =
+ "When a control element has ':ignore', elements with and without that attribute should return empty diffs")]
+ [MemberData(nameof(IgnoreAttributeTestData.ControlAndHtmlData), MemberType = typeof(IgnoreAttributeTestData))]
+ public void Test007(string controlHtml, string testHtml)
+ {
+ var diffs = DiffBuilder.Compare(controlHtml).WithTest(testHtml).Build();
+ Assert.Empty(diffs);
+ }
+
+ [Theory(DisplayName =
+ "When a control element has ':ignore', but IgnoreAttributeComparer is not active, diffs should be found")]
+ [MemberData(nameof(IgnoreAttributeTestData.ControlHtmlAndDiffData), MemberType = typeof(IgnoreAttributeTestData))]
+ public void Test008(string controlHtml, string testHtml, DiffResult expectedDiffResult)
+ {
+ var diffs = DiffBuilder
+ .Compare(controlHtml)
+ .WithTest(testHtml)
+ .WithOptions(a => a // Most important thing to note here is we do not have a ignore attribute comparer
+ .AddSearchingNodeMatcher()
+ .AddMatcher(AttributeNameMatcher.Match, StrategyType.Generalized)
+ .AddElementComparer(enforceTagClosing: false)
+ .AddMatcher(PostfixedAttributeMatcher.Match, StrategyType.Specialized)
+ .AddComparer(AttributeComparer.Compare, StrategyType.Generalized)
+ .AddClassAttributeComparer()
+ .AddBooleanAttributeComparer(BooleanAttributeComparision.Strict)
+ .AddStyleAttributeComparer())
+ .Build()
+ .ToList();
+
+ Assert.Single(diffs);
+ Assert.Equal(DiffTarget.Attribute, diffs[0].Target);
+ Assert.Equal(expectedDiffResult, diffs[0].Result);
+ }
+}
\ No newline at end of file
diff --git a/src/AngleSharp.Diffing.Tests/Strategies/AttributeStrategies/IgnoreAttributeComparerTest.cs b/src/AngleSharp.Diffing.Tests/Strategies/AttributeStrategies/IgnoreAttributeComparerTest.cs
index a59efc3..34bb922 100644
--- a/src/AngleSharp.Diffing.Tests/Strategies/AttributeStrategies/IgnoreAttributeComparerTest.cs
+++ b/src/AngleSharp.Diffing.Tests/Strategies/AttributeStrategies/IgnoreAttributeComparerTest.cs
@@ -17,7 +17,7 @@ public void Test000(CompareResult currentResult)
@"
", "foo"
);
- IgnoreAttributeComparer
+ IgnoreAttributeStrategy
.Compare(comparison, currentResult)
.ShouldBe(currentResult);
}
@@ -30,8 +30,8 @@ public void Test003()
@"", "foo"
);
- IgnoreAttributeComparer.Compare(comparison, CompareResult.Different).ShouldBe(CompareResult.Different);
- IgnoreAttributeComparer.Compare(comparison, CompareResult.Same).ShouldBe(CompareResult.Same);
+ IgnoreAttributeStrategy.Compare(comparison, CompareResult.Different).ShouldBe(CompareResult.Different);
+ IgnoreAttributeStrategy.Compare(comparison, CompareResult.Same).ShouldBe(CompareResult.Same);
}
[Fact(DisplayName = "When a attribute does contain have the ':ignore' postfix, Same is returned")]
@@ -42,6 +42,6 @@ public void Test004()
@"", "foo"
);
- IgnoreAttributeComparer.Compare(comparison, CompareResult.Unknown).ShouldBe(CompareResult.Same);
+ IgnoreAttributeStrategy.Compare(comparison, CompareResult.Unknown).ShouldBe(CompareResult.Same);
}
}
diff --git a/src/AngleSharp.Diffing.Tests/TestData/IgnoreAttributeTestData.cs b/src/AngleSharp.Diffing.Tests/TestData/IgnoreAttributeTestData.cs
new file mode 100644
index 0000000..daded07
--- /dev/null
+++ b/src/AngleSharp.Diffing.Tests/TestData/IgnoreAttributeTestData.cs
@@ -0,0 +1,45 @@
+namespace AngleSharp.Diffing.TestData;
+
+internal static class IgnoreAttributeTestData
+{
+ public static TheoryData ControlAndHtmlData()
+ {
+ var theoryData = new TheoryData();
+ foreach (var (controlHtml, expectedHtml, _) in TestCases)
+ {
+ theoryData.Add(controlHtml, expectedHtml);
+ }
+
+ return theoryData;
+ }
+
+ public static TheoryData ControlHtmlAndDiffData()
+ {
+ var theoryData = new TheoryData();
+ foreach (var (controlHtml, expectedHtml, expectedDiffResult) in TestCases)
+ {
+ theoryData.Add(controlHtml, expectedHtml, expectedDiffResult);
+ }
+
+ return theoryData;
+ }
+
+ private static readonly IEnumerable<(string controlHtml, string expectedHtml, DiffResult expectedDiffResult)>
+ TestCases =
+ [
+ ("", "", DiffResult.Different),
+ ("", "", DiffResult.Different),
+ ("", "", DiffResult.Different),
+ ("", "", DiffResult.Missing),
+ ("", "", DiffResult.Different),
+ ("", "", DiffResult.Different),
+ ("", "", DiffResult.Different),
+ ("", "", DiffResult.Missing),
+ ("", "", DiffResult.Different),
+ ("", "", DiffResult.Missing),
+ ("", "", DiffResult.Different),
+ ("", "", DiffResult.Missing),
+ ("", "", DiffResult.Different),
+ ("", "", DiffResult.Missing),
+ ];
+}
\ No newline at end of file
diff --git a/src/AngleSharp.Diffing/Core/HtmlDifferenceEngine.cs b/src/AngleSharp.Diffing/Core/HtmlDifferenceEngine.cs
index 575ca96..35734aa 100644
--- a/src/AngleSharp.Diffing/Core/HtmlDifferenceEngine.cs
+++ b/src/AngleSharp.Diffing/Core/HtmlDifferenceEngine.cs
@@ -1,4 +1,5 @@
using AngleSharp.Diffing.Core.Diffs;
+using AngleSharp.Diffing.Strategies.AttributeStrategies;
namespace AngleSharp.Diffing.Core;
diff --git a/src/AngleSharp.Diffing/Core/SourceMap.cs b/src/AngleSharp.Diffing/Core/SourceMap.cs
index 4f99c8d..4b30d12 100644
--- a/src/AngleSharp.Diffing/Core/SourceMap.cs
+++ b/src/AngleSharp.Diffing/Core/SourceMap.cs
@@ -70,7 +70,7 @@ public IEnumerable GetUnmatched()
{
foreach (var source in _sources.Values)
{
- if (!_matched.Contains(source.Attribute.Name))
+ if (IsUnmatched(source.Attribute.Name))
yield return source;
}
}
diff --git a/src/AngleSharp.Diffing/Strategies/AttributeStrategies/DiffingStrategyPipelineBuilderExtensions.cs b/src/AngleSharp.Diffing/Strategies/AttributeStrategies/DiffingStrategyPipelineBuilderExtensions.cs
index 17b8223..ca9f18d 100644
--- a/src/AngleSharp.Diffing/Strategies/AttributeStrategies/DiffingStrategyPipelineBuilderExtensions.cs
+++ b/src/AngleSharp.Diffing/Strategies/AttributeStrategies/DiffingStrategyPipelineBuilderExtensions.cs
@@ -23,6 +23,7 @@ public static IDiffingStrategyCollection IgnoreDiffAttributes(this IDiffingStrat
public static IDiffingStrategyCollection AddAttributeNameMatcher(this IDiffingStrategyCollection builder)
{
builder.AddMatcher(AttributeNameMatcher.Match, StrategyType.Generalized);
+ builder.AddMatcher(IgnoreAttributeStrategy.Match, StrategyType.Generalized);
return builder;
}
@@ -33,7 +34,7 @@ public static IDiffingStrategyCollection AddAttributeComparer(this IDiffingStrat
{
builder.AddMatcher(PostfixedAttributeMatcher.Match, StrategyType.Specialized);
builder.AddComparer(AttributeComparer.Compare, StrategyType.Generalized);
- builder.AddComparer(IgnoreAttributeComparer.Compare, StrategyType.Specialized);
+ builder.AddComparer(IgnoreAttributeStrategy.Compare, StrategyType.Specialized);
return builder;
}
diff --git a/src/AngleSharp.Diffing/Strategies/AttributeStrategies/IgnoreAttributeComparer.cs b/src/AngleSharp.Diffing/Strategies/AttributeStrategies/IgnoreAttributeComparer.cs
index c74f619..eb42457 100644
--- a/src/AngleSharp.Diffing/Strategies/AttributeStrategies/IgnoreAttributeComparer.cs
+++ b/src/AngleSharp.Diffing/Strategies/AttributeStrategies/IgnoreAttributeComparer.cs
@@ -3,6 +3,7 @@
///
/// Represents the ignore attribute comparer.
///
+[Obsolete("Has been moved to IgnoreAttributeStrategy")]
public static class IgnoreAttributeComparer
{
private const string DIFF_IGNORE_POSTFIX = ":ignore";
@@ -15,8 +16,13 @@ public static CompareResult Compare(in AttributeComparison comparison, CompareRe
if (currentDecision.IsSameOrSkip)
return currentDecision;
- return comparison.Control.Attribute.Name.EndsWith(DIFF_IGNORE_POSTFIX, StringComparison.OrdinalIgnoreCase)
+ return IsIgnoreAttribute(comparison.Control.Attribute)
? CompareResult.Same
: currentDecision;
}
-}
+
+ private static bool IsIgnoreAttribute(IAttr source)
+ {
+ return source.Name.EndsWith(DIFF_IGNORE_POSTFIX, StringComparison.OrdinalIgnoreCase);
+ }
+}
\ No newline at end of file
diff --git a/src/AngleSharp.Diffing/Strategies/AttributeStrategies/IgnoreAttributeStrategy.cs b/src/AngleSharp.Diffing/Strategies/AttributeStrategies/IgnoreAttributeStrategy.cs
new file mode 100644
index 0000000..84d24b6
--- /dev/null
+++ b/src/AngleSharp.Diffing/Strategies/AttributeStrategies/IgnoreAttributeStrategy.cs
@@ -0,0 +1,47 @@
+namespace AngleSharp.Diffing.Strategies.AttributeStrategies;
+
+///
+/// Ignore Attribute matcher strategy.
+///
+public static class IgnoreAttributeStrategy
+{
+ private const string DIFF_IGNORE_POSTFIX = ":ignore";
+
+ ///
+ /// The ignore attribute comparer.
+ ///
+ public static CompareResult Compare(in AttributeComparison comparison, CompareResult currentDecision)
+ {
+ if (currentDecision.IsSameOrSkip)
+ return currentDecision;
+
+ return IsIgnoreAttribute(comparison.Control.Attribute)
+ ? CompareResult.Same
+ : currentDecision;
+ }
+
+ ///
+ /// Attribute name matcher strategy.
+ ///
+ public static IEnumerable Match(IDiffContext context, SourceMap controlSources, SourceMap testSources)
+ {
+ if (controlSources is null)
+ throw new ArgumentNullException(nameof(controlSources));
+ if (testSources is null)
+ throw new ArgumentNullException(nameof(testSources));
+
+ foreach (var control in controlSources.GetUnmatched())
+ {
+ // An unmatched :ignore attribute can just be matched with itself if it isn't
+ // matched with a "test" attribute of the same name already.
+ // this means an ignored attribute is ignored even if it does not appear in the test html.
+ if (control.Attribute.Name.EndsWith(DIFF_IGNORE_POSTFIX, StringComparison.OrdinalIgnoreCase))
+ yield return new AttributeComparison(control, control);
+ }
+ }
+
+ private static bool IsIgnoreAttribute(IAttr source)
+ {
+ return source.Name.EndsWith(DIFF_IGNORE_POSTFIX, StringComparison.OrdinalIgnoreCase);
+ }
+}
\ No newline at end of file