summaryrefslogtreecommitdiff
path: root/lib/gitlab/diff/highlight.rb
diff options
context:
space:
mode:
authorRubén Dávila <rdavila84@gmail.com>2016-01-07 22:37:01 -0500
committerRubén Dávila <rdavila84@gmail.com>2016-01-07 22:37:01 -0500
commit21b602c60ad787b63039d804a5e15b43d0d3c32c (patch)
tree91a068f9360b295c14599dd6547972c416a3614d /lib/gitlab/diff/highlight.rb
parentf1f4fdf778245cab74ff9cda2a421315c21a99aa (diff)
downloadgitlab-ce-21b602c60ad787b63039d804a5e15b43d0d3c32c.tar.gz
Change strategy to highlight diffs. #3945
Now we apply syntax highlighting to the whole old and new files. This basically help us to highlight adequately multiline content.
Diffstat (limited to 'lib/gitlab/diff/highlight.rb')
-rw-r--r--lib/gitlab/diff/highlight.rb70
1 files changed, 53 insertions, 17 deletions
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
index 7f340de65cc..0d0a3268107 100644
--- a/lib/gitlab/diff/highlight.rb
+++ b/lib/gitlab/diff/highlight.rb
@@ -1,22 +1,43 @@
module Gitlab
module Diff
class Highlight
+ attr_reader :diff_file
+
+ delegate :repository, :old_path, :new_path, :old_ref, :new_ref,
+ to: :diff_file, prefix: :diff
+
# Apply syntax highlight to provided source code
#
- # file_name - The file name related to the code.
- # lines - It can be an Array of Gitlab::Diff::Line objects or simple Strings.
- # When passing Strings you need to provide the required 'end of lines'
- # chars ("\n") for each String given that we don't append them automatically.
+ # diff_file - an instance of Gitlab::Diff::File
#
# Returns an Array with the processed items.
- def self.process_diff_lines(file_name, lines)
- processor = new(file_name, lines)
+ def self.process_diff_lines(diff_file)
+ processor = new(diff_file)
processor.highlight
end
- def initialize(file_name, lines)
- @file_name = file_name
- @lines = lines
+ def self.process_file(repository, ref, file_name)
+ blob = repository.blob_at(ref, file_name)
+ return [] unless blob
+
+ content = blob.data
+ lexer = Rouge::Lexer.guess(filename: file_name, source: content).new rescue Rouge::Lexers::PlainText.new
+ formatter.format(lexer.lex(content)).lines
+ end
+
+ def self.formatter
+ @formatter ||= Rouge::Formatters::HTMLGitlab.new(
+ nowrap: true,
+ cssclass: 'code highlight',
+ lineanchors: true,
+ lineanchorsid: 'LC'
+ )
+ end
+
+ def initialize(diff_file)
+ @diff_file = diff_file
+ @file_name = diff_file.new_path
+ @lines = diff_file.diff_lines
end
def highlight
@@ -47,7 +68,7 @@ module Gitlab
def extract_line_prefixes
@diff_line_prefixes ||= begin
if is_diff_line?
- text_lines.map { |line| line.sub!(/\A((\+|\-)\s*)/, '');$1 }
+ text_lines.map { |line| line.sub!(/\A((\+|\-))/, '');$1 }
else
[]
end
@@ -57,11 +78,17 @@ module Gitlab
def update_diff_lines
@highlighted_code.lines.each_with_index do |line, i|
diff_line = @lines[i]
+ line_prefix = @diff_line_prefixes[i] || ' '
# ignore highlighting for "match" lines
next if diff_line.type == 'match'
- diff_line.text = "#{@diff_line_prefixes[i]}#{line}"
+ case diff_line.type
+ when 'new', nil
+ diff_line.text = new_lines[diff_line.new_pos - 1].try(:gsub!, /\A\s/, line_prefix)
+ when 'old'
+ diff_line.text = old_lines[diff_line.old_pos - 1].try(:gsub!, /\A\s/, line_prefix)
+ end
end
@lines
@@ -79,12 +106,21 @@ module Gitlab
end
def formatter
- Rouge::Formatters::HTMLGitlab.new(
- nowrap: true,
- cssclass: 'code highlight',
- lineanchors: true,
- lineanchorsid: 'LC'
- )
+ self.class.formatter
+ end
+
+ def old_lines
+ @old_lines ||= begin
+ lines = self.class.process_file(diff_repository, diff_old_ref, diff_old_path)
+ lines.map! { |line| " #{line}" }
+ end
+ end
+
+ def new_lines
+ @new_lines ||= begin
+ lines = self.class.process_file(diff_repository, diff_new_ref, diff_new_path)
+ lines.map! { |line| " #{line}" }
+ end
end
end
end