class Diffy::HtmlFormatter

def clean_line(line)

remove +/- or wrap in html
def clean_line(line)
  if @options[:include_plus_and_minus_in_html]
    line.sub(/^(.)/, '<span class="symbol">\1</span>')
  else
    line.sub(/^./, '')
  end.chomp
end

def highlight(lines)

def highlight(lines)
  "<strong>" +
    lines.
      # strip diff tokens (e.g. +,-,etc.)
      gsub(/(^|\\n)./, '').
      # mark line boundaries from higher level line diff
      # html is all escaped so using brackets should make this safe.
      gsub('\n', '<LINE_BOUNDARY>').
      # join characters back by stripping out newlines
      gsub("\n", '').
      # close and reopen strong tags.  we don't want inline elements
      # spanning block elements which get added later.
      gsub('<LINE_BOUNDARY>',"</strong>\n<strong>") + "</strong>"
end

def highlighted_words

def highlighted_words
  chunks = @diff.each_chunk.
    reject{|c| c == '\ No newline at end of file'"\n"}
  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 ['-', '+']
      if chunk1.each_char.take(3).join("") =~ /^(---|\+\+\+|\\\\)/ and
          chunk2.each_char.take(3).join("") =~ /^(---|\+\+\+|\\\\)/
        ERB::Util.h(chunk1)
      else
        line_diff = Diffy::Diff.new(
                                    split_characters(chunk1),
                                    split_characters(chunk2),
                                    Diffy::Diff::ORIGINAL_DEFAULT_OPTIONS
                                    )
        hi1 = reconstruct_characters(line_diff, '-')
        hi2 = reconstruct_characters(line_diff, '+')
        processed << (index + 1)
        [hi1, hi2]
      end
    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 initialize(diff, options = {})

def initialize(diff, options = {})
  @diff = diff
  @options = options
end

def reconstruct_characters(line_diff, type)

def reconstruct_characters(line_diff, type)
  enum = line_diff.each_chunk.to_a
  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[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('</strong><strong>' , '')
  end
end

def split_characters(chunk)

def split_characters(chunk)
  chunk.gsub(/^./, '').each_line.map do |line|
    if @options[:ignore_crlf]
      (line.chomp.split('') + ['\n']).map{|chr| ERB::Util.h(chr) }
    else
      chars = line.sub(/([\r\n]$)/, '').split('')
      # add escaped newlines
      chars << '\n'
      chars.map{|chr| ERB::Util.h(chr) }
    end
  end.flatten.join("\n") + "\n"
end

def to_s

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

def wrap_line(line)

def wrap_line(line)
  cleaned = clean_line(line)
  case line
  when /^(---|\+\+\+|\\\\)/
    '    <li class="diff-comment"><span>' + line.chomp + '</span></li>'
  when /^\+/
    '    <li class="ins"><ins>' + cleaned + '</ins></li>'
  when /^-/
    '    <li class="del"><del>' + cleaned + '</del></li>'
  when /^ /
    '    <li class="unchanged"><span>' + cleaned + '</span></li>'
  when /^@@/
    '    <li class="diff-block-info"><span>' + line.chomp + '</span></li>'
  end
end

def wrap_lines(lines)

def wrap_lines(lines)
  if lines.empty?
    %'<div class="diff"></div>'
  else
    %'<div class="diff">\n  <ul>\n#{lines.join("\n")}\n  </ul>\n</div>\n'
  end
end