summaryrefslogtreecommitdiff
path: root/lib/gitlab/diff/suggestions_parser.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/diff/suggestions_parser.rb')
-rw-r--r--lib/gitlab/diff/suggestions_parser.rb51
1 files changed, 51 insertions, 0 deletions
diff --git a/lib/gitlab/diff/suggestions_parser.rb b/lib/gitlab/diff/suggestions_parser.rb
new file mode 100644
index 00000000000..c8c03d5d001
--- /dev/null
+++ b/lib/gitlab/diff/suggestions_parser.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Diff
+ class SuggestionsParser
+ # Matches for instance "-1", "+1" or "-1+2".
+ SUGGESTION_CONTEXT = /^(\-(?<above>\d+))?(\+(?<below>\d+))?$/.freeze
+
+ class << self
+ # Returns an array of Gitlab::Diff::Suggestion which represents each
+ # suggestion in the given text.
+ #
+ def parse(text, position:, project:)
+ return [] unless position.complete?
+
+ html = Banzai.render(text, project: nil, no_original_data: true)
+ doc = Nokogiri::HTML(html)
+ suggestion_nodes = doc.search('pre.suggestion')
+
+ return [] if suggestion_nodes.empty?
+
+ diff_file = position.diff_file(project.repository)
+
+ suggestion_nodes.map do |node|
+ lang_param = node['data-lang-params']
+
+ lines_above, lines_below = nil
+
+ if lang_param && suggestion_params = fetch_suggestion_params(lang_param)
+ lines_above, lines_below =
+ suggestion_params[:above],
+ suggestion_params[:below]
+ end
+
+ Gitlab::Diff::Suggestion.new(node.text,
+ line: position.new_line,
+ above: lines_above.to_i,
+ below: lines_below.to_i,
+ diff_file: diff_file)
+ end
+ end
+
+ private
+
+ def fetch_suggestion_params(lang_param)
+ lang_param.match(SUGGESTION_CONTEXT)
+ end
+ end
+ end
+ end
+end