gitlab-org--gitlab-foss/app/presenters/blobs/unfold_presenter.rb
Patrick Bajao bf230da05d Support selective highlighting of lines
Instead of highlighting all lines when not all of them
are needed, only highlight from the beginning up to
the specified limit.

The `BlobPresenter#highlight` method has been updated
to support `to` param. This param will be used to limit
the content to be highlighted.
2019-09-02 11:44:45 +08:00

112 lines
2.7 KiB
Ruby

# frozen_string_literal: true
module Blobs
class UnfoldPresenter < BlobPresenter
include ActiveModel::Attributes
include ActiveModel::AttributeAssignment
include Gitlab::Utils::StrongMemoize
attribute :full, :boolean, default: false
attribute :since, :integer, default: 1
attribute :to, :integer, default: 1
attribute :bottom, :boolean, default: false
attribute :unfold, :boolean, default: true
attribute :offset, :integer, default: 0
attribute :indent, :integer, default: 0
alias_method :full?, :full
alias_method :bottom?, :bottom
alias_method :unfold?, :unfold
def initialize(blob, params)
super(blob)
self.attributes = params
# Load all blob data first as we need to ensure they're all loaded first
# so we can accurately show the rest of the diff when unfolding.
load_all_blob_data
handle_full_or_end!
end
# Returns an array of Gitlab::Diff::Line with match line added
def diff_lines
diff_lines = lines.map.with_index do |line, index|
full_line = limited_blob_lines[index].delete("\n")
Gitlab::Diff::Line.new(full_line, nil, nil, nil, nil, rich_text: line)
end
add_match_line(diff_lines)
diff_lines
end
def lines
strong_memoize(:lines) do
limit(highlight(to: to).lines).map(&:html_safe)
end
end
def match_line_text
return '' if bottom?
lines_length = lines.length - 1
line = [since, lines_length].join(',')
"@@ -#{line}+#{line} @@"
end
private
def handle_full_or_end!
return unless full? || to == -1
self.since = 1 if full?
self.attributes = {
to: all_lines_size,
bottom: false,
unfold: false,
offset: 0,
indent: 0
}
end
def all_lines_size
strong_memoize(:all_lines_size) do
all_lines.size
end
end
def add_match_line(diff_lines)
return unless unfold?
return if bottom? && to >= all_lines_size
if bottom? && to < all_lines_size
old_pos = to - offset
new_pos = to
elsif since != 1
old_pos = new_pos = since
end
# Match line is not needed when it reaches the top limit or bottom limit of the file.
return unless new_pos
match_line = Gitlab::Diff::Line.new(match_line_text, 'match', nil, old_pos, new_pos)
bottom? ? diff_lines.push(match_line) : diff_lines.unshift(match_line)
end
def limited_blob_lines
strong_memoize(:limited_blob_lines) do
limit(all_lines)
end
end
def limit(lines)
return lines if full?
lines[since - 1..to - 1]
end
end
end