Created
January 23, 2014 15:08
-
-
Save jonmagic/8580057 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Gollum | |
module HTML | |
# Extract all tags into the tagmap and replace with placeholders. | |
# | |
# Returns the placeholder'd String data. | |
class ExtractWikiLinksFilter < ::HTML::Pipeline::TextFilter | |
def call | |
result[:wiki_links] = {} | |
return @text if context[:format] == :asciidoc | |
@text.gsub!(/(.?)\[\[(.+?)\]\]([^\[]?)/m) do | |
if $1 == "'" && $3 != "'" | |
"[[#{$2}]]#{$3}" | |
elsif $2.include?('][') | |
if $2[0..4] == 'file:' | |
pre = $1 | |
post = $3 | |
parts = $2.split('][') | |
parts[0][0..4] = "" | |
link = "#{parts[1]}|#{parts[0].sub(/\.org/,'')}" | |
id = Digest::SHA1.hexdigest(link) | |
result[:wiki_links][id] = link | |
"#{pre}#{id}#{post}" | |
else | |
$& | |
end | |
else | |
id = Digest::SHA1.hexdigest($2) | |
result[:wiki_links][id] = $2 | |
"#{$1}#{id}#{$3}" | |
end | |
end | |
@text | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Gollum | |
module HTML | |
# HTML::Pipeline filter for processing contents with GitHub::Markup | |
class MarkupFilter < ::HTML::Pipeline::TextFilter | |
def call | |
GitHub::Markup.render(context[:name], @text) | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Gollum | |
module HTML | |
class ProcessWikiLinksFilter < ::HTML::Pipeline::Filter | |
# Process all tags from the tagmap and replace the placeholders with the | |
# final markup. | |
def call | |
return doc if !result[:wiki_links] || result[:wiki_links].empty? | |
link_pattern = /(#{result[:wiki_links].keys.map { |name| Regexp.escape(name) }.join('|')})/ | |
doc.search('text()').each do |node| | |
content = node.to_html | |
# html = emoji_image_filter(content) | |
content.gsub!(link_pattern) do |id| | |
if has_ancestor?(node, %w(pre code)) | |
# Replace original content if inside of a code block | |
"[[#{result[:wiki_links][id]}]]" | |
else | |
process_tag(result[:wiki_links][id]) | |
end | |
end | |
# next if html == content | |
node.replace(content) | |
end | |
doc | |
end | |
def wiki | |
context[:wiki] | |
end | |
# 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) | |
if html = process_image_tag(tag) | |
html | |
elsif html = process_file_link_tag(tag) | |
html | |
else | |
process_page_link_tag(tag) | |
end | |
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(tag) | |
parts = tag.split('|') | |
return if parts.size.zero? | |
name = parts[0].strip | |
path = if file = find_file(name) | |
::File.join wiki.base_path, file.path | |
elsif name =~ /^https?:\/\/.+(jpg|png|gif|svg|bmp)$/i | |
name | |
end | |
if path | |
opts = parse_image_tag_options(tag) | |
containered = false | |
classes = [] # applied to whatever the outermost container is | |
attrs = [] # applied to the image | |
align = opts['align'] | |
if opts['float'] | |
containered = true | |
align ||= 'left' | |
if %w{left right}.include?(align) | |
classes << "float-#{align}" | |
end | |
elsif %w{top texttop middle absmiddle bottom absbottom baseline}.include?(align) | |
attrs << %{align="#{align}"} | |
elsif align | |
if %w{left center right}.include?(align) | |
containered = true | |
classes << "align-#{align}" | |
end | |
end | |
if width = opts['width'] | |
if width =~ /^\d+(\.\d+)?(em|px)$/ | |
attrs << %{width="#{width}"} | |
end | |
end | |
if height = opts['height'] | |
if height =~ /^\d+(\.\d+)?(em|px)$/ | |
attrs << %{height="#{height}"} | |
end | |
end | |
if alt = opts['alt'] | |
attrs << %{alt="#{alt}"} | |
end | |
attr_string = attrs.size > 0 ? attrs.join(' ') + ' ' : '' | |
if opts['frame'] || containered | |
classes << 'frame' if opts['frame'] | |
%{<span class="#{classes.join(' ')}">} + | |
%{<span>} + | |
%{<img src="#{path}" #{attr_string}/>} + | |
(alt ? %{<span>#{alt}</span>} : '') + | |
%{</span>} + | |
%{</span>} | |
else | |
%{<img src="#{path}" #{attr_string}/>} | |
end | |
end | |
end | |
# Parse any options present on the image tag and extract them into a | |
# Hash of option names and values. | |
# | |
# tag - The String tag contents (the stuff inside the double brackets). | |
# | |
# Returns the options Hash: | |
# key - The String option name. | |
# val - The String option value or true if it is a binary option. | |
def parse_image_tag_options(tag) | |
tag.split('|')[1..-1].inject({}) do |memo, attr| | |
parts = attr.split('=').map { |x| x.strip } | |
memo[parts[0]] = (parts.size == 1 ? true : parts[1]) | |
memo | |
end | |
end | |
# Attempt to process the tag as a file link tag. | |
# | |
# tag - The String tag contents (the stuff inside the double | |
# brackets). | |
# | |
# Returns the String HTML if the tag is a valid file link tag or nil | |
# if it is not. | |
def process_file_link_tag(tag) | |
parts = tag.split('|') | |
return if parts.size.zero? | |
name = parts[0].strip | |
path = parts[1] && parts[1].strip | |
path = if path && file = find_file(path) | |
::File.join wiki.base_path, file.path | |
elsif path =~ %r{^https?://} | |
path | |
else | |
nil | |
end | |
if name && path && file | |
%{<a href="#{::File.join wiki.base_path, file.path}">#{name}</a>} | |
elsif name && path | |
%{<a href="#{path}">#{name}</a>} | |
else | |
nil | |
end | |
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(tag) | |
parts = tag.split('|') | |
parts.reverse! if context[:format] == :mediawiki | |
name, page_name = *parts.compact.map(&:strip) | |
cname = wiki.page_class.cname(page_name || name) | |
if name =~ %r{^https?://} && page_name.nil? | |
%{<a href="#{name}">#{name}</a>} | |
else | |
presence = "absent" | |
link_name = cname | |
page, extra = find_page_from_name(cname) | |
if page | |
link_name = wiki.page_class.cname(page.name) | |
presence = "present" | |
end | |
link = ::File.join(wiki.base_path, CGI.escape(link_name)) | |
%{<a class="internal #{presence}" href="#{link}#{extra}">#{name}</a>} | |
end | |
end | |
# Find the given file in the repo. | |
# | |
# name - The String absolute or relative path of the file. | |
# | |
# Returns the Gollum::File or nil if none was found. | |
def find_file(name) | |
if name =~ /^\// | |
wiki.file(name[1..-1], context[:version]) | |
else | |
path = context[:dir] == '.' ? name : ::File.join(context[:dir], name) | |
wiki.file(path, context[:version]) | |
end | |
end | |
# Find a page from a given cname. If the page has an anchor (#) and has | |
# no match, strip the anchor and try again. | |
# | |
# cname - The String canonical page name. | |
# | |
# Returns a Gollum::Page instance if a page is found, or an Array of | |
# [Gollum::Page, String extra] if a page without the extra anchor data | |
# is found. | |
def find_page_from_name(cname) | |
if page = wiki.page(cname) | |
return page | |
end | |
if pos = cname.index('#') | |
[wiki.page(cname[0...pos]), cname[pos..-1]] | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment