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
|
class BlobPresenter < Gitlab::View::Presenter::Delegated
|
||||||
presents :blob
|
presents :blob
|
||||||
|
|
||||||
def highlight(plain: nil)
|
def highlight(since: nil, to: nil, plain: nil)
|
||||||
load_all_blob_data
|
load_all_blob_data
|
||||||
|
|
||||||
Gitlab::Highlight.highlight(
|
Gitlab::Highlight.highlight(
|
||||||
blob.path,
|
blob.path,
|
||||||
blob.data,
|
limited_blob_data(since: since, to: to),
|
||||||
|
since: since,
|
||||||
language: blob.language_from_gitattributes,
|
language: blob.language_from_gitattributes,
|
||||||
plain: plain
|
plain: plain
|
||||||
)
|
)
|
||||||
|
|
@ -23,4 +24,18 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
|
||||||
def load_all_blob_data
|
def load_all_blob_data
|
||||||
blob.load_all_data! if blob.respond_to?(:load_all_data!)
|
blob.load_all_data! if blob.respond_to?(:load_all_data!)
|
||||||
end
|
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
|
end
|
||||||
|
|
|
||||||
|
|
@ -21,20 +21,19 @@ module Blobs
|
||||||
load_all_blob_data
|
load_all_blob_data
|
||||||
|
|
||||||
@subject = blob
|
@subject = blob
|
||||||
@all_lines = blob.data.lines
|
|
||||||
super(params)
|
super(params)
|
||||||
|
|
||||||
if full?
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns an array of Gitlab::Diff::Line with match line added
|
# Returns an array of Gitlab::Diff::Line with match line added
|
||||||
def diff_lines
|
def diff_lines
|
||||||
diff_lines = lines.map.with_index do |line, index|
|
diff_lines = limited_blob_lines(since, to).map.with_index do |line, index|
|
||||||
full_line = limited_blob_lines[index].delete("\n")
|
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
|
end
|
||||||
|
|
||||||
add_match_line(diff_lines)
|
add_match_line(diff_lines)
|
||||||
|
|
@ -43,7 +42,7 @@ module Blobs
|
||||||
end
|
end
|
||||||
|
|
||||||
def lines
|
def lines
|
||||||
@lines ||= limit(highlight.lines).map(&:html_safe)
|
@lines ||= highlight(since: since, to: to).lines.map(&:html_safe)
|
||||||
end
|
end
|
||||||
|
|
||||||
def match_line_text
|
def match_line_text
|
||||||
|
|
@ -59,7 +58,7 @@ module Blobs
|
||||||
def add_match_line(diff_lines)
|
def add_match_line(diff_lines)
|
||||||
return unless unfold?
|
return unless unfold?
|
||||||
|
|
||||||
if bottom? && to < @all_lines.size
|
if bottom? && to < all_lines.size
|
||||||
old_pos = to - offset
|
old_pos = to - offset
|
||||||
new_pos = to
|
new_pos = to
|
||||||
elsif since != 1
|
elsif since != 1
|
||||||
|
|
@ -73,15 +72,5 @@ module Blobs
|
||||||
|
|
||||||
bottom? ? diff_lines.push(match_line) : diff_lines.unshift(match_line)
|
bottom? ? diff_lines.push(match_line) : diff_lines.unshift(match_line)
|
||||||
end
|
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
|
||||||
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
|
TIMEOUT_FOREGROUND = 3.seconds
|
||||||
MAXIMUM_TEXT_HIGHLIGHT_SIZE = 1.megabyte
|
MAXIMUM_TEXT_HIGHLIGHT_SIZE = 1.megabyte
|
||||||
|
|
||||||
def self.highlight(blob_name, blob_content, language: nil, plain: false)
|
def self.highlight(blob_name, blob_content, since: nil, language: nil, plain: false)
|
||||||
new(blob_name, blob_content, language: language)
|
new(blob_name, blob_content, since: since, language: language)
|
||||||
.highlight(blob_content, continue: false, plain: plain)
|
.highlight(blob_content, continue: false, plain: plain)
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :blob_name
|
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
|
@formatter = Rouge::Formatters::HTMLGitlab
|
||||||
|
@since = since
|
||||||
@language = language
|
@language = language
|
||||||
@blob_name = blob_name
|
@blob_name = blob_name
|
||||||
@blob_content = blob_content
|
@blob_content = blob_content
|
||||||
|
|
@ -53,13 +54,13 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
def highlight_plain(text)
|
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
|
end
|
||||||
|
|
||||||
def highlight_rich(text, continue: true)
|
def highlight_rich(text, continue: true)
|
||||||
tag = lexer.tag
|
tag = lexer.tag
|
||||||
tokens = lexer.lex(text, continue: continue)
|
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
|
rescue Timeout::Error => e
|
||||||
Gitlab::Sentry.track_exception(e)
|
Gitlab::Sentry.track_exception(e)
|
||||||
highlight_plain(text)
|
highlight_plain(text)
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ module Rouge
|
||||||
# Creates a new <tt>Rouge::Formatter::HTMLGitlab</tt> instance.
|
# Creates a new <tt>Rouge::Formatter::HTMLGitlab</tt> instance.
|
||||||
#
|
#
|
||||||
# [+tag+] The tag (language) of the lexer used to generate the formatted tokens
|
# [+tag+] The tag (language) of the lexer used to generate the formatted tokens
|
||||||
def initialize(tag: nil)
|
def initialize(tag: nil, since: nil)
|
||||||
@line_number = 1
|
@line_number = since || 1
|
||||||
@tag = tag
|
@tag = tag
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,14 @@ describe Gitlab::Highlight do
|
||||||
expect(lines[2].text).to eq(' """')
|
expect(lines[2].text).to eq(' """')
|
||||||
end
|
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
|
context 'diff highlighting' do
|
||||||
let(:file_name) { 'test.diff' }
|
let(:file_name) { 'test.diff' }
|
||||||
let(:content) { "+aaa\n+bbb\n- ccc\n ddd\n"}
|
let(:content) { "+aaa\n+bbb\n- ccc\n ddd\n"}
|
||||||
|
|
|
||||||
|
|
@ -28,24 +28,70 @@ describe BlobPresenter, :seed_helper do
|
||||||
subject { described_class.new(blob) }
|
subject { described_class.new(blob) }
|
||||||
|
|
||||||
it 'returns highlighted content' do
|
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
|
subject.highlight
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns plain content when :plain is true' do
|
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)
|
subject.highlight(plain: true)
|
||||||
end
|
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
|
context 'gitlab-language contains a match' do
|
||||||
before do
|
before do
|
||||||
allow(blob).to receive(:language_from_gitattributes).and_return('ruby')
|
allow(blob).to receive(:language_from_gitattributes).and_return('ruby')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'passes language to inner call' do
|
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
|
subject.highlight
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue