diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-18 13:34:06 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-18 13:34:06 +0300 |
commit | 859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch) | |
tree | d7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /lib/gitlab/diff/char_diff.rb | |
parent | 446d496a6d000c73a304be52587cd9bbc7493136 (diff) |
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'lib/gitlab/diff/char_diff.rb')
-rw-r--r-- | lib/gitlab/diff/char_diff.rb | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/lib/gitlab/diff/char_diff.rb b/lib/gitlab/diff/char_diff.rb new file mode 100644 index 00000000000..c8bb39e9f5d --- /dev/null +++ b/lib/gitlab/diff/char_diff.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +module Gitlab + module Diff + class CharDiff + include Gitlab::Utils::StrongMemoize + + def initialize(old_string, new_string) + @old_string = old_string.to_s + @new_string = new_string.to_s + @changes = [] + end + + def generate_diff + @changes = diff_match_patch.diff_main(@old_string, @new_string) + diff_match_patch.diff_cleanupSemantic(@changes) + + @changes + end + + def changed_ranges(offset: 0) + old_diffs = [] + new_diffs = [] + new_pointer = old_pointer = offset + + generate_diff.each do |(action, content)| + content_size = content.size + + if action == :equal + new_pointer += content_size + old_pointer += content_size + end + + if action == :delete + old_diffs << (old_pointer..(old_pointer + content_size - 1)) + old_pointer += content_size + end + + if action == :insert + new_diffs << (new_pointer..(new_pointer + content_size - 1)) + new_pointer += content_size + end + end + + [old_diffs, new_diffs] + end + + def to_html + @changes.map do |op, text| + %{<span class="#{html_class_names(op)}">#{ERB::Util.html_escape(text)}</span>} + end.join.html_safe + end + + private + + def diff_match_patch + strong_memoize(:diff_match_patch) { DiffMatchPatch.new } + end + + def html_class_names(operation) + class_names = ['idiff'] + + case operation + when :insert + class_names << 'addition' + when :delete + class_names << 'deletion' + end + + class_names.join(' ') + end + end + end +end |