/usr/lib/ruby/vendor_ruby/diff/lcs/htmldiff.rb is in ruby-diff-lcs 1.2.5-2build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | # -*- ruby encoding: utf-8 -*-
require 'cgi'
class Diff::LCS::HTMLDiff
class << self
attr_accessor :can_expand_tabs #:nodoc:
end
self.can_expand_tabs = true
class Callbacks
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|<pre class="#{__send__(css_class)}">#{element}</pre>\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,
}
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] < 0
@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] > 0 && self.class.can_expand_tabs
formatter = Text::Format.new
formatter.tabstop = @options[:expand_tabs]
@left = left.map { |line| formatter.expand(line.chomp) }
@right = right.map { |line| formatter.expand(line.chomp) }
end
@left.map! { |line| CGI.escapeHTML(line.chomp) }
@right.map! { |line| CGI.escapeHTML(line.chomp) }
@options[:output] << <<-OUTPUT
<html>
<head>
<title>#{@options[:title]}</title>
<style type="text/css">
#{@options[:css]}
</style>
</head>
<body>
<h1>#{@options[:title]}</h1>
<p>Legend: <span class="only_a">Only in Old</span>
<span class="only_b">Only in New</span></p>
<div class="diff">
OUTPUT
callbacks = Callbacks.new(@options[:output])
Diff::LCS.traverse_sequences(@left, @right, callbacks)
@options[:output] << <<-OUTPUT
</div>
</body>
</html>
OUTPUT
end
end
|