Class: Webby::Filters::Outline

Inherits:
Object
  • Object
show all
Includes:
ERB::Util
Defined in:
lib/webby/filters/outline.rb

Overview

The Outline filter is used to insert outline numbering into HTML heading tags (h1, h2, h3, etc.) and to generate a table of contents based on the heading tags. The table of contents is inserted into the page at the location of the <toc /> tag. If there is no <toc /> tag, then a table of contents will not be created but outline numbering will still take place.

If a table of contents is desired without outline number being inserted into the heading tags, this can be specified in the attibutes of the <toc /> tag itself.

<toc numbering="off" />

This will generate a table of contents, but not insert outline numbering into the heading tags.

The Outline filter will only work on valid HTML or XHTML pages. Therefore it should be used after any markup langauge filters (textile, markdown, etc.).

The following attributes can be specified in the <toc /> tag itself to control how outline numbering is performed by the filter. The attributes can be used in combination with one another.

numbering

If set to "off", this will prevent numbers from being inserted into the page. The default is "on".

<toc numbering="off" />

numbering_start

This is the number to start with when inserting outline numbers into a page. The default is 1.

<toc numbering_start="3" />

toc_style

The style of the Table of Contents list to generated. This will be either "ol" for an ordered list or "ul" for an unordered list. The default is an ordered list.

<toc toc_style="ul" />

toc_range

This limits the numbering to only a subset of the HTML heading tags. The defaul is to number all the heading tags.

<toc toc_range="h1-h3" />

In this example, only the heading tags h1, h2, and h3 will be numbered and included in the table of contents listing.

Example

Generate a table of contents using an unordered list, starting with the number 2, and only numbering heading levels 2, 3, and 4.

<toc numbering_start="2" toc_style="ul" toc_range="h2-h4" />

Constant Summary

Constant Summary

Constants included from ERB::Util

ERB::Util::HTML_ESCAPE

Instance Method Summary (collapse)

Methods included from ERB::Util

#html_escape

Constructor Details

- (Outline) initialize(str)

call-seq:

Outline.new( html )

Creates a new outline filter that will operate on the given html string.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/webby/filters/outline.rb', line 77

def initialize( str )
  @str = str

  @cur_level, @base_level, @cur_depth = nil
  @level = [0] * 6
  @h_rgxp = %r/^h(\d)$/o

  @numbering = true
  @numbering_start = 1

  @toc = []
  @toc_style = 'ol'
  @toc_range = 'h1-h6'
  @list_opening = nil
end

Instance Method Details

- (Object) filter

call-seq:

filter    => html

Process the original html document passed to the filter when it was created. The document will be scanned for heading tags (h1, h2, etc.) and outline numbering and id attributes will be inserted. A table of contents will also be created and inserted into the page if a <toc /> tag is found.

For example, if there is a heading tag

<h3>Get Fuzzy</h3>

somewhere in a page about comic strips, the tag might be altered as such

<h3 id="h2_2_1"><span class="heading-num">2.2.1</span>Get Fuzzy</h3>

The id attribute is used to generate a linke from the table of contents to this particular heading tag. The original text of the tag is used in the table of contents -- "Get Fuzzy" in this example.



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/webby/filters/outline.rb', line 114

def filter
  doc = Hpricot.XML(@str)

  # extract directives from the "toc" tag
  toc_elem = doc.search('toc').first

  unless toc_elem.nil?
    @numbering = toc_elem['numbering'] !~ %r/off/i
    @numbering_start = Integer(toc_elem['numbering_start']) if toc_elem.has_attribute? 'numbering_start'
    @toc_style = toc_elem['toc_style'] if toc_elem.has_attribute? 'toc_style'
    @toc_range = toc_elem['toc_range'] if toc_elem.has_attribute? 'toc_range'
  end

  unless %w[ul ol].include? @toc_style
    raise ArgumentError, "unknown ToC list type '#{@toc_style}'"
  end

  m = %r/h(\d)\s*-\s*h(\d)/i.match @toc_range
  @toc_range = Integer(m[1])..Integer(m[2])
  @list_opening = build_list_opening(toc_elem)

  headers = @toc_range.map {|x| "h#{x}"}
  doc.traverse_element(*headers) do |elem|
    text, id = heading_info(elem)
    add_to_toc(text, id) if @toc_range.include? current_level
  end

  toc_elem.swap(toc) unless toc_elem.nil?
  doc.to_html
end