Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRubén Dávila <rdavila84@gmail.com>2015-12-30 08:52:50 +0300
committerRubén Dávila <rdavila84@gmail.com>2015-12-30 08:52:50 +0300
commitbb96d631537d3d8181f0d3b762603a012219c3e6 (patch)
tree3520e34f8f99dd1a3a401ee83d1cb067cd9e3e66 /lib/gitlab/diff
parentc031b9d9cd1ea41ab68f46eb5e630efaf901933a (diff)
New implementation for highlighting diff files. #3945
* It is more performant given now we process all the diff file instead of processing line by line. * Multiline comments are highlighted correctly.
Diffstat (limited to 'lib/gitlab/diff')
-rw-r--r--lib/gitlab/diff/file.rb4
-rw-r--r--lib/gitlab/diff/highlight.rb55
-rw-r--r--lib/gitlab/diff/line.rb1
3 files changed, 60 insertions, 0 deletions
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index 79061cd0141..ff8765b8e26 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -15,6 +15,10 @@ module Gitlab
@lines ||= parser.parse(raw_diff.lines)
end
+ def highlighted_diff_lines
+ Gitlab::Diff::Highlight.process_diff_lines(self)
+ end
+
def mode_changed?
!!(diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode)
end
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
new file mode 100644
index 00000000000..f10b55eb00b
--- /dev/null
+++ b/lib/gitlab/diff/highlight.rb
@@ -0,0 +1,55 @@
+module Gitlab
+ module Diff
+ class Highlight
+ def self.process_diff_lines(diff_file)
+ processor = new(diff_file)
+ processor.highlight
+ end
+
+ def initialize(diff_file)
+ text_lines = diff_file.diff_lines.map(&:text)
+ @diff_file = diff_file
+ @diff_lines = diff_file.diff_lines
+ @diff_line_prefixes = text_lines.map { |line| line.sub!(/\A((\+|\-)\s*)/, '');$1 }
+ @raw_lines = text_lines.join("\n")
+ end
+
+ def highlight
+ @code = unescape_html(@raw_lines)
+ @highlighted_code = formatter.format(lexer.lex(@code))
+
+ update_diff_lines
+ end
+
+ private
+
+ def update_diff_lines
+ @highlighted_code.lines.each_with_index do |line, i|
+ @diff_lines[i].highlighted_text = "#{@diff_line_prefixes[i]}#{line}"
+ end
+
+ @diff_lines
+ end
+
+ def lexer
+ parent = Rouge::Lexer.guess(filename: @diff_file.new_path, source: @code).new rescue Rouge::Lexers::PlainText.new
+ Rouge::Lexers::GitlabDiff.new(parent_lexer: parent)
+ end
+
+ def unescape_html(content)
+ text = CGI.unescapeHTML(content)
+ text.gsub!('&nbsp;', ' ')
+ text
+ end
+
+ def formatter
+ @formatter ||= Rouge::Formatters::HTMLGitlab.new(
+ nowrap: true,
+ cssclass: 'code highlight',
+ lineanchors: true,
+ lineanchorsid: 'LC'
+ )
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb
index 0072194606e..c48c69fb344 100644
--- a/lib/gitlab/diff/line.rb
+++ b/lib/gitlab/diff/line.rb
@@ -2,6 +2,7 @@ module Gitlab
module Diff
class Line
attr_reader :type, :text, :index, :old_pos, :new_pos
+ attr_accessor :highlighted_text
def initialize(text, type, index, old_pos, new_pos)
@text, @type, @index = text, type, index