Skip to content

Commit 8449eab

Browse files
committed
Tweaked DiffBuilders options handling, updated documentation
1 parent 62ada9f commit 8449eab

16 files changed

+220
-295
lines changed

README.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# AngleSharp Diffing - A diff/compare library for AngleSharp
2+
[![Build status](https://ci.appveyor.com/api/projects/status/8awr3r4ylwy9habm?svg=true)](https://ci.appveyor.com/project/FlorianRappl/anglesharp-diffing)
3+
24
This library makes it possible to compare a AngleSharp _control_ `INodeList` and a _test_ `INodeList` and get a list of `IDiff` differences between them.
35

46
The _control_ nodes represents the expected HTML tree, i.e. how the nodes are expected to look, and the _test_ nodes represents the nodes that should be compared to the _control_ nodes.
@@ -16,17 +18,16 @@ To find the differences between a control HTML fragment and a test HTML fragment
1618
var controlHtml = "<p>Hello World</p>";
1719
var testHtml = "<p>World, I say hello</p>";
1820
var diffs = DiffBuilder
19-
.Compare(controlHtml)
20-
.WithTest(testHtml)
21-
.WithDefaultOptions()
21+
.Compare(control)
22+
.WithTest(test)
2223
.Build();
2324
```
2425

25-
Read more about the available options on the [Diffing Options/Strategies](/docs/Strategies.md) page.
26+
Read more about the available options on the [Options](/docs/Options.md) page.
2627

2728
# Documentation
28-
- [Diffing Options/Strategies](/docs/Strategies.md)
29-
- [Creating custom diffing options/strategies](/docs/CustomStrategies.md)
29+
- [Options](/docs/Options.md)
30+
- [Creating custom diffing options](/docs/CustomOptions.md)
3031
- [Difference engine internals](/docs/DiffingEngineInternals.md)
3132

3233
## Acknowledgments
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Creating custom diffing strategies
22

3-
TODO!
4-
53
### Filters
64
- default starting decision is `true`.
75
- if a filter receives a source that it does not have an opinion on, it should always return the current decision, whatever it may be.

docs/Strategies.md renamed to docs/Options.md

+86-62
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Diffing options/strategies:
1+
# Diffing Options
22
The library comes with a bunch of options (internally referred to as strategies), for the following three main steps in the diffing process:
33

44
1. Filtering out irrelevant nodes and attributes
@@ -7,44 +7,55 @@ The library comes with a bunch of options (internally referred to as strategies)
77

88
To make it easier to configure the diffing engine, the library comes with a `DiffBuilder` class, which handles the relative complex task of setting up the `HtmlDifferenceEngine`.
99

10-
Using the `UseDefaultOptions()` method is equivalent to setting the following options explicitly:
11-
12-
To learn how to create your own strategies, visit the [Custom Strategies](CustomStrategies.md) page.
10+
To learn how to create your own strategies, visit the [Custom Options](CustomOptions.md) page.
1311

1412
The following section documents the current built-in strategies that are available.
1513

1614
## Default Options
17-
In most cases, calling the `UseDefaultOptions()` method on a `DiffBuilder` instance will give you a good set of strategies for a comparison, e.g.
15+
In most cases, calling `DiffBuilder.Compare(...).WithTest(...).Build()` will give you a good set of default options for a comparison, e.g.
1816

1917
```csharp
2018
var controlHtml = "<p>Hello World</p>";
2119
var testHtml = "<p>World, I say hello</p>";
2220
var diffs = DiffBuilder
2321
.Compare(controlHtml)
2422
.WithTest(testHtml)
25-
.WithDefaultOptions()
2623
.Build();
2724
```
2825

29-
Calling the `WithDefaultOptions()` method is equivalent to specifying the following options explicitly:
26+
If you want to be more explicit, the following is equivalent to the code above:
27+
28+
```csharp
29+
var controlHtml = "<p>Hello World</p>";
30+
var testHtml = "<p>World, I say hello</p>";
31+
var diffs = DiffBuilder
32+
.Compare(control)
33+
.WithTest(test)
34+
.WithOptions((IDiffingStrategyCollection options) => options.AddDefaultOptions())
35+
.Build();
36+
```
37+
38+
Calling the `AddDefaultOptions()` method is equivalent to specifying the following options explicitly:
3039

3140
```csharp
3241
var diffs = DiffBuilder
3342
.Compare(controlHtml)
3443
.WithTest(testHtml)
35-
.IgnoreDiffAttributes()
36-
.IgnoreComments()
37-
.WithSearchingNodeMatcher()
38-
.WithCssSelectorMatcher()
39-
.WithAttributeNameMatcher()
40-
.WithNodeNameComparer()
41-
.WithIgnoreElementSupport()
42-
.WithStyleSheetComparer()
43-
.WithTextComparer(WhitespaceOption.Normalize, ignoreCase: false)
44-
.WithAttributeComparer()
45-
.WithClassAttributeComparer()
46-
.WithBooleanAttributeComparer(BooleanAttributeComparision.Strict)
47-
.WithStyleAttributeComparer()
44+
.WithOptions((IDiffingStrategyCollection options) => options
45+
.IgnoreDiffAttributes()
46+
.IgnoreComments()
47+
.AddSearchingNodeMatcher()
48+
.AddCssSelectorMatcher()
49+
.AddAttributeNameMatcher()
50+
.AddElementComparer()
51+
.AddIgnoreElementSupport()
52+
.AddStyleSheetComparer()
53+
.AddTextComparer(WhitespaceOption.Normalize, ignoreCase: false)
54+
.AddAttributeComparer()
55+
.AddClassAttributeComparer()
56+
.AddBooleanAttributeComparer(BooleanAttributeComparision.Strict)
57+
.AddStyleAttributeComparer()
58+
)
4859
.Build();
4960
```
5061

@@ -54,28 +65,49 @@ Read more about each of the strategies below, including some that are not part o
5465
These are the built-in filter strategies.
5566

5667
### Ignore comments
57-
Enabling this strategy will ignore all comment nodes during comparison. Activate by calling the `IgnoreComments()` method on a `DiffBuilder` instance, e.g.:
68+
Enabling this strategy will ignore all comment nodes during comparison. Activate by calling the `IgnoreComments()` method on a `IDiffingStrategyCollection` type, e.g.:
5869

5970
```csharp
6071
var diffs = DiffBuilder
6172
.Compare(controlHtml)
6273
.WithTest(testHtml)
63-
.IgnoreComments()
74+
.WithOptions(options => options.IgnoreComments())
6475
.Build();
6576
```
6677

6778
_**NOTE**: Currently, the ignore comment strategy does NOT remove comments from CSS or JavaScript embedded in `<style>` or `<script>` tags._
6879

80+
### Ignore element attribute
81+
If the `diff:ignore="true"` attribute is used on a control element (`="true"` implicit/optional), all their attributes and child nodes are skipped/ignored during comparison, including those of the test element, the control element is matched with.
82+
83+
In this example, the `<h1>` tag, it's attribute and children are considered the same as the element it is matched with:
84+
85+
```html
86+
<header>
87+
<h1 class="heading-1" diff:ignore>Hello world</h1>
88+
</header>
89+
```
90+
91+
Activate this strategy by calling the `AddIgnoreElementSupport()` method on the `IDiffingStrategyCollection` type, e.g.:
92+
93+
```csharp
94+
var diffs = DiffBuilder
95+
.Compare(controlHtml)
96+
.WithTest(testHtml)
97+
.WithOptions(options => options.AddIgnoreElementSupport())
98+
.Build();
99+
```
100+
69101
### Ignoring special "diff"-attributes
70102
Any attributes that starts with `diff:` are automatically filtered out before matching/comparing happens. E.g. `diff:whitespace="..."` does not show up as a missing diff when added to an control element.
71103

72-
To enable this option, use the `IgnoreDiffAttributes()` method on the `DiffBuilder` class, e.g.:
104+
To enable this option, use the `IgnoreDiffAttributes()` method on the `IDiffingStrategyCollection` type, e.g.:
73105

74106
```csharp
75107
var diffs = DiffBuilder
76108
.Compare(controlHtml)
77109
.WithTest(testHtml)
78-
.IgnoreDiffAttributes()
110+
.WithOptions(options => options.IgnoreDiffAttributes())
79111
.Build();
80112
```
81113

@@ -92,13 +124,13 @@ If either of the lists is shorter than the other, the remaining items will be re
92124

93125
If a node has been marked as matched by a previous executed matcher, the One-to-one matcher will not use that node in its matching, and skip over it.
94126

95-
To choose this matcher, use the `WithOneToOneNodeMatcher()` method on the `DiffBuilder` class, e.g.:
127+
To choose this matcher, use the `AddOneToOneNodeMatcher()` method on the `IDiffingStrategyCollection` type, e.g.:
96128

97129
```csharp
98130
var diffs = DiffBuilder
99131
.Compare(controlHtml)
100132
.WithTest(testHtml)
101-
.WithOneToOneNodeMatcher()
133+
.WithOptions(options => options.AddOneToOneNodeMatcher())
102134
.Build();
103135
```
104136

@@ -128,13 +160,13 @@ forwardSearchingMatcher(controlNodes, testNodes) {
128160
}
129161
```
130162

131-
To choose this matcher, use the `WithSearchingNodeMatcher()` method on the `DiffBuilder` class, e.g.:
163+
To choose this matcher, use the `AddSearchingNodeMatcher()` method on the `IDiffingStrategyCollection` type, e.g.:
132164

133165
```csharp
134166
var diffs = DiffBuilder
135167
.Compare(controlHtml)
136168
.WithTest(testHtml)
137-
.WithSearchingNodeMatcher()
169+
.WithOptions(options => options.AddSearchingNodeMatcher())
138170
.Build();
139171
```
140172

@@ -163,13 +195,13 @@ The following control node will be compared against the `<h1>` in the `<header>`
163195

164196
One use case of the CSS-selector element matcher is where you only want to test one part of a sub-tree, and ignore the rest. The example above will report the unmatched test nodes as *unexpected*, but those "diffs" can be ignored, since that is expected. This approach can save you from specifying all the needed control nodes, if only part of a sub tree needs to be compared.
165197

166-
To choose this matcher, use the `WithCssSelectorMatcher()` method on the `DiffBuilder` class, e.g.:
198+
To choose this matcher, use the `AddCssSelectorMatcher()` method on the `IDiffingStrategyCollection` type, e.g.:
167199

168200
```csharp
169201
var diffs = DiffBuilder
170202
.Compare(controlHtml)
171203
.WithTest(testHtml)
172-
.WithCssSelectorMatcher()
204+
.WithOptions(options => options.AddCssSelectorMatcher())
173205
.Build();
174206
```
175207

@@ -179,50 +211,42 @@ These are the built-in attribute matching strategies.
179211
#### Attribute name matcher
180212
This selector will match attributes on a control element with attributes on a test element using the attribute's name. If an *control* attribute is not matched, it is reported as *missing* and if a *test* attribute is not matched, it is reported as *unexpected*.
181213

182-
To choose this matcher, use the `WithAttributeNameMatcher()` method on the `DiffBuilder` class, e.g.:
214+
To choose this matcher, use the `AddAttributeNameMatcher()` method on the `IDiffingStrategyCollection` type, e.g.:
183215

184216
```csharp
185217
var diffs = DiffBuilder
186218
.Compare(controlHtml)
187219
.WithTest(testHtml)
188-
.WithAttributeNameMatcher()
220+
.WithOptions(options => options.AddAttributeNameMatcher())
189221
.Build();
190222
```
191223

192224
## Comparing strategies
193225
These are the built-in comparing strategies.
194226

195-
### Node and element compare strategy
196-
The basic node compare strategy will simply check if the node's types and node's name are equal.
227+
### Element compare strategy
228+
The basic element compare strategy will simply check if the both nodes's are elements and the element's name are the same.
197229

198-
To choose this comparer, use the `WithNodeNameComparer()` method on the `DiffBuilder` class, e.g.:
230+
To choose this comparer, use the `AddElementComparer()` method on the `IDiffingStrategyCollection` type, e.g.:
199231

200232
```csharp
201233
var diffs = DiffBuilder
202234
.Compare(controlHtml)
203235
.WithTest(testHtml)
204-
.WithNodeNameComparer()
236+
.WithOptions(options => options.AddElementComparer())
205237
.Build();
206238
```
207239

208-
#### Ignore element attribute
209-
If the `diff:ignore="true"` attribute is used on a control element (`="true"` implicit/optional), all their attributes and child nodes are skipped/ignored during comparison, including those of the test element, the control element is matched with.
210-
211-
In this example, the `<h1>` tag, it's attribute and children are considered the same as the element it is matched with:
212-
213-
```html
214-
<header>
215-
<h1 class="heading-1" diff:ignore>Hello world</h1>
216-
</header>
217-
```
240+
### Comment compare strategy
241+
The basic comment compare strategy will simply check if the both nodes's are comments.
218242

219-
Activate this strategy by calling the `WithIgnoreElementSupport()` method on a `DiffBuilder` instance, e.g.:
243+
To choose this comparer, use the `AddCommentComparer()` method on the `IDiffingStrategyCollection` type, e.g.:
220244

221245
```csharp
222246
var diffs = DiffBuilder
223247
.Compare(controlHtml)
224248
.WithTest(testHtml)
225-
.WithIgnoreElementSupport()
249+
.WithOptions(options => options.AddCommentComparer())
226250
.Build();
227251
```
228252

@@ -240,13 +264,13 @@ Whitespace can be a source of false-positives when comparing two HTML fragments.
240264

241265
These options can be set either _globally_ for the entire comparison, or inline on a _specific subtrees in the comparison_.
242266

243-
To set a global default, call the method `WithTextComparer(WhitespaceOption)` on a `DiffBuilder` instance, e.g.:
267+
To set a global default, call the method `AddTextComparer(WhitespaceOption)` on the `IDiffingStrategyCollection` type, e.g.:
244268

245269
```csharp
246270
var diffs = DiffBuilder
247271
.Compare(controlHtml)
248272
.WithTest(testHtml)
249-
.WithTextComparer(WhitespaceOption.Normalize)
273+
.WithOptions(options => options.AddTextComparer(WhitespaceOption.Normalize))
250274
.Build();
251275
```
252276

@@ -267,13 +291,13 @@ To configure/override whitespace rules on a specific subtree in the comparison,
267291
This should ensure that the meaning of the content in those tags doesn't change by default. To deal correctly with whitespace in `<style>` tags, use the [Style sheet text comparer](#style-sheet-text-comparer).
268292

269293
#### Perform case-_insensitve_ text comparison
270-
To compare the text in two text nodes to each other using a case-insensitive comparison, call the `WithTextComparer(ignoreCase: true)` method on a `DiffBuilder` instance, e.g.:
294+
To compare the text in two text nodes to each other using a case-insensitive comparison, call the `AddTextComparer(ignoreCase: true)` method on the `IDiffingStrategyCollection` type, e.g.:
271295

272296
```csharp
273297
var diffs = DiffBuilder
274298
.Compare(controlHtml)
275299
.WithTest(testHtml)
276-
.WithTextComparer(ignoreCase: true)
300+
.WithOptions(options => options.AddTextComparer(ignoreCase: true))
277301
.Build();
278302
```
279303

@@ -301,13 +325,13 @@ The above control text would use case-insensitive regular expression to match a
301325
#### Style sheet text comparer
302326
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.
303327

304-
To add this comparer, use the `WithStyleSheetComparer()` method on the `DiffBuilder` class, e.g.:
328+
To add this comparer, use the `AddStyleSheetComparer()` method on the `IDiffingStrategyCollection` type, e.g.:
305329

306330
```csharp
307331
var diffs = DiffBuilder
308332
.Compare(controlHtml)
309333
.WithTest(testHtml)
310-
.WithStyleSheetComparer()
334+
.WithOptions(options => options.AddStyleSheetComparer())
311335
.Build();
312336
```
313337

@@ -321,13 +345,13 @@ The *"name and value comparison"* is the base comparison option, and that will t
321345
- `attr="foo"` is the NOT same as `attr="bar"`
322346
- `foo="attr"` is the NOT same as `bar="attr"`
323347

324-
To choose this comparer, use the `WithAttributeComparer()` method on the `DiffBuilder` class, e.g.:
348+
To choose this comparer, use the `AddAttributeComparer()` method on the `IDiffingStrategyCollection` type, e.g.:
325349

326350
```csharp
327351
var diffs = DiffBuilder
328352
.Compare(controlHtml)
329353
.WithTest(testHtml)
330-
.WithAttributeComparer()
354+
.WithOptions(options => options.AddAttributeComparer())
331355
.Build();
332356
```
333357

@@ -352,13 +376,13 @@ The class attribute is special in HTML. It can contain a space separated list of
352376

353377
- `class="foo bar"` is the same as `class="bar foo"`
354378

355-
To enable the special handling of the class attribute, call the `WithClassAttributeComparer()` on a `DiffBuilder` instance, e.g.:
379+
To enable the special handling of the class attribute, call the `AddClassAttributeComparer()` on the `IDiffingStrategyCollection` type, e.g.:
356380

357381
```csharp
358382
var diffs = DiffBuilder
359383
.Compare(controlHtml)
360384
.WithTest(testHtml)
361-
.WithClassAttributeComparer()
385+
.WithOptions(options => options.AddClassAttributeComparer())
362386
.Build();
363387
```
364388

@@ -374,26 +398,26 @@ For example, in **strict** mode, the following are considered equal:
374398
- `required=""` is the same as `required="required"`
375399
- `required="required"` is the same as `required="required"`
376400

377-
To enable the special handling of boolean attributes, call the `WithBooleanAttributeComparer(BooleanAttributeComparision.Strict)` or `WithBooleanAttributeComparer(BooleanAttributeComparision.Loose)` on a `DiffBuilder` instance, e.g.:
401+
To enable the special handling of boolean attributes, call the `AddBooleanAttributeComparer(BooleanAttributeComparision.Strict)` or `AddBooleanAttributeComparer(BooleanAttributeComparision.Loose)` on the `IDiffingStrategyCollection` type, e.g.:
378402

379403
```csharp
380404
var diffs = DiffBuilder
381405
.Compare(controlHtml)
382406
.WithTest(testHtml)
383-
.WithBooleanAttributeComparer(BooleanAttributeComparision.Strict)
407+
.WithOptions(options => options.AddBooleanAttributeComparer(BooleanAttributeComparision.Strict))
384408
.Build();
385409
```
386410

387411
#### Style attribute comparer
388412
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.
389413

390-
To add this comparer, use the `WithStyleAttributeComparer()` method on the `DiffBuilder` class, e.g.:
414+
To add this comparer, use the `AddStyleAttributeComparer()` method on the `IDiffingStrategyCollection` type, e.g.:
391415

392416
```csharp
393417
var diffs = DiffBuilder
394418
.Compare(controlHtml)
395419
.WithTest(testHtml)
396-
.WithStyleAttributeComparer()
420+
.WithOptions(options => options.AddStyleAttributeComparer())
397421
.Build();
398422
```
399423

0 commit comments

Comments
 (0)