Moved Maruku (and its dependencies) and XHTMLDiff (and its dependencies) to vendor/plugins/ .
Synced with Instiki SVN.
This commit is contained in:
parent
64037c67ac
commit
63e217bcfd
59 changed files with 40 additions and 1 deletions
179
vendor/plugins/xhtmldiff/lib/xhtmldiff.rb
vendored
Normal file
179
vendor/plugins/xhtmldiff/lib/xhtmldiff.rb
vendored
Normal file
|
@ -0,0 +1,179 @@
|
|||
#!/usr/bin/env ruby
|
||||
# Author: Aredridel <aredridel@nbtsc.org>
|
||||
# Website: http://theinternetco.net/projects/ruby/xhtmldiff.html
|
||||
# Licence: same as Ruby
|
||||
# Version: 1.2.2
|
||||
#
|
||||
# Tweaks by Jacques Distler <distler@golem.ph.utexas.edu>
|
||||
# -- add classnames to <del> and <ins> elements added by XHTMLDiff,
|
||||
# for better CSS styling
|
||||
|
||||
require 'diff/lcs'
|
||||
require 'rexml/document'
|
||||
require 'delegate'
|
||||
|
||||
def Math.max(a, b)
|
||||
a > b ? a : b
|
||||
end
|
||||
|
||||
module REXML
|
||||
|
||||
class Text
|
||||
def deep_clone
|
||||
clone
|
||||
end
|
||||
end
|
||||
|
||||
class HashableElementDelegator < DelegateClass(Element)
|
||||
def initialize(sub)
|
||||
super sub
|
||||
end
|
||||
def == other
|
||||
res = other.to_s.strip == self.to_s.strip
|
||||
res
|
||||
end
|
||||
|
||||
def eql? other
|
||||
self == other
|
||||
end
|
||||
|
||||
def[](k)
|
||||
r = super
|
||||
if r.kind_of? __getobj__.class
|
||||
self.class.new(r)
|
||||
else
|
||||
r
|
||||
end
|
||||
end
|
||||
|
||||
def hash
|
||||
r = __getobj__.to_s.hash
|
||||
r
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class XHTMLDiff
|
||||
include REXML
|
||||
attr_accessor :output
|
||||
|
||||
class << self
|
||||
BLOCK_CONTAINERS = ['div', 'ul', 'li']
|
||||
def diff(a, b)
|
||||
if a == b
|
||||
return a.deep_clone
|
||||
end
|
||||
if REXML::HashableElementDelegator === a and REXML::HashableElementDelegator === b
|
||||
o = REXML::Element.new(a.name)
|
||||
o.add_attributes a.attributes
|
||||
hd = self.new(o)
|
||||
Diff::LCS.traverse_balanced(a, b, hd)
|
||||
o
|
||||
elsif REXML::Text === a and REXML::Text === b
|
||||
o = REXML::Element.new('span')
|
||||
aa = a.value.split(/\s/)
|
||||
ba = b.value.split(/\s/)
|
||||
hd = XHTMLTextDiff.new(o)
|
||||
Diff::LCS.traverse_balanced(aa, ba, hd)
|
||||
o
|
||||
else
|
||||
raise ArgumentError.new("both arguments must be equal or both be elements. a is #{a.class.name} and b is #{b.class.name}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def diff(a, b)
|
||||
self.class.diff(a,b)
|
||||
end
|
||||
|
||||
def initialize(output)
|
||||
@output = output
|
||||
end
|
||||
|
||||
# This will be called with both elements are the same
|
||||
def match(event)
|
||||
@output << event.old_element.deep_clone if event.old_element
|
||||
end
|
||||
|
||||
# This will be called when there is an element in A that isn't in B
|
||||
def discard_a(event)
|
||||
@output << wrap(event.old_element, 'del', 'diffdel')
|
||||
end
|
||||
|
||||
def change(event)
|
||||
begin
|
||||
sd = diff(event.old_element, event.new_element)
|
||||
rescue ArgumentError
|
||||
sd = nil
|
||||
end
|
||||
if sd and (ratio = (Float(rs = sd.to_s.gsub(%r{<(ins|del)>.*</\1>}, '').size) / bs = Math.max(event.old_element.to_s.size, event.new_element.to_s.size))) > 0.5
|
||||
@output << sd
|
||||
else
|
||||
@output << wrap(event.old_element, 'del', 'diffmod')
|
||||
@output << wrap(event.new_element, 'ins', 'diffmod')
|
||||
end
|
||||
end
|
||||
|
||||
# This will be called when there is an element in B that isn't in A
|
||||
def discard_b(event)
|
||||
@output << wrap(event.new_element, 'ins', 'diffins')
|
||||
end
|
||||
|
||||
def choose_event(event, element, tag)
|
||||
end
|
||||
|
||||
def wrap(element, tag = nil, class_name = nil)
|
||||
if tag
|
||||
el = Element.new tag
|
||||
el << element.deep_clone
|
||||
else
|
||||
el = element.deep_clone
|
||||
end
|
||||
if class_name
|
||||
el.add_attribute('class', class_name)
|
||||
end
|
||||
el
|
||||
end
|
||||
|
||||
class XHTMLTextDiff < XHTMLDiff
|
||||
def change(event)
|
||||
@output << wrap(event.old_element, 'del', 'diffmod')
|
||||
@output << wrap(event.new_element, 'ins', 'diffmod')
|
||||
end
|
||||
|
||||
# This will be called with both elements are the same
|
||||
def match(event)
|
||||
@output << wrap(event.old_element, nil, nil) if event.old_element
|
||||
end
|
||||
|
||||
# This will be called when there is an element in A that isn't in B
|
||||
def discard_a(event)
|
||||
@output << wrap(event.old_element, 'del', 'diffdel')
|
||||
end
|
||||
|
||||
# This will be called when there is an element in B that isn't in A
|
||||
def discard_b(event)
|
||||
@output << wrap(event.new_element, 'ins', 'diffins')
|
||||
end
|
||||
|
||||
def wrap(element, tag = nil, class_name = nil)
|
||||
element = REXML::Text.new(" " << element) if String === element
|
||||
return element unless tag
|
||||
wrapper_element = REXML::Element.new(tag)
|
||||
wrapper_element.add_text element
|
||||
if class_name
|
||||
wrapper_element.add_attribute('class', class_name)
|
||||
end
|
||||
wrapper_element
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if $0 == __FILE__
|
||||
|
||||
$stderr.puts "No tests available yet"
|
||||
exit(1)
|
||||
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue