canon 0.1.23 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +155 -30
- data/docs/INDEX.adoc +4 -0
- data/docs/advanced/diff-classification.adoc +3 -2
- data/docs/advanced/verbose-mode-architecture.adoc +23 -0
- data/docs/features/configuration-profiles.adoc +288 -0
- data/docs/features/diff-formatting/character-visualization.adoc +153 -454
- data/docs/features/diff-formatting/display-filtering.adoc +44 -0
- data/docs/features/diff-formatting/display-preprocessing.adoc +656 -0
- data/docs/features/diff-formatting/index.adoc +47 -0
- data/docs/features/diff-formatting/pretty-diff-mode.adoc +154 -0
- data/docs/features/environment-configuration/override-system.adoc +10 -3
- data/docs/features/index.adoc +9 -0
- data/docs/features/match-options/html-policies.adoc +3 -0
- data/docs/features/match-options/index.adoc +32 -42
- data/docs/features/match-options/pretty-printed-fixtures.adoc +270 -0
- data/docs/guides/choosing-configuration.adoc +22 -0
- data/docs/reference/environment-variables.adoc +121 -1
- data/docs/reference/options-across-interfaces.adoc +182 -2
- data/lib/canon/cli.rb +20 -0
- data/lib/canon/commands/diff_command.rb +7 -2
- data/lib/canon/commands/format_command.rb +1 -1
- data/lib/canon/comparison/html_comparator.rb +29 -19
- data/lib/canon/comparison/html_compare_profile.rb +4 -4
- data/lib/canon/comparison/markup_comparator.rb +12 -3
- data/lib/canon/comparison/match_options/base_resolver.rb +29 -7
- data/lib/canon/comparison/match_options/json_resolver.rb +9 -0
- data/lib/canon/comparison/match_options/xml_resolver.rb +16 -2
- data/lib/canon/comparison/match_options/yaml_resolver.rb +10 -0
- data/lib/canon/comparison/match_options.rb +4 -1
- data/lib/canon/comparison/whitespace_sensitivity.rb +189 -137
- data/lib/canon/comparison/xml_comparator/child_comparison.rb +21 -4
- data/lib/canon/comparison/xml_comparator.rb +14 -12
- data/lib/canon/comparison/xml_node_comparison.rb +51 -6
- data/lib/canon/comparison.rb +52 -9
- data/lib/canon/config/env_schema.rb +32 -4
- data/lib/canon/config/override_resolver.rb +16 -3
- data/lib/canon/config/profile_loader.rb +135 -0
- data/lib/canon/config/profiles/metanorma.yml +74 -0
- data/lib/canon/config/profiles/metanorma_debug.yml +8 -0
- data/lib/canon/config/type_converter.rb +8 -0
- data/lib/canon/config.rb +469 -5
- data/lib/canon/diff/diff_classifier.rb +41 -11
- data/lib/canon/diff_formatter/diff_detail_formatter/dimension_formatter.rb +48 -17
- data/lib/canon/diff_formatter/diff_detail_formatter/node_utils.rb +58 -0
- data/lib/canon/diff_formatter/diff_detail_formatter.rb +73 -17
- data/lib/canon/diff_formatter.rb +493 -36
- data/lib/canon/pretty_printer/xml_normalized.rb +395 -0
- data/lib/canon/rspec_matchers.rb +36 -0
- data/lib/canon/version.rb +1 -1
- data/lib/canon/xml/nodes/namespace_node.rb +4 -0
- data/lib/canon/xml/nodes/processing_instruction_node.rb +4 -0
- data/lib/canon/xml/nodes/root_node.rb +4 -0
- data/lib/canon/xml/nodes/text_node.rb +4 -0
- data/lib/tasks/performance_helpers.rb +2 -2
- metadata +24 -2
|
@@ -72,6 +72,19 @@ Make invisible characters visible in diff output:
|
|
|
72
72
|
* Non-ASCII character detection
|
|
73
73
|
* CJK-safe Unicode symbols
|
|
74
74
|
|
|
75
|
+
Controlled via `Canon::Config`:
|
|
76
|
+
|
|
77
|
+
* `true` — (default) apply the full visualization map; spaces → `░`, tabs → `⇥`, NBSP → `␣`
|
|
78
|
+
* `false` — disable all substitution; useful for copying output or CI tooling that cannot render Unicode symbols
|
|
79
|
+
* `:content_only` — reserved; currently behaves as `true`
|
|
80
|
+
|
|
81
|
+
[source,ruby]
|
|
82
|
+
----
|
|
83
|
+
Canon::Config.configure do |cfg|
|
|
84
|
+
cfg.xml.diff.character_visualization = false
|
|
85
|
+
end
|
|
86
|
+
----
|
|
87
|
+
|
|
75
88
|
See link:character-visualization.adoc[Character visualization] for details.
|
|
76
89
|
|
|
77
90
|
=== Context and grouping
|
|
@@ -83,6 +96,40 @@ Control how much surrounding context to show:
|
|
|
83
96
|
|
|
84
97
|
See link:context-and-grouping.adoc[Context and grouping] for details.
|
|
85
98
|
|
|
99
|
+
=== Display preprocessing
|
|
100
|
+
|
|
101
|
+
Normalize both documents through the same formatter before the line diff, so
|
|
102
|
+
that formatting differences between expected and actual do not confuse the LCS
|
|
103
|
+
algorithm:
|
|
104
|
+
|
|
105
|
+
* `:none` — use documents as-is (default)
|
|
106
|
+
* `:pretty_print` — run through `Canon::PrettyPrinter::Xml` (one tag per line)
|
|
107
|
+
* `:c14n` — run through XML C14N normalization
|
|
108
|
+
|
|
109
|
+
See link:display-preprocessing.adoc[Display preprocessing] for details,
|
|
110
|
+
including the character-visualization constraint for future extensibility.
|
|
111
|
+
|
|
112
|
+
=== Pretty-diff mode
|
|
113
|
+
|
|
114
|
+
`:pretty_diff` is a text-LCS diff mode that bypasses DiffNodeMapper entirely.
|
|
115
|
+
It applies `display_preprocessing` to both sides and runs `Diff::LCS.sdiff`
|
|
116
|
+
on the resulting plain-text lines, guaranteeing that every line-level change
|
|
117
|
+
is visible — even when DiffNodeMapper's DOM-address correlation is unreliable.
|
|
118
|
+
|
|
119
|
+
Use it as a reliable fallback when `:by_line` shows no output for changes you
|
|
120
|
+
know are present (issue #85).
|
|
121
|
+
|
|
122
|
+
[source,ruby]
|
|
123
|
+
----
|
|
124
|
+
formatter = Canon::DiffFormatter.new(
|
|
125
|
+
mode: :pretty_diff,
|
|
126
|
+
display_preprocessing: :pretty_print,
|
|
127
|
+
context_lines: 3,
|
|
128
|
+
)
|
|
129
|
+
----
|
|
130
|
+
|
|
131
|
+
See link:pretty-diff-mode.adoc[Pretty-diff mode] for details and limitations.
|
|
132
|
+
|
|
86
133
|
=== Algorithm-specific output
|
|
87
134
|
|
|
88
135
|
Different diff algorithms produce different output styles:
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Pretty-diff mode
|
|
3
|
+
parent: Diff Formatting
|
|
4
|
+
grand_parent: Features
|
|
5
|
+
nav_order: 9
|
|
6
|
+
---
|
|
7
|
+
= Pretty-diff mode
|
|
8
|
+
:toc:
|
|
9
|
+
:toclevels: 2
|
|
10
|
+
|
|
11
|
+
== Purpose
|
|
12
|
+
|
|
13
|
+
`:pretty_diff` is a text-LCS diff mode that bypasses DiffNodeMapper entirely.
|
|
14
|
+
It applies `display_preprocessing` to both sides, then runs
|
|
15
|
+
`Diff::LCS.sdiff` on the resulting plain-text lines.
|
|
16
|
+
|
|
17
|
+
This guarantees that every line-level change is visible, regardless of whether
|
|
18
|
+
DiffNodeMapper's DOM-address correlation is accurate.
|
|
19
|
+
|
|
20
|
+
== When to use
|
|
21
|
+
|
|
22
|
+
Use `:pretty_diff` when:
|
|
23
|
+
|
|
24
|
+
* `:by_line` mode shows no diff output for changes you *know* are present
|
|
25
|
+
(the issue #85 class of bug where DiffNodeMapper maps DiffNodes to the
|
|
26
|
+
wrong post-preprocessing line numbers)
|
|
27
|
+
* You want a quick human-readable text diff and do not need inline
|
|
28
|
+
character-level highlighting
|
|
29
|
+
|
|
30
|
+
Use `:by_line` when:
|
|
31
|
+
|
|
32
|
+
* Inline character highlighting within a line matters
|
|
33
|
+
* `show_diffs: :normative` / `:informative` filtering is required (these
|
|
34
|
+
filters rely on DiffNodes that `:pretty_diff` does not use)
|
|
35
|
+
|
|
36
|
+
== Usage
|
|
37
|
+
|
|
38
|
+
=== Basic usage
|
|
39
|
+
|
|
40
|
+
[source,ruby]
|
|
41
|
+
----
|
|
42
|
+
formatter = Canon::DiffFormatter.new(
|
|
43
|
+
mode: :pretty_diff,
|
|
44
|
+
display_preprocessing: :normalize_pretty_print, # recommended for mixed-content XML
|
|
45
|
+
context_lines: 3,
|
|
46
|
+
use_color: true,
|
|
47
|
+
)
|
|
48
|
+
output = formatter.format(differences, :xml, doc1: expected, doc2: actual)
|
|
49
|
+
----
|
|
50
|
+
|
|
51
|
+
Combining with `display_preprocessing: :normalize_pretty_print` is strongly
|
|
52
|
+
recommended for XML with inline markup (Metanorma, DocBook, DITA). It breaks
|
|
53
|
+
every mixed-content element onto separate lines and visualizes inter-element
|
|
54
|
+
whitespace, so the LCS diff can pinpoint changes inside `<p>`, `<formattedref>`,
|
|
55
|
+
and similar elements.
|
|
56
|
+
|
|
57
|
+
`display_preprocessing: :pretty_print` is sufficient for element-only XML
|
|
58
|
+
(no mixed content).
|
|
59
|
+
|
|
60
|
+
=== Controlling per-element whitespace visualization
|
|
61
|
+
|
|
62
|
+
By default, `:normalize_pretty_print` treats all inter-element whitespace as
|
|
63
|
+
structural formatting noise and drops it silently — both compact XML and
|
|
64
|
+
indented XML serialize to identical lines. This is the correct default for
|
|
65
|
+
purely structural elements such as `<formattedref>` or `<bibdata>`.
|
|
66
|
+
|
|
67
|
+
For mixed-content elements where whitespace *presence* is meaningful (e.g. the
|
|
68
|
+
word-boundary space in `<p>See <xref/>`), opt in with
|
|
69
|
+
`collapse_whitespace_elements`:
|
|
70
|
+
|
|
71
|
+
[source,ruby]
|
|
72
|
+
----
|
|
73
|
+
formatter = Canon::DiffFormatter.new(
|
|
74
|
+
mode: :pretty_diff,
|
|
75
|
+
display_preprocessing: :normalize_pretty_print,
|
|
76
|
+
collapse_whitespace_elements: %w[p li td th],
|
|
77
|
+
context_lines: 3,
|
|
78
|
+
use_color: true,
|
|
79
|
+
)
|
|
80
|
+
----
|
|
81
|
+
|
|
82
|
+
Or via `Canon::Config` (recommended in `spec_helper.rb`):
|
|
83
|
+
|
|
84
|
+
[source,ruby]
|
|
85
|
+
----
|
|
86
|
+
Canon::Config.configure do |cfg|
|
|
87
|
+
cfg.xml.diff.mode = :pretty_diff
|
|
88
|
+
cfg.xml.diff.display_preprocessing = :normalize_pretty_print
|
|
89
|
+
cfg.xml.diff.collapse_whitespace_elements = %w[p li td th]
|
|
90
|
+
end
|
|
91
|
+
----
|
|
92
|
+
|
|
93
|
+
For preformatted elements where every whitespace character is significant, use
|
|
94
|
+
`preserve_whitespace_elements` instead (e.g. `%w[pre code]`).
|
|
95
|
+
|
|
96
|
+
See
|
|
97
|
+
link:display-preprocessing.adoc#_controlling_whitespace_visualization_with_element_classification[display-preprocessing:
|
|
98
|
+
element classification] for the full three-way classification system and HTML
|
|
99
|
+
format defaults.
|
|
100
|
+
|
|
101
|
+
== Output format
|
|
102
|
+
|
|
103
|
+
The output uses the same header/context/separator conventions as `:by_line`:
|
|
104
|
+
|
|
105
|
+
[source]
|
|
106
|
+
----
|
|
107
|
+
Pretty diff (XML mode):
|
|
108
|
+
<section>
|
|
109
|
+
<title>Introduction</title>
|
|
110
|
+
- <para>This describes the <strong>old</strong> behaviour.</para>
|
|
111
|
+
+ <para>This describes the <strong>new</strong> behaviour.</para>
|
|
112
|
+
<note>See also: Appendix A.</note>
|
|
113
|
+
</section>
|
|
114
|
+
----
|
|
115
|
+
|
|
116
|
+
* Lines prefixed `- ` are removals (present in `doc1`, absent in `doc2`)
|
|
117
|
+
* Lines prefixed `+ ` are additions (absent in `doc1`, present in `doc2`)
|
|
118
|
+
* Lines prefixed ` ` are context (unchanged)
|
|
119
|
+
* `--- ---` separates non-adjacent change blocks
|
|
120
|
+
|
|
121
|
+
== Context windowing
|
|
122
|
+
|
|
123
|
+
`context_lines` (default 3) controls how many unchanged lines are shown around
|
|
124
|
+
each change. Nearby windows whose expanded ranges overlap or are adjacent are
|
|
125
|
+
merged into a single block. A `--- ---` separator is emitted between blocks
|
|
126
|
+
that are not adjacent.
|
|
127
|
+
|
|
128
|
+
Setting `context_lines: 0` shows only the changed lines with no surrounding
|
|
129
|
+
context.
|
|
130
|
+
|
|
131
|
+
== Limitations
|
|
132
|
+
|
|
133
|
+
`:pretty_diff` trades DiffNode integration for reliability:
|
|
134
|
+
|
|
135
|
+
* `show_diffs: :normative` / `:informative` filtering is **not supported**.
|
|
136
|
+
All line differences are shown regardless of their classification.
|
|
137
|
+
* Inline character-level highlighting (e.g. highlighting the changed word
|
|
138
|
+
within a changed line) is **not available**; granularity is whole-line only.
|
|
139
|
+
* The `differences` array passed to `DiffFormatter#format` is **ignored**;
|
|
140
|
+
the diff is computed purely from `doc1` and `doc2` via LCS.
|
|
141
|
+
|
|
142
|
+
== Implementation note
|
|
143
|
+
|
|
144
|
+
`Diff::LCS.sdiff` is invoked with `::Diff::LCS` (absolute constant path)
|
|
145
|
+
to avoid resolving against `Canon::Diff` which is an unrelated internal module.
|
|
146
|
+
|
|
147
|
+
== See also
|
|
148
|
+
|
|
149
|
+
* link:display-preprocessing.adoc[Display preprocessing] — normalising input
|
|
150
|
+
before the diff
|
|
151
|
+
* link:context-and-grouping.adoc[Context and grouping] — context_lines and
|
|
152
|
+
diff grouping
|
|
153
|
+
* link:display-filtering.adoc[Display filtering] — normative/informative
|
|
154
|
+
filtering (`:by_line` only)
|
|
@@ -16,7 +16,7 @@ This page explains how the priority chain works, when overrides apply, and how t
|
|
|
16
16
|
|
|
17
17
|
== Priority chain
|
|
18
18
|
|
|
19
|
-
Configuration values are resolved using a strict
|
|
19
|
+
Configuration values are resolved using a strict four-level priority:
|
|
20
20
|
|
|
21
21
|
[source]
|
|
22
22
|
----
|
|
@@ -26,18 +26,25 @@ Configuration values are resolved using a strict three-level priority:
|
|
|
26
26
|
└──────────────┬──────────────────┘
|
|
27
27
|
↓ overrides
|
|
28
28
|
┌─────────────────────────────────┐
|
|
29
|
-
│ 2. Programmatic Configuration │
|
|
29
|
+
│ 2. Programmatic Configuration │
|
|
30
30
|
│ (config.xml.diff.algorithm) │
|
|
31
31
|
└──────────────┬──────────────────┘
|
|
32
32
|
↓ overrides
|
|
33
33
|
┌─────────────────────────────────┐
|
|
34
|
-
│ 3.
|
|
34
|
+
│ 3. Profile Values │
|
|
35
|
+
│ (from YAML config profile) │
|
|
36
|
+
└──────────────┬──────────────────┘
|
|
37
|
+
↓ overrides
|
|
38
|
+
┌─────────────────────────────────┐
|
|
39
|
+
│ 4. Default Values │ ← Lowest Priority
|
|
35
40
|
│ (defined in Canon::Config) │
|
|
36
41
|
└─────────────────────────────────┘
|
|
37
42
|
----
|
|
38
43
|
|
|
39
44
|
**Rule**: Higher priority always wins, regardless of when values are set.
|
|
40
45
|
|
|
46
|
+
See link:../configuration-profiles.adoc[Configuration Profiles] for details on the profile layer.
|
|
47
|
+
|
|
41
48
|
== How overrides work
|
|
42
49
|
|
|
43
50
|
=== Environment variables override programmatic settings
|
data/docs/features/index.adoc
CHANGED
|
@@ -77,6 +77,15 @@ Customize how differences are displayed.
|
|
|
77
77
|
* link:diff-formatting/context-and-grouping[Context and Grouping] - Surrounding lines
|
|
78
78
|
* link:diff-formatting/character-visualization[Character Visualization] - Whitespace visibility
|
|
79
79
|
|
|
80
|
+
=== Configuration Profiles
|
|
81
|
+
|
|
82
|
+
link:configuration-profiles.adoc[**Configuration Profiles**]::
|
|
83
|
+
Bundle all settings into named presets defined in YAML.
|
|
84
|
+
+
|
|
85
|
+
* Built-in profiles (metanorma, metanorma_debug)
|
|
86
|
+
* Custom profiles from local YAML files
|
|
87
|
+
* Profile inheritance
|
|
88
|
+
|
|
80
89
|
=== System Configuration
|
|
81
90
|
|
|
82
91
|
link:environment-configuration/[**Environment Configuration**]::
|
|
@@ -226,6 +226,9 @@ Canon::Comparison.equivalent?(html1, html2, preprocessing: :rendered)
|
|
|
226
226
|
Pretty-prints before comparison:
|
|
227
227
|
- Consistent indentation
|
|
228
228
|
- One element per line
|
|
229
|
+
- Whitespace-only text nodes in strip-context elements (e.g. `<div>`) are
|
|
230
|
+
removed after formatting, so differences in structural whitespace between
|
|
231
|
+
elements do not produce false normative differences
|
|
229
232
|
- Good for visual diffs
|
|
230
233
|
|
|
231
234
|
[source,ruby]
|
|
@@ -30,6 +30,7 @@ Match options control which aspects of documents are compared and how strictly t
|
|
|
30
30
|
* link:profiles.adoc[Match Profiles] - Predefined configurations
|
|
31
31
|
* link:algorithm-specific-behavior.adoc[Algorithm-Specific Behavior] - How DOM and Semantic algorithms interpret options differently
|
|
32
32
|
* link:html-policies.adoc[HTML-Specific Policies] - HTML format-specific comparison policies
|
|
33
|
+
* link:pretty-printed-fixtures.adoc[Pretty-Printed Fixture Support] - Comparing compact generated XML against hand-indented fixture heredocs without spurious whitespace differences
|
|
33
34
|
|
|
34
35
|
== Match dimensions overview
|
|
35
36
|
|
|
@@ -188,34 +189,25 @@ Canon::Comparison.equivalent?(xml1, xml2,
|
|
|
188
189
|
----
|
|
189
190
|
====
|
|
190
191
|
|
|
191
|
-
====
|
|
192
|
+
==== Element classification options
|
|
192
193
|
|
|
193
|
-
You can explicitly
|
|
194
|
+
You can explicitly classify elements for whitespace handling:
|
|
194
195
|
|
|
195
196
|
[source,ruby]
|
|
196
197
|
----
|
|
197
|
-
# Short names (preferred)
|
|
198
198
|
Canon::Comparison.equivalent?(xml1, xml2,
|
|
199
199
|
match: {
|
|
200
200
|
structural_whitespace: :strict,
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
# Long names (backward-compatible)
|
|
207
|
-
Canon::Comparison.equivalent?(xml1, xml2,
|
|
208
|
-
match: {
|
|
209
|
-
structural_whitespace: :strict,
|
|
210
|
-
whitespace_sensitive_elements: ["pre", "code", "sample"],
|
|
211
|
-
whitespace_insensitive_elements: ["div", "span"]
|
|
201
|
+
preserve_whitespace_elements: ["pre", "code", "sample"],
|
|
202
|
+
collapse_whitespace_elements: ["p", "li", "td"],
|
|
203
|
+
strip_whitespace_elements: ["div", "span"]
|
|
212
204
|
}
|
|
213
205
|
)
|
|
214
206
|
----
|
|
215
207
|
|
|
216
208
|
**Element names are strings** (not symbols) for consistency with XML/HTML conventions.
|
|
217
209
|
|
|
218
|
-
**
|
|
210
|
+
**Priority order**: strip > preserve > collapse > format defaults.
|
|
219
211
|
|
|
220
212
|
==== respect_xml_space option
|
|
221
213
|
|
|
@@ -248,21 +240,19 @@ When determining if an element is whitespace-sensitive, Canon uses this priority
|
|
|
248
240
|
----
|
|
249
241
|
1. respect_xml_space: false → User config only (ignore xml:space)
|
|
250
242
|
↓
|
|
251
|
-
2.
|
|
243
|
+
2. Ancestor walk (strip wins; then preserve; then collapse)
|
|
252
244
|
↓
|
|
253
|
-
3.
|
|
245
|
+
3. xml:space="preserve" → Element classified as :preserve
|
|
254
246
|
↓
|
|
255
|
-
4.
|
|
247
|
+
4. xml:space="default" → Use configured behaviour
|
|
256
248
|
↓
|
|
257
|
-
5.
|
|
258
|
-
↓
|
|
259
|
-
6. xml:space="default" → Use steps 1-4
|
|
260
|
-
----
|
|
249
|
+
5. Format defaults (HTML: preserve + collapse; XML: strip)
|
|
261
250
|
|
|
262
251
|
==== Format-specific defaults
|
|
263
252
|
|
|
264
|
-
**HTML**:: `["pre", "textarea", "script", "style"]` -
|
|
265
|
-
**
|
|
253
|
+
**HTML preserve**:: `["pre", "textarea", "script", "style"]` - Every whitespace character significant
|
|
254
|
+
**HTML collapse**:: `["p", "li", "td", "th", "dt", "dd", "h1"-"h6", ...]` - Whitespace collapsed
|
|
255
|
+
**XML**:: No defaults — all elements are :strip unless explicitly configured
|
|
266
256
|
|
|
267
257
|
==== Two types of whitespace sensitivity
|
|
268
258
|
|
|
@@ -272,28 +262,28 @@ Canon handles two distinct whitespace concerns:
|
|
|
272
262
|
|
|
273
263
|
**2. Text content comparison** — how non-whitespace text content is compared. Controlled by `structural_whitespace` and `text_content` dimension behaviors (`:strict`, `:normalize`, `:ignore`).
|
|
274
264
|
|
|
275
|
-
The `
|
|
265
|
+
The `preserve_whitespace_elements`, `collapse_whitespace_elements`, and `strip_whitespace_elements` options control both concerns:
|
|
276
266
|
|
|
277
267
|
[source,ruby]
|
|
278
268
|
----
|
|
279
269
|
# For XML: structural whitespace is stripped by default
|
|
280
|
-
# Use
|
|
270
|
+
# Use preserve_whitespace_elements to preserve whitespace in specific elements
|
|
281
271
|
xml1 = "<root><item>Test</item></root>"
|
|
282
272
|
xml2 = "<root>\n <item>Test</item>\n</root>"
|
|
283
273
|
|
|
284
|
-
# With
|
|
274
|
+
# With preserve_whitespace_elements, whitespace inside <item> is preserved
|
|
285
275
|
Canon::Comparison.equivalent?(xml1, xml2,
|
|
286
276
|
match: {
|
|
287
277
|
structural_whitespace: :strict,
|
|
288
|
-
|
|
278
|
+
preserve_whitespace_elements: ["item"]
|
|
289
279
|
}
|
|
290
280
|
)
|
|
291
281
|
# => true
|
|
292
282
|
----
|
|
293
283
|
|
|
294
|
-
**Precedence**:
|
|
284
|
+
**Precedence**: `strip_whitespace_elements` > `preserve_whitespace_elements` > `collapse_whitespace_elements` > format defaults
|
|
295
285
|
|
|
296
|
-
**
|
|
286
|
+
**Ancestor-based**: The closest matching ancestor determines classification.
|
|
297
287
|
|
|
298
288
|
==== Examples
|
|
299
289
|
|
|
@@ -321,17 +311,17 @@ Canon::Comparison.equivalent?(xml1, xml2,
|
|
|
321
311
|
# => false
|
|
322
312
|
----
|
|
323
313
|
|
|
324
|
-
.Using
|
|
314
|
+
.Using preserve_whitespace_elements
|
|
325
315
|
[source,ruby]
|
|
326
316
|
----
|
|
327
|
-
# Make <sample> elements whitespace
|
|
317
|
+
# Make <sample> elements preserve whitespace exactly (strings, not symbols)
|
|
328
318
|
xml1 = "<sample>\n content\n</sample>"
|
|
329
319
|
xml2 = "<sample>content</sample>"
|
|
330
320
|
|
|
331
321
|
Canon::Comparison.equivalent?(xml1, xml2,
|
|
332
322
|
match: {
|
|
333
323
|
structural_whitespace: :strict,
|
|
334
|
-
|
|
324
|
+
preserve_whitespace_elements: ["sample"]
|
|
335
325
|
}
|
|
336
326
|
)
|
|
337
327
|
# => false (structural whitespace differs in <sample>)
|
|
@@ -340,30 +330,30 @@ Canon::Comparison.equivalent?(xml1, xml2,
|
|
|
340
330
|
.Overriding HTML defaults
|
|
341
331
|
[source,ruby]
|
|
342
332
|
----
|
|
343
|
-
# Make <script> NOT whitespace-
|
|
333
|
+
# Make <script> NOT whitespace-preserved (override HTML default)
|
|
344
334
|
Canon::Comparison.equivalent?(html1, html2,
|
|
345
335
|
format: :html,
|
|
346
336
|
match: {
|
|
347
337
|
structural_whitespace: :strict,
|
|
348
|
-
|
|
338
|
+
strip_whitespace_elements: ["script"]
|
|
349
339
|
}
|
|
350
340
|
)
|
|
351
341
|
----
|
|
352
342
|
|
|
353
|
-
.Using text_content: :normalize with
|
|
343
|
+
.Using text_content: :normalize with strip_whitespace_elements
|
|
354
344
|
[source,ruby]
|
|
355
345
|
----
|
|
356
|
-
# HTML defaults:
|
|
357
|
-
#
|
|
346
|
+
# HTML defaults: pre, code, textarea, script, style are :preserve
|
|
347
|
+
# Adding code to strip list removes it from preserve
|
|
358
348
|
html1 = '<root><pre> indented </pre><code> code </code></root>'
|
|
359
349
|
html2 = '<root><pre> indented </pre><code>code</code></root>'
|
|
360
350
|
|
|
361
|
-
# With :code
|
|
351
|
+
# With :code in strip list, whitespace in <code> is normalized (formatting-only)
|
|
362
352
|
# HTML uses text_content: :normalize by default
|
|
363
353
|
Canon::Comparison.equivalent?(html1, html2,
|
|
364
354
|
format: :html,
|
|
365
355
|
match: {
|
|
366
|
-
|
|
356
|
+
strip_whitespace_elements: [:code],
|
|
367
357
|
}
|
|
368
358
|
)
|
|
369
359
|
# => true (whitespace differences in <code> are formatting-only)
|
|
@@ -737,7 +727,7 @@ expect(actual).to be_xml_equivalent_to(expected,
|
|
|
737
727
|
match: { structural_whitespace: :strict }
|
|
738
728
|
)
|
|
739
729
|
.with_options(
|
|
740
|
-
|
|
730
|
+
preserve_whitespace_elements: ["pre", "code", "sample"],
|
|
741
731
|
respect_xml_space: true
|
|
742
732
|
)
|
|
743
733
|
|
|
@@ -746,7 +736,7 @@ expect(html).to be_html_equivalent_to(expected,
|
|
|
746
736
|
match: { structural_whitespace: :strict }
|
|
747
737
|
)
|
|
748
738
|
.with_options(
|
|
749
|
-
|
|
739
|
+
strip_whitespace_elements: ["script", "style"]
|
|
750
740
|
)
|
|
751
741
|
====
|
|
752
742
|
|