Replace Gollum `[[_TOC_]]` tag with result of TableOfContentsFilter
Closes #2494
This commit is contained in:
parent
9f80118e05
commit
bc43ad71ef
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue