canon 0.1.21 → 0.1.22
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 +43 -43
- data/README.adoc +8 -3
- data/docs/advanced/diff-pipeline.adoc +36 -9
- data/docs/features/diff-formatting/colors-and-symbols.adoc +82 -0
- data/docs/features/diff-formatting/index.adoc +12 -0
- data/docs/features/diff-formatting/themes.adoc +353 -0
- data/docs/features/environment-configuration/index.adoc +23 -0
- data/docs/internals/diff-char-range-pipeline.adoc +249 -0
- data/docs/internals/diffnode-enrichment.adoc +1 -0
- data/docs/internals/index.adoc +52 -4
- data/docs/reference/environment-variables.adoc +6 -0
- data/docs/understanding/architecture.adoc +5 -0
- data/examples/show_themes.rb +217 -0
- data/lib/canon/comparison/comparison_result.rb +9 -4
- data/lib/canon/config/env_schema.rb +3 -1
- data/lib/canon/config.rb +11 -0
- data/lib/canon/diff/diff_block.rb +7 -0
- data/lib/canon/diff/diff_block_builder.rb +2 -2
- data/lib/canon/diff/diff_char_range.rb +140 -0
- data/lib/canon/diff/diff_line.rb +42 -4
- data/lib/canon/diff/diff_line_builder.rb +907 -0
- data/lib/canon/diff/diff_node.rb +5 -1
- data/lib/canon/diff/diff_node_enricher.rb +1418 -0
- data/lib/canon/diff/diff_node_mapper.rb +54 -0
- data/lib/canon/diff/source_locator.rb +105 -0
- data/lib/canon/diff/text_decomposer.rb +103 -0
- data/lib/canon/diff_formatter/by_line/base_formatter.rb +264 -24
- data/lib/canon/diff_formatter/by_line/html_formatter.rb +35 -20
- data/lib/canon/diff_formatter/by_line/json_formatter.rb +36 -19
- data/lib/canon/diff_formatter/by_line/simple_formatter.rb +33 -19
- data/lib/canon/diff_formatter/by_line/xml_formatter.rb +583 -98
- data/lib/canon/diff_formatter/by_line/yaml_formatter.rb +36 -19
- data/lib/canon/diff_formatter/by_object/base_formatter.rb +62 -13
- data/lib/canon/diff_formatter/by_object/json_formatter.rb +59 -24
- data/lib/canon/diff_formatter/by_object/xml_formatter.rb +74 -34
- data/lib/canon/diff_formatter/diff_detail_formatter/color_helper.rb +4 -5
- data/lib/canon/diff_formatter/diff_detail_formatter.rb +1 -1
- data/lib/canon/diff_formatter/legend.rb +4 -2
- data/lib/canon/diff_formatter/theme.rb +857 -0
- data/lib/canon/diff_formatter.rb +11 -6
- data/lib/canon/tree_diff/matchers/hash_matcher.rb +15 -15
- data/lib/canon/tree_diff/matchers/similarity_matcher.rb +10 -0
- data/lib/canon/tree_diff/operations/operation_detector.rb +5 -1
- data/lib/canon/tree_diff/tree_diff_integrator.rb +1 -1
- data/lib/canon/version.rb +1 -1
- metadata +11 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ba5fabd7a7d0057f365952f8aecc01381ef88f2f1dd28679e9e8947945b54104
|
|
4
|
+
data.tar.gz: 3e4119f7fc69a7c2534957c7654b6a567a868208179262fc921ea1266b5a1a6c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 44a74c7bb2010a2aa22855258affa6889003585edba717538bb579c63f6694757b21b74bc929b07bd0f87660f0bb3bd02f158b0a91be18017e938100f1fee491
|
|
7
|
+
data.tar.gz: be61d26774ae22a5547b2ba0ec1d578b11d37be0899add26d7f14ac63c197637568b74a9d0cad76535e5ab6a82d297af7b917f225f972361f09549964917576b
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-03-
|
|
3
|
+
# on 2026-03-31 12:44:31 UTC using RuboCop version 1.86.0.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
@@ -13,34 +13,25 @@ Gemspec/RequiredRubyVersion:
|
|
|
13
13
|
|
|
14
14
|
# Offense count: 1
|
|
15
15
|
# This cop supports safe autocorrection (--autocorrect).
|
|
16
|
-
# Configuration parameters:
|
|
17
|
-
|
|
18
|
-
Layout/BlockAlignment:
|
|
16
|
+
# Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, DefLikeMacros, AllowAdjacentOneLineDefs, NumberOfEmptyLines.
|
|
17
|
+
Layout/EmptyLineBetweenDefs:
|
|
19
18
|
Exclude:
|
|
20
|
-
- '
|
|
19
|
+
- 'lib/canon/diff_formatter/by_line/xml_formatter.rb'
|
|
21
20
|
|
|
22
21
|
# Offense count: 1
|
|
23
22
|
# This cop supports safe autocorrection (--autocorrect).
|
|
24
|
-
Layout/
|
|
25
|
-
Exclude:
|
|
26
|
-
- 'spec/canon/diff/diff_node_mapper_comments_spec.rb'
|
|
27
|
-
|
|
28
|
-
# Offense count: 2
|
|
29
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
30
|
-
# Configuration parameters: Width, EnforcedStyleAlignWith, AllowedPatterns.
|
|
31
|
-
# SupportedStylesAlignWith: start_of_line, relative_to_receiver
|
|
32
|
-
Layout/IndentationWidth:
|
|
23
|
+
Layout/EmptyLines:
|
|
33
24
|
Exclude:
|
|
34
|
-
- '
|
|
25
|
+
- 'lib/canon/diff_formatter/by_line/xml_formatter.rb'
|
|
35
26
|
|
|
36
|
-
# Offense count:
|
|
27
|
+
# Offense count: 1094
|
|
37
28
|
# This cop supports safe autocorrection (--autocorrect).
|
|
38
29
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
39
30
|
# URISchemes: http, https
|
|
40
31
|
Layout/LineLength:
|
|
41
32
|
Enabled: false
|
|
42
33
|
|
|
43
|
-
# Offense count:
|
|
34
|
+
# Offense count: 55
|
|
44
35
|
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
|
45
36
|
Lint/DuplicateBranch:
|
|
46
37
|
Enabled: false
|
|
@@ -80,33 +71,43 @@ Lint/UnusedMethodArgument:
|
|
|
80
71
|
- 'lib/canon/diff_formatter/by_line/xml_formatter.rb'
|
|
81
72
|
- 'lib/canon/diff_formatter/by_object/base_formatter.rb'
|
|
82
73
|
|
|
83
|
-
# Offense count:
|
|
74
|
+
# Offense count: 1
|
|
75
|
+
Lint/UselessConstantScoping:
|
|
76
|
+
Exclude:
|
|
77
|
+
- 'lib/canon/diff_formatter/theme.rb'
|
|
78
|
+
|
|
79
|
+
# Offense count: 297
|
|
84
80
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
85
81
|
Metrics/AbcSize:
|
|
86
82
|
Enabled: false
|
|
87
83
|
|
|
88
|
-
# Offense count:
|
|
84
|
+
# Offense count: 29
|
|
89
85
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
|
|
90
86
|
# AllowedMethods: refine
|
|
91
87
|
Metrics/BlockLength:
|
|
92
|
-
Max:
|
|
88
|
+
Max: 92
|
|
89
|
+
|
|
90
|
+
# Offense count: 1
|
|
91
|
+
# Configuration parameters: CountBlocks, CountModifierForms.
|
|
92
|
+
Metrics/BlockNesting:
|
|
93
|
+
Max: 4
|
|
93
94
|
|
|
94
|
-
# Offense count:
|
|
95
|
+
# Offense count: 261
|
|
95
96
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
96
97
|
Metrics/CyclomaticComplexity:
|
|
97
98
|
Enabled: false
|
|
98
99
|
|
|
99
|
-
# Offense count:
|
|
100
|
+
# Offense count: 485
|
|
100
101
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
101
102
|
Metrics/MethodLength:
|
|
102
|
-
Max:
|
|
103
|
+
Max: 146
|
|
103
104
|
|
|
104
|
-
# Offense count:
|
|
105
|
+
# Offense count: 56
|
|
105
106
|
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
|
106
107
|
Metrics/ParameterLists:
|
|
107
|
-
Max:
|
|
108
|
+
Max: 10
|
|
108
109
|
|
|
109
|
-
# Offense count:
|
|
110
|
+
# Offense count: 212
|
|
110
111
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
111
112
|
Metrics/PerceivedComplexity:
|
|
112
113
|
Enabled: false
|
|
@@ -130,11 +131,12 @@ Naming/VariableNumber:
|
|
|
130
131
|
- 'lib/canon/comparison/markup_comparator.rb'
|
|
131
132
|
- 'lib/canon/comparison/xml_comparator/diff_node_builder.rb'
|
|
132
133
|
|
|
133
|
-
# Offense count:
|
|
134
|
+
# Offense count: 4
|
|
134
135
|
# Configuration parameters: MinSize.
|
|
135
136
|
Performance/CollectionLiteralInLoop:
|
|
136
137
|
Exclude:
|
|
137
138
|
- 'lib/canon/comparison/html_comparator.rb'
|
|
139
|
+
- 'lib/canon/diff_formatter/theme.rb'
|
|
138
140
|
- 'lib/canon/xml/xml_base_handler.rb'
|
|
139
141
|
- 'spec/canon/diff/diff_node_mapper_comments_spec.rb'
|
|
140
142
|
|
|
@@ -144,7 +146,7 @@ Performance/CollectionLiteralInLoop:
|
|
|
144
146
|
RSpec/ContextWording:
|
|
145
147
|
Enabled: false
|
|
146
148
|
|
|
147
|
-
# Offense count:
|
|
149
|
+
# Offense count: 33
|
|
148
150
|
# Configuration parameters: IgnoredMetadata.
|
|
149
151
|
RSpec/DescribeClass:
|
|
150
152
|
Enabled: false
|
|
@@ -155,10 +157,10 @@ RSpec/DescribeMethod:
|
|
|
155
157
|
- 'spec/canon/comparison/multiple_differences_spec.rb'
|
|
156
158
|
- 'spec/canon/diff_formatter/character_map_customization_spec.rb'
|
|
157
159
|
|
|
158
|
-
# Offense count:
|
|
160
|
+
# Offense count: 736
|
|
159
161
|
# Configuration parameters: CountAsOne.
|
|
160
162
|
RSpec/ExampleLength:
|
|
161
|
-
Max:
|
|
163
|
+
Max: 44
|
|
162
164
|
|
|
163
165
|
# Offense count: 8
|
|
164
166
|
# This cop supports safe autocorrection (--autocorrect).
|
|
@@ -207,7 +209,7 @@ RSpec/MultipleDescribes:
|
|
|
207
209
|
Exclude:
|
|
208
210
|
- 'spec/canon/comparison/match_options_spec.rb'
|
|
209
211
|
|
|
210
|
-
# Offense count:
|
|
212
|
+
# Offense count: 590
|
|
211
213
|
RSpec/MultipleExpectations:
|
|
212
214
|
Max: 15
|
|
213
215
|
|
|
@@ -240,10 +242,11 @@ RSpec/NoExpectationExample:
|
|
|
240
242
|
- 'spec/canon/isodoc_blockquotes_spec.rb'
|
|
241
243
|
- 'spec/canon/match_scenarios_spec.rb'
|
|
242
244
|
|
|
243
|
-
# Offense count:
|
|
245
|
+
# Offense count: 4
|
|
244
246
|
RSpec/RepeatedExample:
|
|
245
247
|
Exclude:
|
|
246
248
|
- 'spec/canon/comparison/encoding_normalization_spec.rb'
|
|
249
|
+
- 'spec/canon/diff_display_spec.rb'
|
|
247
250
|
|
|
248
251
|
# Offense count: 7
|
|
249
252
|
# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
|
|
@@ -270,17 +273,6 @@ RSpec/VerifiedDoubles:
|
|
|
270
273
|
- 'spec/canon/diff_formatter/diff_detail_formatter_spec.rb'
|
|
271
274
|
- 'spec/canon/tree_diff/operation_converter_spec.rb'
|
|
272
275
|
|
|
273
|
-
# Offense count: 1
|
|
274
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
275
|
-
# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
|
|
276
|
-
# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
|
|
277
|
-
# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
|
|
278
|
-
# FunctionalMethods: let, let!, subject, watch
|
|
279
|
-
# AllowedMethods: lambda, proc, it
|
|
280
|
-
Style/BlockDelimiters:
|
|
281
|
-
Exclude:
|
|
282
|
-
- 'spec/canon/diff/diff_node_mapper_comments_spec.rb'
|
|
283
|
-
|
|
284
276
|
# Offense count: 1
|
|
285
277
|
# This cop supports safe autocorrection (--autocorrect).
|
|
286
278
|
# Configuration parameters: EnforcedStyle, AllowComments.
|
|
@@ -309,3 +301,11 @@ Style/IdenticalConditionalBranches:
|
|
|
309
301
|
Style/OptionalBooleanParameter:
|
|
310
302
|
Exclude:
|
|
311
303
|
- 'lib/canon/diff_formatter/debug_output.rb'
|
|
304
|
+
|
|
305
|
+
# Offense count: 1
|
|
306
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
307
|
+
# Configuration parameters: AllowedMethods.
|
|
308
|
+
# AllowedMethods: infinite?, nonzero?
|
|
309
|
+
Style/RedundantCondition:
|
|
310
|
+
Exclude:
|
|
311
|
+
- 'lib/canon/diff/diff_node_enricher.rb'
|
data/README.adoc
CHANGED
|
@@ -586,10 +586,15 @@ See link:docs/ENV_CONFIG#size-limits[ENV_CONFIG] for details on size limit confi
|
|
|
586
586
|
|
|
587
587
|
**By-line mode**: Traditional line-by-line diff with:
|
|
588
588
|
|
|
589
|
+
* **DiffCharRange pipeline**: DiffNodes are enriched with character-level positions (Phase 1: DiffNodeEnricher using SourceLocator + TextDecomposer), then assembled into display lines (Phase 2: DiffLineBuilder). The formatter only reads pre-computed positions — no tokenization or LCS during rendering.
|
|
590
|
+
* **Character-level highlighting**: Within changed lines, only the specific changed characters are highlighted, not entire lines. A text change like "Hello World" → "Hello Universe" shows "World" in red and "Universe" in green, with "Hello " in default color.
|
|
591
|
+
* **Inline and separate-line display modes**: Changed lines can be displayed inline (old→new on same line with effects) or as separate lines (traditional `-`/`+` format).
|
|
592
|
+
* **Mixed change detection**: The `*` marker identifies lines with multiple separate changed regions, distinguishing them from simple word replacements.
|
|
593
|
+
* **Legacy terminal support**: For terminals without ANSI support, forces separate-line mode with no color codes.
|
|
589
594
|
* DOM-guided semantic matching for XML
|
|
590
|
-
*
|
|
591
|
-
*
|
|
592
|
-
*
|
|
595
|
+
* Context lines around changes with configurable grouping
|
|
596
|
+
* Whitespace visualization (`░` for spaces, `⇥` for tabs)
|
|
597
|
+
* Three-tier classification with directional colors
|
|
593
598
|
|
|
594
599
|
**By-object mode**: Tree-based semantic diff with:
|
|
595
600
|
|
|
@@ -84,17 +84,21 @@ end
|
|
|
84
84
|
|
|
85
85
|
== Layer 3: Mapping
|
|
86
86
|
|
|
87
|
-
**Responsibility**:
|
|
87
|
+
**Responsibility**: Enrich semantic diffs with character-level positions and map to text lines
|
|
88
88
|
|
|
89
89
|
**Input**: DiffNode array + original text documents
|
|
90
90
|
|
|
91
91
|
**Process**:
|
|
92
|
-
1.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
1. **Enrichment** (DiffNodeEnricher): For each DiffNode, locate serialized content in source text and decompose into character ranges
|
|
93
|
+
- SourceLocator: Find serialized content position (char offset, line, column)
|
|
94
|
+
- TextDecomposer: Split into common prefix / changed / common suffix
|
|
95
|
+
- Create DiffCharRange objects with exact character positions
|
|
96
|
+
2. **Assembly** (DiffLineBuilder): Build DiffLine sequence from enriched DiffNodes
|
|
97
|
+
- Map DiffCharRanges to source lines
|
|
98
|
+
- Fill in unchanged lines between changes
|
|
99
|
+
- Detect reflow (lines that moved but content unchanged)
|
|
96
100
|
|
|
97
|
-
**Output**: Array of DiffLine objects
|
|
101
|
+
**Output**: Array of DiffLine objects, each carrying DiffCharRange arrays
|
|
98
102
|
|
|
99
103
|
[source,ruby]
|
|
100
104
|
----
|
|
@@ -102,13 +106,27 @@ end
|
|
|
102
106
|
{
|
|
103
107
|
line_number: 5,
|
|
104
108
|
content: "<p>Changed text</p>",
|
|
109
|
+
new_content: "<p>New text</p>",
|
|
105
110
|
type: :changed, # :added, :removed, :unchanged
|
|
106
111
|
diff_node: DiffNode reference,
|
|
112
|
+
char_ranges: [DiffCharRange, ...], # text1 side
|
|
113
|
+
new_char_ranges: [DiffCharRange, ...], # text2 side
|
|
107
114
|
normative: true # from diff_node
|
|
108
115
|
}
|
|
116
|
+
|
|
117
|
+
# DiffCharRange structure
|
|
118
|
+
{
|
|
119
|
+
line_number: 5,
|
|
120
|
+
start_col: 3,
|
|
121
|
+
end_col: 14,
|
|
122
|
+
side: :old,
|
|
123
|
+
status: :changed_old, # :unchanged, :changed_new, :removed, :added
|
|
124
|
+
role: :changed, # :before, :changed, :after
|
|
125
|
+
diff_node: DiffNode reference
|
|
126
|
+
}
|
|
109
127
|
----
|
|
110
128
|
|
|
111
|
-
**Key Point**: This layer bridges semantic differences to their textual representation.
|
|
129
|
+
**Key Point**: This layer bridges semantic differences to their textual representation with precise character-level positions. The two-phase approach (enrich then assemble) ensures the formatter receives pre-computed data requiring no further computation.
|
|
112
130
|
|
|
113
131
|
== Layer 4: Blocking
|
|
114
132
|
|
|
@@ -272,7 +290,15 @@ Result: Files differ, diff shown in red/green
|
|
|
272
290
|
|
|
273
291
|
=== Processing Layers
|
|
274
292
|
|
|
275
|
-
[`
|
|
293
|
+
[`DiffNodeEnricher`](../../lib/canon/diff/diff_node_enricher.rb):: Phase 1: Enriches DiffNodes with character-level positions (SourceLocator + TextDecomposer)
|
|
294
|
+
|
|
295
|
+
[`DiffLineBuilder`](../../lib/canon/diff/diff_line_builder.rb):: Phase 2: Assembles DiffLines from enriched DiffNodes (replaces DiffNodeMapper)
|
|
296
|
+
|
|
297
|
+
[`DiffCharRange`](../../lib/canon/diff/diff_char_range.rb):: Value object: a character range within a source line linked to a DiffNode
|
|
298
|
+
|
|
299
|
+
[`TextDecomposer`](../../lib/canon/diff/text_decomposer.rb):: Decomposes two strings into common prefix / changed / common suffix
|
|
300
|
+
|
|
301
|
+
[`SourceLocator`](../../lib/canon/diff/source_locator.rb):: Locates serialized content within source text, returns char offset + line/col
|
|
276
302
|
|
|
277
303
|
[`DiffBlockBuilder`](../../lib/canon/diff/diff_block_builder.rb):: Groups contiguous lines into blocks, filters by show_diffs
|
|
278
304
|
|
|
@@ -296,7 +322,8 @@ Each class does ONE thing:
|
|
|
296
322
|
|
|
297
323
|
* **Comparator**: Compares → DiffNodes
|
|
298
324
|
* **Classifier**: Classifies → normative flags
|
|
299
|
-
* **
|
|
325
|
+
* **Enricher**: Enriches → char positions on DiffNodes
|
|
326
|
+
* **LineBuilder**: Assembles → DiffLines with char ranges
|
|
300
327
|
* **BlockBuilder**: Groups lines → blocks
|
|
301
328
|
* **ContextBuilder**: Adds context → contexts
|
|
302
329
|
* **Formatter**: Renders → string
|
|
@@ -49,6 +49,13 @@ Green (added)
|
|
|
49
49
|
| Semantic differences that affect match results. +
|
|
50
50
|
Requires developer attention. +
|
|
51
51
|
Represents actual content changes.
|
|
52
|
+
|
|
53
|
+
h| Mixed
|
|
54
|
+
| `*`
|
|
55
|
+
| Yellow
|
|
56
|
+
| Line contains multiple separate changed regions. +
|
|
57
|
+
Both old and new lines are modified. +
|
|
58
|
+
Appears on both OLD and NEW lines.
|
|
52
59
|
|===
|
|
53
60
|
|
|
54
61
|
=== Classification hierarchy
|
|
@@ -141,6 +148,13 @@ Normative changes use red/green for high visual priority:
|
|
|
141
148
|
* `-` - Line removed (normative difference, red)
|
|
142
149
|
* `+` - Line added (normative difference, green)
|
|
143
150
|
|
|
151
|
+
==== Mixed Marker (Yellow)
|
|
152
|
+
|
|
153
|
+
* `*` - Line with multiple separate changed regions (yellow)
|
|
154
|
+
** Appears on BOTH old and new lines when changes are interleaved.
|
|
155
|
+
** A simple word replacement (e.g., "John" → "Jane") uses `-`/`+`, not `*`.
|
|
156
|
+
** Only used when there are 2+ separate changed regions in the same line.
|
|
157
|
+
|
|
144
158
|
==== Context Marker
|
|
145
159
|
|
|
146
160
|
* ` ` (space) - Unchanged line (context)
|
|
@@ -457,6 +471,17 @@ The whitespace difference is informative because `structural_whitespace: :ignore
|
|
|
457
471
|
|
|
458
472
|
== Color Control
|
|
459
473
|
|
|
474
|
+
=== Theme System
|
|
475
|
+
|
|
476
|
+
Canon supports multiple color themes that adapt the diff display to your terminal background and personal preference. Four built-in themes are available:
|
|
477
|
+
|
|
478
|
+
* `:light` -- Light terminal backgrounds
|
|
479
|
+
* `:dark` -- Dark terminals (default)
|
|
480
|
+
* `:retro` -- Amber CRT, low blue light, accessibility
|
|
481
|
+
* `:claude` -- Claude Code diff style with red/green backgrounds
|
|
482
|
+
|
|
483
|
+
See link:themes.adoc[Diff display themes] for full theme documentation.
|
|
484
|
+
|
|
460
485
|
=== Automatic Color Detection
|
|
461
486
|
|
|
462
487
|
Canon automatically detects whether the terminal supports color output:
|
|
@@ -522,6 +547,63 @@ canon diff file1.xml file2.xml
|
|
|
522
547
|
|
|
523
548
|
The `NO_COLOR` variable always takes precedence over other color settings.
|
|
524
549
|
|
|
550
|
+
== Diff Display Modes
|
|
551
|
+
|
|
552
|
+
Canon supports two display modes for changed lines, controlled by the `diff_mode` option:
|
|
553
|
+
|
|
554
|
+
=== Separate-Line Mode (default)
|
|
555
|
+
|
|
556
|
+
Each changed line is shown as two lines — old on top, new on bottom:
|
|
557
|
+
|
|
558
|
+
[source]
|
|
559
|
+
----
|
|
560
|
+
2| - | <p>John░Doe</p>
|
|
561
|
+
| 2+ | <p>Jane░Doe</p>
|
|
562
|
+
----
|
|
563
|
+
|
|
564
|
+
* Old line: line number on left, `-` marker, full content
|
|
565
|
+
* New line: line number on right, `+` marker, full content
|
|
566
|
+
* Changes are highlighted with colors (red for old, green for new)
|
|
567
|
+
|
|
568
|
+
=== Inline Mode
|
|
569
|
+
|
|
570
|
+
Old and new content shown on the same line, with inline highlighting:
|
|
571
|
+
|
|
572
|
+
* When color is ON: removed text appears in red, added text in green
|
|
573
|
+
* When color is OFF: removed text has strikethrough (`\e[9m`), added text has underline (`\e[4m`)
|
|
574
|
+
* Both sides of the change are visible simultaneously
|
|
575
|
+
|
|
576
|
+
[source,ruby]
|
|
577
|
+
----
|
|
578
|
+
result = Canon::Comparison.equivalent?(xml1, xml2,
|
|
579
|
+
verbose: true,
|
|
580
|
+
diff_mode: :inline
|
|
581
|
+
)
|
|
582
|
+
----
|
|
583
|
+
|
|
584
|
+
=== Legacy Terminal Mode
|
|
585
|
+
|
|
586
|
+
For terminals without ANSI support, Canon forces separate-line mode with no color codes:
|
|
587
|
+
|
|
588
|
+
[source,ruby]
|
|
589
|
+
----
|
|
590
|
+
result = Canon::Comparison.equivalent?(xml1, xml2,
|
|
591
|
+
verbose: true,
|
|
592
|
+
legacy_terminal: true
|
|
593
|
+
)
|
|
594
|
+
----
|
|
595
|
+
|
|
596
|
+
Legacy terminal mode automatically sets `diff_mode: :separate` and disables all color output.
|
|
597
|
+
|
|
598
|
+
=== Color-Off Effects (Separate-Line Mode)
|
|
599
|
+
|
|
600
|
+
When colors are disabled but ANSI is supported, Canon uses text effects to distinguish changes:
|
|
601
|
+
|
|
602
|
+
* **Strikethrough** (`\e[9m`): Removed text
|
|
603
|
+
* **Underline** (`\e[4m`): Added text
|
|
604
|
+
|
|
605
|
+
These provide visual distinction even without color support.
|
|
606
|
+
|
|
525
607
|
=== Environment Variables
|
|
526
608
|
|
|
527
609
|
In addition to `NO_COLOR`, Canon supports these environment variables:
|
|
@@ -23,6 +23,7 @@ Canon's diff formatting includes:
|
|
|
23
23
|
* **Display filtering**: Control which differences appear in output based on
|
|
24
24
|
whether they affect equivalence
|
|
25
25
|
* **Colors and symbols**: Visual indicators for different types of changes
|
|
26
|
+
* **Diff display themes**: Choose from light, dark, retro, or claude color schemes
|
|
26
27
|
* **Character visualization**: Make invisible characters visible
|
|
27
28
|
* **Context and grouping**: Control how much surrounding context to show
|
|
28
29
|
* **Algorithm-specific output**: Different output styles for different diff
|
|
@@ -52,6 +53,17 @@ Canon uses color-coded output to distinguish different types of changes:
|
|
|
52
53
|
|
|
53
54
|
See link:colors-and-symbols.adoc[Colors and symbols] for details.
|
|
54
55
|
|
|
56
|
+
=== Diff display themes
|
|
57
|
+
|
|
58
|
+
Choose from 4 predefined color themes (light, dark, retro, claude) or create custom themes:
|
|
59
|
+
|
|
60
|
+
* Light theme: Light terminal backgrounds
|
|
61
|
+
* Dark theme: Dark terminals (default)
|
|
62
|
+
* Retro theme: Amber CRT, low blue light
|
|
63
|
+
* Claude theme: Maximum contrast with colored backgrounds
|
|
64
|
+
|
|
65
|
+
See link:themes.adoc[Themes] for complete theme documentation.
|
|
66
|
+
|
|
55
67
|
=== Character visualization
|
|
56
68
|
|
|
57
69
|
Make invisible characters visible in diff output:
|