BigW Consortium Gitlab

inline_diff.rb 2.44 KB
Newer Older
Valeriy Sizov committed
1 2 3 4 5 6
module Gitlab
  class InlineDiff
    class << self

      START  = "#!idiff-start!#"
      FINISH = "#!idiff-finish!#"
7

8
      def processing(diff_arr)
Valeriy Sizov committed
9 10 11 12 13 14 15
        indexes = _indexes_of_changed_lines diff_arr

        indexes.each do |index|
          first_line = diff_arr[index+1]
          second_line = diff_arr[index+2]
          max_length = [first_line.size, second_line.size].max

16 17 18
          # Skip inline diff if empty line was replaced with content
          next if first_line == "-\n"

Valeriy Sizov committed
19 20 21 22 23 24 25
          first_the_same_symbols = 0
          (0..max_length + 1).each do |i|
            first_the_same_symbols = i - 1
            if first_line[i] != second_line[i] && i > 0
              break
            end
          end
26

Valeriy Sizov committed
27
          first_token = first_line[0..first_the_same_symbols][1..-1]
28
          start = first_token + START
29 30 31 32 33 34 35 36 37 38

          if first_token.empty?
            # In case if we remove string of spaces in commit
            diff_arr[index+1].sub!("-", "-" => "-#{START}")
            diff_arr[index+2].sub!("+", "+" => "+#{START}")
          else
            diff_arr[index+1].sub!(first_token, first_token => start)
            diff_arr[index+2].sub!(first_token, first_token => start)
          end

Valeriy Sizov committed
39 40 41
          last_the_same_symbols = 0
          (1..max_length + 1).each do |i|
            last_the_same_symbols = -i
Valeriy Sizov committed
42 43
            shortest_line = second_line.size > first_line.size ? first_line : second_line
            if ( first_line[-i] != second_line[-i] ) || "#{first_token}#{START}".size == shortest_line[1..-i].size
Valeriy Sizov committed
44 45 46 47 48
              break
            end
          end
          last_the_same_symbols += 1
          last_token = first_line[last_the_same_symbols..-1]
49 50
          diff_arr[index+1].sub!(/#{Regexp.escape(last_token)}$/, FINISH + last_token)
          diff_arr[index+2].sub!(/#{Regexp.escape(last_token)}$/, FINISH + last_token)
Valeriy Sizov committed
51 52 53 54
        end
        diff_arr
      end

55
      def _indexes_of_changed_lines(diff_arr)
Valeriy Sizov committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
        chain_of_first_symbols = ""
        diff_arr.each_with_index do |line, i|
          chain_of_first_symbols += line[0]
        end
        chain_of_first_symbols.gsub!(/[^\-\+]/, "#")

        offset = 0
        indexes = []
        while index = chain_of_first_symbols.index("#-+#", offset)
          indexes << index
          offset = index + 1
        end
        indexes
      end

71
      def replace_markers(line)
Valeriy Sizov committed
72 73 74 75 76 77 78
        line.gsub!(START, "<span class='idiff'>")
        line.gsub!(FINISH, "</span>")
        line
      end
    end
  end
end