diff options
author | Douwe Maan <douwe@gitlab.com> | 2016-01-15 16:02:48 +0100 |
---|---|---|
committer | Douwe Maan <douwe@gitlab.com> | 2016-01-15 16:02:48 +0100 |
commit | 5de8971ddfa10cbc6a082316eee7377038670f75 (patch) | |
tree | f69cb6eed018d7e2bdcae59aebb84a471655a7be /lib/gitlab/diff/inline_diff_marker.rb | |
parent | 13f10efcf120f2d5244bf6abe934dc7c026834ef (diff) | |
download | gitlab-ce-5de8971ddfa10cbc6a082316eee7377038670f75.tar.gz |
Whoops, forgot to add files
Diffstat (limited to 'lib/gitlab/diff/inline_diff_marker.rb')
-rw-r--r-- | lib/gitlab/diff/inline_diff_marker.rb | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb new file mode 100644 index 00000000000..4bb755e3d3d --- /dev/null +++ b/lib/gitlab/diff/inline_diff_marker.rb @@ -0,0 +1,85 @@ +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 |