lib/asciidoctor/abstract_block.rb in asciidoctor-1.5.8 vs lib/asciidoctor/abstract_block.rb in asciidoctor-2.0.0.rc.1
- old
+ new
@@ -1,53 +1,59 @@
-# encoding: UTF-8
+# frozen_string_literal: true
module Asciidoctor
class AbstractBlock < AbstractNode
- # Public: Get the Array of Asciidoctor::AbstractBlock sub-blocks for this block
+ # Public: Get the Array of {AbstractBlock} child blocks for this block. Only applies if content model is :compound.
attr_reader :blocks
- # Public: Set the caption for this block
+ # Public: Set the caption for this block.
attr_writer :caption
- # Public: The types of content that this block can accomodate
+ # Public: Describes the type of content this block accepts and how it should be converted. Acceptable values are:
+ # * :compound - this block contains other blocks
+ # * :simple - this block holds a paragraph of prose that receives normal substitutions
+ # * :verbatim - this block holds verbatim text (displayed "as is") that receives verbatim substitutions
+ # * :raw - this block holds unprocessed content passed directly to the output with no sustitutions applied
+ # * :empty - this block has no content
attr_accessor :content_model
- # Public: Set the Integer level of this Section or the Section level in which this Block resides
+ # Public: Set the Integer level of this {Section} or the level of the Section to which this {AbstractBlock} belongs.
attr_accessor :level
- # Public: Get/Set the numeral of this block (if section, relative to parent, otherwise absolute)
- # Only assigned to section if automatic section numbering is enabled
- # Only assigned to formal block (block with title) if corresponding caption attribute is present
+ # Public: Get/Set the numeral of this block (if section, relative to parent, otherwise absolute).
+ # Only assigned to section if automatic section numbering is enabled.
+ # Only assigned to formal block (block with title) if corresponding caption attribute is present.
attr_accessor :numeral
- # Deprecated: Legacy property to get/set the numeral of this block
+ # Deprecated: Legacy property to get/set the numeral of this block.
alias number numeral
alias number= numeral=
- # Public: Gets/Sets the location in the AsciiDoc source where this block begins
+ # Public: Gets/Sets the location in the AsciiDoc source where this block begins.
attr_accessor :source_location
# Public: Get/Set the String style (block type qualifier) for this block.
attr_accessor :style
- # Public: Substitutions to be applied to content in this block
+ # Public: Substitutions to be applied to content in this block.
attr_reader :subs
+ # Internal: Set the default subs applied to this block; used during block creation
+ attr_writer :default_subs
+
def initialize parent, context, opts = {}
super
@content_model = :compound
@blocks = []
@subs = []
- @id = @title = @title_converted = @caption = @numeral = @style = @default_subs = @source_location = nil
- if context == :document
- @level = 0
- elsif parent && context != :section
- @level = parent.level
+ @id = @title = @caption = @numeral = @style = @default_subs = @source_location = nil
+ case context
+ when :document, :section
+ @level = @next_section_index = 0
+ @next_section_ordinal = 1
else
- @level = nil
+ @level = AbstractBlock === parent ? parent.level : nil
end
- @next_section_index = 0
- @next_section_ordinal = 1
end
def block?
true
end
@@ -99,14 +105,14 @@
#
# block - The new child block.
#
# Examples
#
- # block = Block.new(parent, :preamble, :content_model => :compound)
+ # block = Block.new(parent, :preamble, content_model: :compound)
#
- # block << Block.new(block, :paragraph, :source => 'p1')
- # block << Block.new(block, :paragraph, :source => 'p2')
+ # block << Block.new(block, :paragraph, source: 'p1')
+ # block << Block.new(block, :paragraph, source: 'p2')
# block.blocks?
# # => true
# block.blocks.size
# # => 2
#
@@ -168,60 +174,10 @@
result
end
alias query find_by
- # Internal: Performs the work for find_by, but does not handle the StopIteration exception.
- def find_by_internal selector = {}, result = [], &block
- if ((any_context = !(context_selector = selector[:context])) || context_selector == @context) &&
- (!(style_selector = selector[:style]) || style_selector == @style) &&
- (!(role_selector = selector[:role]) || (has_role? role_selector)) &&
- (!(id_selector = selector[:id]) || id_selector == @id)
- if id_selector
- result.replace block_given? ? ((yield self) ? [self] : []) : [self]
- raise ::StopIteration
- elsif block_given?
- if (verdict = yield self)
- case verdict
- when :skip_children
- result << self
- return result
- when :skip
- return result
- else
- result << self
- end
- end
- else
- result << self
- end
- end
-
- # process document header as a section if present
- if @context == :document && (any_context || context_selector == :section) && header?
- @header.find_by_internal selector, result, &block
- end
-
- unless context_selector == :document # optimization
- # yuck, dlist is a special case
- if @context == :dlist
- if any_context || context_selector != :section # optimization
- @blocks.flatten.each do |li|
- # NOTE the list item of a dlist can be nil, so we have to check
- li.find_by_internal selector, result, &block if li
- end
- end
- elsif
- @blocks.each do |b|
- next if (context_selector == :section && b.context != :section) # optimization
- b.find_by_internal selector, result, &block
- end
- end
- end
- result
- end
-
# Move to the next adjacent block in document order. If the current block is the last
# item in a list, this method will return the following sibling of the list block.
def next_adjacent_block
(sib = (p = parent).blocks[(p.blocks.find_index self) + 1]) ? sib : p.next_adjacent_block unless @context == :document
end
@@ -232,16 +188,16 @@
#
# Examples
#
# doc << (sect1 = Section.new doc, 1)
# sect1.title = 'Section 1'
- # para1 = Block.new sect1, :paragraph, :source => 'Paragraph 1'
- # para2 = Block.new sect1, :paragraph, :source => 'Paragraph 2'
+ # para1 = Block.new sect1, :paragraph, source: 'Paragraph 1'
+ # para2 = Block.new sect1, :paragraph, source: 'Paragraph 2'
# sect1 << para1 << para2
# sect1 << (sect1_1 = Section.new sect1, 2)
# sect1_1.title = 'Section 1.1'
- # sect1_1 << (Block.new sect1_1, :paragraph, :source => 'Paragraph 3')
+ # sect1_1 << (Block.new sect1_1, :paragraph, source: 'Paragraph 3')
# sect1.blocks?
# # => true
# sect1.blocks.size
# # => 3
# sect1.sections.size
@@ -316,11 +272,11 @@
# => "Foo 3^ # :: Bar(1)"
#
# Returns the converted String title for this Block, or nil if the source title is falsy
def title
# prevent substitutions from being applied to title multiple times
- @title_converted ? @converted_title : (@converted_title = (@title_converted = true) && @title && (apply_title_subs @title))
+ @converted_title ||= @title && (apply_title_subs @title)
end
# Public: A convenience method that checks whether the title of this block is defined.
#
# Returns a [Boolean] indicating whether this block has a title.
@@ -330,11 +286,12 @@
# Public: Set the String block title.
#
# Returns the new String title assigned to this Block
def title= val
- @title, @title_converted = val, nil
+ @converted_title = nil
+ @title = val
end
# Public: A convenience method that checks whether the specified
# substitution is enabled for this block.
#
@@ -377,11 +334,11 @@
val
# NOTE xrefstyle only applies to blocks with a title and a caption or number
elsif xrefstyle && @title && @caption
case xrefstyle
when 'full'
- quoted_title = sprintf sub_quotes(@document.compat_mode ? %q(``%s'') : '"`%s`"'), title
+ quoted_title = sub_placeholder (sub_quotes @document.compat_mode ? %q(``%s'') : '"`%s`"'), title
if @numeral && (prefix = @document.attributes[@context == :image ? 'figure-caption' : %(#{@context}-caption)])
%(#{prefix} #{@numeral}, #{quoted_title})
else
%(#{@caption.chomp '. '}, #{quoted_title})
end
@@ -475,37 +432,71 @@
block.reindex_sections
end
end
end
-# stage the Enumerable mixin until we're sure we've got it right
-=begin
- include ::Enumerable
-
- # Public: Yield the block on this block node and all its descendant
- # block node children to satisfy the Enumerable contract.
- #
- # Returns nothing
- def each &block
- # yucky, dlist is a special case
- if @context == :dlist
- @blocks.flatten.each &block
+ # Internal: Performs the work for find_by, but does not handle the StopIteration exception.
+ protected def find_by_internal selector = {}, result = [], &block
+ if ((any_context = (context_selector = selector[:context]) ? nil : true) || context_selector == @context) &&
+ (!(style_selector = selector[:style]) || style_selector == @style) &&
+ (!(role_selector = selector[:role]) || (has_role? role_selector)) &&
+ (!(id_selector = selector[:id]) || id_selector == @id)
+ if id_selector
+ block_given? && !(yield self) ? result.clear : (result.replace [self])
+ raise ::StopIteration
+ elsif block_given?
+ if (verdict = yield self)
+ case verdict
+ when :skip_children
+ result << self
+ return result
+ when :skip
+ return result
+ else
+ result << self
+ end
+ end
+ else
+ result << self
+ end
+ end
+ case @context
+ when :document
+ unless context_selector == :document
+ # process document header as a section, if present
+ if header? && (any_context || context_selector == :section)
+ @header.find_by_internal selector, result, &block
+ end
+ @blocks.each do |b|
+ next if (context_selector == :section && b.context != :section) # optimization
+ b.find_by_internal selector, result, &block
+ end
+ end
+ when :dlist
+ # dlist has different structure than other blocks
+ if any_context || context_selector != :section # optimization
+ # NOTE the list item of a dlist can be nil, so we have to check
+ @blocks.flatten.each {|b| b.find_by_internal selector, result, &block if b }
+ end
+ when :table
+ if selector[:traverse_documents]
+ rows.head.each {|r| r.each {|c| c.find_by_internal selector, result, &block } }
+ selector = selector.merge context: :document if context_selector == :inner_document
+ (rows.body + rows.foot).each do |r|
+ r.each do |c|
+ c.find_by_internal selector, result, &block
+ c.inner_document.find_by_internal selector, result, &block if c.style == :asciidoc
+ end
+ end
+ else
+ (rows.head + rows.body + rows.foot).each {|r| r.each {|c| c.find_by_internal selector, result, &block } }
+ end
else
- #yield self.header if @context == :document && header?
- @blocks.each &block
+ @blocks.each do |b|
+ next if (context_selector == :section && b.context != :section) # optimization
+ b.find_by_internal selector, result, &block
+ end
end
+ result
end
-
- #--
- # TODO is there a way to make this lazy?
- def each_recursive &block
- block = lambda {|node| node } unless block_given?
- results = []
- self.each do |node|
- results << block.call(node)
- results.concat(node.each_recursive(&block)) if ::Enumerable === node
- end
- block_given? ? results : results.to_enum
- end
-=end
end
end