Open bwl21 opened 7 years ago
So…I’m not 100% sure, to be honest. I don't see adding an htmldiff
method the way you’ve written its suggested output (I don’t agree with the <ul>
/<li>
output), but there is a class, Diff::LCS::HTMLDiff
which may lead you in the direction you are after creating. You’d end up creating the appropriate callbacks to put the sort of output you want.
Just to explain the context. I have a bunch of text snippets ( in particular a bunch of requirement spec items), and I want to generate an HTML file which shows the difference between the two versions as a table with one row per spec item. The styling of the difference is done by css.
I don't care if it uses li or div or whatever as long as I can style it properly. As of now, I use, what Diffy provides.
I managed to somehow use Diff::LCS::HTMLDiff
but it seems to be not close to what I want:
so I think I will try to add another method to Diffy (Diffy.diff_noshell) and replace the code that calls the external diff command by some code from ldiff.rb.
There is a related issue there https://github.com/samg/diffy/issues/63.
So we can close this if you do not want to provide a htmldiff method.
I’m not against the idea of an htmldiff
method as such, but I’d rather work on something that makes the whole toolkit easier to use—because the styling and choices that people would make for how they show a diff in HTML will be different for every person and use case. What I’m suggesting is to look at the implementations of both ldiff
and htmldiff
(which are in Diff::LCS::Ldiff
and Diff::LCS::HTMLDiff
) respectively to implement it as you have suggested. I’m more than happy to work through your implementation and from that we may be able to figure out a way to have an htmldiff
method that provides an HTML-structured diff output that allows for deep customization (and, in the process, improve the existing htmldiff
program which is pretty crappy, IMO).
I went in to the thing again and found a solution which works for me. As it is not generic I cannot prepare a pull request. But it might be of interest. I copy it from my rspec
describe "arhtmldiff" do
it "calls sdiff" do
require 'diff/lcs'
class Callbacks
attr_accessor :output
def initialize(output, options = {})
@output = output
@state = :init
options ||= {}
@styles={
ins: "text-decoration: underline;color:blue;",
del: "text-decoration: line-through;color:red;",
eq: ""
}
end
def to_html(element)
element #.gsub(/./, {'<' => '<', '>' => '>', '&' => '&'})
end
def handle_entry(element, state)
#binding.pry
unless @state == state
@output.push "</span>" unless @state == :init
@state = state
@output.push %Q{<span style="#{@styles[state]}">}
end
@output.push(to_html(element))
end
private :handle_entry
# This will be called with both lines are the same
def match(event)
handle_entry(event.old_element, :eq)
end
# This will be called when there is a line in A that isn't in B
def discard_a(event)
handle_entry(event.old_element, :del)
end
# This will be called when there is a line in B that isn't in A
def discard_b(event)
handle_entry(event.new_element, :ins)
end
end
data_old = %q{
foo
bar}
data_new = %q{
boo
far
and more
}
output = []
output.push %Q{<pre>}
callback_obj = Callbacks.new(output)
xx = Diff::LCS.traverse_sequences(data_old, data_new, callback_obj)
output.push %Q{</pre>}
puts output.join
expect(output.join).to eq %q{<pre><span style="">
</span><span style="text-decoration: line-through;color:red;">f</span><span style="text-decoration: underline;color:blue;">b</span><span style="">oo
</span><span style="text-decoration: line-through;color:red;">b</span><span style="text-decoration: underline;color:blue;">f</span><span style="">ar</span><span style="text-decoration: underline;color:blue;">
and more
</pre>}
end
end
Thanks. I’ll look this over to see if I can extract something common.
Thanks @bwl21 - that was very useful!
I currently use
But diffy calls another executable. In our case we use ldiff as provided by liff-lcs.
I wanted to achieve something like
which should yield
How can I achieve this?