class Asciidoctor::AbstractBlock
Attributes
Public: Get the Array
of {AbstractBlock} child blocks for this block. Only applies if content model is :compound.
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 substitutions applied
-
:empty - this block has no content
Public: Set the Integer level of this {Section} or the level of the Section
to which this {AbstractBlock} belongs.
Public: Get/Set the String
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: Gets/Sets the location in the AsciiDoc source where this block begins.
Public: Get/Set the String
style (block type qualifier) for this block.
Public: Substitutions to be applied to content in this block.
Public Class Methods
# File lib/asciidoctor/abstract_block.rb, line 35 def initialize parent, context, opts = {} super @content_model = :compound @blocks = [] @subs = [] @id = @title = @caption = @numeral = @style = @default_subs = @source_location = nil if context == :document || context == :section @level = @next_section_index = 0 @next_section_ordinal = 1 elsif AbstractBlock === parent @level = parent.level else @level = nil end end
Public Instance Methods
Public: Append a content block to this block’s list of blocks.
block - The new child block.
Examples
block = Block.new(parent, :preamble, content_model: :compound) block << Block.new(block, :paragraph, source: 'p1') block << Block.new(block, :paragraph, source: 'p2') block.blocks? # => true block.blocks.size # => 2
Returns The parent Block
# File lib/asciidoctor/abstract_block.rb, line 114 def << block block.parent = self unless block.parent == self @blocks << block self end
Public: Returns the converted alt text for this block image.
Returns the [String] value of the alt attribute with XML special character and replacement substitutions applied.
# File lib/asciidoctor/abstract_block.rb, line 225 def alt if (text = @attributes['alt']) if text == @attributes['default-alt'] sub_specialchars text else text = sub_specialchars text (ReplaceableTextRx.match? text) ? (sub_replacements text) : text end else '' end end
Internal: Assign the next index (0-based) and numeral (1-based) to the section. If the section is an appendix, the numeral is a letter (starting with A). This method also assigns the appendix caption.
section - The section to which to assign the next index and numeral.
Assign to the specified section the next index and, if the section is numbered, the numeral within this block (its parent).
Returns nothing
# File lib/asciidoctor/abstract_block.rb, line 407 def assign_numeral section @next_section_index = (section.index = @next_section_index) + 1 if (like = section.numbered) if (sectname = section.sectname) == 'appendix' section.numeral = @document.counter 'appendix-number', 'A' section.caption = (caption = @document.attributes['appendix-caption']) ? %(#{caption} #{section.numeral}: ) : %(#{section.numeral}. ) # NOTE currently chapters in a book doctype are sequential even for multi-part books (see #979) elsif sectname == 'chapter' || like == :chapter section.numeral = (@document.counter 'chapter-number', 1).to_s else section.numeral = sectname == 'part' ? (Helpers.int_to_roman @next_section_ordinal) : @next_section_ordinal.to_s @next_section_ordinal += 1 end end nil end
# File lib/asciidoctor/abstract_block.rb, line 51 def block? true end
Public: Get the converted result of the child blocks by converting the children appropriate to content model that this block supports.
# File lib/asciidoctor/abstract_block.rb, line 83 def content @blocks.map {|b| b.convert }.join LF end
Public: Update the context of this block.
This method changes the context of this block. It also updates the node name accordingly.
context - the context Symbol context to assign to this block
Returns the specified Symbol context
# File lib/asciidoctor/abstract_block.rb, line 94 def context= context @node_name = (@context = context).to_s end
Public: Get the converted String
content for this Block
. If the block has child blocks, the content method should cause them to be converted and returned as content that can be included in the parent block’s template.
# File lib/asciidoctor/abstract_block.rb, line 73 def convert @document.playback_attributes @attributes converter.convert self end
Public: Get the source file where this block started
# File lib/asciidoctor/abstract_block.rb, line 60 def file @source_location && @source_location.file end
Public: Walk the document tree and find all block-level nodes that match the specified selector (context, style, id, role, and/or custom filter).
If a Ruby block is given, it’s applied as a supplemental filter. If the filter returns true (which implies :accept), the node is accepted and node traversal continues. If the filter returns false (which implies :skip), the node is skipped, but its children are still visited. If the filter returns :reject, the node and all its descendants are rejected. If the filter returns :prune, the node is accepted, but its descendants are rejected. If no selector or filter block is supplied, all block-level nodes in the tree are returned.
Examples
doc.find_by context: :section #=> Asciidoctor::Section@14459860 { level: 0, title: "Hello, AsciiDoc!", blocks: 0 } #=> Asciidoctor::Section@14505460 { level: 1, title: "First Section", blocks: 1 } doc.find_by(context: :section) {|section| section.level == 1 } #=> Asciidoctor::Section@14505460 { level: 1, title: "First Section", blocks: 1 } doc.find_by context: :listing, style: 'source' #=> Asciidoctor::Block@13136720 { context: :listing, content_model: :verbatim, style: "source", lines: 1 }
Returns An Array
of block-level nodes that match the filter or an empty Array
if no matches are found
# File lib/asciidoctor/abstract_block.rb, line 175 def find_by selector = {}, &block find_by_internal selector, (result = []), &block rescue ::StopIteration result end
# File lib/asciidoctor/abstract_block.rb, line 55 def inline? false end
Public: Get the source line number where this block started
# File lib/asciidoctor/abstract_block.rb, line 65 def lineno @source_location && @source_location.lineno end
Public: Retrieve the list marker keyword for the specified list type.
For use in the HTML type attribute.
list_type - the type of list; default to the @style if not specified
Returns the single-character [String] keyword that represents the marker for the specified list type
# File lib/asciidoctor/abstract_block.rb, line 270 def list_marker_keyword list_type = nil ORDERED_LIST_KEYWORDS[list_type || @style] 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.
# File lib/asciidoctor/abstract_block.rb, line 185 def next_adjacent_block unless @context == :document if (p = @parent).context == :dlist && @context == :list_item (sib = p.items[(p.items.find_index {|terms, desc| (terms.include? self) || desc == self }) + 1]) ? sib : p.next_adjacent_block else (sib = p.blocks[(p.blocks.find_index self) + 1]) ? sib : p.next_adjacent_block end end end
Deprecated: Legacy property to get the String
or Integer numeral of this section.
# File lib/asciidoctor/abstract_block.rb, line 142 def number (Integer @numeral) rescue @numeral end
Deprecated: Legacy property to set the numeral of this section by coercing the value to a String
.
# File lib/asciidoctor/abstract_block.rb, line 147 def number= val @numeral = val.to_s end
Internal: Reassign the section indexes
Walk the descendents of the current Document
or Section
and reassign the section 0-based index value to each Section
as it appears in document order.
IMPORTANT You must invoke this method on a node after removing child sections or else the internal counters will be off.
Returns nothing
# File lib/asciidoctor/abstract_block.rb, line 434 def reindex_sections @next_section_index = 0 @next_section_ordinal = 1 @blocks.each do |block| if block.context == :section assign_numeral block block.reindex_sections end end end
Public: Remove a substitution from this block
sub - The Symbol substitution name
Returns nothing
# File lib/asciidoctor/abstract_block.rb, line 323 def remove_sub sub @subs.delete sub nil end
Public: Get the Array
of child Section
objects
Only applies to Document
and Section
instances
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' 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.blocks? # => true sect1.blocks.size # => 3 sect1.sections.size # => 1
Returns an [Array] of Section
objects
# File lib/asciidoctor/abstract_block.rb, line 217 def sections @blocks.select {|block| block.context == :section } end
Public: Check whether this block has any child Section
objects.
Acts an an abstract method that always returns false unless this block is an instance of Document
or Section
. Both Document
and Section
provide overrides for this method.
Returns false
# File lib/asciidoctor/abstract_block.rb, line 137 def sections? false end
Public: A convenience method that checks whether the specified substitution is enabled for this block.
name - The Symbol substitution name
Returns A Boolean indicating whether the specified substitution is enabled for this block
# File lib/asciidoctor/abstract_block.rb, line 314 def sub? name @subs.include? name end
Public: Get the String
title of this Block
with title substitutions applied
The following substitutions are applied to block and section titles:
:specialcharacters, :quotes, :replacements, :macros, :attributes and :post_replacements
Examples
block.title = "Foo 3^ # {two-colons} Bar(1)" block.title => "Foo 3^ # :: Bar(1)"
Returns the converted String
title for this Block
, or nil if the source title is falsy
# File lib/asciidoctor/abstract_block.rb, line 287 def title # prevent substitutions from being applied to title multiple times @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.
# File lib/asciidoctor/abstract_block.rb, line 295 def title? @title ? true : false end
Public: Generate cross reference text (xreftext) that can be used to refer to this block.
Use the explicit reftext for this block, if specified, retrieved from the {#reftext} method. Otherwise, if this is a section or captioned block (a block with both a title and caption), generate the xreftext according to the value of the xrefstyle argument (e.g., full, short). This logic may leverage the {Substitutors#sub_quotes} method to apply formatting to the text. If this is not a captioned block, return the title, if present, or nil otherwise.
xrefstyle - An optional String
that specifies the style to use to format
the xreftext ('full', 'short', or 'basic') (default: nil).
Returns the generated [String] xreftext used to refer to this block or nothing if there isn’t sufficient information to generate one.
# File lib/asciidoctor/abstract_block.rb, line 344 def xreftext xrefstyle = nil if (val = reftext) && !val.empty? val # NOTE xrefstyle only applies to blocks with a title and a caption or number elsif xrefstyle && @title && !@caption.nil_or_empty? case xrefstyle when 'full' quoted_title = sub_placeholder (sub_quotes @document.compat_mode ? %q(``%s'') : '"`%s`"'), title if @numeral && (caption_attr_name = CAPTION_ATTRIBUTE_NAMES[@context]) && (prefix = @document.attributes[caption_attr_name]) %(#{prefix} #{@numeral}, #{quoted_title}) else %(#{@caption.chomp '. '}, #{quoted_title}) end when 'short' if @numeral && (caption_attr_name = CAPTION_ATTRIBUTE_NAMES[@context]) && (prefix = @document.attributes[caption_attr_name]) %(#{prefix} #{@numeral}) else @caption.chomp '. ' end else # 'basic' title end else title end end
Protected Instance Methods
Internal: Performs the work for find_by
, but does not handle the StopIteration exception.
# File lib/asciidoctor/abstract_block.rb, line 448 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 block_given? if (verdict = yield self) case verdict when :prune result << self raise ::StopIteration if id_selector return result when :reject raise ::StopIteration if id_selector return result when :stop raise ::StopIteration else result << self raise ::StopIteration if id_selector end elsif id_selector raise ::StopIteration end else result << self raise ::StopIteration if id_selector 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 @blocks.each do |b| next if context_selector == :section && b.context != :section # optimization b.find_by_internal selector, result, &block end end result end