class Gollum::Filter::Tags

Render all tags (things in double-square-brackets). This one's a biggie.

Constants

INCLUDE_TAG
PREFORMATTED_TAGS

Public Instance Methods

extract(data) click to toggle source

Extract all tags into the tagmap and replace with placeholders.

# File lib/gollum-lib/filter/tags.rb, line 6
def extract(data)
  data.gsub!(/(.?)\[\[(.+?)\]\]([^\[]?)/) do
    if Regexp.last_match[1] == "'" && Regexp.last_match[3] != "'"
      "[[#{Regexp.last_match[2]}]]#{Regexp.last_match[3]}"
    elsif Regexp.last_match[2].include?('][')
      if Regexp.last_match[2][0..4] == 'file:'
        pre            = Regexp.last_match[1]
        post           = Regexp.last_match[3]
        parts          = Regexp.last_match[2].split('][')
        parts[0][0..4] = ""
        link           = "#{parts[1]}|#{parts[0].sub(/\.org/, '')}"
        id             = register_tag(link)
        "#{pre}#{id}#{post}"
      else
        Regexp.last_match[0]
      end
    else
      id = register_tag(Regexp.last_match[2])
      "#{Regexp.last_match[1]}#{id}#{Regexp.last_match[3]}"
    end
  end
  data
end
process(rendered_data) click to toggle source

Process all text nodes from the doc and replace the placeholders with the final markup.

# File lib/gollum-lib/filter/tags.rb, line 32
def process(rendered_data)
  doc  = Nokogiri::HTML::DocumentFragment.parse(rendered_data)
  doc.traverse do |node|
    if node.text? then
      content = node.content
      content.gsub!(%r{#{open_pattern}[a-f0-9]+#{close_pattern}}) do |id|
        if (tag = @map[id]) then
          if is_preformatted?(node) then
            "[[#{tag}]]"
          else
            process_tag(tag).gsub('%2f', '/')
          end
        end
      end
      node.replace(content) if content != node.content
    end
  end

  doc.to_html
end

Private Instance Methods

find_page_or_file_from_path(path, kind = :page) click to toggle source

Find a page from a given path

path - The String path to search for.

Returns a Gollum::Page instance if a page is found, or nil otherwise

# File lib/gollum-lib/filter/tags.rb, line 243
def find_page_or_file_from_path(path, kind = :page)
  if Pathname.new(path).relative?
    result = @markup.wiki.send(kind, ::File.join(@markup.dir, path))
    if result.nil? && @markup.wiki.global_tag_lookup # 4.x link compatibility option. Slow!
      result = @markup.wiki.send(kind, path, nil, true)
    end
    result
  else
    @markup.wiki.send(kind, path)
  end
end
generate_href_for_path(path, extra = nil) click to toggle source

Generate a normalized href for a path, taking into consideration the wiki's path settings.

path - The String path to generate an href for. extra - The String anchor to add to the href. Optional.

Returns a String href.

# File lib/gollum-lib/filter/tags.rb, line 274
def generate_href_for_path(path, extra = nil)
  return extra if !path && extra # Internal anchor link
  "#{trim_leading_slashes(::File.join(@markup.wiki.base_path, path))}#{extra}"
end
generate_image(path, options = nil) click to toggle source

Generate an HTML image tag.

path - The String path (href) of the image. options - The Hash of parsed image options.

Returns a String HTML img tag.

# File lib/gollum-lib/filter/tags.rb, line 307
def generate_image(path, options = nil)
  classes, attrs, containered = generate_image_attributes(options)
  attrs[:alt] = 'Image not found' if path.empty?
  attr_string = attrs.map {|key, value| "#{key}=\"#{value}\""}.join(' ')

  if containered
    %{<span class="d-flex #{classes[:container].join(' ')}">} +
        %{<span class="#{classes[:nested].join(' ')}">} +
        %{<img src="#{path}" #{attr_string}/>} +
        (options[:frame] && attrs[:alt] ? %{<span class="clearfix">#{attrs[:alt]}</span>} : '') +
        %{</span>} +
        %{</span>}
  else
    %{<img src="#{path}" #{attr_string}/>}
  end
end
generate_image_attributes(options) click to toggle source

Helper method to generate the styling attributes and elements for an image tag.

options - The Hash of parsed image options.

Returns a Hash containing CSS class Arrays, a Hash of CSS attributes, and a Boolean indicating whether or not the image is containered.

# File lib/gollum-lib/filter/tags.rb, line 329
def generate_image_attributes(options)
  containered = false
  classes = {container: [], nested: []} # applied to the container(s)
  attrs   = {} # applied to the image

  align = options[:align]
  if options[:float]
    containered = true
    align = 'left' unless align == 'right'
    classes[:container] << "float-#{align} pb-4"
  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
      text_align = "text-#{align}"
      align = 'end' if align == 'right'
      classes[:container] << "flex-justify-#{align} #{text_align}"
    end
  end

  if options[:frame] 
    containered = true
    classes[:nested] << 'border p-4'
  end

  attrs[:alt]    = options[:alt]    if options[:alt]
  attrs[:width]  = options[:width]  if options[:width]  =~ /^\d+(\.\d+)?(em|px)$/
  attrs[:height] = options[:height] if options[:height] =~ /^\d+(\.\d+)?(em|px)$/

  return classes, attrs, containered
end
is_preformatted?(node) click to toggle source
# File lib/gollum-lib/filter/tags.rb, line 64
def is_preformatted?(node)
  node && (PREFORMATTED_TAGS.include?(node.name) ||
      node.ancestors.any? { |a| PREFORMATTED_TAGS.include?(a.name) })
end
parse_image_tag_options(options) click to toggle source

Parse any options present on the image tag (comma separated) and extract them into a Hash of option names and values.

options - The String image options (the stuff in the after '|').

Returns the options Hash:

key - The String option name.
val - The String option value or true if it is a binary option.
# File lib/gollum-lib/filter/tags.rb, line 163
def parse_image_tag_options(options)
  return {} if options.nil?
  options.split(',').inject({}) do |memo, attr|
    parts                 = attr.split('=').map { |x| x.strip }
    memo[parts[0].to_sym] = (parts.size == 1 ? true : parts[1])
    memo
  end
end
parse_tag_parts(tag) click to toggle source

Parse the tag (stuff between the double brackets) into a link part and additional information (a pretty name, description, or image options).

tag - The String tag contents (the stuff inside the double

brackets).

Returns an Array of the form [link_part, extra], where both elements are Strings and the second element may be nil.

# File lib/gollum-lib/filter/tags.rb, line 105
def parse_tag_parts(tag)
  parts = tag.split('|').map(&:strip)[0..1]
  parts.reverse! if @markup.reverse_links?
  if parts[1]
    return parts[1], parts[0]
  else
    return parts[0], nil
  end
end
process_image_tag(path, options = nil) click to toggle source

Attempt to process the tag as an image tag.

path - The String path to the image. options - The String of options for the image (the stuff after the '|'). Optional.

Returns the String HTML if the tag is a valid image tag or nil

if it is not.
# File lib/gollum-lib/filter/tags.rb, line 144
def process_image_tag(path, options = nil)
  opts = parse_image_tag_options(options)
  if path =~ /^https?:\/\/.+$/i
    generate_image(path, opts)
  elsif file = find_page_or_file_from_path(path, :file)
    generate_image(generate_href_for_path(file.url_path), opts)
  else
    generate_image('', opts)
  end
end
process_include_tag(tag) click to toggle source

Attempt to process the tag as an include tag

tag - The String tag contents (the stuff inside the double brackets).

Returns the String HTML if the tag includes a valid page or an error message if the page could not be found.

# File lib/gollum-lib/filter/tags.rb, line 120
def process_include_tag(tag)
  len = INCLUDE_TAG.length
  return html_error('Cannot process include directive: no page name given') if tag.length <= len
  page_name          = tag[len..-1]
  resolved_page_name = ::File.join(@markup.dir, page_name)
  if @markup.include_levels > 0
    page = find_page_or_file_from_path(resolved_page_name)
    if page
      page.formatted_data(@markup.encoding, @markup.include_levels-1)
    else
      html_error("Cannot include #{process_page_link_tag(resolved_page_name)} - does not exist yet")
    end
  else
    html_error("Too many levels of included pages, will not include #{process_page_link_tag(resolved_page_name)}")
  end
end
process_tag(tag) click to toggle source

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.

# File lib/gollum-lib/filter/tags.rb, line 75
def process_tag(tag)
  link_part, extra = parse_tag_parts(tag)
  return generate_link('', nil, nil, :page_absent) if link_part.nil?
  img_args = extra ? [extra, link_part] : [link_part]
  mime = MIME::Types.type_for(::File.extname(img_args.first.to_s)).first
  result = if tag =~ /^_TOC_/
    %{[[#{tag}]]}
  elsif link_part =~ /^_$/
    %{<div class="clearfloats"></div>}
  elsif link_part =~ /^#{INCLUDE_TAG}/
    process_include_tag(link_part)
  elsif mime && mime.content_type =~ /^image/
    process_image_tag(*img_args)
  elsif external = process_external_link_tag(link_part, extra)
    external
  end
  result ? result : process_link_tag(link_part, extra)
end
register_tag(tag) click to toggle source
# File lib/gollum-lib/filter/tags.rb, line 58
def register_tag(tag)
  id       = "#{open_pattern}#{Digest::SHA1.hexdigest(tag)}#{close_pattern}"
  @map[id] = tag
  id
end