markdown :: MDLine :: defaultinit
# A markdown line.
class MDLine
# Location of `self` in the original input.
var location: MDLocation
# Text contained in this line.
var value: String is writable
# Is this line empty?
# Lines containing only spaces are considered empty.
var is_empty: Bool = true is writable
# Previous line in `MDBlock` or null if first line.
var prev: nullable MDLine = null is writable
# Next line in `MDBlock` or null if last line.
var next: nullable MDLine = null is writable
# Is the previous line empty?
var prev_empty: Bool = false is writable
# Is the next line empty?
var next_empty: Bool = false is writable
# Initialize a new MDLine from its string value
init do
self.leading = process_leading
if leading != value.length then
self.is_empty = false
self.trailing = process_trailing
end
end
# Set `value` as an empty String and update `leading`, `trailing` and is_`empty`.
fun clear do
value = ""
leading = 0
trailing = 0
is_empty = true
if prev != null then prev.as(not null).next_empty = true
if next != null then next.as(not null).prev_empty = true
end
# Number or leading spaces on this line.
var leading: Int = 0 is writable
# Compute `leading` depending on `value`.
fun process_leading: Int do
var count = 0
var value = self.value
while count < value.length and value[count] == ' ' do count += 1
if leading == value.length then clear
return count
end
# Number of trailing spaces on this line.
var trailing: Int = 0 is writable
# Compute `trailing` depending on `value`.
fun process_trailing: Int do
var count = 0
var value = self.value
while value[value.length - count - 1] == ' ' do
count += 1
end
return count
end
# Count the amount of `ch` in this line.
# Return A value > 0 if this line only consists of `ch` end spaces.
fun count_chars(ch: Char): Int do
var count = 0
for c in value do
if c == ' ' then
continue
end
if c == ch then
count += 1
continue
end
count = 0
break
end
return count
end
# Count the amount of `ch` at the start of this line ignoring spaces.
fun count_chars_start(ch: Char): Int do
var count = 0
for c in value do
if c == ' ' then
continue
end
if c == ch then
count += 1
else
break
end
end
return count
end
# Last XML line if any.
private var xml_end_line: nullable MDLine = null
# Does `value` contains valid XML markup?
private fun check_html: Bool do
var tags = new Array[String]
var tmp = new FlatBuffer
var pos = leading
if pos + 1 < value.length and value[pos + 1] == '!' then
if read_xml_comment(self, pos) > 0 then return true
end
pos = value.read_xml(tmp, pos, false)
var tag: String
if pos > -1 then
tag = tmp.xml_tag
if not tag.is_html_block then
return false
end
if tag == "hr" then
xml_end_line = self
return true
end
tags.add tag
var line: nullable MDLine = self
while line != null do
while pos < line.value.length and line.value[pos] != '<' do
pos += 1
end
if pos >= line.value.length then
if pos - 2 >= 0 and line.value[pos - 2] == '/' then
tags.pop
if tags.is_empty then
xml_end_line = line
break
end
end
line = line.next
pos = 0
else
tmp = new FlatBuffer
var new_pos = line.value.read_xml(tmp, pos, false)
if new_pos > 0 then
tag = tmp.xml_tag
if tag.is_html_block and not tag == "hr" then
if tmp[1] == '/' then
if tags.last != tag then
return false
end
tags.pop
else
tags.add tag
end
end
if tags.is_empty then
xml_end_line = line
break
end
pos = new_pos
else
pos += 1
end
end
end
return tags.is_empty
end
return false
end
# Read a XML comment.
# Used by `check_html`.
private fun read_xml_comment(first_line: MDLine, start: Int): Int do
var line: nullable MDLine = first_line
if start + 3 < line.as(not null).value.length then
if line.as(not null).value[2] == '-' and line.as(not null).value[3] == '-' then
var pos = start + 4
while line != null do
while pos < line.value.length and line.value[pos] != '-' do
pos += 1
end
if pos == line.value.length then
line = line.next
pos = 0
else
if pos + 2 < line.value.length then
if line.value[pos + 1] == '-' and line.value[pos + 2] == '>' then
first_line.xml_end_line = line
return pos + 3
end
end
pos += 1
end
end
end
end
return -1
end
# Extract the text of `self` without leading and trailing.
fun text: String do return value.substring(leading, value.length - trailing)
end
lib/markdown/markdown.nit:1430,1--1632,3