summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jirutka <jakub@jirutka.cz>2015-05-13 01:07:48 +0200
committerJakub Jirutka <jakub@jirutka.cz>2015-05-18 20:48:03 +0200
commit8dbc4746fe7c723b67f3c90cbf40fd7bf6c29cb7 (patch)
tree268aba3884c8e2e09fdefda9cad7a4c569154cc2
parentdc348baf18240dc05e209ec781daada2cbcfe16f (diff)
downloadgitlab-ce-8dbc4746fe7c723b67f3c90cbf40fd7bf6c29cb7.tar.gz
Handle AsciiDoc better, reuse HTML pipeline filters (fixes #9263)
-rw-r--r--app/helpers/application_helper.rb12
-rw-r--r--app/helpers/gitlab_markdown_helper.rb15
-rw-r--r--app/helpers/tree_helper.rb2
-rw-r--r--lib/gitlab/asciidoc.rb60
-rw-r--r--lib/gitlab/markdown_helper.rb11
-rw-r--r--spec/helpers/application_helper_spec.rb9
-rw-r--r--spec/helpers/gitlab_markdown_helper_spec.rb8
-rw-r--r--spec/lib/gitlab/asciidoc_spec.rb59
-rw-r--r--spec/lib/gitlab/gitlab_markdown_helper_spec.rb14
9 files changed, 184 insertions, 6 deletions
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index ea9722b9bef..bc07c09cd4a 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -222,8 +222,12 @@ module ApplicationHelper
end
def render_markup(file_name, file_content)
- GitHub::Markup.render(file_name, file_content).
- force_encoding(file_content.encoding).html_safe
+ if asciidoc?(file_name)
+ asciidoc(file_content)
+ else
+ GitHub::Markup.render(file_name, file_content).
+ force_encoding(file_content.encoding).html_safe
+ end
rescue RuntimeError
simple_format(file_content)
end
@@ -236,6 +240,10 @@ module ApplicationHelper
Gitlab::MarkdownHelper.gitlab_markdown?(filename)
end
+ def asciidoc?(filename)
+ Gitlab::MarkdownHelper.asciidoc?(filename)
+ end
+
# Overrides ActionView::Helpers::UrlHelper#link_to to add `rel="nofollow"` to
# external links
def link_to(name = nil, options = nil, html_options = {})
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index 846aded4bda..7bcc011fd5f 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -56,6 +56,16 @@ module GitlabMarkdownHelper
@markdown.render(text).html_safe
end
+ def asciidoc(text)
+ Gitlab::Asciidoc.render(text, {
+ commit: @commit,
+ project: @project,
+ project_wiki: @project_wiki,
+ requested_path: @path,
+ ref: @ref
+ })
+ end
+
# Return the first line of +text+, up to +max_chars+, after parsing the line
# as Markdown. HTML tags in the parsed output are not counted toward the
# +max_chars+ limit. If the length limit falls within a tag's contents, then
@@ -67,8 +77,11 @@ module GitlabMarkdownHelper
end
def render_wiki_content(wiki_page)
- if wiki_page.format == :markdown
+ case wiki_page.format
+ when :markdown
markdown(wiki_page.content)
+ when :asciidoc
+ asciidoc(wiki_page.content)
else
wiki_page.formatted_content.html_safe
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 6dd9b6f017c..c03564a71ab 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -27,6 +27,8 @@ module TreeHelper
def render_readme(readme)
if gitlab_markdown?(readme.name)
preserve(markdown(readme.data))
+ elsif asciidoc?(readme.name)
+ asciidoc(readme.data)
elsif markup?(readme.name)
render_markup(readme.name, readme.data)
else
diff --git a/lib/gitlab/asciidoc.rb b/lib/gitlab/asciidoc.rb
new file mode 100644
index 00000000000..bf33e5b1b1e
--- /dev/null
+++ b/lib/gitlab/asciidoc.rb
@@ -0,0 +1,60 @@
+require 'asciidoctor'
+require 'html/pipeline'
+
+module Gitlab
+ # Parser/renderer for the AsciiDoc format that uses Asciidoctor and filters
+ # the resulting HTML through HTML pipeline filters.
+ module Asciidoc
+
+ # Provide autoload paths for filters to prevent a circular dependency error
+ autoload :RelativeLinkFilter, 'gitlab/markdown/relative_link_filter'
+
+ DEFAULT_ADOC_ATTRS = [
+ 'showtitle', 'idprefix=user-content-', 'idseparator=-', 'env=gitlab',
+ 'env-gitlab', 'source-highlighter=html-pipeline'
+ ].freeze
+
+ # Public: Converts the provided Asciidoc markup into HTML.
+ #
+ # input - the source text in Asciidoc format
+ # context - a Hash with the template context:
+ # :commit
+ # :project
+ # :project_wiki
+ # :requested_path
+ # :ref
+ # asciidoc_opts - a Hash of options to pass to the Asciidoctor converter
+ # html_opts - a Hash of options for HTML output:
+ # :xhtml - output XHTML instead of HTML
+ #
+ def self.render(input, context, asciidoc_opts = {}, html_opts = {})
+ asciidoc_opts = asciidoc_opts.reverse_merge(
+ safe: :secure,
+ backend: html_opts[:xhtml] ? :xhtml5 : :html5,
+ attributes: []
+ )
+ asciidoc_opts[:attributes].unshift(*DEFAULT_ADOC_ATTRS)
+
+ html = ::Asciidoctor.convert(input, asciidoc_opts)
+
+ if context[:project]
+ result = HTML::Pipeline.new(filters).call(html, context)
+
+ save_opts = html_opts[:xhtml] ?
+ Nokogiri::XML::Node::SaveOptions::AS_XHTML : 0
+
+ html = result[:output].to_html(save_with: save_opts)
+ end
+
+ html.html_safe
+ end
+
+ private
+
+ def self.filters
+ [
+ Gitlab::Markdown::RelativeLinkFilter
+ ]
+ end
+ end
+end
diff --git a/lib/gitlab/markdown_helper.rb b/lib/gitlab/markdown_helper.rb
index 5e3cfc0585b..70384b1db2c 100644
--- a/lib/gitlab/markdown_helper.rb
+++ b/lib/gitlab/markdown_helper.rb
@@ -9,7 +9,7 @@ module Gitlab
# Returns boolean
def markup?(filename)
filename.downcase.end_with?(*%w(.textile .rdoc .org .creole .wiki
- .mediawiki .rst .adoc .asciidoc .asc))
+ .mediawiki .rst .adoc .ad .asciidoc))
end
# Public: Determines if a given filename is compatible with
@@ -22,6 +22,15 @@ module Gitlab
filename.downcase.end_with?(*%w(.mdown .md .markdown))
end
+ # Public: Determines if the given filename has AsciiDoc extension.
+ #
+ # filename - Filename string to check
+ #
+ # Returns boolean
+ def asciidoc?(filename)
+ filename.downcase.end_with?(*%w(.adoc .ad .asciidoc))
+ end
+
def previewable?(filename)
gitlab_markdown?(filename) || markup?(filename)
end
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index d4cf6540080..59870dfb192 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -261,12 +261,19 @@ describe ApplicationHelper do
end
end
- describe 'markup_render' do
+ describe 'render_markup' do
let(:content) { 'Noël' }
it 'should preserve encoding' do
expect(content.encoding.name).to eq('UTF-8')
expect(render_markup('foo.rst', content).encoding.name).to eq('UTF-8')
end
+
+ it "should delegate to #asciidoc when file name corresponds to AsciiDoc" do
+ expect(self).to receive(:asciidoc?).with('foo.adoc').and_return(true)
+ expect(self).to receive(:asciidoc).and_return('NOEL')
+
+ expect(render_markup('foo.adoc', content)).to eq('NOEL')
+ end
end
end
diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb
index 9f3e8cf585e..0d0418f84a7 100644
--- a/spec/helpers/gitlab_markdown_helper_spec.rb
+++ b/spec/helpers/gitlab_markdown_helper_spec.rb
@@ -110,6 +110,14 @@ describe GitlabMarkdownHelper do
helper.render_wiki_content(@wiki)
end
+ it "should use Asciidoctor for asciidoc files" do
+ allow(@wiki).to receive(:format).and_return(:asciidoc)
+
+ expect(helper).to receive(:asciidoc).with('wiki content')
+
+ helper.render_wiki_content(@wiki)
+ end
+
it "should use the Gollum renderer for all other file types" do
allow(@wiki).to receive(:format).and_return(:rdoc)
formatted_content_stub = double('formatted_content')
diff --git a/spec/lib/gitlab/asciidoc_spec.rb b/spec/lib/gitlab/asciidoc_spec.rb
new file mode 100644
index 00000000000..23f83339ec5
--- /dev/null
+++ b/spec/lib/gitlab/asciidoc_spec.rb
@@ -0,0 +1,59 @@
+require 'spec_helper'
+require 'nokogiri'
+
+module Gitlab
+ describe Asciidoc do
+
+ let(:input) { '<b>ascii</b>' }
+ let(:context) { {} }
+ let(:html) { 'H<sub>2</sub>O' }
+
+ context "without project" do
+
+ it "should convert the input using Asciidoctor and default options" do
+ expected_asciidoc_opts = { safe: :secure, backend: :html5,
+ attributes: described_class::DEFAULT_ADOC_ATTRS }
+
+ expect(Asciidoctor).to receive(:convert)
+ .with(input, expected_asciidoc_opts).and_return(html)
+
+ expect( render(input, context) ).to eql html
+ end
+
+ context "with asciidoc_opts" do
+
+ let(:asciidoc_opts) { {safe: :safe, attributes: ['foo']} }
+
+ it "should merge the options with default ones" do
+ expected_asciidoc_opts = { safe: :safe, backend: :html5,
+ attributes: described_class::DEFAULT_ADOC_ATTRS + ['foo'] }
+
+ expect(Asciidoctor).to receive(:convert)
+ .with(input, expected_asciidoc_opts).and_return(html)
+
+ render(input, context, asciidoc_opts)
+ end
+ end
+ end
+
+ context "with project in context" do
+
+ let(:context) { {project: create(:project)} }
+
+ it "should filter converted input via HTML pipeline and return result" do
+ filtered_html = '<b>ASCII</b>'
+
+ allow(Asciidoctor).to receive(:convert).and_return(html)
+ expect_any_instance_of(HTML::Pipeline).to receive(:call)
+ .with(html, context)
+ .and_return(output: Nokogiri::HTML.fragment(filtered_html))
+
+ expect( render('foo', context) ).to eql filtered_html
+ end
+ end
+
+ def render(*args)
+ described_class.render(*args)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/gitlab_markdown_helper_spec.rb b/spec/lib/gitlab/gitlab_markdown_helper_spec.rb
index ab613193f41..beaafd56352 100644
--- a/spec/lib/gitlab/gitlab_markdown_helper_spec.rb
+++ b/spec/lib/gitlab/gitlab_markdown_helper_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe Gitlab::MarkdownHelper do
describe '#markup?' do
%w(textile rdoc org creole wiki
- mediawiki rst adoc asciidoc asc).each do |type|
+ mediawiki rst adoc ad asciidoc).each do |type|
it "returns true for #{type} files" do
expect(Gitlab::MarkdownHelper.markup?("README.#{type}")).to be_truthy
end
@@ -25,4 +25,16 @@ describe Gitlab::MarkdownHelper do
expect(Gitlab::MarkdownHelper.gitlab_markdown?('README.rb')).not_to be_truthy
end
end
+
+ describe '#asciidoc?' do
+ %w(adoc ad asciidoc ADOC).each do |type|
+ it "returns true for #{type} files" do
+ expect(Gitlab::MarkdownHelper.asciidoc?("README.#{type}")).to be_truthy
+ end
+ end
+
+ it 'returns false when given a non-asciidoc filename' do
+ expect(Gitlab::MarkdownHelper.asciidoc?('README.rb')).not_to be_truthy
+ end
+ end
end