canon 0.2.0 → 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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bfa3648b7c5308716c22fbdc377d875dc60d479eb0e376cfe347eb02a279d3d7
|
|
4
|
+
data.tar.gz: 87024447cc6a13eaa8cb9d1edf91d360e35d2e6cb5a1f2b7035c067050fae24a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6299802984ef5bab4c658c534105491f853c9d6cd297a5df49e5f8c83e0b36d1b01d140c1ea510002cf2916f3902035e764dcd589e4e01c5eec10c4ba76fda28
|
|
7
|
+
data.tar.gz: 42e73a1c3f80942d7ad102187b8a19148eb8a4046539eabb45561a716711fa3a51ea228e7bc372b4f675f4777db9ad964ed6c4873c19a5be9dc375af8639d92d
|
|
@@ -130,10 +130,33 @@ Each difference displays:
|
|
|
130
130
|
* **Status indicator**: `[NORMATIVE]` (green) or `[INFORMATIVE]` (yellow)
|
|
131
131
|
* **Dimension**: Which aspect differs (colorized in magenta)
|
|
132
132
|
* **Location**: XPath for XML/HTML, path for JSON/YAML (colorized in blue)
|
|
133
|
+
* **Reason**: When the reason contains visualized whitespace characters (░),
|
|
134
|
+
it is split across two lines with the before and after text vertically
|
|
135
|
+
aligned for easier visual comparison:
|
|
136
|
+
+
|
|
137
|
+
[source]
|
|
138
|
+
----
|
|
139
|
+
Reason: Text: "░░term2░definition░░"
|
|
140
|
+
vs.: "░term2░definition░"
|
|
141
|
+
----
|
|
142
|
+
+
|
|
143
|
+
When no visualized whitespace is present, the reason remains a single line.
|
|
133
144
|
* **Expected section**: What was in File 1 (red heading, bold)
|
|
134
145
|
* **Actual section**: What was in File 2 (green heading, bold)
|
|
135
146
|
* **Changes summary**: Actionable description of the difference (yellow, bold)
|
|
136
147
|
|
|
148
|
+
When both the Expected and Actual values are short (under 30 characters), they
|
|
149
|
+
are rendered as compact single lines with aligned colons for succinctness:
|
|
150
|
+
|
|
151
|
+
[source]
|
|
152
|
+
----
|
|
153
|
+
⊖ Expected (File 1): "term2 definition"
|
|
154
|
+
⊕ Actual (File 2) : "term2 definition"
|
|
155
|
+
----
|
|
156
|
+
|
|
157
|
+
For longer values, they appear on separate lines with no blank line between
|
|
158
|
+
them.
|
|
159
|
+
|
|
137
160
|
=== Dimension-specific formats
|
|
138
161
|
|
|
139
162
|
==== Attribute presence differences
|
|
@@ -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]
|
|
@@ -393,12 +393,17 @@ module Canon
|
|
|
393
393
|
end
|
|
394
394
|
end
|
|
395
395
|
|
|
396
|
-
# For
|
|
397
|
-
|
|
398
|
-
|
|
396
|
+
# For preprocessing modes that require whitespace filtering,
|
|
397
|
+
# apply the same post-parsing normalization used for string inputs.
|
|
398
|
+
# This is needed because dom_diff() pre-parses HTML5 strings into
|
|
399
|
+
# Nokogiri fragments before calling HtmlComparator, bypassing the
|
|
400
|
+
# string-input path where these filters are normally applied.
|
|
401
|
+
if %i[normalize format rendered].include?(preprocessing)
|
|
399
402
|
frag = node.is_a?(Nokogiri::XML::DocumentFragment) ? node : Nokogiri::XML.fragment(node.to_html)
|
|
400
403
|
normalize_html_style_script_comments(frag)
|
|
401
|
-
|
|
404
|
+
if preprocessing == :rendered
|
|
405
|
+
normalize_rendered_whitespace(frag, match_opts)
|
|
406
|
+
end
|
|
402
407
|
remove_whitespace_only_text_nodes(frag)
|
|
403
408
|
return frag
|
|
404
409
|
end
|
|
@@ -14,6 +14,9 @@ module Canon
|
|
|
14
14
|
# Formats dimension-specific detail for individual differences
|
|
15
15
|
# Provides actionable, colorized output showing exactly what changed
|
|
16
16
|
module DiffDetailFormatter
|
|
17
|
+
ANSI_ESCAPE = /\e\[[0-9;]*m/
|
|
18
|
+
COMPACT_DETAIL_MAX = 30
|
|
19
|
+
|
|
17
20
|
class << self
|
|
18
21
|
# Format all differences as a semantic diff report
|
|
19
22
|
#
|
|
@@ -127,9 +130,7 @@ compact: false, expand_difference: false)
|
|
|
127
130
|
|
|
128
131
|
# show reason if available
|
|
129
132
|
if diff.respond_to?(:reason) && diff.reason
|
|
130
|
-
output
|
|
131
|
-
bold: true)} #{colorize(diff.reason,
|
|
132
|
-
:yellow, use_color)}"
|
|
133
|
+
format_reason_line(output, diff.reason, use_color)
|
|
133
134
|
end
|
|
134
135
|
output << ""
|
|
135
136
|
|
|
@@ -138,13 +139,7 @@ compact: false, expand_difference: false)
|
|
|
138
139
|
diff, use_color, compact: compact, expand_difference: expand_difference
|
|
139
140
|
)
|
|
140
141
|
|
|
141
|
-
output
|
|
142
|
-
bold: true)
|
|
143
|
-
output << " #{detail1}"
|
|
144
|
-
output << ""
|
|
145
|
-
output << colorize("⊕ Actual (File 2):", :green, use_color,
|
|
146
|
-
bold: true)
|
|
147
|
-
output << " #{detail2}"
|
|
142
|
+
format_expected_actual(output, detail1, detail2, use_color)
|
|
148
143
|
|
|
149
144
|
if changes && !changes.empty?
|
|
150
145
|
output << ""
|
|
@@ -182,6 +177,52 @@ compact: false, expand_difference: false)
|
|
|
182
177
|
colorize(error_msg, :red, use_color, bold: true)
|
|
183
178
|
end
|
|
184
179
|
|
|
180
|
+
# Format the Reason line. When the reason contains visualized
|
|
181
|
+
# spaces (░), split into two vertically-aligned lines so the
|
|
182
|
+
# before/after text can be compared visually.
|
|
183
|
+
def format_reason_line(output, reason_text, use_color)
|
|
184
|
+
if reason_text.include?("\u2591") &&
|
|
185
|
+
reason_text.match?(/\A(Text|whitespace): .*\bvs\b/)
|
|
186
|
+
parts = reason_text.split(" vs ", 2)
|
|
187
|
+
if parts.length == 2
|
|
188
|
+
output << "#{colorize('Reason:', :cyan, use_color,
|
|
189
|
+
bold: true)} #{colorize(parts[0],
|
|
190
|
+
:yellow, use_color)}"
|
|
191
|
+
output << "#{' ' * 10}#{colorize("vs.: #{parts[1]}",
|
|
192
|
+
:yellow, use_color)}"
|
|
193
|
+
return
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
output << "#{colorize('Reason:', :cyan, use_color,
|
|
197
|
+
bold: true)} #{colorize(reason_text,
|
|
198
|
+
:yellow, use_color)}"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Format the Expected/Actual block. Short values (both under 30
|
|
202
|
+
# chars) are rendered as compact single lines with aligned colons;
|
|
203
|
+
# longer values use the multi-line layout without a blank line gap.
|
|
204
|
+
def format_expected_actual(output, detail1, detail2, use_color)
|
|
205
|
+
plain1 = detail1.gsub(ANSI_ESCAPE, "")
|
|
206
|
+
plain2 = detail2.gsub(ANSI_ESCAPE, "")
|
|
207
|
+
|
|
208
|
+
if plain1.length < COMPACT_DETAIL_MAX &&
|
|
209
|
+
plain2.length < COMPACT_DETAIL_MAX
|
|
210
|
+
lbl1 = colorize("\u2296 Expected (File 1)", :red, use_color,
|
|
211
|
+
bold: true)
|
|
212
|
+
lbl2 = colorize("\u2295 Actual (File 2) ", :green, use_color,
|
|
213
|
+
bold: true)
|
|
214
|
+
output << "#{lbl1}: #{detail1}"
|
|
215
|
+
output << "#{lbl2}: #{detail2}"
|
|
216
|
+
else
|
|
217
|
+
output << colorize("\u2296 Expected (File 1):", :red, use_color,
|
|
218
|
+
bold: true)
|
|
219
|
+
output << " #{detail1}"
|
|
220
|
+
output << colorize("\u2295 Actual (File 2):", :green, use_color,
|
|
221
|
+
bold: true)
|
|
222
|
+
output << " #{detail2}"
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
185
226
|
# Helper: Colorize text
|
|
186
227
|
def colorize(text, color, use_color, bold: false)
|
|
187
228
|
DiffDetailFormatterHelpers::ColorHelper.colorize(text, color,
|
data/lib/canon/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: canon
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-04-
|
|
11
|
+
date: 2026-04-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: diff-lcs
|