module HypDiff
@api public
Constants
- VERSION
Public Class Methods
Compare two html snippets. @param before [String] the first html snippet @param after [String] the second html snippet @option options [Proc] :render_insertion provide a callback to render insertions. The callback will receive the inserted text as a html snippet. It should return a new html snippet that will be used in the output. If no callback is given, `<ins>`-Tags will be used to highlight insertions. @option options [Proc] :render_deletion provide a callback to render deletions. The callback will receive the deleted text as a html snippet. It should return a new html snippet that will be used in the output. If no callback is given, `<del>`-Tags will be used to highlight deletions. @option options [String] :markup_from specify if the markup from `before` or `after` should be used as the basis for the output. Possible values: “before” and “after”. Default: “after” @return [String] a new html snippet that highlights changes between `before` and `after` @api public
# File lib/hyp_diff.rb, line 17 def compare(before, after, options = {}) parsed_after = parse(after) parsed_before = parse(before) text_changes = Diff::LCS.sdiff(extract_text(parsed_before), extract_text(parsed_after)) markup_from_before = options[:markup_from] == "before" change_node_tuples = text_changes.map do |change| text_from_node = markup_from_before ? change.old_element : change.new_element [change, text_from_node && text_from_node.node] end render_deletion = options[:render_deletion] || proc { |html| "<del>#{html}</del>" } render_insertion = options[:render_insertion] || proc { |html| "<ins>#{html}</ins>" } NodeMap.for(change_node_tuples).each do |node, changes| node.replace(ChangeRenderer.render(changes, render_deletion, render_insertion)) end modified_fragment = markup_from_before ? parsed_before : parsed_after modified_fragment.to_html end
Private Class Methods
# File lib/hyp_diff.rb, line 165 def extract_text(node) filter_whitespace(text_fragments(node)) end
# File lib/hyp_diff.rb, line 177 def filter_whitespace(node_list) result = [] last_node_whitespace = false node_list.each do |node| node_whitespace = node.whitespace? result << node unless last_node_whitespace && node_whitespace last_node_whitespace = node_whitespace end result end
# File lib/hyp_diff.rb, line 161 def parse(text) Nokogiri::HTML.fragment(text) end
# File lib/hyp_diff.rb, line 169 def text_fragments(node) if node.is_a?(Nokogiri::XML::Text) node.text.split(/(?=[.!,<> ])|\b/).map { |token| TextFromNode.new(token, node) } else node.children.map { |c| text_fragments(c) }.flatten end end