# frozen_string_literal: true require 'cgi' # Produce a simple HTML diff view. class Diff::LCS::HTMLDiff class << self attr_accessor :can_expand_tabs #:nodoc: end self.can_expand_tabs = true class Callbacks #:nodoc: attr_accessor :output attr_accessor :match_class attr_accessor :only_a_class attr_accessor :only_b_class def initialize(output, options = {}) @output = output options ||= {} @match_class = options[:match_class] || 'match' @only_a_class = options[:only_a_class] || 'only_a' @only_b_class = options[:only_b_class] || 'only_b' end def htmlize(element, css_class) element = ' ' if element.empty? %Q(
#{element}\n)
end
private :htmlize
# This will be called with both lines are the same
def match(event)
@output << htmlize(event.old_element, :match_class)
end
# This will be called when there is a line in A that isn't in B
def discard_a(event)
@output << htmlize(event.old_element, :only_a_class)
end
# This will be called when there is a line in B that isn't in A
def discard_b(event)
@output << htmlize(event.new_element, :only_b_class)
end
end
DEFAULT_OPTIONS = {
:expand_tabs => nil,
:output => nil,
:css => nil,
:title => nil
}.freeze
DEFAULT_CSS = <<-CSS
body { margin: 0; }
.diff
{
border: 1px solid black;
margin: 1em 2em;
}
p
{
margin-left: 2em;
}
pre
{
padding-left: 1em;
margin: 0;
font-family: Inconsolata, Consolas, Lucida, Courier, monospaced;
white-space: pre;
}
.match { }
.only_a
{
background-color: #fdd;
color: red;
text-decoration: line-through;
}
.only_b
{
background-color: #ddf;
color: blue;
border-left: 3px solid blue
}
h1 { margin-left: 2em; }
CSS
def initialize(left, right, options = nil)
@left = left
@right = right
@options = options
@options = DEFAULT_OPTIONS.dup if @options.nil?
end
def verify_options
@options[:expand_tabs] ||= 4
@options[:expand_tabs] = 4 if @options[:expand_tabs].negative?
@options[:output] ||= $stdout
@options[:css] ||= DEFAULT_CSS.dup
@options[:title] ||= 'diff'
end
private :verify_options
attr_reader :options
def run
verify_options
if @options[:expand_tabs].positive? && self.class.can_expand_tabs
formatter = Text::Format.new
formatter.tabstop = @options[:expand_tabs]
@left.map! do |line| formatter.expand(line.chomp) end
@right.map! do |line| formatter.expand(line.chomp) end
end
@left.map! do |line| CGI.escapeHTML(line.chomp) end
@right.map! do |line| CGI.escapeHTML(line.chomp) end
@options[:output] << <<-OUTPUT
Legend: Only in Old Only in New