lib/asciidoctor/section.rb in asciidoctor-0.0.7 vs lib/asciidoctor/section.rb in asciidoctor-0.0.9

- old
+ new

@@ -1,115 +1,85 @@ -# Public: Methods for managing sections of Asciidoc content in a document. +# Public: Methods for managing sections of AsciiDoc content in a document. # The section responds as an Array of content blocks by delegating # block-related methods to its @blocks Array. # # Examples # # section = Asciidoctor::Section.new -# section.name = 'DESCRIPTION' -# section.anchor = 'DESCRIPTION' +# section.title = 'Section 1' +# section.id = 'sect1' # # section.size # => 0 # -# section.section_id -# => "_description" +# section.id +# => "sect1" # # section << new_block # section.size # => 1 -class Asciidoctor::Section - # Public: Get/Set the Integer section level. - attr_accessor :level +class Asciidoctor::Section < Asciidoctor::AbstractBlock - # Public: Set the String section name. - attr_writer :name + # Public: Get/Set the Integer index of this section within the parent block + attr_accessor :index - # Public: Get/Set the String section caption. - attr_accessor :caption - - # Public: Get/Set the String section anchor name. - attr_accessor :anchor - alias :id :anchor - - # Public: Get the Hash of attributes for this block - attr_accessor :attributes - - # Public: Get the Array of section blocks. - attr_reader :blocks - # Public: Initialize an Asciidoctor::Section object. # # parent - The parent Asciidoc Object. - def initialize(parent) - @parent = parent - @attributes = {} - @blocks = [] + def initialize(parent = nil, level = nil) + super(parent, :section) + if level.nil? && !parent.nil? + @level = parent.level + 1 + end + @index = 0 end - # Public: Get the String section name with intrinsics converted + # Public: The name of this section, an alias of the section title + alias :name :title + + # Public: Generate a String id for this section. # - # Examples + # The generated id is prefixed with value of the 'idprefix' attribute, which + # is an underscore by default. # - # section.name = "git-web{litdd}browse(1) Manual Page" - # section.name - # => "git-web--browse(1) Manual Page" + # Section id synthesis can be disabled by undefining the 'sectids' attribute. # - # Returns the String section name - def name - @name && - @name.gsub(/(^|[^\\])\{(\w[\w\-]+\w)\}/) { $1 + Asciidoctor::INTRINSICS[$2] }. - gsub( /`([^`]+)`/, '<tt>\1</tt>' ) - end - - # Public: Get the String section id prefixed with value of idprefix attribute, otherwise an underscore + # If the generated id is already in use in the document, a count is appended + # until a unique id is found. # - # Section ID synthesis can be disabled by undefining the sectids attribute. - # # Examples # # section = Section.new(parent) - # section.name = "Foo" - # section.section_id + # section.title = "Foo" + # section.generate_id # => "_foo" - def section_id - if self.document.attributes.has_key? 'sectids' - self.document.attributes.fetch('idprefix', '_') + "#{name && name.downcase.gsub(/\W+/,'_').gsub(/_+$/, '')}".tr_s('_', '_') + # + # another_section = Section.new(parent) + # another_section.title = "Foo" + # another_section.generate_id + # => "_foo_1" + def generate_id + if @document.attr?('sectids') + base_id = @document.attr('idprefix', '_') + title.downcase.gsub(/&#[0-9]+;/, '_'). + gsub(/\W+/, '_').tr_s('_', '_').gsub(/^_?(.*?)_?$/, '\1') + gen_id = base_id + cnt = 2 + while @document.references[:ids].has_key? gen_id + gen_id = "#{base_id}_#{cnt}" + cnt += 1 + end + @document.references[:ids][gen_id] = title + gen_id else nil end end - # Public: Get the Asciidoctor::Document instance to which this Block belongs - def document - @parent.is_a?(Asciidoctor::Document) ? @parent : @parent.document - end - - def attr(name, default = nil) - default.nil? ? @attributes.fetch(name.to_s, self.document.attr(name)) : - @attributes.fetch(name.to_s, self.document.attr(name, default)) - end - - def attr?(name) - @attributes.has_key?(name.to_s) || self.document.attr?(name) - end - - def update_attributes(attributes) - @attributes.update(attributes) - end - - # Public: Get the Asciidoctor::Renderer instance being used for the ancestor - # Asciidoctor::Document instance. - def renderer - Asciidoctor.debug "Section#renderer: Looking for my renderer up in #{@parent}" - @parent.renderer - end - # Public: Get the rendered String content for this Section and all its child # Blocks. def render - Asciidoctor.debug "Now rendering section for #{self}" + Asciidoctor.debug { "Now rendering section for #{self}" } renderer.render('section', self) end # Public: Get the String section content by aggregating rendered section blocks. # @@ -120,131 +90,72 @@ # section << 'bar' # section << 'baz' # section.content # "<div class=\"paragraph\"><p>foo</p></div>\n<div class=\"paragraph\"><p>bar</p></div>\n<div class=\"paragraph\"><p>baz</p></div>" def content - @blocks.map do |block| - Asciidoctor.debug "Begin rendering block #{block.is_a?(Asciidoctor::Section) ? block.name : 'n/a'} #{block} (context: #{block.is_a?(Asciidoctor::Block) ? block.context : 'n/a' })" - poo = block.render - Asciidoctor.debug "===> Done rendering block #{block.is_a?(Asciidoctor::Section) ? block.name : 'n/a'} #{block} (context: #{block.is_a?(Asciidoctor::Block) ? block.context : 'n/a' })" - poo - end.join + @blocks.map {|b| b.render }.join end - # Public: The title of this section, an alias of the section name - def title - @name - end - - # Public: Get the Integer number of blocks in the section. + # Public: Get the section number for the current Section # - # Examples + # The section number is a unique, dot separated String + # where each entry represents one level of nesting and + # the value of each entry is the 1-based index of + # the Section amongst its sibling Sections # - # section = Section.new + # delimiter - the delimiter to separate the number for each level + # append - the String to append at the end of the section number + # or Boolean to indicate the delimiter should not be + # appended to the final level + # (default: nil) # - # section.size - # => 0 + # Examples # - # section << 'foo' - # section << 'bar' - # section.size - # => 2 - def size - @blocks.size - end - - # Public: Get the element at i in the array of section blocks. + # sect1 = Section.new(document) + # sect1.level = 1 + # sect1_1 = Section.new(sect1) + # sect1_1.level = 2 + # sect1_2 = Section.new(sect1) + # sect1_2.level = 2 + # sect1 << sect1_1 + # sect1 << sect1_2 + # sect1_1_1 = Section.new(sect1_1) + # sect1_1_1.level = 3 + # sect1_1 << sect1_1_1 # - # i - The Integer array index number. + # sect1.sectnum + # # => 1. # - # section = Section.new + # sect1_1.sectnum + # # => 1.1. # - # section << 'foo' - # section << 'bar' - # section[1] - # => "bar" - def [](i) - @blocks[i] - end - - # Public: Delete the element at i in the array of section blocks, - # returning that element or nil if i is out of range. + # sect1_2.sectnum + # # => 1.2. # - # i - The Integer array index number. + # sect1_1_1.sectnum + # # => 1.1.1. # - # section = Section.new + # sect1_1_1.sectnum(',', false) + # # => 1,1,1 # - # section << 'foo' - # section << 'bar' - # section.delete_at(1) - # => "bar" - # - # section.blocks - # => ["foo"] - def delete_at(i) - @blocks.delete_at(i) + # Returns the section number as a String + def sectnum(delimiter = '.', append = nil) + append ||= (append == false ? '' : delimiter) + if !@level.nil? && @level > 1 && @parent.is_a?(::Asciidoctor::Section) + "#{@parent.sectnum(delimiter)}#{@index + 1}#{append}" + else + "#{@index + 1}#{append}" + end end - # Public: Append a content block to this section's list of blocks. - # - # block - The new section block. - # - # section = Section.new - # - # section << 'foo' - # section << 'bar' - # section.blocks - # => ["foo", "bar"] - def <<(block) - @blocks << block - end - - # Public: Clear this Section's list of blocks. - # - # section = Section.new - # - # section << 'foo' - # section << 'bar' - # section.blocks - # => ["foo", "bar"] - # section.clear_blocks - # section.blocks - # => [] - def clear_blocks - @blocks = [] - end - - # Public: Insert a content block at the specified index in this section's - # list of blocks. - # - # i - The Integer array index number. - # val = The content block to insert. - # - # section = Section.new - # - # section << 'foo' - # section << 'baz' - # section.insert(1, 'bar') - # section.blocks - # ["foo", "bar", "baz"] - def insert(i, block) - @blocks.insert(i, block) - end - - # Public: Get the Integer index number of the first content block element - # for which the provided block returns true. Returns nil if no match is - # found. - # - # block - A block that can be used to determine whether a supplied element - # is a match. - # - # section = Section.new - # - # section << 'foo' - # section << 'bar' - # section << 'baz' - # section.index{|el| el =~ /^ba/} - # => 1 - def index(&block) - @blocks.index(&block) + def to_s + if @title + if @level && @index + %[#{super.to_s} - #{sectnum} #@title [blocks:#{@blocks.size}]] + else + %[#{super.to_s} - #@title [blocks:#{@blocks.size}]] + end + else + super.to_s + end end end