Class: Goat::DOMDiff
Class Method Summary collapse
Instance Method Summary collapse
- #added(new, par, pos = nil) ⇒ Object
- #array_desc(old, new, par) ⇒ Object
- #attrs(node) ⇒ Object
- #body(node) ⇒ Object
- #compare_attrs(a, b) ⇒ Object
- #desc(old, new, par) ⇒ Object
- #diff ⇒ Object
- #dom_node?(node) ⇒ Boolean
- #domid(node) ⇒ Object
-
#initialize(old, new, id) ⇒ DOMDiff
constructor
A new instance of DOMDiff.
- #is_replacement?(d1, d2) ⇒ Boolean
- #localized_change(dold, dnew, par, changes) ⇒ Object
- #minimized_changes(ch) ⇒ Object
- #nested_application(ch) ⇒ Object
- #node_desc(old, new, par) ⇒ Object
- #old_and_new(d1, d2) ⇒ Object
- #removed(old, par, pos = nil) ⇒ Object
- #tag(node) ⇒ Object
Constructor Details
#initialize(old, new, id) ⇒ DOMDiff
Returns a new instance of DOMDiff.
870 871 872 873 874 875 |
# File 'lib/goat.rb', line 870 def initialize(old, new, id) @old = old @new = new @id = id @diffs = [] end |
Class Method Details
.diff(old, new, id) ⇒ Object
866 867 868 |
# File 'lib/goat.rb', line 866 def self.diff(old, new, id) self.new(old, new, id).diff end |
Instance Method Details
#added(new, par, pos = nil) ⇒ Object
915 |
# File 'lib/goat.rb', line 915 def added(new, par, pos=nil); [:add, new, par, pos]; end |
#array_desc(old, new, par) ⇒ Object
947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 |
# File 'lib/goat.rb', line 947 def array_desc(old, new, par) #$stderr.puts "array_desc #{old.inspect} #{new.inspect} #{par.inspect}" chgs = Diff::LCS.diff(old, new).map do |diff| #$stderr.puts "diff: #{diff.inspect}" if is_replacement?(diff[0], diff[1]) dold, dnew = old_and_new(diff[0], diff[1]) old = dold.element new = dnew.element if dom_node?(old) && dom_node?(new) && tag(old) == tag(new) && compare_attrs(old, new) localized_change(dold, dnew, par, desc(body(old), body(new), domid(old))) elsif old.is_a?(Array) && new.is_a?(Array) #&& old.all?{|x| !dom_node?(x)} && new.all?{|x| !dom_node?(x)} array_desc(old, new, par) else [added(new, par, diff[1].position), removed(old, par, diff[0].position)] end else if diff.size == 1 diff = diff[0] if diff.action == '+' [added(diff.element, par, diff.position)] elsif diff.action == '-' [removed(diff.element, par, diff.position)] else raise "Don't understand diff in a bad way" end else $stderr.puts "Don't understand diff" #$stderr.puts "Diff failed" raise JustRerenderError end end end chgs.flatten(1) end |
#attrs(node) ⇒ Object
922 |
# File 'lib/goat.rb', line 922 def attrs(node); node[1] if node[1].is_a?(Hash); end |
#body(node) ⇒ Object
923 |
# File 'lib/goat.rb', line 923 def body(node); node[1].is_a?(Hash) ? node[2..-1] : node[1..-1]; end |
#compare_attrs(a, b) ⇒ Object
984 985 986 987 988 989 990 991 992 993 |
# File 'lib/goat.rb', line 984 def compare_attrs(a, b) if a.is_a?(Hash) && b.is_a?(Hash) a_, b_ = a.clone, b.clone a.select{|k,v| a_.delete(k) if v =~ /^dom_/} b.select{|k,v| b_.delete(k) if v =~ /^dom_/} a_ == b_ else false end end |
#desc(old, new, par) ⇒ Object
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 |
# File 'lib/goat.rb', line 1013 def desc(old, new, par) #$stderr.puts "desc #{old.inspect} #{new.inspect} #{par.inspect}" #$stderr.puts "desc #{self.class.name} #{par.inspect}" if old.class != new.class [added(new, par), removed(old, par)] elsif old.is_a?(Array) dom_node?(old) ? node_desc(old, new, domid(old)) : array_desc(old, new, par) elsif old.is_a?(String) if old != new [added(new, par), removed(old, par)] end else raise TypeError.new("Unknown object in the DOM: #{old.class} #{new.class}") end end |
#diff ⇒ Object
877 878 879 |
# File 'lib/goat.rb', line 877 def diff nested_application(minimized_changes(desc(@old, @new, @id))) end |
#dom_node?(node) ⇒ Boolean
918 919 920 |
# File 'lib/goat.rb', line 918 def dom_node?(node) node.is_a?(Array) && node.first.is_a?(Symbol) end |
#domid(node) ⇒ Object
924 |
# File 'lib/goat.rb', line 924 def domid(node); attrs(node) ? attrs(node)[:id] : nil; end |
#is_replacement?(d1, d2) ⇒ Boolean
937 938 939 940 941 |
# File 'lib/goat.rb', line 937 def is_replacement?(d1, d2) d1 && d2 && ( (d1.action == '+' && d2.action == '-') || (d1.action == '-' && d2.action == '+')) end |
#localized_change(dold, dnew, par, changes) ⇒ Object
926 927 928 929 930 931 932 933 934 935 |
# File 'lib/goat.rb', line 926 def localized_change(dold, dnew, par, changes) old = dold.element new = dnew.element #$stderr.puts "changes: #{changes.inspect} / #{old.inspect} / #{par.inspect}" if changes.all?{|ch| ch[2].nil?} && par [added(new, par, dold.position), removed(old, par, dnew.position)] else changes end end |
#minimized_changes(ch) ⇒ Object
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 |
# File 'lib/goat.rb', line 897 def minimized_changes(ch) new = [] merged = Set.new ch.each do |c| if c[0] == :rem if n = ch.detect{|x| x[0] == :add && x[2] == c[2] && x[3] == c[3]} new << [:rep, *n[1..3]] merged << n else new << c end else new << c end end new.reject{|c| merged.include?(c)} end |
#nested_application(ch) ⇒ Object
881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 |
# File 'lib/goat.rb', line 881 def nested_application(ch) applied = Set.new ch.sort_by{|x| x[3]}.each do |c| if (c[0] == :rem || c[0] == :add) && !applied.include?(c) if n = ch.detect{|x| x != c && x[2] == c[2] && x[3] >= c[3]} n[3] += (c[0] == :rem) ? -1 : 1 end end applied << c end ch end |
#node_desc(old, new, par) ⇒ Object
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 |
# File 'lib/goat.rb', line 995 def node_desc(old, new, par) #$stderr.puts "node_desc #{old.inspect} #{new.inspect} #{par.inspect}" if tag(old) != tag(new) || !compare_attrs(old, new) [removed(old, par), added(new, par)] else # only body changed (maybe) bold = body(old) bnew = body(new) if bold && bnew desc(bold, bnew, domid(old)) elsif bold && !bnew [removed(bold, domid(old))] else [added(bnew, domid(old))] end end end |
#old_and_new(d1, d2) ⇒ Object
943 944 945 |
# File 'lib/goat.rb', line 943 def old_and_new(d1, d2) d1.action == '+' ? [d2, d1] : [d1, d2] end |
#removed(old, par, pos = nil) ⇒ Object
916 |
# File 'lib/goat.rb', line 916 def removed(old, par, pos=nil); [:rem, old, par, pos]; end |
#tag(node) ⇒ Object
921 |
# File 'lib/goat.rb', line 921 def tag(node); node[0]; end |