summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/banzai/filter/gollum_tags_filter.rb35
-rw-r--r--lib/banzai/pipeline/wiki_pipeline.rb6
-rw-r--r--spec/lib/banzai/filter/gollum_tags_filter_spec.rb52
3 files changed, 85 insertions, 8 deletions
diff --git a/lib/banzai/filter/gollum_tags_filter.rb b/lib/banzai/filter/gollum_tags_filter.rb
index fe01dae4850..bcf5297e382 100644
--- a/lib/banzai/filter/gollum_tags_filter.rb
+++ b/lib/banzai/filter/gollum_tags_filter.rb
@@ -50,21 +50,30 @@ module Banzai
# See https://github.com/gollum/gollum/wiki
#
# Rubular: http://rubular.com/r/7dQnE5CUCH
- TAGS_PATTERN = %r{\[\[(.+?)\]\]}
+ TAGS_PATTERN = %r{\[\[(.+?)\]\]}.freeze
# Pattern to match allowed image extensions
- ALLOWED_IMAGE_EXTENSIONS = %r{.+(jpg|png|gif|svg|bmp)\z}i
+ ALLOWED_IMAGE_EXTENSIONS = %r{.+(jpg|png|gif|svg|bmp)\z}i.freeze
def call
search_text_nodes(doc).each do |node|
- content = node.content
+ # A Gollum ToC tag is `[[_TOC_]]`, but due to MarkdownFilter running
+ # before this one, it will be converted into `[[<em>TOC</em>]]`, so it
+ # needs special-case handling
+ if toc_tag?(node)
+ next unless result[:toc].present?
- next unless content.match(TAGS_PATTERN)
+ process_toc_tag(node)
+ else
+ content = node.content
- html = process_tag($1)
+ next unless content =~ TAGS_PATTERN
- if html && html != node.content
- node.replace(html)
+ html = process_tag($1)
+
+ if html && html != node.content
+ node.replace(html)
+ end
end
end
@@ -73,6 +82,12 @@ module Banzai
private
+ # Replace an entire `[[<em>TOC</em>]]` node with the result generated by
+ # TableOfContentsFilter
+ def process_toc_tag(node)
+ node.parent.parent.replace(result[:toc])
+ end
+
# Process a single tag into its final HTML form.
#
# tag - The String tag contents (the stuff inside the double brackets).
@@ -108,6 +123,12 @@ module Banzai
end
end
+ def toc_tag?(node)
+ node.content == 'TOC' &&
+ node.parent.name == 'em' &&
+ node.parent.parent.text == '[[TOC]]'
+ end
+
def image?(path)
path =~ ALLOWED_IMAGE_EXTENSIONS
end
diff --git a/lib/banzai/pipeline/wiki_pipeline.rb b/lib/banzai/pipeline/wiki_pipeline.rb
index 50b5450e70b..bc2bf111971 100644
--- a/lib/banzai/pipeline/wiki_pipeline.rb
+++ b/lib/banzai/pipeline/wiki_pipeline.rb
@@ -4,7 +4,11 @@ module Banzai
module Pipeline
class WikiPipeline < FullPipeline
def self.filters
- super.insert(1, Filter::GollumTagsFilter)
+ @filters ||= begin
+ filters = super
+ toc = filters.index(Filter::TableOfContentsFilter)
+ filters.insert(toc + 1, Filter::GollumTagsFilter)
+ end
end
end
end
diff --git a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb
index 38baa819957..11cc290d6d0 100644
--- a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb
+++ b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb
@@ -86,4 +86,56 @@ describe Banzai::Filter::GollumTagsFilter, lib: true do
expect(doc.at_css('a')['href']).to eq 'wiki-slug'
end
end
+
+ context 'table of contents' do
+ let(:pipeline) { Banzai::Pipeline[:wiki] }
+
+ it 'replaces the tag with the TableOfContentsFilter result' do
+ markdown = <<-MD.strip_heredoc
+ [[_TOC_]]
+
+ ## Header
+
+ Foo
+ MD
+
+ result = pipeline.call(markdown, project_wiki: project_wiki, project: project)
+
+ aggregate_failures do
+ expect(result[:output].text).not_to include '[[_TOC_]]'
+ expect(result[:output].text).not_to include '[['
+ expect(result[:output].to_html).to include(result[:toc])
+ end
+ end
+
+ it 'is case-sensitive' do
+ markdown = <<-MD.strip_heredoc
+ [[_toc_]]
+
+ # Header 1
+
+ Foo
+ MD
+
+ output = pipeline.to_html(markdown, project_wiki: project_wiki, project: project)
+
+ expect(output).to include('[[<em>toc</em>]]')
+ end
+
+ it 'handles an empty pipeline result' do
+ # No Markdown headers in this doc, so `result[:toc]` will be empty
+ markdown = <<-MD.strip_heredoc
+ [[_TOC_]]
+
+ Foo
+ MD
+
+ output = pipeline.to_html(markdown, project_wiki: project_wiki, project: project)
+
+ aggregate_failures do
+ expect(output).not_to include('<ul>')
+ expect(output).to include('[[<em>TOC</em>]]')
+ end
+ end
+ end
end