diff --git a/Gemfile b/Gemfile index ecbf6fd3dc4..81e8ff60ad5 100644 --- a/Gemfile +++ b/Gemfile @@ -61,7 +61,7 @@ gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: 'omniauth-ldap' # Git Wiki # Required manually in config/initializers/gollum.rb to control load order -gem 'gollum-lib', '~> 4.1.0', require: false +gem 'gollum-lib', '~> 4.2', require: false gem 'gollum-rugged_adapter', '~> 0.4.2', require: false # Language detection @@ -105,7 +105,7 @@ gem 'seed-fu', '~> 2.3.5' # Markdown and HTML processing gem 'html-pipeline', '~> 1.11.0' gem 'task_list', '~> 1.0.2', require: 'task_list/railtie' -gem 'github-markup', '~> 1.3.1' +gem 'github-markup', '~> 1.4' gem 'redcarpet', '~> 3.3.3' gem 'RedCloth', '~> 4.3.2' gem 'rdoc', '~>3.6' @@ -113,7 +113,7 @@ gem 'org-ruby', '~> 0.9.12' gem 'creole', '~> 0.5.0' gem 'wikicloth', '0.8.1' gem 'asciidoctor', '~> 1.5.2' -gem 'rouge', '~> 1.11' +gem 'rouge', '~> 2.0' # See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s # and https://groups.google.com/forum/#!topic/ruby-security-ann/Dy7YiKb_pMM diff --git a/Gemfile.lock b/Gemfile.lock index 8430881e677..0987fd5665a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -264,7 +264,7 @@ GEM escape_utils (~> 1.1.0) mime-types (>= 1.19) rugged (>= 0.23.0b) - github-markup (1.3.3) + github-markup (1.4.0) gitlab-flowdock-git-hook (1.0.1) flowdock (~> 0.7) gitlab-grit (>= 2.4.1) @@ -287,13 +287,13 @@ GEM rubyntlm (~> 0.3) globalid (0.3.6) activesupport (>= 4.1.0) - gollum-grit_adapter (1.0.0) + gollum-grit_adapter (1.0.1) gitlab-grit (~> 2.7, >= 2.7.1) - gollum-lib (4.1.0) - github-markup (~> 1.3.3) + gollum-lib (4.2.1) + github-markup (~> 1.4.0) gollum-grit_adapter (~> 1.0) nokogiri (~> 1.6.4) - rouge (~> 1.9) + rouge (~> 2.0) sanitize (~> 2.1.0) stringex (~> 2.5.1) gollum-rugged_adapter (0.4.2) @@ -578,7 +578,7 @@ GEM railties (>= 4.2.0, < 5.1) rinku (2.0.0) rotp (2.1.2) - rouge (1.11.0) + rouge (2.0.3) rqrcode (0.7.0) chunky_png rqrcode-rails3 (0.1.7) @@ -859,12 +859,12 @@ DEPENDENCIES gemnasium-gitlab-service (~> 0.2) gemojione (~> 2.6) github-linguist (~> 4.7.0) - github-markup (~> 1.3.1) + github-markup (~> 1.4) gitlab-flowdock-git-hook (~> 1.0.1) gitlab_git (~> 10.2) gitlab_meta (= 7.0) gitlab_omniauth-ldap (~> 1.2.1) - gollum-lib (~> 4.1.0) + gollum-lib (~> 4.2) gollum-rugged_adapter (~> 0.4.2) gon (~> 6.0.1) grape (~> 0.13.0) @@ -933,7 +933,7 @@ DEPENDENCIES request_store (~> 1.3.0) rerun (~> 0.11.0) responders (~> 2.0) - rouge (~> 1.11) + rouge (~> 2.0) rqrcode-rails3 (~> 0.1.7) rspec-rails (~> 3.5.0) rspec-retry (~> 0.4.5) diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 428a42266d0..abe115d8c68 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -1,10 +1,7 @@ module BlobHelper - def highlighter(blob_name, blob_content, repository: nil, nowrap: false) - Gitlab::Highlight.new(blob_name, blob_content, nowrap: nowrap, repository: repository) - end - - def highlight(blob_name, blob_content, repository: nil, nowrap: false, plain: false) - Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap, plain: plain, repository: repository) + def highlight(blob_name, blob_content, repository: nil, plain: false) + highlighted = Gitlab::Highlight.highlight(blob_name, blob_content, plain: plain, repository: repository) + raw %(
#{highlighted})
end
def no_highlight_files
diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb
index 536b478979f..028edef704b 100644
--- a/lib/banzai/filter/syntax_highlight_filter.rb
+++ b/lib/banzai/filter/syntax_highlight_filter.rb
@@ -19,8 +19,15 @@ module Banzai
language = node.attr('class')
code = node.text
+ lexer = Rouge::Lexer.find_fancy(language)
+ formatter = Rouge::Formatters::HTML.new
+ css_classes = "code highlight js-syntax-highlight #{lexer.tag}"
+
begin
- highlighted = block_code(code, language)
+ highlighted = ''
+ highlighted << %()
+ highlighted << formatter.format(lexer.lex(code))
+ highlighted << %()
rescue
# Gracefully handle syntax highlighter bugs/errors to ensure
# users can still access an issue/comment/etc.
@@ -40,8 +47,7 @@ module Banzai
# Override Rouge::Plugins::Redcarpet#rouge_formatter
def rouge_formatter(lexer)
- Rouge::Formatters::HTMLGitlab.new(
- cssclass: "code highlight js-syntax-highlight #{lexer.tag}")
+ Rouge::Formatters::HTML.new
end
end
end
diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb
index 41296415e35..9360afedfcb 100644
--- a/lib/gitlab/highlight.rb
+++ b/lib/gitlab/highlight.rb
@@ -1,7 +1,7 @@
module Gitlab
class Highlight
- def self.highlight(blob_name, blob_content, repository: nil, nowrap: true, plain: false)
- new(blob_name, blob_content, nowrap: nowrap, repository: repository).
+ def self.highlight(blob_name, blob_content, repository: nil, plain: false)
+ new(blob_name, blob_content, repository: repository).
highlight(blob_content, continue: false, plain: plain)
end
@@ -13,30 +13,34 @@ module Gitlab
highlight(file_name, blob.data, repository: repository).lines.map!(&:html_safe)
end
- attr_reader :lexer
- def initialize(blob_name, blob_content, repository: nil, nowrap: true)
+ def initialize(blob_name, blob_content, repository: nil)
+ @formatter = Rouge::Formatters::HTMLGitlab.new
+ @repository = repository
@blob_name = blob_name
@blob_content = blob_content
- @repository = repository
- @formatter = rouge_formatter(nowrap: nowrap)
-
- @lexer = custom_language || begin
- Rouge::Lexer.guess(filename: blob_name, source: blob_content).new
- rescue Rouge::Lexer::AmbiguousGuess => e
- e.alternatives.sort_by(&:tag).first
- end
end
def highlight(text, continue: true, plain: false)
if plain
- @formatter.format(Rouge::Lexers::PlainText.lex(text)).html_safe
+ hl_lexer = Rouge::Lexers::PlainText
+ continue = false
else
- @formatter.format(@lexer.lex(text, continue: continue)).html_safe
+ hl_lexer = self.lexer
end
+
+ @formatter.format(hl_lexer.lex(text, continue: continue)).html_safe
rescue
@formatter.format(Rouge::Lexers::PlainText.lex(text)).html_safe
end
+ def lexer
+ @lexer ||= custom_language || begin
+ Rouge::Lexer.guess(filename: @blob_name, source: @blob_content).new
+ rescue Rouge::Guesser::Ambiguous => e
+ e.alternatives.sort_by(&:tag).first
+ end
+ end
+
private
def custom_language
@@ -46,16 +50,5 @@ module Gitlab
Rouge::Lexer.find_fancy(language_name)
end
-
- def rouge_formatter(options = {})
- options = options.reverse_merge(
- nowrap: true,
- cssclass: 'code highlight',
- lineanchors: true,
- lineanchorsid: 'LC'
- )
-
- Rouge::Formatters::HTMLGitlab.new(options)
- end
end
end
diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb
index 3358ed6773e..f818dc78d34 100644
--- a/lib/rouge/formatters/html_gitlab.rb
+++ b/lib/rouge/formatters/html_gitlab.rb
@@ -1,171 +1,27 @@
-require 'cgi'
-
module Rouge
module Formatters
- class HTMLGitlab < Rouge::Formatter
+ class HTMLGitlab < Rouge::Formatters::HTML
tag 'html_gitlab'
# Creates a new Rouge::Formatter::HTMLGitlab instance.
#
- # [+nowrap+] If set to True, don't wrap the output at all, not
- # even inside a tag (default: false).
- # [+cssclass+] CSS class for the wrapping tag (default: false).
- def initialize(
- nowrap: false,
- cssclass: 'highlight',
- linenos: nil,
- linenostart: 1,
- lineanchors: false,
- lineanchorsid: 'L',
- anchorlinenos: false,
- inline_theme: nil
- )
- @nowrap = nowrap
- @cssclass = cssclass
- @linenos = linenos
+ def initialize(linenostart: 1)
@linenostart = linenostart
- @lineanchors = lineanchors
- @lineanchorsid = lineanchorsid
- @anchorlinenos = anchorlinenos
- @inline_theme = Theme.find(inline_theme).new if inline_theme.is_a?(String)
+ @line_number = linenostart
end
- def render(tokens)
- case @linenos
- when 'table'
- render_tableized(tokens)
- when 'inline'
- render_untableized(tokens)
- else
- render_untableized(tokens)
- end
- end
+ def stream(tokens, &b)
+ is_first = true
+ token_lines(tokens) do |line|
+ yield "\n" unless is_first
+ is_first = false
- alias_method :format, :render
+ yield %()
+ line.each { |token, value| yield span(token, value) }
+ yield %()
- private
-
- def render_untableized(tokens)
- data = process_tokens(tokens)
-
- html = ''
- html << "" unless @nowrap
- html << wrap_lines(data[:code])
- html << "
\n" unless @nowrap
- html
- end
-
- def render_tableized(tokens)
- data = process_tokens(tokens)
-
- html = ''
- html << "" unless @nowrap
- html << ''
- html << ""
- html << wrap_linenos(data[:numbers])
- html << '
'
- html << ""
- html << wrap_lines(data[:code])
- html << '
'
- html << '
'
- html << '' unless @nowrap
- html
- end
-
- def process_tokens(tokens)
- rendered = []
- current_line = ''
-
- tokens.each do |tok, val|
- # In the case of multi-line values (e.g. comments), we need to apply
- # styling to each line since span elements are inline.
- 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
-
- # Add leftover text
- rendered << current_line if current_line.present?
-
- num_lines = rendered.size
- numbers = (@linenostart..num_lines + @linenostart - 1).to_a
-
- { numbers: numbers, code: rendered }
- end
-
- def wrap_linenos(numbers)
- if @anchorlinenos
- numbers.map! do |number|
- "#{number}"
- end
- end
- numbers.join("\n")
- end
-
- def wrap_lines(lines)
- if @lineanchors
- lines = lines.each_with_index.map do |line, index|
- number = index + @linenostart
-
- if @linenos == 'inline'
- "" \
- "#{number}" \
- "#{line}" \
- ''
- else
- "#{line}" \
- ''
- end
- end
- elsif @linenos == 'inline'
- lines = lines.each_with_index.map do |line, index|
- number = index + @linenostart
- "#{number}#{line}"
- end
- end
-
- lines.join("\n")
- end
-
- def span(tok, val)
- # http://stackoverflow.com/a/1600584/2587286
- val = CGI.escapeHTML(val)
-
- if tok.shortname.empty?
- val
- else
- if @inline_theme
- rules = @inline_theme.style_for(tok).rendered_rules
- ""
- else
- "#{val}"
- end
+ @line_number += 1
end
end
end
diff --git a/spec/fixtures/parallel_diff_result.yml b/spec/fixtures/parallel_diff_result.yml
index 333eda1191a..37066c8e930 100644
--- a/spec/fixtures/parallel_diff_result.yml
+++ b/spec/fixtures/parallel_diff_result.yml
@@ -121,7 +121,7 @@
:type: old
:number: 9
:text: |
- - raise "System commands must be given as an array of strings"
+ - raise "System commands must be given as an array of strings"
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9
:position: !ruby/object:Gitlab::Diff::Position
attributes:
@@ -136,7 +136,7 @@
:type: new
:number: 9
:text: |
- + raise RuntimeError, "System commands must be given as an array of strings"
+ + raise RuntimeError, "System commands must be given as an array of strings"
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9
:position: !ruby/object:Gitlab::Diff::Position
attributes:
@@ -241,7 +241,7 @@
:type: old
:number: 13
:text: |
- - vars = { "PWD" => path }
+ - vars = { "PWD" => path }
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_13_13
:position: !ruby/object:Gitlab::Diff::Position
attributes:
@@ -315,7 +315,7 @@
:type: new
:number: 15
:text: |
- + "PWD" => path
+ + "PWD" => path
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15
:position: !ruby/object:Gitlab::Diff::Position
attributes:
@@ -623,7 +623,7 @@
:type:
:number: 20
:text: |2
- @cmd_output = ""
+ @cmd_output = ""
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26
:position: !ruby/object:Gitlab::Diff::Position
attributes:
@@ -638,7 +638,7 @@
:type:
:number: 26
:text: |2
- @cmd_output = ""
+ @cmd_output = ""
:line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26
:position: !ruby/object:Gitlab::Diff::Position
attributes:
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index 6d1c02db297..bd0108f9938 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -16,19 +16,19 @@ describe BlobHelper do
describe '#highlight' do
it 'should return plaintext for unknown lexer context' do
- result = helper.highlight(blob_name, no_context_content, nowrap: true)
- expect(result).to eq(':type "assem"))')
+ result = helper.highlight(blob_name, no_context_content)
+ expect(result).to eq(%[:type "assem"))
])
end
it 'should highlight single block' do
- expected = %Q[(make-pathname :defaults name
-:type "assem"))]
+ expected = %Q[(make-pathname :defaults name
+:type "assem"))
]
- expect(helper.highlight(blob_name, blob_content, nowrap: true)).to eq(expected)
+ expect(helper.highlight(blob_name, blob_content)).to eq(expected)
end
it 'should highlight multi-line comments' do
- result = helper.highlight(blob_name, multiline_content, nowrap: true)
+ result = helper.highlight(blob_name, multiline_content)
html = Nokogiri::HTML(result)
lines = html.search('.s')
expect(lines.count).to eq(3)
@@ -41,33 +41,19 @@ describe BlobHelper do
let(:blob_name) { 'test.diff' }
let(:blob_content) { "+aaa\n+bbb\n- ccc\n ddd\n"}
let(:expected) do
- %q(+aaa
+ %q(+aaa
+bbb
- ccc
- ddd)
+ ddd
)
end
it 'should highlight each line properly' do
- result = helper.highlight(blob_name, blob_content, nowrap: true)
+ result = helper.highlight(blob_name, blob_content)
expect(result).to eq(expected)
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 = [
- '(make-pathname :defaults name',
- ':type "assem"))'
- ]
-
- highlighter = helper.highlighter(blob_name, blob_content, nowrap: true)
- result = split_content.map{ |content| highlighter.highlight(content) }
- expect(result).to eq(expected)
- end
- end
-
describe "#sanitize_svg" do
let(:input_svg_path) { File.join(Rails.root, 'spec', 'fixtures', 'unsanitized.svg') }
let(:data) { open(input_svg_path).read }
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index c0d2be98e85..6b5e3d93d48 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -57,7 +57,7 @@ describe EventsHelper do
expected = '' \
"def test\n" \
" \'hello world\'\n" \
- "end" \
+ "end\n" \
''
expect(helper.event_note(input)).to eq(expected)
end
diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
index 407617f3307..48ebc81cf82 100644
--- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
+++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
@@ -5,11 +5,11 @@ describe Banzai::Filter::SyntaxHighlightFilter, lib: true do
it 'highlights valid code blocks' do
result = filter('def fun end')
- expect(result.to_html).to eq("def fun end
\n")
+ expect(result.to_html).to eq("def fun end
")
end
it 'passes through invalid code blocks' do
- allow_any_instance_of(described_class).to receive(:block_code).and_raise(StandardError)
+ allow_any_instance_of(Rouge::Formatter).to receive(:format).and_raise(StandardError)
result = filter('This is a test
')
expect(result.to_html).to eq('This is a test
')
diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb
index fb5d50a5c68..88e4115c453 100644
--- a/spec/lib/gitlab/diff/highlight_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_spec.rb
@@ -28,13 +28,13 @@ describe Gitlab::Diff::Highlight, lib: true do
end
it 'highlights and marks removed lines' do
- code = %Q{- raise "System commands must be given as an array of strings"\n}
+ code = %Q{- raise "System commands must be given as an array of strings"\n}
expect(subject[4].text).to eq(code)
end
it 'highlights and marks added lines' do
- code = %Q{+ raise RuntimeError, "System commands must be given as an array of strings"\n}
+ code = %Q{+ raise RuntimeError, "System commands must be given as an array of strings"\n}
expect(subject[5].text).to eq(code)
end