Property definitions

markdown $ MDBlock :: defaultinit
# A block of markdown lines.
# A `MDBlock` can contains lines and/or sub-blocks.
class MDBlock

	# Position of `self` in the input.
	var location: MDLocation

	# Kind of block.
	# See `Block`.
	var kind: Block = new BlockNone(self) is writable

	# First line if any.
	var first_line: nullable MDLine = null is writable

	# Last line if any.
	var last_line: nullable MDLine = null is writable

	# First sub-block if any.
	var first_block: nullable MDBlock = null is writable

	# Last sub-block if any.
	var last_block: nullable MDBlock = null is writable

	# Previous block if any.
	var prev: nullable MDBlock = null is writable

	# Next block if any.
	var next: nullable MDBlock = null is writable

	# Does this block contain subblocks?
	fun has_blocks: Bool do return first_block != null

	# Count sub-blocks.
	fun count_blocks: Int do
		var count = 0
		var block = first_block
		while block != null do
			count += 1
			block = block.next
		end
		return count
	end

	# Does this block contain lines?
	fun has_lines: Bool do return first_line != null

	# Count block lines.
	fun count_lines: Int do
		var count = 0
		var line = first_line
		while line != null do
			count += 1
			line = line.next
		end
		return count
	end

	# Split `self` creating a new sub-block having `line` has `last_line`.
	fun split(line: MDLine): MDBlock do
		# location for new block
		var new_loc = new MDLocation(
			first_line.as(not null).location.line_start,
			first_line.as(not null).location.column_start,
			line.location.line_end,
			line.location.column_end)
		# create block
		var block = new MDBlock(new_loc)
		block.first_line = first_line
		block.last_line = line
		first_line = line.next
		line.next = null
		if first_line == null then
			last_line = null
		else
			first_line.as(not null).prev = null
			# update current block loc
			location.line_start = first_line.as(not null).location.line_start
			location.column_start = first_line.as(not null).location.column_start
		end
		if first_block == null then
			first_block = block
			last_block = block
		else
			last_block.as(not null).next = block
			last_block = block
		end
		return block
	end

	# Add a `line` to this block.
	fun add_line(line: MDLine) do
		if last_line == null then
			first_line = line
			last_line = line
		else
			last_line.as(not null).next_empty = line.is_empty
			line.prev_empty = last_line.as(not null).is_empty
			line.prev = last_line
			last_line.as(not null).next = line
			last_line = line
		end
	end

	# Remove `line` from this block.
	fun remove_line(line: MDLine) do
		if line.prev == null then
			first_line = line.next
		else
			line.prev.as(not null).next = line.next
		end
		if line.next == null then
			last_line = line.prev
		else
			line.next.as(not null).prev = line.prev
		end
		line.prev = null
		line.next = null
	end

	# Remove leading empty lines.
	fun remove_leading_empty_lines: Bool do
		var was_empty = false
		var line = first_line
		while line != null and line.is_empty do
			remove_line line
			line = first_line
			was_empty = true
		end
		return was_empty
	end

	# Remove trailing empty lines.
	fun remove_trailing_empty_lines: Bool do
		var was_empty = false
		var line = last_line
		while line != null and line.is_empty do
			remove_line line
			line = last_line
			was_empty = true
		end
		return was_empty
	end

	# Remove leading and trailing empty lines.
	fun remove_surrounding_empty_lines: Bool do
		var was_empty = false
		if remove_leading_empty_lines then was_empty = true
		if remove_trailing_empty_lines then was_empty = true
		return was_empty
	end

	# Remove list markers and up to 4 leading spaces.
	# Used to clean nested lists.
	fun remove_list_indent(v: MarkdownProcessor) do
		var line = first_line
		while line != null do
			if not line.is_empty then
				var kind = v.line_kind(line)
				if kind isa LineList then
					line.value = kind.extract_value(line)
				else
					line.value = line.value.substring_from(line.leading.min(4))
				end
				line.leading = line.process_leading
			end
			line = line.next
		end
	end

	# Collect block line text.
	fun text: String do
		var text = new FlatBuffer
		var line = first_line
		while line != null do
			if not line.is_empty then
				text.append line.text
			end
			text.append "\n"
			line = line.next
		end
		var block = first_block
		while block != null do
			text.append block.text
			text.append "\n"
			block = block.next
		end
		return text.write_to_string
	end
end
lib/markdown/markdown.nit:944,1--1132,3