lib/nanoc/toolbox/filters/add_sections.rb
module Nanoc::Toolbox::Filters
# This filters adds section div’s based on headers. For example, this:
# @example
# h1
# p
# foo
# p
# h2
# p
# p
# h2
# p
# p
# h1
# p
#
# section
# h1
# p
# foo
# p
# section
# h2
# p
# p
# section
# h2
# p
# p
# section
# p
# @author Denis Defreyne <denis.defreyne@stoneship.org>
class AddSections < Nanoc::Filter
identifiers :add_sections
def run(content, arguments={})
require 'nokogiri'
# Parse
doc = Nokogiri::HTML.fragment(content)
# Add sections for all headers
(1..6).each do |level|
# For each header on this level
doc.css("h#{level}").each do |header|
# Get all siblings
siblings = header.parent.children
# Remove previous siblings
siblings_after = []
should_include = false
siblings.each do |sibling|
if sibling == header
should_include = true
elsif should_include
siblings_after << sibling
end
end
# Remove next siblings that should not be part of this section
siblings_in_between = []
siblings_after.each do |sibling|
if sibling.name =~ /^h(\d)/ && $1.to_i <= level
break
else
siblings_in_between << sibling
end
end
# Create section
section = Nokogiri::XML::Node.new('div', doc)
section['class'] = 'section'
section['id'] = header.content.downcase.gsub(/\W+/, '-').gsub(/^-|-$/, '')
header.add_previous_sibling(section)
# Move children into section
header.unlink
section.add_child(header)
siblings_in_between.each do |sibling|
sibling.unlink
section.add_child(sibling)
end
end
end
# Done
doc.to_s
end
end
end