diff options
-rw-r--r-- | lib/gitlab/diff/inline_diff.rb | 1 | ||||
-rw-r--r-- | lib/gitlab/diff/inline_diff_marker.rb | 10 | ||||
-rw-r--r-- | spec/lib/gitlab/diff/inline_diff_marker_spec.rb | 15 | ||||
-rw-r--r-- | spec/lib/gitlab/diff/inline_diff_spec.rb | 27 |
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 |