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
#
# "
+ 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