module WikiPageVersionsHelper def wiki_page_diff(thispage, otherpage) pattern = Regexp.new('(?:<.+?>)|(?:\w+)|(?:[ \t]+)|(?:\r?\n)|(?:.+?)') other_names_pattern = Regexp.new('\S+|\s+') 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 = lambda {|str| str.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, '') end hunk.reverse_each do |chg| case chg.action when '-' oldstart = chg.old_position output[chg.old_position] = '
' if chg.old_element.match(/^\r?\n$/) when '+' if chg.new_element.match(/^\r?\n$/) output.insert(chg.old_position, '
') else output.insert(chg.old_position, "#{escape_html[chg.new_element]}") end end end if newchange.action == '+' output.insert(newstart, '') end if hunk[0].action == '-' output.insert((newstart == oldstart || newchange.action != '+') ? newstart+1 : newstart, '') output.insert(oldstart, '') end end output.join.gsub(/\r?\n/, '
').html_safe end end