module Diffy
class HtmlFormatter
def initialize(diff, options = {})
@diff = diff
@options = options
end
def to_s
if @options[:highlight_words]
wrap_lines(highlighted_words)
else
wrap_lines(@diff.map{|line| wrap_line(ERB::Util.h(line))})
end
end
private
def wrap_line(line)
cleaned = line.gsub(/^./, '').chomp
case line
when /^\+/
'
' + cleaned + ''
when /^-/
' ' + cleaned + ''
when /^ /
' ' + cleaned + ''
end
end
def wrap_lines(lines)
%'\n'
end
def highlighted_words
chunks = @diff.each_chunk.to_a
processed = []
lines = chunks.each_with_index.map do |chunk1, index|
next if processed.include? index
processed << index
chunk1 = chunk1
chunk2 = chunks[index + 1]
if not chunk2
next ERB::Util.h(chunk1)
end
dir1 = chunk1.each_char.first
dir2 = chunk2.each_char.first
case [dir1, dir2]
when ['-', '+']
line_diff = Diffy::Diff.new(
split_characters(chunk1),
split_characters(chunk2)
)
hi1 = reconstruct_characters(line_diff, '-')
hi2 = reconstruct_characters(line_diff, '+')
processed << (index + 1)
[hi1, hi2]
else
ERB::Util.h(chunk1)
end
end.flatten
lines.map{|line| line.each_line.map(&:chomp).to_a if line }.flatten.compact.
map{|line|wrap_line(line) }.compact
end
def split_characters(chunk)
chunk.gsub(/^./, '').each_line.map do |line|
(line.chomp.split('') + ['\n']).map{|chr| ERB::Util.h(chr) }
end.flatten.join("\n") + "\n"
end
def reconstruct_characters(line_diff, type)
enum = line_diff.each_chunk
enum.each_with_index.map do |l, i|
re = /(^|\\n)#{Regexp.escape(type)}/
case l
when re
highlight(l)
when /^ /
if i > 1 and enum.to_a[i+1] and l.each_line.to_a.size < 4
highlight(l)
else
l.gsub(/^./, '').gsub("\n", '').
gsub('\r', "\r").gsub('\n', "\n")
end
end
end.join('').split("\n").map do |l|
type + l.gsub('' , '')
end
end
def highlight(lines)
"" + lines.gsub(/(^|\\n)./, '').gsub("\n", '').
gsub('\n', "\n") + ""
end
end
end