Commit 5de8971d authored by Douwe Maan's avatar Douwe Maan

Whoops, forgot to add files

parent 13f10efc
module Gitlab
module Diff
class InlineDiff
attr_accessor :lines
def initialize(lines)
@lines = lines
end
def inline_diffs
inline_diffs = []
local_edit_indexes.each do |index|
old_index = index
new_index = index + 1
old_line = @lines[old_index]
new_line = @lines[new_index]
suffixless_old_line = old_line[1..-1]
suffixless_new_line = new_line[1..-1]
# Skip inline diff if empty line was replaced with content
next if suffixless_old_line == ""
# Add one, because this is based on the suffixless version
lcp = longest_common_prefix(suffixless_old_line, suffixless_new_line) + 1
lcs = longest_common_suffix(suffixless_old_line, suffixless_new_line)
old_diff_range = lcp..(old_line.length - lcs - 1)
new_diff_range = lcp..(new_line.length - lcs - 1)
inline_diffs[old_index] = [old_diff_range] if old_diff_range.begin <= old_diff_range.end
inline_diffs[new_index] = [new_diff_range] if new_diff_range.begin <= new_diff_range.end
end
inline_diffs
end
private
def local_edit_indexes
line_prefixes = @lines.map { |line| line.match(/\A([+-])/) ? $1 : ' ' }
joined_line_prefixes = " #{line_prefixes.join} "
offset = 0
local_edit_indexes = []
while index = joined_line_prefixes.index(" -+ ", offset)
local_edit_indexes << index
offset = index + 1
end
local_edit_indexes
end
def longest_common_prefix(a, b)
max_length = [a.length, b.length].max
length = 0
(0..max_length - 1).each do |pos|
old_char = a[pos]
new_char = b[pos]
break if old_char != new_char
length += 1
end
length
end
def longest_common_suffix(a, b)
longest_common_prefix(a.reverse, b.reverse)
end
end
end
end
module Gitlab
module Diff
class InlineDiffMarker
attr_accessor :raw_line, :rich_line
def initialize(raw_line, rich_line = raw_line)
@raw_line = raw_line
@rich_line = rich_line
end
def mark(line_inline_diffs)
offset = 0
line_inline_diffs.each do |inline_diff_range|
inline_diff_positions = position_mapping[inline_diff_range]
marker_ranges = collapse_ranges(inline_diff_positions)
marker_ranges.each do |range|
offset = insert_around_range(rich_line, range, "<span class='idiff'>", "</span>", offset)
end
end
rich_line
end
def position_mapping
@position_mapping ||= begin
mapping = []
raw_pos = 0
rich_pos = 0
(0..raw_line.length).each do |raw_pos|
raw_char = raw_line[raw_pos]
rich_char = rich_line[rich_pos]
while rich_char == '<'
until rich_char == '>'
rich_pos += 1
rich_char = rich_line[rich_pos]
end
rich_pos += 1
rich_char = rich_line[rich_pos]
end
mapping[raw_pos] = rich_pos
rich_pos += 1
end
mapping
end
end
def collapse_ranges(positions)
return [] if positions.empty?
ranges = []
start = prev = positions[0]
range = start..prev
positions[1..-1].each do |pos|
if pos == prev + 1
range = start..pos
prev = pos
else
ranges << range
start = prev = pos
range = start..prev
end
end
ranges << range
ranges
end
def insert_around_range(text, range, before, after, offset = 0)
text.insert(offset + range.begin, before)
offset += before.length
text.insert(offset + range.end + 1, after)
offset += after.length
offset
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment