lib/asciidoctor/parser.rb in asciidoctor-2.0.1 vs lib/asciidoctor/parser.rb in asciidoctor-2.0.2
- old
+ new
@@ -467,30 +467,31 @@
# reader - The Reader from which to retrieve the next Block.
# parent - The Document, Section or Block to which the next Block belongs.
# attributes - A Hash of attributes that will become the attributes
# associated with the parsed Block (default: {}).
# options - An options Hash to control parsing (default: {}):
- # * :text indicates that the parser is only looking for text content
+ # * :text_only indicates that the parser is only looking for text content
+ # * :list_type indicates this block will be attached to a list item in a list of the specified type
#
# Returns a Block object built from the parsed content of the processed
# lines, or nothing if no block is found.
def self.next_block(reader, parent, attributes = {}, options = {})
# skip ahead to the block content; bail if we've reached the end of the reader
return unless (skipped = reader.skip_blank_lines)
# check for option to find list item text only
# if skipped a line, assume a list continuation was
# used and block content is acceptable
- if (text_only = options[:text]) && skipped > 0
- options.delete :text
+ if (text_only = options[:text_only]) && skipped > 0
+ options.delete :text_only
text_only = nil
end
document = parent.document
if options.fetch :parse_metadata, true
- # read lines until there are no more metadata lines to read
+ # read lines until there are no more metadata lines to read; note that :text_only option impacts parsing rules
while parse_block_metadata_line reader, document, attributes, options
# discard the line just processed
reader.shift
# QUESTION should we clear the attributes? no known cases when it's necessary
reader.skip_blank_lines || return
@@ -602,11 +603,11 @@
# NOTE assume % units if not specified
attributes['scaledwidth'] = (TrailingDigitsRx.match? scaledwidth) ? %(#{scaledwidth}%) : scaledwidth
end
if attributes['title']
block.title = block_title = attributes.delete 'title'
- block.assign_caption (attributes.delete 'caption'), 'figure'
+ block.assign_caption (attributes.delete 'caption')
end
end
attributes['target'] = target
break
@@ -720,21 +721,21 @@
reader.unshift_line this_line
# a literal paragraph: contiguous lines starting with at least one whitespace character
# NOTE style can only be nil or "normal" at this point
if indented && !style
- lines = read_paragraph_lines reader, (list_item = options[:list_item]) && skipped == 0, skip_line_comments: text_only
+ lines = read_paragraph_lines reader, (content_adjacent = skipped == 0 ? options[:list_type] : nil), skip_line_comments: text_only
adjust_indentation! lines
- block = Block.new(parent, :literal, content_model: :verbatim, source: lines, attributes: attributes)
- if list_item
- # a literal gets special meaning inside of a description list
- block.set_option 'listparagraph'
- block.default_subs = []
+ if text_only || content_adjacent == :dlist
+ # this block gets folded into the list item text
+ block = Block.new(parent, :paragraph, content_model: :simple, source: lines, attributes: attributes)
+ else
+ block = Block.new(parent, :literal, content_model: :verbatim, source: lines, attributes: attributes)
end
# a normal paragraph: contiguous non-blank/non-continuation lines (left-indented or normal style)
else
- lines = read_paragraph_lines reader, skipped == 0 && options[:list_item], skip_line_comments: true
+ lines = read_paragraph_lines reader, skipped == 0 && options[:list_type], skip_line_comments: true
# NOTE don't check indented here since it's extremely rare
#if text_only || indented
if text_only
# if [normal] is used over an indented paragraph, shift content to left margin
# QUESTION do we even need to shift since whitespace is normalized by XML in this case?
@@ -895,12 +896,12 @@
# FIXME we've got to clean this up, it's horrible!
block.source_location = reader.cursor_at_mark if document.sourcemap
# FIXME title and caption should be assigned when block is constructed (though we need to handle all cases)
if attributes['title']
block.title = block_title = attributes.delete 'title'
- if CAPTIONABLE_BLOCKS[block_context = block.context] && document.attributes[%(#{block.context}-caption)]
- block.assign_caption (attributes.delete 'caption'), block_context
+ if (caption_attr_name = CAPTION_ATTR_NAMES[block.context]) && document.attributes[caption_attr_name]
+ block.assign_caption (attributes.delete 'caption')
end
end
# TODO eventually remove the style attribute from the attributes hash
#block.style = attributes.delete 'style'
block.style = attributes['style']
@@ -1331,35 +1332,29 @@
list_item.source_location = block_cursor if sourcemap_assignment_deferred
# NOTE peek on the other side of any comment lines
comment_lines = list_item_reader.skip_line_comments
if (subsequent_line = list_item_reader.peek_line)
list_item_reader.unshift_lines comment_lines unless comment_lines.empty?
- if (continuation_connects_first_block = subsequent_line.empty?)
- content_adjacent = false
- else
+ unless subsequent_line.empty?
content_adjacent = true
# treat lines as paragraph text if continuation does not connect first block (i.e., has_text = nil)
has_text = nil unless dlist
end
- else
- # NOTE we have no use for any trailing comment lines we might have found
- continuation_connects_first_block = false
- content_adjacent = false
end
# reader is confined to boundaries of list, which means only blocks will be found (no sections)
- if (block = next_block(list_item_reader, list_item, {}, text: !has_text, list_item: true))
+ if (block = next_block(list_item_reader, list_item, {}, text_only: has_text ? nil : true, list_type: list_type))
list_item.blocks << block
end
while list_item_reader.has_more_lines?
- if (block = next_block(list_item_reader, list_item, {}, list_item: true))
+ if (block = next_block(list_item_reader, list_item, {}, list_type: list_type))
list_item.blocks << block
end
end
- list_item.fold_first(continuation_connects_first_block, content_adjacent)
+ list_item.fold_first if content_adjacent && (first_block = list_item.blocks[0]) && first_block.context == :paragraph
end
dlist ? [[list_term], (list_item.text? || list_item.blocks? ? list_item : nil)] : list_item
end
@@ -1535,24 +1530,24 @@
this_line = nil
end
reader.unshift_line this_line if this_line
- if detached_continuation
- buffer.delete_at detached_continuation
+ buffer.delete_at detached_continuation if detached_continuation
+
+ until buffer.empty?
+ # strip trailing blank lines to prevent empty blocks
+ if (last_line = buffer[-1]).empty?
+ buffer.pop
+ else
+ # drop optional trailing continuation
+ # (a blank line would have served the same purpose in the document)
+ buffer.pop if last_line == LIST_CONTINUATION
+ break
+ end
end
- # strip trailing blank lines to prevent empty blocks
- buffer.pop while !buffer.empty? && buffer[-1].empty?
-
- # We do need to replace the optional trailing continuation
- # a blank line would have served the same purpose in the document
- buffer.pop if !buffer.empty? && buffer[-1] == LIST_CONTINUATION
-
- #warn "BUFFER[#{list_type},#{sibling_trait}]>#{buffer.join LF}<BUFFER"
- #warn "BUFFER[#{list_type},#{sibling_trait}]>#{buffer.inspect}<BUFFER"
-
buffer
end
# Internal: Initialize a new Section object and assign any attributes provided
#
@@ -1985,11 +1980,11 @@
#
# reader - the source reader
# document - the current Document
# attributes - a Hash of attributes in which any metadata found will be stored (default: {})
# options - a Hash of options to control processing: (default: {})
- # * :text indicates that parser is only looking for text content
+ # * :text_only indicates that parser is only looking for text content
# and thus the block title should not be captured
#
# returns the Hash of attributes including any metadata found
def self.parse_block_metadata_lines reader, document, attributes = {}, options = {}
while parse_block_metadata_line reader, document, attributes, options
@@ -2014,16 +2009,16 @@
#
# reader - the source reader
# document - the current Document
# attributes - a Hash of attributes in which any metadata found will be stored
# options - a Hash of options to control processing: (default: {})
- # * :text indicates the parser is only looking for text content,
+ # * :text_only indicates the parser is only looking for text content,
# thus neither a block title or attribute entry should be captured
#
# returns true if the line contains metadata, otherwise falsy
def self.parse_block_metadata_line reader, document, attributes, options = {}
if (next_line = reader.peek_line) &&
- (options[:text] ? (next_line.start_with? '[', '/') : (normal = next_line.start_with? '[', '.', '/', ':'))
+ (options[:text_only] ? (next_line.start_with? '[', '/') : (normal = next_line.start_with? '[', '.', '/', ':'))
if next_line.start_with? '['
if next_line.start_with? '[['
if (next_line.end_with? ']]') && BlockAnchorRx =~ next_line
# NOTE registration of id and reftext is deferred until block is processed
attributes['id'] = $1