X-Git-Url: http://nitlanguage.org diff --git a/lib/markdown/markdown.nit b/lib/markdown/markdown.nit index 664b145..10dbcc6 100644 --- a/lib/markdown/markdown.nit +++ b/lib/markdown/markdown.nit @@ -31,9 +31,9 @@ import template class MarkdownProcessor # `MarkdownEmitter` used for ouput. - var emitter: MarkdownEmitter is noinit + var emitter: MarkdownEmitter is noinit, protected writable - # Work in extended mode. + # Work in extended mode (default). # # Behavior changes when using extended mode: # @@ -69,6 +69,26 @@ class MarkdownProcessor # end # ``` # + # * Code blocks meta + # + # If you want to use syntax highlighting tools, most of them need to know what kind + # of language they are highlighting. + # You can add an optional language identifier after the fence declaration to output + # it in the HTML render. + # + # ```nit + # import markdown + # + # print "# Hello World!".md_to_html + # ``` + # + # Becomes + # + #
import markdown
+	#
+	#		print "Hello World!".md_to_html
+	#		
+ # # * Underscores (Emphasis) # # Underscores in the middle of a word like: @@ -93,12 +113,12 @@ class MarkdownProcessor # becomes # # Mistaken text. - var ext_mode = false + var ext_mode = true init do self.emitter = new MarkdownEmitter(self) # Process the mardown `input` string and return the processed output. - fun process(input: String): Streamable do + fun process(input: String): Writable do # init processor link_refs.clear last_link_ref = null @@ -517,7 +537,7 @@ class MarkdownEmitter end # Append `e` to current buffer. - fun add(e: Streamable) do + fun add(e: Writable) do if e isa Text then current_buffer.append e else @@ -535,9 +555,9 @@ end # A Link Reference. # Links that are specified somewhere in the mardown document to be reused as shortcuts. # -# Example: -# -# [1]: http://example.com/ "Optional title" +# ~~~raw +# [1]: http://example.com/ "Optional title" +# ~~~ class LinkRef # Link href @@ -667,7 +687,11 @@ class HTMLDecorator end redef fun add_code(v, block) do - v.add "
"
+		if block isa BlockFence and block.meta != null then
+			v.add "
"
+		else
+			v.add "
"
+		end
 		v.emit_in block
 		v.add "
\n" end @@ -1105,6 +1129,9 @@ end class BlockFence super BlockCode + # Any string found after fence token. + var meta: nullable Text + # Fence code lines start at 0 spaces. redef var line_start = 0 end @@ -1624,7 +1651,8 @@ class LineFence else block = v.current_block.split(v.current_block.last_line.as(not null)) end - block.kind = new BlockFence(block) + var meta = block.first_line.value.meta_from_fence + block.kind = new BlockFence(block, meta) block.first_line.clear var last = block.last_line if last != null and v.line_kind(last) isa LineFence then @@ -2238,6 +2266,7 @@ redef class Text # Safe mode can be activated to limit reading to valid xml. private fun read_xml(out: FlatBuffer, start: Int, safe_mode: Bool): Int do var pos = 0 + var is_valid = true var is_close_tag = false if start + 1 >= length then return -1 if self[start + 1] == '/' then @@ -2255,7 +2284,11 @@ redef class Text pos = read_xml_until(tmp, pos, ' ', '/', '>') if pos == -1 then return -1 var tag = tmp.write_to_string.trim.to_lower - if tag.is_html_unsafe then + if not tag.is_valid_html_tag then + out.append "<" + pos = -1 + else if tag.is_html_unsafe then + is_valid = false out.append "<" if is_close_tag then out.add '/' out.append tmp @@ -2278,7 +2311,11 @@ redef class Text if pos == -1 then return -1 end if self[pos] == '>' then - out.add '>' + if is_valid then + out.add '>' + else + out.append ">" + end return pos end return -1 @@ -2350,6 +2387,14 @@ redef class Text return tpl.write_to_string.to_lower end + private fun is_valid_html_tag: Bool do + if is_empty then return false + for c in self do + if not c.is_alpha then return false + end + return true + end + # Read and escape the markdown contained in `self`. private fun escape(out: FlatBuffer, c: Char, pos: Int): Int do if c == '\\' or c == '[' or c == ']' or c == '(' or c == ')' or c == '{' or @@ -2363,6 +2408,17 @@ redef class Text return pos end + # Extract string found at end of fence opening. + private fun meta_from_fence: nullable Text do + for i in [0..chars.length[ do + var c = chars[i] + if c != ' ' and c != '`' and c != '~' then + return substring_from(i).trim + end + end + return null + end + # Is `self` an unsafe HTML element? private fun is_html_unsafe: Bool do return html_unsafe_tags.has(self.write_to_string) @@ -2386,7 +2442,7 @@ redef class String # var md = "**Hello World!**" # var html = md.md_to_html # assert html == "

Hello World!

\n" - fun md_to_html: Streamable do + fun md_to_html: Writable do var processor = new MarkdownProcessor return processor.process(self) end