debian-mirror-gitlab/lib/banzai/filter/gollum_tags_filter.rb

161 lines
4.3 KiB
Ruby
Raw Normal View History

2018-11-18 11:00:15 +05:30
# frozen_string_literal: true
module Banzai
module Filter
# HTML Filter for parsing Gollum's tags in HTML. It's only parses the
# following tags:
#
# - Link to internal pages:
#
# * [[Bug Reports]]
# * [[How to Contribute|Contributing]]
#
# - Link to external resources:
#
# * [[http://en.wikipedia.org/wiki/Git_(software)]]
# * [[Git|http://en.wikipedia.org/wiki/Git_(software)]]
#
# - Link internal images, the special attributes will be ignored:
#
# * [[images/logo.png]]
# * [[images/logo.png|alt=Logo]]
#
# - Link external images, the special attributes will be ignored:
#
# * [[http://example.com/images/logo.png]]
# * [[http://example.com/images/logo.png|alt=Logo]]
#
# Based on Gollum::Filter::Tags
#
2020-03-13 15:44:24 +05:30
# Note: the table of contents tag is now handled by TableOfContentsTagFilter
#
# Context options:
2020-06-23 00:09:42 +05:30
# :wiki [Wiki] (required) - Current wiki instance.
#
class GollumTagsFilter < HTML::Pipeline::Filter
include ActionView::Helpers::TagHelper
# Pattern to match tags content that should be parsed in HTML.
#
# Gollum's tags have been made to resemble the tags of other markups,
# especially MediaWiki. The basic syntax is:
#
# [[tag]]
#
# Some tags will accept attributes which are separated by pipe
# symbols.Some attributes must precede the tag and some must follow it:
#
# [[prefix-attribute|tag]]
# [[tag|suffix-attribute]]
#
# See https://github.com/gollum/gollum/wiki
#
# Rubular: http://rubular.com/r/7dQnE5CUCH
2018-03-17 18:26:18 +05:30
TAGS_PATTERN = /\[\[(.+?)\]\]/.freeze
# Pattern to match allowed image extensions
2018-03-17 18:26:18 +05:30
ALLOWED_IMAGE_EXTENSIONS = /.+(jpg|png|gif|svg|bmp)\z/i.freeze
2018-11-08 19:23:39 +05:30
# Do not perform linking inside these tags.
IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set
def call
2021-06-02 17:11:27 +05:30
doc.xpath('descendant-or-self::text()').each do |node|
2018-11-08 19:23:39 +05:30
next if has_ancestor?(node, IGNORED_ANCESTOR_TAGS)
2020-03-13 15:44:24 +05:30
next unless node.content =~ TAGS_PATTERN
2018-11-08 19:23:39 +05:30
2020-11-24 15:15:51 +05:30
html = process_tag(Regexp.last_match(1))
2020-03-13 15:44:24 +05:30
node.replace(html) if html && html != node.content
end
doc
end
private
# Process a single tag into its final HTML form.
#
# tag - The String tag contents (the stuff inside the double brackets).
#
# Returns the String HTML version of the tag.
def process_tag(tag)
parts = tag.split('|')
2020-10-24 23:57:45 +05:30
return if parts.empty?
process_image_tag(parts) || process_page_link_tag(parts)
end
# Attempt to process the tag as an image tag.
#
# tag - The String tag contents (the stuff inside the double brackets).
#
# Returns the String HTML if the tag is a valid image tag or nil
# if it is not.
def process_image_tag(parts)
content = parts[0].strip
return unless image?(content)
2021-04-29 21:17:54 +05:30
path =
if url?(content)
content
elsif file = wiki.find_file(content, load_content: false)
file.path
end
if path
2021-04-29 21:17:54 +05:30
content_tag(:img, nil, src: path, class: 'gfm')
end
end
def image?(path)
path =~ ALLOWED_IMAGE_EXTENSIONS
end
def url?(path)
path.start_with?(*%w(http https))
end
# Attempt to process the tag as a page link tag.
#
# tag - The String tag contents (the stuff inside the double brackets).
#
# Returns the String HTML if the tag is a valid page link tag or nil
# if it is not.
def process_page_link_tag(parts)
if parts.size == 1
2016-06-02 11:05:42 +05:30
reference = parts[0].strip
else
name, reference = *parts.compact.map(&:strip)
end
2017-08-17 22:00:37 +05:30
href =
if url?(reference)
reference
else
2020-06-23 00:09:42 +05:30
::File.join(wiki_base_path, reference)
2017-08-17 22:00:37 +05:30
end
2016-06-02 11:05:42 +05:30
content_tag(:a, name || reference, href: href, class: 'gfm')
end
2020-06-23 00:09:42 +05:30
def wiki
context[:wiki]
end
2020-06-23 00:09:42 +05:30
def wiki_base_path
wiki&.wiki_base_path
end
2020-06-23 00:09:42 +05:30
# Ensure that a :wiki key exists in context
#
# Note that while the key might exist, its value could be nil!
def validate
2020-06-23 00:09:42 +05:30
needs :wiki
end
end
end
end