canon 0.3.35 → 0.3.36
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/diff_node_enricher.rb +54 -10
- data/lib/canon/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 53129bc040b25503b792d4c1afa96498715cd05363d462afb87aa004dbe37004
|
|
4
|
+
data.tar.gz: de9d2c032c3b20e73f6737bcd0d092130dd9622851cca6c9353d6c10ea7da0f8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2471eebf546ec921fa8d307a02363b9d1112ef5111fd0f0edd57d1894a3e04e7039965fede0a4b4f8e02fa05540dad05324e6dc1e052676512407a7965c0ea83
|
|
7
|
+
data.tar.gz: a58130908f35634360d689eba9e27d48845f955c9cd44eae6eab771e0bfb0b84af35cd97db05137eb1563baa3449a1591237fc3eac01a74ef839df5c3811e386
|
|
@@ -613,13 +613,17 @@ module Canon
|
|
|
613
613
|
# occurrence. Shorter strings match too many places in the document.
|
|
614
614
|
min_locate_length = 3
|
|
615
615
|
|
|
616
|
-
# Element added (only in text2)
|
|
616
|
+
# Element added (only in text2). Index-aware first — see the
|
|
617
|
+
# removed branch note (identical-sibling anchor bug).
|
|
617
618
|
if before.nil?
|
|
618
|
-
loc = if
|
|
619
|
-
|
|
620
|
-
else
|
|
621
|
-
SourceLocator.locate(after, @text2, @line_map2)
|
|
619
|
+
loc = if path
|
|
620
|
+
locate_element_at_index(after, @text2, @line_map2, path)
|
|
622
621
|
end
|
|
622
|
+
loc ||= if after.length < min_locate_length && path
|
|
623
|
+
locate_via_parent_element(path, @text2, @line_map2)
|
|
624
|
+
else
|
|
625
|
+
SourceLocator.locate(after, @text2, @line_map2)
|
|
626
|
+
end
|
|
623
627
|
|
|
624
628
|
if loc
|
|
625
629
|
end_line = find_end_line(loc[:line_number], @line_map2, after)
|
|
@@ -643,13 +647,20 @@ module Canon
|
|
|
643
647
|
return
|
|
644
648
|
end
|
|
645
649
|
|
|
646
|
-
# Element removed (only in text1)
|
|
650
|
+
# Element removed (only in text1). The path-aware locate runs
|
|
651
|
+
# FIRST: an identical sibling earlier in the document would win
|
|
652
|
+
# a plain first-occurrence search, anchoring the deletion to
|
|
653
|
+
# the wrong element and letting the line builder absorb it
|
|
654
|
+
# into a formatting gap (issue #85/#86).
|
|
647
655
|
if after.nil?
|
|
648
|
-
loc = if
|
|
649
|
-
|
|
650
|
-
else
|
|
651
|
-
SourceLocator.locate(before, @text1, @line_map1)
|
|
656
|
+
loc = if path
|
|
657
|
+
locate_element_at_index(before, @text1, @line_map1, path)
|
|
652
658
|
end
|
|
659
|
+
loc ||= if before.length < min_locate_length && path
|
|
660
|
+
locate_via_parent_element(path, @text1, @line_map1)
|
|
661
|
+
else
|
|
662
|
+
SourceLocator.locate(before, @text1, @line_map1)
|
|
663
|
+
end
|
|
653
664
|
|
|
654
665
|
if loc
|
|
655
666
|
end_line = find_end_line(loc[:line_number], @line_map1, before)
|
|
@@ -982,6 +993,39 @@ module Canon
|
|
|
982
993
|
SourceLocator.locate(value, text, line_map)
|
|
983
994
|
end
|
|
984
995
|
|
|
996
|
+
# Index-aware location for element_structure changes: the path's
|
|
997
|
+
# last bracketed segment names the element itself (unlike
|
|
998
|
+
# text_content paths, whose last segment is the text node).
|
|
999
|
+
# Picks the occurrence whose element index matches the path, so
|
|
1000
|
+
# identical siblings anchor at the right one; falls back to the
|
|
1001
|
+
# first occurrence when no indexed match exists.
|
|
1002
|
+
def locate_element_at_index(value, text, line_map, path)
|
|
1003
|
+
return nil if value.nil? || value.length < 3
|
|
1004
|
+
|
|
1005
|
+
segments = path.split("/").reject(&:empty?)
|
|
1006
|
+
element_segment = segments.reverse.find { |seg| seg.include?("[") }
|
|
1007
|
+
return nil unless element_segment
|
|
1008
|
+
|
|
1009
|
+
element_match = element_segment.match(/([a-zA-Z0-9_:-]+)\[(\d+)\]/)
|
|
1010
|
+
return nil unless element_match
|
|
1011
|
+
|
|
1012
|
+
element_name = element_match[1]
|
|
1013
|
+
target_index = element_match[2].to_i
|
|
1014
|
+
|
|
1015
|
+
# Occurrence offsets point AT the element's own opening tag,
|
|
1016
|
+
# so the prefix scan counts exactly the preceding siblings —
|
|
1017
|
+
# no "inside the element" correction (count_elements_before_
|
|
1018
|
+
# position subtracts one for text-node offsets).
|
|
1019
|
+
opener = /<#{element_name}[>\s]/
|
|
1020
|
+
occurrences = SourceLocator.locate_all(value, text, line_map)
|
|
1021
|
+
occurrences.each do |occ|
|
|
1022
|
+
count = text[0...occ[:char_offset]].scan(opener).length
|
|
1023
|
+
return occ if count == target_index
|
|
1024
|
+
end
|
|
1025
|
+
|
|
1026
|
+
SourceLocator.locate(value, text, line_map)
|
|
1027
|
+
end
|
|
1028
|
+
|
|
985
1029
|
# Fallback location strategy for text_content when locate_at_element_index
|
|
986
1030
|
# fails (e.g., the text value is too short to locate reliably).
|
|
987
1031
|
# Walks the full element hierarchy from the path to locate the correct
|
data/lib/canon/version.rb
CHANGED