Skip to content

Commit b4c8d32

Browse files
committed
Special diffing of style attributes
1 parent 10cf1d6 commit b4c8d32

File tree

6 files changed

+110
-3
lines changed

6 files changed

+110
-3
lines changed

AngleSharp.Diffing.v3.ncrunchsolution

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<SolutionConfiguration>
2+
<Settings>
3+
<AllowParallelTestExecution>True</AllowParallelTestExecution>
4+
<SolutionConfigured>True</SolutionConfigured>
5+
</Settings>
6+
</SolutionConfiguration>

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ var testHtml = "<p>World, I say hello</p>";
1818
var diffs = DiffBuilder
1919
.Compare(controlHtml)
2020
.WithTest(testHtml)
21-
.UseDefaultOptions()
21+
.WithDefaultOptions()
2222
.Build();
2323
```
2424

docs/Strategies.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ var diffs = DiffBuilder
4444
.WithAttributeComparer()
4545
.WithClassAttributeComparer()
4646
.WithBooleanAttributeComparer(BooleanAttributeComparision.Strict)
47+
.WithStyleAttributeComparer()
4748
.WithInlineAttributeIgnoreSupport()
4849
.Build();
4950
```
@@ -297,7 +298,7 @@ By using the inline attribute `diff:regex` on the element containing the text no
297298
The above control text would use case-insensitive regular expression to match against a test text string (e.g. "HELLO WORLD 2020").
298299

299300
#### Style sheet text comparer
300-
Different rules whitespace apply to style sheets (style information) inside `<style>` tags and `style="..."` attributes, than to HTML5. This comparer will parse the style information inside `<style>` tags and `style="..."` attributes and compare the result of the parsing, instead doing a direct string comparison. This should remove false-positives where e.g. insignificant whitespace makes two otherwise equal set of style informations result in a diff.
301+
Different whitespace rules apply to style sheets (style information) inside `<style>` tags, than to HTML5. This comparer will parse the style information inside `<style>` tags and compare the result of the parsing, instead doing a direct string comparison. This should remove false-positives where e.g. insignificant whitespace makes two otherwise equal set of style informations result in a diff.
301302

302303
To add this comparer, use the `WithStyleSheetComparer()` method on the `DiffBuilder` class, e.g.:
303304

@@ -382,7 +383,20 @@ var diffs = DiffBuilder
382383
.Build();
383384
```
384385

385-
### Ignore attributes during diffing
386+
#### Style attribute comparer
387+
Different whitespace rules apply to style information inside `style="..."` attributes, than to HTML5. This comparer will parse the style information inside `style="..."` attributes and compare the result of the parsing, instead doing a direct string comparison. This should remove false-positives where e.g. insignificant whitespace makes two otherwise equal set of style informations result in a diff.
388+
389+
To add this comparer, use the `WithStyleAttributeComparer()` method on the `DiffBuilder` class, e.g.:
390+
391+
```csharp
392+
var diffs = DiffBuilder
393+
.Compare(controlHtml)
394+
.WithTest(testHtml)
395+
.WithStyleAttributeComparer()
396+
.Build();
397+
```
398+
399+
#### Ignore attributes during diffing
386400
To ignore a specific attribute during comparison, add the `:ignore` postfix to the attribute on the control element. Thus will simply skip comparing the two attributes and not report any differences between them. E.g. to ignore the `class` attribute, do:
387401

388402
```html

src/Strategies/AttributeStrategies/DiffingStrategyPipelineExtensions.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,14 @@ public static DiffingStrategyPipeline WithInlineAttributeIgnoreSupport(this Diff
6363
pipeline.AddComparer(IgnoreAttributeComparer.Compare, isSpecializedComparer: true);
6464
return pipeline;
6565
}
66+
67+
/// <summary>
68+
/// Enables the special style attributes comparer during diffing.
69+
/// </summary>
70+
public static DiffingStrategyPipeline WithStyleAttributeComparer(this DiffingStrategyPipeline pipeline)
71+
{
72+
pipeline.AddComparer(StyleAttributeComparer.Compare, isSpecializedComparer: true);
73+
return pipeline;
74+
}
6675
}
6776
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Egil.AngleSharp.Diffing.Core;
7+
using AngleSharp.Css.Dom;
8+
using AngleSharp.Css.Parser;
9+
using AngleSharp.Dom;
10+
11+
namespace Egil.AngleSharp.Diffing.Strategies.AttributeStrategies
12+
{
13+
public static class StyleAttributeComparer
14+
{
15+
public static CompareResult Compare(in AttributeComparison comparison, CompareResult currentDecision)
16+
{
17+
if (currentDecision.IsDecisionFinal()) return currentDecision;
18+
19+
return IsStyleAttributeComparison(comparison)
20+
? CompareElementStyle(comparison)
21+
: currentDecision;
22+
}
23+
24+
private static CompareResult CompareElementStyle(in AttributeComparison comparison)
25+
{
26+
var (ctrlElm, testElm) = comparison.GetNodesAsElements();
27+
var ctrlStyle = ctrlElm.GetStyle();
28+
var testStyle = testElm.GetStyle();
29+
return ctrlStyle.CssText.Equals(testStyle.CssText, StringComparison.Ordinal)
30+
? CompareResult.Same
31+
: CompareResult.Different;
32+
}
33+
34+
private static bool IsStyleAttributeComparison(in AttributeComparison comparison)
35+
{
36+
return comparison.Control.Attribute.Name.Equals(AttributeNames.Style, StringComparison.Ordinal) &&
37+
comparison.Test.Attribute.Name.Equals(AttributeNames.Style, StringComparison.Ordinal);
38+
}
39+
}
40+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Egil.AngleSharp.Diffing.Core;
2+
using Shouldly;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using Xunit;
9+
10+
namespace Egil.AngleSharp.Diffing.Strategies.AttributeStrategies
11+
{
12+
public class StyleAttributeComparerTest : DiffingTestBase
13+
{
14+
[Fact(DisplayName = "When attribute is not style the current decision is used")]
15+
public void Test001()
16+
{
17+
var comparison = ToAttributeComparison(@"<p foo=""bar"">", "foo", @"<p foo=""zab"">", "foo");
18+
StyleAttributeComparer.Compare(comparison, CompareResult.Different).ShouldBe(CompareResult.Different);
19+
StyleAttributeComparer.Compare(comparison, CompareResult.Same).ShouldBe(CompareResult.Same);
20+
StyleAttributeComparer.Compare(comparison, CompareResult.DifferentAndBreak).ShouldBe(CompareResult.DifferentAndBreak);
21+
StyleAttributeComparer.Compare(comparison, CompareResult.SameAndBreak).ShouldBe(CompareResult.SameAndBreak);
22+
}
23+
24+
[Fact(DisplayName = "When style attributes has different values then Different is returned")]
25+
public void Test002()
26+
{
27+
var comparison = ToAttributeComparison(@"<p style=""color: red"">", "style", @"<p style=""color: black"">", "style");
28+
StyleAttributeComparer.Compare(comparison, CompareResult.Different).ShouldBe(CompareResult.Different);
29+
}
30+
31+
[Fact(DisplayName = "Comparer should correctly ignore insignificant whitespace")]
32+
public void Test003()
33+
{
34+
var comparison = ToAttributeComparison(@"<p style=""color: red"">", "style", @"<p style=""color:red"">", "style");
35+
StyleAttributeComparer.Compare(comparison, CompareResult.Different).ShouldBe(CompareResult.Same);
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)