summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/gitlab/diff/inline_diff.rb1
-rw-r--r--lib/gitlab/diff/inline_diff_marker.rb10
-rw-r--r--spec/lib/gitlab/diff/inline_diff_marker_spec.rb15
-rw-r--r--spec/lib/gitlab/diff/inline_diff_spec.rb27
4 files changed, 53 insertions, 0 deletions
diff --git a/lib/gitlab/diff/inline_diff.rb b/lib/gitlab/diff/inline_diff.rb
index bae297ab00f..e5986fd69e2 100644
--- a/lib/gitlab/diff/inline_diff.rb
+++ b/lib/gitlab/diff/inline_diff.rb
@@ -38,6 +38,7 @@ module Gitlab
private
+ # Find runs of single line edits
def local_edit_indexes
line_prefixes = @lines.map { |line| line.match(/\A([+-])/) ? $1 : ' ' }
joined_line_prefixes = " #{line_prefixes.join} "
diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb
index 4bb755e3d3d..405465a641f 100644
--- a/lib/gitlab/diff/inline_diff_marker.rb
+++ b/lib/gitlab/diff/inline_diff_marker.rb
@@ -11,9 +11,12 @@ module Gitlab
def mark(line_inline_diffs)
offset = 0
line_inline_diffs.each do |inline_diff_range|
+ # Map the inline-diff range based on the raw line to character positions in the rich line
inline_diff_positions = position_mapping[inline_diff_range]
+ # Turn the array of character positions into ranges
marker_ranges = collapse_ranges(inline_diff_positions)
+ # Mark each range
marker_ranges.each do |range|
offset = insert_around_range(rich_line, range, "<span class='idiff'>", "</span>", offset)
end
@@ -22,6 +25,9 @@ module Gitlab
rich_line
end
+ private
+
+ # Mapping of character positions in the raw line, to the rich (highlighted) line
def position_mapping
@position_mapping ||= begin
mapping = []
@@ -31,6 +37,8 @@ module Gitlab
raw_char = raw_line[raw_pos]
rich_char = rich_line[rich_pos]
+ # The raw and rich lines are the same except for HTML tags,
+ # so skip over any `<...>` segment
while rich_char == '<'
until rich_char == '>'
rich_pos += 1
@@ -50,6 +58,7 @@ module Gitlab
end
end
+ # Takes an array of integers, and returns an array of ranges covering the same integers
def collapse_ranges(positions)
return [] if positions.empty?
ranges = []
@@ -71,6 +80,7 @@ module Gitlab
ranges
end
+ # Inserts tags around the characters identified by the given range
def insert_around_range(text, range, before, after, offset = 0)
text.insert(offset + range.begin, before)
offset += before.length
diff --git a/spec/lib/gitlab/diff/inline_diff_marker_spec.rb b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb
new file mode 100644
index 00000000000..5d6aea17509
--- /dev/null
+++ b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe Gitlab::Diff::InlineDiffMarker, lib: true do
+ describe '#inline_diffs' do
+ let(:raw) { "abc def" }
+ let(:rich) { %{<span class="abc">abc</span><span class="space"> </span><span class="def">def</span>} }
+ let(:inline_diffs) { [2..4] }
+
+ let(:subject) { Gitlab::Diff::InlineDiffMarker.new(raw, rich).mark(inline_diffs) }
+
+ it 'marks the inline diffs' do
+ expect(subject).to eq(%{<span class="abc">ab<span class='idiff'>c</span></span><span class="space"><span class='idiff'> </span></span><span class="def"><span class='idiff'>d</span>ef</span>})
+ end
+ end
+end
diff --git a/spec/lib/gitlab/diff/inline_diff_spec.rb b/spec/lib/gitlab/diff/inline_diff_spec.rb
new file mode 100644
index 00000000000..056917df893
--- /dev/null
+++ b/spec/lib/gitlab/diff/inline_diff_spec.rb
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe Gitlab::Diff::InlineDiff, lib: true do
+ describe '#inline_diffs' do
+ let(:diff) do
+ <<eos
+ class Test
+- def initialize(test = true)
++ def initialize(test = false)
+ @test = test
+ end
+ end
+eos
+ end
+
+ let(:subject) { Gitlab::Diff::InlineDiff.new(diff.lines).inline_diffs }
+
+ it 'finds all inline diffs' do
+ expect(subject[0]).to be_nil
+ expect(subject[1]).to eq([25..27])
+ expect(subject[2]).to eq([25..28])
+ expect(subject[3]).to be_nil
+ expect(subject[4]).to be_nil
+ expect(subject[5]).to be_nil
+ end
+ end
+end