X-Git-Url: http://nitlanguage.org diff --git a/lib/markdown/markdown.nit b/lib/markdown/markdown.nit index c385e66..0d264cb 100644 --- a/lib/markdown/markdown.nit +++ b/lib/markdown/markdown.nit @@ -134,17 +134,21 @@ class MarkdownProcessor # Split `input` string into `MDLines` and create a parent `MDBlock` with it. private fun read_lines(input: String): MDBlock do - var block = new MDBlock + var block = new MDBlock(new MDLocation(1, 1, 1, 1)) var value = new FlatBuffer var i = 0 + + var line_pos = 0 + var col_pos = 0 + while i < input.length do value.clear var pos = 0 var eol = false while not eol and i < input.length do + col_pos += 1 var c = input[i] if c == '\n' then - i += 1 eol = true else if c == '\t' then var np = pos + (4 - (pos.bin_and(3))) @@ -152,18 +156,20 @@ class MarkdownProcessor value.add ' ' pos += 1 end - i += 1 else pos += 1 value.add c - i += 1 end + i += 1 end + line_pos += 1 - var line = new MDLine(value.write_to_string) + var loc = new MDLocation(line_pos, 1, line_pos, col_pos) + var line = new MDLine(loc, value.write_to_string) var is_link_ref = check_link_ref(line) # Skip link refs if not is_link_ref then block.add_line line + col_pos = 0 end return block end @@ -370,70 +376,72 @@ class MarkdownProcessor c2 = ' ' end + var loc = text.pos_to_loc(pos) + if c == '*' then if c1 == '*' then if c0 != ' ' or c2 != ' ' then - return new TokenStrongStar(pos, c) + return new TokenStrongStar(loc, pos, c) else - return new TokenEmStar(pos, c) + return new TokenEmStar(loc, pos, c) end end if c0 != ' ' or c1 != ' ' then - return new TokenEmStar(pos, c) + return new TokenEmStar(loc, pos, c) else - return new TokenNone(pos, c) + return new TokenNone(loc, pos, c) end else if c == '_' then if c1 == '_' then if c0 != ' ' or c2 != ' 'then - return new TokenStrongUnderscore(pos, c) + return new TokenStrongUnderscore(loc, pos, c) else - return new TokenEmUnderscore(pos, c) + return new TokenEmUnderscore(loc, pos, c) end end if ext_mode then if (c0.is_letter or c0.is_digit) and c0 != '_' and (c1.is_letter or c1.is_digit) then - return new TokenNone(pos, c) + return new TokenNone(loc, pos, c) else - return new TokenEmUnderscore(pos, c) + return new TokenEmUnderscore(loc, pos, c) end end if c0 != ' ' or c1 != ' ' then - return new TokenEmUnderscore(pos, c) + return new TokenEmUnderscore(loc, pos, c) else - return new TokenNone(pos, c) + return new TokenNone(loc, pos, c) end else if c == '!' then - if c1 == '[' then return new TokenImage(pos, c) - return new TokenNone(pos, c) + if c1 == '[' then return new TokenImage(loc, pos, c) + return new TokenNone(loc, pos, c) else if c == '[' then - return new TokenLink(pos, c) + return new TokenLink(loc, pos, c) else if c == ']' then - return new TokenNone(pos, c) + return new TokenNone(loc, pos, c) else if c == '`' then if c1 == '`' then - return new TokenCodeDouble(pos, c) + return new TokenCodeDouble(loc, pos, c) else - return new TokenCodeSingle(pos, c) + return new TokenCodeSingle(loc, pos, c) end else if c == '\\' then if c1 == '\\' or c1 == '[' or c1 == ']' or c1 == '(' or c1 == ')' or c1 == '{' or c1 == '}' or c1 == '#' or c1 == '"' or c1 == '\'' or c1 == '.' or c1 == '<' or c1 == '>' or c1 == '*' or c1 == '+' or c1 == '-' or c1 == '_' or c1 == '!' or c1 == '`' or c1 == '~' or c1 == '^' then - return new TokenEscape(pos, c) + return new TokenEscape(loc, pos, c) else - return new TokenNone(pos, c) + return new TokenNone(loc, pos, c) end else if c == '<' then - return new TokenHTML(pos, c) + return new TokenHTML(loc, pos, c) else if c == '&' then - return new TokenEntity(pos, c) + return new TokenEntity(loc, pos, c) else if ext_mode then if c == '~' and c1 == '~' then - return new TokenStrike(pos, c) + return new TokenStrike(loc, pos, c) end end - return new TokenNone(pos, c) + return new TokenNone(loc, pos, c) end end @@ -552,10 +560,10 @@ class MarkdownEmitter end # Append `c` to current buffer. - fun addc(c: Char) do current_buffer.add c + fun addc(c: Char) do add c.to_s # Append a "\n" line break. - fun addn do current_buffer.add '\n' + fun addn do add "\n" end # A Link Reference. @@ -856,9 +864,31 @@ class HTMLDecorator private var allowed_id_chars: Array[Char] = ['-', '_', ':', '.'] end +# Location in a Markdown input. +class MDLocation + + # Starting line number (starting from 1). + var line_start: Int + + # Starting column number (starting from 1). + var column_start: Int + + # Stopping line number (starting from 1). + var line_end: Int + + # Stopping column number (starting from 1). + var column_end: Int + + redef fun to_s do return "{line_start},{column_start}--{line_end},{column_end}" +end + # 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 @@ -911,7 +941,14 @@ class MDBlock # Split `self` creating a new sub-block having `line` has `last_line`. fun split(line: MDLine): MDBlock do - var block = new MDBlock + # location for new block + var new_loc = new MDLocation( + first_line.location.line_start, + first_line.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 @@ -920,6 +957,9 @@ class MDBlock last_line = null else first_line.prev = null + # update current block loc + location.line_start = first_line.location.line_start + location.column_start = first_line.location.column_start end if first_block == null then first_block = block @@ -1292,6 +1332,9 @@ end # 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 @@ -1799,7 +1842,10 @@ end # Some tokens have a specific markup behaviour that is handled here. abstract class Token - # Position of `self` in markdown input. + # Location of `self` in the original input. + var location: MDLocation + + # Position of `self` in input independant from lines. var pos: Int # Character found at `pos` in the markdown input. @@ -2428,6 +2474,24 @@ redef class Text return null end + # Init a `MDLocation` instance at `pos` in `self`. + private fun pos_to_loc(pos: Int): MDLocation do + assert pos <= length + var line = 1 + var col = 0 + var i = 0 + while i <= pos do + col += 1 + var c = self[i] + if c == '\n' then + line +=1 + col = 0 + end + i +=1 + end + return new MDLocation(line, col, line, col) + end + # Is `self` an unsafe HTML element? private fun is_html_unsafe: Bool do return html_unsafe_tags.has(self.write_to_string)