Commit 15d5dfdb authored by Stan Hu's avatar Stan Hu

Fix diff syntax highlighting

Refactored HTML parser to avoid duplication of newline parsing.

Closes #2235
parent 77f37fa9
...@@ -93,16 +93,27 @@ module Rouge ...@@ -93,16 +93,27 @@ module Rouge
end end
def process_tokens(tokens) def process_tokens(tokens)
num_lines = 0 rendered = []
last_val = '' current_line = ''
rendered = ''
tokens.each do |tok, val| tokens.each do |tok, val|
last_val = val # In the case of multi-line values (e.g. comments), we need to apply
num_lines += val.scan(/\n/).size # styling to each line since span elements are inline.
rendered << span(tok, val) val.lines.each do |line|
stripped = line.chomp
current_line << span(tok, stripped)
if line.end_with?("\n")
rendered << current_line
current_line = ''
end
end
end end
# Add leftover text
rendered << current_line if current_line.present?
num_lines = rendered.size
numbers = (@linenostart..num_lines + @linenostart - 1).to_a numbers = (@linenostart..num_lines + @linenostart - 1).to_a
{ numbers: numbers, code: rendered } { numbers: numbers, code: rendered }
...@@ -117,9 +128,8 @@ module Rouge ...@@ -117,9 +128,8 @@ module Rouge
numbers.join("\n") numbers.join("\n")
end end
def wrap_lines(rendered) def wrap_lines(lines)
if @lineanchors if @lineanchors
lines = rendered.split("\n")
lines = lines.each_with_index.map do |line, index| lines = lines.each_with_index.map do |line, index|
number = index + @linenostart number = index + @linenostart
...@@ -136,24 +146,17 @@ module Rouge ...@@ -136,24 +146,17 @@ module Rouge
lines.join("\n") lines.join("\n")
else else
if @linenos == 'inline' if @linenos == 'inline'
lines = rendered.split("\n")
lines = lines.each_with_index.map do |line, index| lines = lines.each_with_index.map do |line, index|
number = index + @linenostart number = index + @linenostart
"<span class=\"linenos\">#{number}</span>#{line}" "<span class=\"linenos\">#{number}</span>#{line}"
end end
lines.join("\n") lines.join("\n")
else else
rendered lines.join("\n")
end end
end end
end end
def wrap_values(val, element)
lines = val.split("\n")
lines = lines.map{ |x| "<span #{element}>#{x}</span>" }
lines.join("\n")
end
def span(tok, val) def span(tok, val)
# http://stackoverflow.com/a/1600584/2587286 # http://stackoverflow.com/a/1600584/2587286
val = CGI.escapeHTML(val) val = CGI.escapeHTML(val)
...@@ -161,13 +164,11 @@ module Rouge ...@@ -161,13 +164,11 @@ module Rouge
if tok.shortname.empty? if tok.shortname.empty?
val val
else else
# In the case of multi-line values (e.g. comments), we need to apply
# styling to each line since span elements are inline.
if @inline_theme if @inline_theme
rules = @inline_theme.style_for(tok).rendered_rules rules = @inline_theme.style_for(tok).rendered_rules
wrap_values(val, "style=\"#{rules.to_a.join(';')}\"") "<span style=\"#{rules.to_a.join(';')}\"#{val}</span>"
else else
wrap_values(val, "class=\"#{tok.shortname}\"") "<span class=\"#{tok.shortname}\">#{val}</span>"
end end
end end
end end
......
...@@ -47,5 +47,21 @@ describe BlobHelper do ...@@ -47,5 +47,21 @@ describe BlobHelper do
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
let(:blob_name) { 'test.diff' }
let(:blob_content) { "+aaa\n+bbb\n- ccc\n ddd\n"}
let(:expected) do
%q(<span id="LC1" class="line"><span class="gi">+aaa</span></span>
<span id="LC2" class="line"><span class="gi">+bbb</span></span>
<span id="LC3" class="line"><span class="gd">- ccc</span></span>
<span id="LC4" class="line"> ddd</span>)
end
it 'should highlight each line properly' do
result = highlight(blob_name, blob_content, nowrap: true, continue: false)
expect(result).to eq(expected)
end
end
end end
end end
...@@ -58,7 +58,7 @@ describe EventsHelper do ...@@ -58,7 +58,7 @@ describe EventsHelper do
expected = '<pre class="code highlight white ruby">' \ expected = '<pre class="code highlight white ruby">' \
"<code><span class=\"k\">def</span> <span class=\"nf\">test</span>\n" \ "<code><span class=\"k\">def</span> <span class=\"nf\">test</span>\n" \
" <span class=\"s1\">\'hello world\'</span>\n" \ " <span class=\"s1\">\'hello world\'</span>\n" \
"<span class=\"k\">end</span>\n" \ "<span class=\"k\">end</span>" \
'</code></pre>' '</code></pre>'
expect(event_note(input)).to eq(expected) expect(event_note(input)).to eq(expected)
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