Move diff logic out of helper
This commit is contained in:
@@ -12,59 +12,13 @@ module WikiPageVersionsHelper
|
|||||||
status.join(" ")
|
status.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
def wiki_page_diff(thispage, otherpage)
|
def wiki_other_names_diff(thispage, otherpage)
|
||||||
|
pattern = Regexp.new('\S+|\s+')
|
||||||
|
DiffBuilder.new("#{thispage.other_names}\n\n", "#{otherpage.other_names}\n\n", pattern).build
|
||||||
|
end
|
||||||
|
|
||||||
|
def wiki_body_diff(thispage, otherpage)
|
||||||
pattern = Regexp.new('(?:<.+?>)|(?:\w+)|(?:[ \t]+)|(?:\r?\n)|(?:.+?)')
|
pattern = Regexp.new('(?:<.+?>)|(?:\w+)|(?:[ \t]+)|(?:\r?\n)|(?:.+?)')
|
||||||
other_names_pattern = Regexp.new('\S+|\s+')
|
DiffBuilder.new(thispage.body, otherpage.body, pattern).build
|
||||||
|
|
||||||
thisarr = thispage.body.scan(pattern)
|
|
||||||
otharr = otherpage.body.scan(pattern)
|
|
||||||
|
|
||||||
if thispage.other_names.present? || otherpage.other_names.present?
|
|
||||||
thisarr = "#{thispage.other_names}\n\n".scan(other_names_pattern) + thisarr
|
|
||||||
otharr = "#{otherpage.other_names}\n\n".scan(other_names_pattern) + otharr
|
|
||||||
end
|
|
||||||
|
|
||||||
cbo = Diff::LCS::ContextDiffCallbacks.new
|
|
||||||
diffs = thisarr.diff(otharr, cbo)
|
|
||||||
|
|
||||||
escape_html = ->(str) {str.gsub(/&/, '&').gsub(/</, '<').gsub(/>/, '>')}
|
|
||||||
|
|
||||||
output = thisarr
|
|
||||||
output.each { |q| q.replace(escape_html[q]) }
|
|
||||||
|
|
||||||
diffs.reverse_each do |hunk|
|
|
||||||
newchange = hunk.max {|a, b| a.old_position <=> b.old_position}
|
|
||||||
newstart = newchange.old_position
|
|
||||||
oldstart = hunk.min {|a, b| a.old_position <=> b.old_position}.old_position
|
|
||||||
|
|
||||||
if newchange.action == '+'
|
|
||||||
output.insert(newstart, '</ins>')
|
|
||||||
end
|
|
||||||
|
|
||||||
hunk.reverse_each do |chg|
|
|
||||||
case chg.action
|
|
||||||
when '-'
|
|
||||||
oldstart = chg.old_position
|
|
||||||
output[chg.old_position] = '<br>' if chg.old_element.match(/^\r?\n$/)
|
|
||||||
when '+'
|
|
||||||
if chg.new_element.match(/^\r?\n$/)
|
|
||||||
output.insert(chg.old_position, '<br>')
|
|
||||||
else
|
|
||||||
output.insert(chg.old_position, (escape_html[chg.new_element]).to_s)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if newchange.action == '+'
|
|
||||||
output.insert(newstart, '<ins>')
|
|
||||||
end
|
|
||||||
|
|
||||||
if hunk[0].action == '-'
|
|
||||||
output.insert((newstart == oldstart || newchange.action != '+') ? newstart + 1 : newstart, '</del>')
|
|
||||||
output.insert(oldstart, '<del>')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
output.join.gsub(/\r?\n/, '<br>').html_safe
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
57
app/logical/diff_builder.rb
Normal file
57
app/logical/diff_builder.rb
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
class DiffBuilder
|
||||||
|
attr_reader :this_text, :that_text, :pattern
|
||||||
|
|
||||||
|
def initialize(this_text, that_text, pattern)
|
||||||
|
@this_text = this_text
|
||||||
|
@that_text = that_text
|
||||||
|
@pattern = pattern
|
||||||
|
end
|
||||||
|
|
||||||
|
def build
|
||||||
|
thisarr = this_text.scan(pattern)
|
||||||
|
otharr = that_text.scan(pattern)
|
||||||
|
|
||||||
|
cbo = Diff::LCS::ContextDiffCallbacks.new
|
||||||
|
diffs = thisarr.diff(otharr, cbo)
|
||||||
|
|
||||||
|
escape_html = ->(str) {str.gsub(/&/, '&').gsub(/</, '<').gsub(/>/, '>')}
|
||||||
|
|
||||||
|
output = thisarr
|
||||||
|
output.each { |q| q.replace(escape_html[q]) }
|
||||||
|
|
||||||
|
diffs.reverse_each do |hunk|
|
||||||
|
newchange = hunk.max {|a, b| a.old_position <=> b.old_position}
|
||||||
|
newstart = newchange.old_position
|
||||||
|
oldstart = hunk.min {|a, b| a.old_position <=> b.old_position}.old_position
|
||||||
|
|
||||||
|
if newchange.action == '+'
|
||||||
|
output.insert(newstart, '</ins>')
|
||||||
|
end
|
||||||
|
|
||||||
|
hunk.reverse_each do |chg|
|
||||||
|
case chg.action
|
||||||
|
when '-'
|
||||||
|
oldstart = chg.old_position
|
||||||
|
output[chg.old_position] = '<br>' if chg.old_element.match(/^\r?\n$/)
|
||||||
|
when '+'
|
||||||
|
if chg.new_element.match(/^\r?\n$/)
|
||||||
|
output.insert(chg.old_position, '<br>')
|
||||||
|
else
|
||||||
|
output.insert(chg.old_position, (escape_html[chg.new_element]).to_s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if newchange.action == '+'
|
||||||
|
output.insert(newstart, '<ins>')
|
||||||
|
end
|
||||||
|
|
||||||
|
if hunk[0].action == '-'
|
||||||
|
output.insert((newstart == oldstart || newchange.action != '+') ? newstart + 1 : newstart, '</del>')
|
||||||
|
output.insert(oldstart, '<del>')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
output.join.gsub(/\r?\n/, '<br>').html_safe
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -7,7 +7,10 @@
|
|||||||
<p>Showing differences between <%= compact_time @thispage.updated_at %> (<%= link_to_user @thispage.updater %>) and <%= compact_time @otherpage.updated_at %> (<%= link_to_user @otherpage.updater %>)</p>
|
<p>Showing differences between <%= compact_time @thispage.updated_at %> (<%= link_to_user @thispage.updater %>) and <%= compact_time @otherpage.updated_at %> (<%= link_to_user @otherpage.updater %>)</p>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<%= wiki_page_diff(@thispage, @otherpage) %>
|
<%= wiki_other_names_diff(@thispage, @otherpage) %>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<%= wiki_body_diff(@thispage, @otherpage) %>
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<p>The artist requested removal of this page.</p>
|
<p>The artist requested removal of this page.</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user