lib/markdown2: introduce wikilinks parsing
authorAlexandre Terrasa <alexandre@moz-code.org>
Wed, 30 May 2018 00:02:24 +0000 (20:02 -0400)
committerAlexandre Terrasa <alexandre@moz-code.org>
Thu, 21 Jun 2018 00:58:45 +0000 (20:58 -0400)
Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

lib/markdown2/markdown_html_rendering.nit
lib/markdown2/markdown_latex_rendering.nit
lib/markdown2/markdown_man_rendering.nit
lib/markdown2/markdown_md_rendering.nit
lib/markdown2/markdown_wikilinks.nit [new file with mode: 0644]
lib/markdown2/tests/test_markdown_wikilinks.nit [new file with mode: 0644]

index e76fd2d..11addf6 100644 (file)
@@ -17,6 +17,7 @@ module markdown_html_rendering
 
 import markdown_rendering
 import markdown_github
+import markdown_wikilinks
 
 # Markdown document renderer to HTML
 class HtmlRenderer
@@ -441,3 +442,17 @@ redef class MdSuper
                v.add_raw "</sup>"
        end
 end
+
+# Wikilinks mode
+
+redef class MdWikilink
+
+       # Dummy rendering of wikilinks
+       #
+       # Clients should redefine this.
+       redef fun render_html(v) do
+               v.add_raw "<wiki link=\"{v.encode_uri(link)}\">"
+               visit_all(v)
+               v.add_raw "</wiki>"
+       end
+end
index a19be27..b7c4abd 100644 (file)
@@ -17,6 +17,7 @@ module markdown_latex_rendering
 
 import markdown_rendering
 import markdown_github
+import markdown_wikilinks
 
 # Markdown document renderer to LaTeX
 class LatexRenderer
@@ -421,3 +422,17 @@ redef class MdSuper
                v.add_raw "\}"
        end
 end
+
+# Wikilinks
+
+redef class MdWikilink
+       redef fun render_latex(v) do
+               v.add_raw "\\texttt\{"
+               var title = self.title
+               if title != null then
+                       v.add_text "{title} | "
+               end
+               v.add_text link
+               v.add_raw "\}"
+       end
+end
index 14ed34b..1e047d6 100644 (file)
@@ -17,6 +17,7 @@ module markdown_man_rendering
 
 import markdown_rendering
 import markdown_github
+import markdown_wikilinks
 
 # Markdown document renderer to Manpage
 class ManRenderer
@@ -241,3 +242,17 @@ redef class MdStrike
                v.add "]"
        end
 end
+
+# Wikilinks
+
+redef class MdWikilink
+       redef fun render_man(v) do
+               v.add "("
+               var title = self.title
+               if title != null then
+                       v.add "{title} | "
+               end
+               v.add link
+               v.add ")"
+       end
+end
index f8fe7ec..eadda1b 100644 (file)
@@ -17,6 +17,7 @@ module markdown_md_rendering
 
 import markdown_rendering
 import markdown_github
+import markdown_wikilinks
 
 # Markdown document renderer to Markdown
 class MarkdownRenderer
@@ -375,3 +376,17 @@ redef class MdText
                v.length += literal.length
        end
 end
+
+# Wikilinks
+
+redef class MdWikilink
+       redef fun render_md(v) do
+               v.add_raw "[["
+               var title = self.title
+               if title != null then
+                       v.add_raw "{title} | "
+               end
+               v.add_raw link
+               v.add_raw "]]"
+       end
+end
diff --git a/lib/markdown2/markdown_wikilinks.nit b/lib/markdown2/markdown_wikilinks.nit
new file mode 100644 (file)
index 0000000..d6cc3a0
--- /dev/null
@@ -0,0 +1,119 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Markdown wikilinks processing
+#
+# Enables parsing of `[[wikilinks]]` syntax.
+module markdown_wikilinks
+
+intrude import markdown_inline_parsing
+intrude import markdown_block_parsing
+
+redef class MdParser
+
+       # Enable wikilinks mode
+       var wikilinks_mode = false is writable
+
+       redef var inline_parser is lazy do
+               var parser = super
+               parser.wikilinks_mode = wikilinks_mode
+               return parser
+       end
+end
+
+redef class MdInlineParser
+
+       # Enable wikilinks mode
+       private var wikilinks_mode = false
+
+       redef fun parse_wikilink do
+               if not wikilinks_mode then return false
+
+               # do we have two opening bracket?
+               var last_bracket = self.last_bracket
+               if last_bracket == null then return false
+               var first_bracket = last_bracket.prev
+               if first_bracket == null then return false
+
+               # was the first bracket an image?
+               if first_bracket.is_image then return false
+
+               # do we have two closing brackets?
+               if index >= input.length or input.chars[index] != ']' then return false
+
+               advance 1 # skip last bracket
+               var start_index = first_bracket.index + 2
+               var end_index = index - 2
+
+               # create wikilink node
+               var content = input.substring(start_index, end_index - start_index)
+               var parts = content.split("|")
+               var title = if parts.length > 1 then parts.first.trim else null
+               var link = parts.last.trim
+
+               var wikilink = new MdWikilink(
+                               new MdLocation(
+                                       first_bracket.node.location.line_start,
+                                       first_bracket.node.location.column_start - 1,
+                                       line,
+                                       column - 1),
+                       link, title)
+
+               var node = last_bracket.node.next
+               var in_link = false
+               while node != null do
+                       var next = node.next
+                       if not in_link then
+                               if node isa MdText and node.literal.has("|") then
+                                       var buf = new Buffer
+                                       for c in node.literal.chars do
+                                               if c == '|' then
+                                                       in_link = true
+                                                       break
+                                               end
+                                               buf.add c
+                                       end
+                                       node.literal = buf.write_to_string.r_trim
+                               end
+                               wikilink.append_child(node)
+                       else
+                               node.unlink
+                       end
+                       node = next
+               end
+
+               append_node(wikilink)
+
+               # Process delimiters such as emphasis inside a link/image
+               process_delimiters(last_bracket.prev_delimiter)
+               merge_child_text_nodes(wikilink)
+
+               # remove brackets
+               first_bracket.node.unlink
+               last_bracket.node.unlink
+
+               return true
+       end
+end
+
+# A Wikilink node
+class MdWikilink
+       super MdNode
+
+       # Wikilink link
+       var link: String is writable
+
+       # Wikilink title
+       var title: nullable String = null is optional, writable
+end
diff --git a/lib/markdown2/tests/test_markdown_wikilinks.nit b/lib/markdown2/tests/test_markdown_wikilinks.nit
new file mode 100644 (file)
index 0000000..8721e14
--- /dev/null
@@ -0,0 +1,180 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Tests for markdown Wikilinks mode
+module test_markdown_wikilinks is test
+
+import test_markdown
+import test_markdown_location
+import test_markdown_md
+import test_markdown_man
+import test_markdown_latex
+
+redef class TestMarkdown
+       redef var md_parser do
+               var parser = super
+               parser.wikilinks_mode = true
+               return parser
+       end
+end
+
+class TestWikilinksLocation
+       super TestMarkdownLocation
+       test
+
+       fun test_wikilinks1 is test do
+               var md = """
+A [[wiki link]] and text.
+"""
+               var loc = """
+MdDocument: 1,1--1,25
+  MdParagraph: 1,1--1,25
+    MdText: 1,1--1,2
+    MdWikilink: 1,3--1,15
+      MdText: 1,5--1,13
+    MdText: 1,16--1,25
+"""
+               assert md_to_loc(md) == loc
+       end
+
+       fun test_wikilinks2 is test do
+               var md = """
+A [[wiki: link | with: more, args: end]] and text.
+"""
+               var loc = """
+MdDocument: 1,1--1,50
+  MdParagraph: 1,1--1,50
+    MdText: 1,1--1,2
+    MdWikilink: 1,3--1,40
+      MdText: 1,5--1,38
+    MdText: 1,41--1,50
+"""
+               assert md_to_loc(md) == loc
+       end
+
+end
+
+class TestWikilinksHtml
+       super TestMarkdownHtml
+       test
+
+       fun test_wikilinks1 is test do
+               var md = """[[foo]]\n"""
+               var html = """<p><wiki link="foo">foo</wiki></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilinks2 is test do
+               var md = """[[foo | bar baz]]\n"""
+               var html = """<p><wiki link="bar%20baz">foo</wiki></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilinks3 is test do
+               var md = """This is a [[link]] and this is another [[one]].\n"""
+               var html = """<p>This is a <wiki link="link">link</wiki> and this is another <wiki link="one">one</wiki>.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilinks4 is test do
+               var md = """[[very: complex | link: with, more: options]]\n"""
+               var html = """<p><wiki link="link:%20with,%20more:%20options">very: complex</wiki></p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilink_bad1 is test do
+               var md = """Not a [wikilink]].\n"""
+               var html = """<p>Not a [wikilink]].</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilink_bad2 is test do
+               var md = """Not a [[wikilink].\n"""
+               var html = """<p>Not a [[wikilink].</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilink_bad3 is test do
+               var md = """Not a ![[wikilink]].\n"""
+               var html = """<p>Not a ![[wikilink]].</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_wikilink_bad4 is test do
+               var md = """Not a [wikilink].\n"""
+               var html = """<p>Not a [wikilink].</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_link is test do
+               var md = """A standard [link](url).\n"""
+               var html = """<p>A standard <a href="url">link</a>.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_image is test do
+               var md = """A standard ![image](url).\n"""
+               var html = """<p>A standard <img src="url" alt="image" />.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_link_ref1 is test do
+               var md = """A standard [link definition].\n\n[link definition]: url\n"""
+               var html = """<p>A standard <a href="url">link definition</a>.</p>\n"""
+               assert md_to_html(md) == html
+       end
+
+       fun test_link_ref2 is test do
+               var md = """[[wikilinks]] are not \n\n[[link definition]]: url\n"""
+               var html = """<p><wiki link="wikilinks">wikilinks</wiki> are not</p>\n<p><wiki link="link%20definition">link definition</wiki>: url</p>\n"""
+               assert md_to_html(md) == html
+       end
+end
+
+class TestWikilinksMd
+       super TestMarkdownMd
+       test
+
+       fun test_wikilinks_md1 is test do
+               var md = """[[foo]]\n"""
+               assert md_to_md(md) == md
+       end
+
+       fun test_wikilinks_md2 is test do
+               var md = """[[foo: bar | baz: b, c: d]]\n"""
+               assert md_to_md(md) == md
+       end
+end
+
+class TestWikilinksMan
+       super TestMarkdownMan
+       test
+
+       fun test_wikilinks_man is test do
+               var md = """[[foo]]\n"""
+               var man = """\n(foo)\n"""
+               assert md_to_man(md) == man
+       end
+end
+
+class TestWikilinksLatex
+       super TestMarkdownLatex
+       test
+
+       fun test_wikilinks_latex is test do
+               var md = """[[foo]]\n"""
+               var tex = """\\texttt{foo}\n"""
+               assert md_to_tex(md) == tex
+       end
+end