Commit 512bebe2 authored by Douwe Maan's avatar Douwe Maan

Refactor Gitlab::Highlight and fix tests

parent 0a8039eb
module BlobHelper module BlobHelper
def highlight(blob_name, blob_content, nowrap: false, continue: false) def highlighter(blob_name, blob_content, nowrap: false)
Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap, continue: continue) Gitlab::Highlight.new(blob_name, blob_content, nowrap: nowrap)
end
def highlight(blob_name, blob_content, nowrap: false)
Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap)
end end
def no_highlight_files def no_highlight_files
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
.file-content.blame.highlight .file-content.blame.highlight
%table %table
- current_line = 1 - current_line = 1
- blame_highlighter = highlighter(@blob.name, @blob.data, nowrap: true)
- @blame.each do |blame_group| - @blame.each do |blame_group|
%tr %tr
%td.blame-commit %td.blame-commit
...@@ -41,5 +42,5 @@ ...@@ -41,5 +42,5 @@
%pre{class: 'code highlight white'} %pre{class: 'code highlight white'}
%code %code
- blame_group[:lines].each do |line| - blame_group[:lines].each do |line|
:erb :preserve
<%= highlight(@blob.name, line, nowrap: true, continue: true).html_safe %> #{blame_highlighter.highlight(line)}
...@@ -9,5 +9,4 @@ ...@@ -9,5 +9,4 @@
%i.fa.fa-link %i.fa.fa-link
= i = i
.blob-content{data: {blob_id: blob.id}} .blob-content{data: {blob_id: blob.id}}
:preserve = highlight(blob.name, blob.data)
#{highlight(blob.name, blob.data)}
module Gitlab module Gitlab
class Highlight class Highlight
def self.highlight(blob_name, blob_content, nowrap: true, continue: false) def self.highlight(blob_name, blob_content, nowrap: true)
formatter = rouge_formatter(nowrap: nowrap) new(blob_name, blob_content, nowrap: nowrap).highlight(blob_content, continue: false)
lexer = Rouge::Lexer.guess(filename: blob_name, source: blob_content).new rescue Rouge::Lexers::PlainText
formatter.format(lexer.lex(blob_content, continue: continue)).html_safe
end end
def self.highlight_lines(repository, ref, file_name) def self.highlight_lines(repository, ref, file_name)
...@@ -14,9 +11,26 @@ module Gitlab ...@@ -14,9 +11,26 @@ module Gitlab
highlight(file_name, blob.data).lines.map!(&:html_safe) highlight(file_name, blob.data).lines.map!(&:html_safe)
end end
def initialize(blob_name, blob_content, nowrap: true)
@formatter = rouge_formatter(nowrap: nowrap)
@lexer = Rouge::Lexer.guess(filename: blob_name, source: blob_content).new rescue Rouge::Lexers::PlainText
end
def highlight(text, continue: true)
@formatter.format(lex(text, continue: continue)).html_safe
end
private private
def self.rouge_formatter(options = {}) def lex(text, continue: true)
if @lexer == Rouge::Lexers::PlainText
@lexer.lex(text)
else
@lexer.lex(text, continue: continue)
end
end
def rouge_formatter(options = {})
options = options.reverse_merge( options = options.reverse_merge(
nowrap: true, nowrap: true,
cssclass: 'code highlight', cssclass: 'code highlight',
......
This diff is collapsed.
require 'spec_helper' require 'spec_helper'
describe BlobHelper do describe BlobHelper do
describe 'highlight' do let(:blob_name) { 'test.lisp' }
let(:blob_name) { 'test.lisp' } let(:no_context_content) { ":type \"assem\"))" }
let(:no_context_content) { ":type \"assem\"))" } let(:blob_content) { "(make-pathname :defaults name\n#{no_context_content}" }
let(:blob_content) { "(make-pathname :defaults name\n#{no_context_content}" } let(:split_content) { blob_content.split("\n") }
let(:split_content) { blob_content.split("\n") } let(:multiline_content) do
let(:multiline_content) do %q(
%q( def test(input):
def test(input): """This is line 1 of a multi-line comment.
"""This is line 1 of a multi-line comment. This is line 2.
This is line 2. """
""" )
) end
end
describe '#highlight' do
it 'should return plaintext for unknown lexer context' do it 'should return plaintext for unknown lexer context' do
result = highlight(blob_name, no_context_content, nowrap: true, continue: false) result = helper.highlight(blob_name, no_context_content, nowrap: true)
expect(result).to eq('<span id="LC1" class="line">:type &quot;assem&quot;))</span>') expect(result).to eq('<span id="LC1" class="line">:type &quot;assem&quot;))</span>')
end end
...@@ -24,28 +24,17 @@ describe BlobHelper do ...@@ -24,28 +24,17 @@ describe BlobHelper do
expected = %Q[<span id="LC1" class="line"><span class="p">(</span><span class="nb">make-pathname</span> <span class="ss">:defaults</span> <span class="nv">name</span></span> expected = %Q[<span id="LC1" class="line"><span class="p">(</span><span class="nb">make-pathname</span> <span class="ss">:defaults</span> <span class="nv">name</span></span>
<span id="LC2" class="line"><span class="ss">:type</span> <span class="s">&quot;assem&quot;</span><span class="p">))</span></span>] <span id="LC2" class="line"><span class="ss">:type</span> <span class="s">&quot;assem&quot;</span><span class="p">))</span></span>]
expect(highlight(blob_name, blob_content, nowrap: true, continue: false)).to eq(expected) expect(helper.highlight(blob_name, blob_content, nowrap: true)).to eq(expected)
end
it 'should highlight continued blocks' do
# Both lines have LC1 as ID since formatter doesn't support continue at the moment
expected = [
'<span id="LC1" class="line"><span class="p">(</span><span class="nb">make-pathname</span> <span class="ss">:defaults</span> <span class="nv">name</span></span>',
'<span id="LC1" class="line"><span class="ss">:type</span> <span class="s">&quot;assem&quot;</span><span class="p">))</span></span>'
]
result = split_content.map{ |content| highlight(blob_name, content, nowrap: true, continue: true) }
expect(result).to eq(expected)
end end
it 'should highlight multi-line comments' do it 'should highlight multi-line comments' do
result = highlight(blob_name, multiline_content, nowrap: true, continue: false) result = helper.highlight(blob_name, multiline_content, nowrap: true)
html = Nokogiri::HTML(result) html = Nokogiri::HTML(result)
lines = html.search('.s') lines = html.search('.s')
expect(lines.count).to eq(3) expect(lines.count).to eq(3)
expect(lines[0].text).to eq('"""This is line 1 of a multi-line comment.') expect(lines[0].text).to eq('"""This is line 1 of a multi-line comment.')
expect(lines[1].text).to eq(' This is line 2.') expect(lines[1].text).to eq(' This is line 2.')
expect(lines[2].text).to eq(' """') expect(lines[2].text).to eq(' """')
end end
context 'diff highlighting' do context 'diff highlighting' do
...@@ -59,9 +48,23 @@ describe BlobHelper do ...@@ -59,9 +48,23 @@ describe BlobHelper do
end end
it 'should highlight each line properly' do it 'should highlight each line properly' do
result = highlight(blob_name, blob_content, nowrap: true, continue: false) result = helper.highlight(blob_name, blob_content, nowrap: true)
expect(result).to eq(expected) expect(result).to eq(expected)
end end
end end
end end
describe "#highlighter" do
it 'should highlight continued blocks' do
# Both lines have LC1 as ID since formatter doesn't support continue at the moment
expected = [
'<span id="LC1" class="line"><span class="p">(</span><span class="nb">make-pathname</span> <span class="ss">:defaults</span> <span class="nv">name</span></span>',
'<span id="LC1" class="line"><span class="ss">:type</span> <span class="s">&quot;assem&quot;</span><span class="p">))</span></span>'
]
highlighter = helper.highlighter(blob_name, blob_content, nowrap: true)
result = split_content.map{ |content| highlighter.highlight(content) }
expect(result).to eq(expected)
end
end
end end
...@@ -8,59 +8,34 @@ describe Gitlab::Diff::Highlight, lib: true do ...@@ -8,59 +8,34 @@ describe Gitlab::Diff::Highlight, lib: true do
let(:diff) { commit.diffs.first } let(:diff) { commit.diffs.first }
let(:diff_file) { Gitlab::Diff::File.new(diff, [commit.parent, commit]) } let(:diff_file) { Gitlab::Diff::File.new(diff, [commit.parent, commit]) }
describe '.process_diff_lines' do describe '#highlight' do
context 'when processing Gitlab::Diff::Line objects' do let(:diff_lines) { Gitlab::Diff::Highlight.new(diff_file).highlight }
let(:diff_lines) { Gitlab::Diff::Highlight.process_diff_lines(diff_file) }
it 'should return Gitlab::Diff::Line elements' do it 'should return Gitlab::Diff::Line elements' do
expect(diff_lines.first).to be_an_instance_of(Gitlab::Diff::Line) expect(diff_lines.first).to be_an_instance_of(Gitlab::Diff::Line)
end end
it 'should highlight the code' do
code = %Q{ <span id="LC7" class="line"> <span class="k">def</span> <span class="nf">popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="kp">nil</span><span class="p">)</span></span>\n}
expect(diff_lines[2].text).to eq(code)
end
it 'should not generate the inline diff markup' do
expect(diff_lines[5].text).not_to match(Regexp.new(Regexp.escape('<span class="idiff">')))
end
it 'should not modify "match" lines' do
expect(diff_lines[0].text).to eq('@@ -6,12 +6,18 @@ module Popen')
expect(diff_lines[22].text).to eq('@@ -19,6 +25,7 @@ module Popen')
end
it 'should highlight unchanged lines' do
code = %Q{ <span id="LC7" class="line"> <span class="k">def</span> <span class="nf">popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="kp">nil</span><span class="p">)</span></span>\n}
expect(diff_lines[2].text).to eq(code) it 'should not modify "match" lines' do
end expect(diff_lines[0].text).to eq('@@ -6,12 +6,18 @@ module Popen')
expect(diff_lines[22].text).to eq('@@ -19,6 +25,7 @@ module Popen')
end
it 'should highlight added lines' do it 'should highlight unchanged lines' do
code = %Q{+<span id="LC9" class="line"> <span class="k">raise</span> <span class="no">RuntimeError</span><span class="p">,</span> <span class="s2">&quot;System commands must be given as an array of strings&quot;</span></span>\n} code = %Q{ <span id="LC7" class="line"> <span class="k">def</span> <span class="nf">popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="kp">nil</span><span class="p">)</span></span>\n}
expect(diff_lines[5].text).to eq(code) expect(diff_lines[2].text).to eq(code)
end end
it 'should highlight removed lines' do it 'should highlight removed lines' do
code = %Q{-<span id="LC9" class="line"> <span class="k">raise</span> <span class="s2">&quot;System commands must be given as an array of strings&quot;</span></span>\n} code = %Q{-<span id="LC9" class="line"> <span class="k">raise</span> <span class="s2">&quot;System commands must be given as an array of strings&quot;</span></span>\n}
expect(diff_lines[4].text).to eq(code) expect(diff_lines[4].text).to eq(code)
end
end end
end
describe '.highlight_lines' do it 'should highlight added lines' do
let(:lines) do code = %Q{+<span id="LC9" class="line"> <span class="k">raise</span> <span class="no"><span class='idiff'>RuntimeError</span></span><span class="p"><span class='idiff'>,</span></span> <span class="s2">&quot;System commands must be given as an array of strings&quot;</span></span>\n}
Gitlab::Diff::Highlight.highlight_lines(project.repository, commit.id, 'files/ruby/popen.rb')
end
it 'should properly highlight all the lines' do expect(diff_lines[5].text).to eq(code)
expect(lines[4]).to eq(%Q{<span id="LC5" class="line"> <span class="kp">extend</span> <span class="nb">self</span></span>\n})
expect(lines[21]).to eq(%Q{<span id="LC22" class="line"> <span class="k">unless</span> <span class="no">File</span><span class="p">.</span><span class="nf">directory?</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></span>\n})
expect(lines[26]).to eq(%Q{<span id="LC27" class="line"> <span class="vi">@cmd_status</span> <span class="o">=</span> <span class="mi">0</span></span>\n})
end end
end end
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