canon 0.3.61 → 0.3.62
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/lib/canon/diff/formatting_detector.rb +49 -37
- data/lib/canon/diff_formatter/by_line/base_formatter.rb +18 -3
- data/lib/canon/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c5ab88d04204cba8fb555ca3ebae0091a6a9d22fbb5e06e58974195e6bace30d
|
|
4
|
+
data.tar.gz: 3f952b1cb790351630ba1cb659e69492e67ff34ede453c98624877df4bb9b5f5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6128ca89822cbf059a28e3f753d42a56e3ab40fd5ed98bb4cca9a467ae1124387b443747d0d480eb0da1bfd8358bc17e870dc4709e12c857b427bd35c56479c4
|
|
7
|
+
data.tar.gz: 1f6100fa01d92715eac814bb0538172b7ebc993cddbeaea34855631a76880cbf5b791403ba581c9b446a7903784aa1217542bc7c45ea18174b3e27eec2d7fb1d
|
|
@@ -107,8 +107,14 @@ module Canon
|
|
|
107
107
|
# case-insensitive (e.g., "UTF-8" equals "utf-8").
|
|
108
108
|
# The standalone declaration in XML 1.1 is also case-insensitive.
|
|
109
109
|
CASE_INSENSITIVE_ATTRS = %w[encoding standalone].freeze
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
# Byte-level scan sets — the tokenizer reads via getbyte, whose
|
|
111
|
+
# Integer results allocate nothing (String#[] mints a 1-char
|
|
112
|
+
# string per character scanned).
|
|
113
|
+
NAME_END_BYTES = [32, 47, 62].freeze # space, /, >
|
|
114
|
+
SKIP_BYTES = [32, 61].freeze # space, =
|
|
115
|
+
QUOTE_BYTES = [34, 39].freeze # ", '
|
|
116
|
+
SPACE_BYTE = 32
|
|
117
|
+
EMPTY_CONTENT_RE = /\A[ \t\r\n\f\v]*\z/
|
|
112
118
|
|
|
113
119
|
# Normalize attribute order within XML tags so that
|
|
114
120
|
# <elem b="2" a="1"> compares equal to <elem a="1" b="2">.
|
|
@@ -121,19 +127,23 @@ module Canon
|
|
|
121
127
|
i = 0
|
|
122
128
|
|
|
123
129
|
while i < text.length
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
130
|
+
lt = text.index("<", i)
|
|
131
|
+
if lt.nil?
|
|
132
|
+
result << text[i..]
|
|
133
|
+
break
|
|
134
|
+
end
|
|
135
|
+
result << text[i...lt] if lt > i
|
|
136
|
+
|
|
137
|
+
# Handle processing instruction <?...?>, comment <!--...-->,
|
|
138
|
+
# and regular tags
|
|
139
|
+
new_i, tag_output = process_tag(text, lt)
|
|
140
|
+
if new_i
|
|
141
|
+
result << tag_output
|
|
142
|
+
i = new_i
|
|
143
|
+
else
|
|
144
|
+
result << "<"
|
|
145
|
+
i = lt + 1
|
|
133
146
|
end
|
|
134
|
-
|
|
135
|
-
result << text[i]
|
|
136
|
-
i += 1
|
|
137
147
|
end
|
|
138
148
|
|
|
139
149
|
result
|
|
@@ -178,57 +188,59 @@ module Canon
|
|
|
178
188
|
# @param tag_content [String] Content between < and >
|
|
179
189
|
# @return [Hash, nil] { name: String, attrs: Array<{name:, value:}> }
|
|
180
190
|
def self.tokenize_tag_content(tag_content)
|
|
181
|
-
return nil if tag_content.
|
|
191
|
+
return nil if tag_content.match?(EMPTY_CONTENT_RE)
|
|
182
192
|
|
|
183
193
|
i = 0
|
|
194
|
+
length = tag_content.length
|
|
184
195
|
# Find tag name (first non-whitespace word)
|
|
185
|
-
i += 1 while i <
|
|
186
|
-
return nil if i >=
|
|
196
|
+
i += 1 while i < length && tag_content.getbyte(i) == SPACE_BYTE
|
|
197
|
+
return nil if i >= length
|
|
187
198
|
|
|
188
199
|
name_start = i
|
|
189
|
-
i += 1 while i <
|
|
190
|
-
tag_content
|
|
200
|
+
i += 1 while i < length &&
|
|
201
|
+
!NAME_END_BYTES.include?(tag_content.getbyte(i))
|
|
191
202
|
tag_name = tag_content[name_start...i]
|
|
192
203
|
|
|
193
204
|
# Skip whitespace
|
|
194
|
-
i += 1 while i <
|
|
205
|
+
i += 1 while i < length && tag_content.getbyte(i) == SPACE_BYTE
|
|
195
206
|
|
|
196
207
|
# Parse attributes
|
|
197
208
|
attrs = []
|
|
198
|
-
while i <
|
|
209
|
+
while i < length
|
|
199
210
|
# Skip whitespace
|
|
200
|
-
i += 1 while i <
|
|
201
|
-
break if i >=
|
|
211
|
+
i += 1 while i < length && tag_content.getbyte(i) == SPACE_BYTE
|
|
212
|
+
break if i >= length
|
|
202
213
|
|
|
203
214
|
# Read attribute name
|
|
204
215
|
attr_start = i
|
|
205
|
-
i += 1 while i <
|
|
206
|
-
tag_content
|
|
207
|
-
tag_content
|
|
208
|
-
break if i >=
|
|
216
|
+
i += 1 while i < length &&
|
|
217
|
+
!NAME_END_BYTES.include?(tag_content.getbyte(i)) &&
|
|
218
|
+
tag_content.getbyte(i) != 61
|
|
219
|
+
break if i >= length || i == attr_start
|
|
209
220
|
|
|
210
221
|
attr_name = tag_content[attr_start...i]
|
|
211
222
|
|
|
212
223
|
# Skip whitespace and =
|
|
213
|
-
i += 1 while i <
|
|
214
|
-
|
|
215
|
-
break if i >=
|
|
224
|
+
i += 1 while i < length &&
|
|
225
|
+
SKIP_BYTES.include?(tag_content.getbyte(i))
|
|
226
|
+
break if i >= length
|
|
216
227
|
|
|
217
228
|
# Read quoted value
|
|
218
|
-
quote = tag_content
|
|
219
|
-
break unless
|
|
229
|
+
quote = tag_content.getbyte(i)
|
|
230
|
+
break unless QUOTE_BYTES.include?(quote)
|
|
220
231
|
|
|
221
232
|
i += 1
|
|
222
233
|
value_start = i
|
|
223
|
-
while i <
|
|
234
|
+
while i < length && tag_content.getbyte(i) != quote
|
|
224
235
|
i += 1
|
|
225
236
|
end
|
|
226
|
-
break if i >=
|
|
237
|
+
break if i >= length
|
|
227
238
|
|
|
228
239
|
attr_value = tag_content[value_start...i]
|
|
229
240
|
i += 1 # skip closing quote
|
|
230
241
|
|
|
231
|
-
|
|
242
|
+
quote_char = quote.chr
|
|
243
|
+
attrs << { name: attr_name, value: "#{quote_char}#{attr_value}#{quote_char}" }
|
|
232
244
|
end
|
|
233
245
|
|
|
234
246
|
{ name: tag_name, attrs: attrs }
|
|
@@ -241,9 +253,9 @@ module Canon
|
|
|
241
253
|
# @param i [Integer] Position of '<'
|
|
242
254
|
# @return [Array(Integer, String), nil] [new_position, tag_string] or nil
|
|
243
255
|
def self.process_tag(text, pos)
|
|
244
|
-
if text
|
|
256
|
+
if text.getbyte(pos + 1) == 63 # ?
|
|
245
257
|
process_processing_instruction(text, pos)
|
|
246
|
-
elsif text
|
|
258
|
+
elsif text.getbyte(pos + 1) == 33 && text[(pos + 2)...(pos + 4)] == "--" # !
|
|
247
259
|
process_comment(text, pos)
|
|
248
260
|
else
|
|
249
261
|
process_regular_tag(text, pos)
|
|
@@ -642,6 +642,23 @@ module Canon
|
|
|
642
642
|
#
|
|
643
643
|
# @param token [String] The token to apply visualization to
|
|
644
644
|
# @param color [Symbol, nil] Optional color to apply
|
|
645
|
+
# Whole-string gsub through the map — the previous
|
|
646
|
+
# chars.map.fetch.join minted two arrays and one 1-char string
|
|
647
|
+
# per character of every displayed line.
|
|
648
|
+
def visualize(token)
|
|
649
|
+
return token if @visualization_map.empty?
|
|
650
|
+
|
|
651
|
+
token.gsub(visualization_union, @visualization_map)
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
# Longer keys first so "\r\n" wins over "\r"/"\n" at the
|
|
655
|
+
# same position.
|
|
656
|
+
def visualization_union
|
|
657
|
+
@visualization_union ||= Regexp.union(
|
|
658
|
+
@visualization_map.keys.sort_by(&:length).reverse,
|
|
659
|
+
)
|
|
660
|
+
end
|
|
661
|
+
|
|
645
662
|
# @return [String] Visualized and optionally colored token
|
|
646
663
|
def apply_visualization(token, color = nil)
|
|
647
664
|
return "" if token.nil?
|
|
@@ -649,9 +666,7 @@ module Canon
|
|
|
649
666
|
visual = if @character_visualization == :content_only
|
|
650
667
|
visualize_content_only(token.to_s)
|
|
651
668
|
else
|
|
652
|
-
token.to_s
|
|
653
|
-
@visualization_map.fetch(char, char)
|
|
654
|
-
end.join
|
|
669
|
+
visualize(token.to_s)
|
|
655
670
|
end
|
|
656
671
|
|
|
657
672
|
if color && @use_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.3.
|
|
4
|
+
version: 0.3.62
|
|
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-09-
|
|
11
|
+
date: 2026-09-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: diff-lcs
|