Class: HTML::Pipeline::TableOfContentsFilter

Inherits:
Filter
  • Object
show all
Defined in:
lib/html/pipeline/toc_filter.rb

Overview

HTML filter that adds an ‘id’ attribute to all headers in a document, so they can be accessed from a table of contents.

Generates the Table of Contents, with links to each header.

Examples

TocPipeline =
  HTML::Pipeline.new [
    HTML::Pipeline::TableOfContentsFilter
  ]
# => #<HTML::Pipeline:0x007fc13c4528d8...>
orig = %(<h1>Ice cube</h1><p>is not for the pop chart</p>)
# => "<h1>Ice cube</h1><p>is not for the pop chart</p>"
result = {}
# => {}
TocPipeline.call(orig, {}, result)
# => {:toc=> ...}
result[:toc]
# => "<ul class=\"section-nav\">\n<li><a href=\"#ice-cube\">...</li><ul>"
result[:output].to_s
# => "<h1>\n<a id=\"ice-cube\" class=\"anchor\" href=\"#ice-cube\">..."

Constant Summary collapse

PUNCTUATION_REGEXP =
RUBY_VERSION > '1.9' ? /[^\p{Word}\- ]/u : /[^\w\- ]/

Instance Attribute Summary

Attributes inherited from Filter

#context, #result

Instance Method Summary collapse

Methods inherited from Filter

#base_url, call, #current_user, #doc, #has_ancestor?, #html, #initialize, #needs, #parse_html, #repository, to_document, to_html, #validate

Constructor Details

This class inherits a constructor from HTML::Pipeline::Filter

Instance Method Details

#anchor_iconObject

The icon that will be placed next to an anchored rendered markdown header



33
34
35
# File 'lib/html/pipeline/toc_filter.rb', line 33

def anchor_icon
  context[:anchor_icon] || '<span aria-hidden="true" class="octicon octicon-link"></span>'
end

#ascii_downcase(str) ⇒ Object



59
60
61
# File 'lib/html/pipeline/toc_filter.rb', line 59

def ascii_downcase(str)
  str.downcase(:ascii)
end

#callObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/html/pipeline/toc_filter.rb', line 37

def call
  result[:toc] = String.new('')

  headers = Hash.new(0)
  doc.css('h1, h2, h3, h4, h5, h6').each do |node|
    text = node.text
    id = ascii_downcase(text)
    id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation
    id.tr!(' ', '-') # replace spaces with dash

    uniq = headers[id] > 0 ? "-#{headers[id]}" : ''
    headers[id] += 1
    if header_content = node.children.first
      result[:toc] << %(<li><a href="##{id}#{uniq}">#{EscapeUtils.escape_html(text)}</a></li>\n)
      header_content.add_previous_sibling(%(<a id="#{id}#{uniq}" class="anchor" href="##{id}#{uniq}" aria-hidden="true">#{anchor_icon}</a>))
    end
  end
  result[:toc] = %(<ul class="section-nav">\n#{result[:toc]}</ul>) unless result[:toc].empty?
  doc
end