markdown2 $ MdListBlockParserFactory :: SELF
Type of this instance, automatically specialized in every classmarkdown2 $ MdListBlockParserFactory :: try_start
Can the associated block parser can start at the current line inparser
?
core :: Object :: class_factory
Implementation used byget_class
to create the specific class.
core :: Object :: defaultinit
core :: Object :: is_same_instance
Return true ifself
and other
are the same instance (i.e. same identity).
core :: Object :: is_same_serialized
Isself
the same as other
in a serialization context?
core :: Object :: is_same_type
Return true ifself
and other
have the same dynamic type.
core :: Object :: output_class_name
Display class name on stdout (debug only).markdown2 :: MdBlockParserFactory :: try_start
Can the associated block parser can start at the current line inparser
?
markdown2 :: MdBlockParserFactory
Block parser factory for a block node for determining when a block starts
# List blocks parser factory
class MdListBlockParserFactory
super MdBlockQuoteParserFactory
redef fun try_start(state, matched_block_parser) do
if state.indent >= 4 and not matched_block_parser isa MdListBlockParser then return null
var marker_index = state.next_non_space_index
var marker_column = state.column + state.indent
var in_paragraph = matched_block_parser isa MdParagraphParser and matched_block_parser.content != null
var list_data = parse_list_marker(state, state.line_string, marker_index, marker_column, in_paragraph)
if list_data == null then return null
var new_column = list_data.content_column
var list_item_parser = new MdListItemParser(
state.line,
state.column + 1,
new_column,
new_column - state.column)
# prepend the list block if needed
if not matched_block_parser isa MdListBlockParser or not lists_match(matched_block_parser.block, list_data) then
var list_block_parser = new MdListBlockParser(state.line, state.column + 1, new_column - state.column, list_data.is_ordered, list_data.bullet, list_data.digit, list_data.delim)
list_block_parser.block.is_tight = true
return (new MdBlockStart([list_block_parser, list_item_parser: MdBlockParser])).at_column(new_column)
end
return (new MdBlockStart([list_item_parser])).at_column(new_column)
end
private fun parse_list_marker(state: MdParser, line: String, marker_index, marker_column: Int, in_paragraph: Bool): nullable MdListData do
var rest = line.substring(marker_index, line.length - marker_index)
var match = rest.search(re_list_marker)
if match == null then return null
var is_ordered
var bullet = null
var digit = null
var delim = null
var bullet_match = match.subs[0]
if bullet_match != null then
is_ordered = false
bullet = bullet_match.to_s.chars[0]
else
is_ordered = true
digit = match.subs[2].as(not null).to_s.to_i
delim = match.subs[3].as(not null).to_s.chars[0]
end
var marker_length = match.length
if match.to_s.has_suffix(" ") or match.to_s.has_suffix("\t") then
marker_length -= 1
end
var index_after_marker = marker_index + marker_length
# marker doesn't include tabs, so counting them as column directly is ok
var column_after_marker = marker_column + marker_length
# the column within the line where the content starts
var content_column = column_after_marker
# see at which column the content starts if there is content
var has_content = false
for i in [index_after_marker .. line.length[ do
var c = line.chars[i]
if c == '\t' then
content_column += content_column.columns_to_next_tab_stop
else if c == ' ' then
content_column += 1
else
has_content = true
break
end
end
if in_paragraph then
# if the list item is ordered, then start number must be 1 to interrupt a paragraph
if is_ordered and digit != 1 then
return null
end
# empty list item can not interrupt a paragraph
if not has_content then
return null
end
end
if not has_content or (content_column - column_after_marker) > 4 then
# if this line is blank or has a code block, default to 1 space after marker
content_column = column_after_marker + 1
end
return new MdListData(is_ordered, bullet, digit, delim, content_column)
end
# Return true if the two list items are of the same type
#
# With the same delimiter and bullet character.
# This is used in agglomerating list items into lists
private fun lists_match(a: MdListBlock, b: MdListData): Bool do
if a isa MdUnorderedList and not b.is_ordered then
return a.bullet_marker == b.bullet
else if a isa MdOrderedList and b.is_ordered then
return a.delimiter == b.delim
end
return false
end
end
lib/markdown2/markdown_block_parsing.nit:1020,1--1127,3