# Fenced code blocks parser
class MdFencedCodeBlockParser
super MdBlockParser
redef type BLOCK: MdFencedCodeBlock
redef var block = new MdFencedCodeBlock(location, fence_char, fence_length, fence_indent) is lazy
# Fence character
var fence_char: Char
# Fence length
var fence_length: Int
# Fence indent
var fence_indent: Int
# Fence first line
var first_line: nullable String = null
# Fence other lines
var other_lines = new Buffer
redef fun try_continue(state) do
var next_non_space = state.next_non_space_index
var new_index = state.index
var line = state.line_string
if state.indent <= 3 and next_non_space < line.length and
line.chars[next_non_space] == fence_char then
var match = line.substring(next_non_space, line.length - next_non_space).
search(re_closing_fence)
if match != null and match.subs[0].as(not null).length >= fence_length then
# closing fence - we're at end of line, so we can finalize now
return new MdBlockContinue.finished
end
end
# skip optional spaces of fence indent
var i = fence_indent
while i > 0 and new_index < line.length and line.chars[new_index] == ' ' do
new_index += 1
i -= 1
end
return new MdBlockContinue.at_index(new_index)
end
redef fun add_line(line) do
if first_line == null then
first_line = line
else
other_lines.append(line)
other_lines.add '\n'
end
end
redef fun finalize(parser) do
super
# first line become info string
var first_line = self.first_line
if first_line != null then
var info = first_line.trim.unescape_string
if not info.is_empty then block.info = info
end
var content = other_lines.to_s
block.literal = content
var lines = content.split("\n")
location.line_end = location.line_start + lines.length
location.column_end = content_offset + fence_indent + fence_length
end
end
lib/markdown2/markdown_block_parsing.nit:843,1--917,3