Support selective highlighting of lines
Instead of highlighting all lines when not all of them are needed, only highlight specific lines. The `BlobPresenter#highlight` method has been updated to support `since` and `to` params. These params will be used to limit the content to be highlighted. Modify `Gitlab::Highlight` to support `since` param which will then be used to determine the starting line number.
This commit is contained in:
parent
fa216b0e86
commit
46631e1023
|
|
@ -3,12 +3,13 @@
|
|||
class BlobPresenter < Gitlab::View::Presenter::Delegated
|
||||
presents :blob
|
||||
|
||||
def highlight(plain: nil)
|
||||
def highlight(since: nil, to: nil, plain: nil)
|
||||
load_all_blob_data
|
||||
|
||||
Gitlab::Highlight.highlight(
|
||||
blob.path,
|
||||
blob.data,
|
||||
limited_blob_data(since: since, to: to),
|
||||
since: since,
|
||||
language: blob.language_from_gitattributes,
|
||||
plain: plain
|
||||
)
|
||||
|
|
@ -23,4 +24,18 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
|
|||
def load_all_blob_data
|
||||
blob.load_all_data! if blob.respond_to?(:load_all_data!)
|
||||
end
|
||||
|
||||
def limited_blob_data(since: nil, to: nil)
|
||||
return blob.data if since.blank? || to.blank?
|
||||
|
||||
limited_blob_lines(since, to).join
|
||||
end
|
||||
|
||||
def limited_blob_lines(since, to)
|
||||
all_lines[since - 1..to - 1]
|
||||
end
|
||||
|
||||
def all_lines
|
||||
@all_lines ||= blob.data.lines
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -21,20 +21,19 @@ module Blobs
|
|||
load_all_blob_data
|
||||
|
||||
@subject = blob
|
||||
@all_lines = blob.data.lines
|
||||
super(params)
|
||||
|
||||
if full?
|
||||
self.attributes = { since: 1, to: @all_lines.size, bottom: false, unfold: false, offset: 0, indent: 0 }
|
||||
self.attributes = { since: 1, to: all_lines.size, bottom: false, unfold: false, offset: 0, indent: 0 }
|
||||
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")
|
||||
diff_lines = limited_blob_lines(since, to).map.with_index do |line, index|
|
||||
full_line = line.delete("\n")
|
||||
|
||||
Gitlab::Diff::Line.new(full_line, nil, nil, nil, nil, rich_text: line)
|
||||
Gitlab::Diff::Line.new(full_line, nil, nil, nil, nil, rich_text: lines[index])
|
||||
end
|
||||
|
||||
add_match_line(diff_lines)
|
||||
|
|
@ -43,7 +42,7 @@ module Blobs
|
|||
end
|
||||
|
||||
def lines
|
||||
@lines ||= limit(highlight.lines).map(&:html_safe)
|
||||
@lines ||= highlight(since: since, to: to).lines.map(&:html_safe)
|
||||
end
|
||||
|
||||
def match_line_text
|
||||
|
|
@ -59,7 +58,7 @@ module Blobs
|
|||
def add_match_line(diff_lines)
|
||||
return unless unfold?
|
||||
|
||||
if bottom? && to < @all_lines.size
|
||||
if bottom? && to < all_lines.size
|
||||
old_pos = to - offset
|
||||
new_pos = to
|
||||
elsif since != 1
|
||||
|
|
@ -73,15 +72,5 @@ module Blobs
|
|||
|
||||
bottom? ? diff_lines.push(match_line) : diff_lines.unshift(match_line)
|
||||
end
|
||||
|
||||
def limited_blob_lines
|
||||
@limited_blob_lines ||= limit(@all_lines)
|
||||
end
|
||||
|
||||
def limit(lines)
|
||||
return lines if full?
|
||||
|
||||
lines[since - 1..to - 1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Support selective highlighting of lines
|
||||
merge_request: 31361
|
||||
author:
|
||||
type: performance
|
||||
|
|
@ -6,15 +6,16 @@ module Gitlab
|
|||
TIMEOUT_FOREGROUND = 3.seconds
|
||||
MAXIMUM_TEXT_HIGHLIGHT_SIZE = 1.megabyte
|
||||
|
||||
def self.highlight(blob_name, blob_content, language: nil, plain: false)
|
||||
new(blob_name, blob_content, language: language)
|
||||
def self.highlight(blob_name, blob_content, since: nil, language: nil, plain: false)
|
||||
new(blob_name, blob_content, since: since, language: language)
|
||||
.highlight(blob_content, continue: false, plain: plain)
|
||||
end
|
||||
|
||||
attr_reader :blob_name
|
||||
|
||||
def initialize(blob_name, blob_content, language: nil)
|
||||
def initialize(blob_name, blob_content, since: nil, language: nil)
|
||||
@formatter = Rouge::Formatters::HTMLGitlab
|
||||
@since = since
|
||||
@language = language
|
||||
@blob_name = blob_name
|
||||
@blob_content = blob_content
|
||||
|
|
@ -53,13 +54,13 @@ module Gitlab
|
|||
end
|
||||
|
||||
def highlight_plain(text)
|
||||
@formatter.format(Rouge::Lexers::PlainText.lex(text)).html_safe
|
||||
@formatter.format(Rouge::Lexers::PlainText.lex(text), since: @since).html_safe
|
||||
end
|
||||
|
||||
def highlight_rich(text, continue: true)
|
||||
tag = lexer.tag
|
||||
tokens = lexer.lex(text, continue: continue)
|
||||
Timeout.timeout(timeout_time) { @formatter.format(tokens, tag: tag).html_safe }
|
||||
Timeout.timeout(timeout_time) { @formatter.format(tokens, tag: tag, since: @since).html_safe }
|
||||
rescue Timeout::Error => e
|
||||
Gitlab::Sentry.track_exception(e)
|
||||
highlight_plain(text)
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ module Rouge
|
|||
# Creates a new <tt>Rouge::Formatter::HTMLGitlab</tt> instance.
|
||||
#
|
||||
# [+tag+] The tag (language) of the lexer used to generate the formatted tokens
|
||||
def initialize(tag: nil)
|
||||
@line_number = 1
|
||||
def initialize(tag: nil, since: nil)
|
||||
@line_number = since || 1
|
||||
@tag = tag
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,14 @@ describe Gitlab::Highlight do
|
|||
expect(lines[2].text).to eq(' """')
|
||||
end
|
||||
|
||||
context 'since param is present' do
|
||||
it 'highlights with the LC starting from "since" param' do
|
||||
lines = described_class.highlight(file_name, content, since: 2).lines
|
||||
|
||||
expect(lines[0]).to include('LC2')
|
||||
end
|
||||
end
|
||||
|
||||
context 'diff highlighting' do
|
||||
let(:file_name) { 'test.diff' }
|
||||
let(:content) { "+aaa\n+bbb\n- ccc\n ddd\n"}
|
||||
|
|
|
|||
|
|
@ -28,24 +28,70 @@ describe BlobPresenter, :seed_helper do
|
|||
subject { described_class.new(blob) }
|
||||
|
||||
it 'returns highlighted content' do
|
||||
expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: nil, language: nil)
|
||||
expect(Gitlab::Highlight)
|
||||
.to receive(:highlight)
|
||||
.with(
|
||||
'files/ruby/regex.rb',
|
||||
git_blob.data,
|
||||
since: nil,
|
||||
plain: nil,
|
||||
language: nil
|
||||
)
|
||||
|
||||
subject.highlight
|
||||
end
|
||||
|
||||
it 'returns plain content when :plain is true' do
|
||||
expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: true, language: nil)
|
||||
expect(Gitlab::Highlight)
|
||||
.to receive(:highlight)
|
||||
.with(
|
||||
'files/ruby/regex.rb',
|
||||
git_blob.data,
|
||||
since: nil,
|
||||
plain: true,
|
||||
language: nil
|
||||
)
|
||||
|
||||
subject.highlight(plain: true)
|
||||
end
|
||||
|
||||
context '"since" and "to" are present' do
|
||||
before do
|
||||
allow(git_blob)
|
||||
.to receive(:data)
|
||||
.and_return("line one\nline two\nline 3\nline 4")
|
||||
end
|
||||
|
||||
it 'returns limited highlighted content' do
|
||||
expect(Gitlab::Highlight)
|
||||
.to receive(:highlight)
|
||||
.with(
|
||||
'files/ruby/regex.rb',
|
||||
"line two\nline 3\n",
|
||||
since: 2,
|
||||
language: nil,
|
||||
plain: nil
|
||||
)
|
||||
|
||||
subject.highlight(since: 2, to: 3)
|
||||
end
|
||||
end
|
||||
|
||||
context 'gitlab-language contains a match' do
|
||||
before do
|
||||
allow(blob).to receive(:language_from_gitattributes).and_return('ruby')
|
||||
end
|
||||
|
||||
it 'passes language to inner call' do
|
||||
expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: nil, language: 'ruby')
|
||||
expect(Gitlab::Highlight)
|
||||
.to receive(:highlight)
|
||||
.with(
|
||||
'files/ruby/regex.rb',
|
||||
git_blob.data,
|
||||
since: nil,
|
||||
plain: nil,
|
||||
language: 'ruby'
|
||||
)
|
||||
|
||||
subject.highlight
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue