Commit d61dab91 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch '65152-selective-highlight' into 'master'

Support selective highlighting of lines

See merge request gitlab-org/gitlab-ce!31361
parents 550e0d45 46631e10
...@@ -3,12 +3,13 @@ ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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
---
title: Support selective highlighting of lines
merge_request: 31361
author:
type: performance
...@@ -6,15 +6,16 @@ module Gitlab ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment