【问题标题】:Make output of diff-lcs human readable使 diff-lcs 的输出具有人类可读性
【发布时间】:2013-03-26 22:49:44
【问题描述】:

我正在使用 diff-lcs gem 来输出两个 html 内容主体之间的差异。这是示例内容。

版本一:

<p>Paragraph one. Sentence one.</p>

<p>Paragraph two. Another sentence.</p>

<p>Paragraph three. I dare you to change me!</p>

第二版:

<p>Paragraph one. Sentence two.</p>

<p>Paragraph two. Another sentence.</p>

<p>Paragraph three. I dare you to update me!</p>

使用这个:

seq1 = @versionOne.body
seq2 = @versionTwo.body

seq = Diff::LCS.diff(seq1, seq2)

你得到了这个怪物:

seq => [[#<Diff::LCS::Change:0x0000000be539f8 @action="-", @position=27, @element="t">, #<Diff::LCS::Change:0x0000000be538b8 @action="-", @position=28, @element="w">], [#<Diff::LCS::Change:0x0000000be53520 @action="+", @position=28, @element="n">, #<Diff::LCS::Change:0x0000000be53408 @action="+", @position=29, @element="e">], [#<Diff::LCS::Change:0x0000000be3aa70 @action="-", @position=110, @element="u">, #<Diff::LCS::Change:0x0000000be3a840 @action="-", @position=111, @element="p">, #<Diff::LCS::Change:0x0000000be34ee0 @action="-", @position=112, @element="d">, #<Diff::LCS::Change:0x0000000be349e0 @action="+", @position=110, @element="c">, #<Diff::LCS::Change:0x0000000be348a0 @action="+", @position=111, @element="h">], [#<Diff::LCS::Change:0x0000000be34580 @action="-", @position=114, @element="t">, #<Diff::LCS::Change:0x0000000be34210 @action="+", @position=113, @element="n">, #<Diff::LCS::Change:0x0000000be33f40 @action="+", @position=114, @element="g">], [#<Diff::LCS::Change:0x0000000be331d0 @action="-", @position=124, @element="">]]

sdiff 的输出和the documentation 中的其他方法同样令人恐惧。我了解数组(数组)的结构,但必须有一种简单的方法以人类可读和可样式化的方式显示差异。

PS - 如果有人想创建diff-lcs 标签,我们将不胜感激。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3.2 diff diff-lcs


    【解决方案1】:

    我输入的 diff-lcs 是一个常规字符串 - 一个字符数组。如果我想要的是字符的比较,我得到了我想要的,但我想要更易读的东西——单词、行或句子的比较。我选择了句子。

    seq1 = @versionOne.body.split('.')
    seq2 = @versionTwo.body.split('.')
    compareDiff = Diff::LCS.sdiff(seq1, seq2)
    

    这产生了更具可读性和可解析性的内容。实际上,我还想按!? 分开。然而,该结构不是普通的数组或哈希数组。浏览器中的输出让我大吃一惊,但它是一个对象数组,你可以像其他任何东西一样解析它。这是我在 rails 控制台中得到的 YAML 格式输出(不知道为什么它没有在浏览器中显示):

    ---
    - !ruby/object:Diff::LCS::ContextChange
      action: "="
      new_element: <p>Paragraph one
      new_position: 0
      old_element: <p>Paragraph one
      old_position: 0
    - !ruby/object:Diff::LCS::ContextChange
      action: "!"
      new_element: " Sentence two"
      new_position: 1
      old_element: " Sentence one"
      old_position: 1
    - !ruby/object:Diff::LCS::ContextChange
      action: "="
      new_element: |-
        </p>
        <p>Paragraph two
      new_position: 2
      old_element: |-
        </p>
        <p>Paragraph two
      old_position: 2
    - !ruby/object:Diff::LCS::ContextChange
      action: "="
      new_element: " Another sentence"
      new_position: 3
      old_element: " Another sentence"
      old_position: 3
    - !ruby/object:Diff::LCS::ContextChange
      action: "="
      new_element: |-
        </p>
        <p>Paragraph three
      new_position: 4
      old_element: |-
        </p>
        <p>Paragraph three
      old_position: 4
    - !ruby/object:Diff::LCS::ContextChange
      action: "!"
      new_element: " I dare you to update me!</p>"
      new_position: 5
      old_element: " I dare you to change me!</p>"
      old_position: 5
     => nil
    

    超级有用!这将输出一个类似于 wiki 的差异:

    sdiff = Diff::LCS.sdiff(seq2, seq1)
    
    diffHTML = ''
    
    sdiff.each do |diff|
      case diff.action
      when '='
        diffHTML << diff.new_element + "."
      when '!'
        # strip_tags only needed on old_element. removes pre-mature end tags.
        diffHTML << "<del>#{diff.old_element.strip_tags}</del> <add>#{diff.new_element}</add>. "
      end
    end
    
    @compareBody = diffHTML.html
    
    ...[format do block]
    

    然后按照您的意愿设置&lt;del&gt;&lt;add&gt; 的样式。如果您正在寻找更简单的东西,diffy 可能就是它,但是一旦您弄清楚了,这将非常灵活。

    【讨论】:

    • 8 年后回来说有更好的开箱即用解决方案。当更改涉及元素的开始或结束时,此解决方案在生成有效 HTML 方面存在问题。为了解决这个问题,您必须使用树差异算法而不是平面字符串差异。有一个名为 html-tree-diff 的 python 包。我在这里为它写了一个 ruby​​ 包装器:github.com/archonic/ruby_html_tree_differ
    【解决方案2】:

    还有你可以使用的块版本,你可以结合数组解构:

    seq1.sdiff(seq2) { |action, (old_pos, old_element), (new_pos, new_element)|
      ...
      puts [action, old_pos, old_element, new_pos, new_element].inspect
      ...
    }
    
    seq1.diff(seq2) { |action, position, element| 
      puts [action, position, element].inspect 
    }
    

    【讨论】:

      猜你喜欢
      • 2022-11-11
      • 2014-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-03
      • 2013-12-10
      • 2013-07-06
      相关资源
      最近更新 更多