From: Alexandre Terrasa Date: Wed, 30 May 2018 00:02:24 +0000 (-0400) Subject: lib/markdown2: introduce wikilinks parsing X-Git-Url: http://nitlanguage.org lib/markdown2: introduce wikilinks parsing Signed-off-by: Alexandre Terrasa --- diff --git a/lib/markdown2/markdown_html_rendering.nit b/lib/markdown2/markdown_html_rendering.nit index e76fd2d..11addf6 100644 --- a/lib/markdown2/markdown_html_rendering.nit +++ b/lib/markdown2/markdown_html_rendering.nit @@ -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 "" end end + +# Wikilinks mode + +redef class MdWikilink + + # Dummy rendering of wikilinks + # + # Clients should redefine this. + redef fun render_html(v) do + v.add_raw "" + visit_all(v) + v.add_raw "" + end +end diff --git a/lib/markdown2/markdown_latex_rendering.nit b/lib/markdown2/markdown_latex_rendering.nit index a19be27..b7c4abd 100644 --- a/lib/markdown2/markdown_latex_rendering.nit +++ b/lib/markdown2/markdown_latex_rendering.nit @@ -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 diff --git a/lib/markdown2/markdown_man_rendering.nit b/lib/markdown2/markdown_man_rendering.nit index 14ed34b..1e047d6 100644 --- a/lib/markdown2/markdown_man_rendering.nit +++ b/lib/markdown2/markdown_man_rendering.nit @@ -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 diff --git a/lib/markdown2/markdown_md_rendering.nit b/lib/markdown2/markdown_md_rendering.nit index f8fe7ec..eadda1b 100644 --- a/lib/markdown2/markdown_md_rendering.nit +++ b/lib/markdown2/markdown_md_rendering.nit @@ -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 index 0000000..d6cc3a0 --- /dev/null +++ b/lib/markdown2/markdown_wikilinks.nit @@ -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 index 0000000..8721e14 --- /dev/null +++ b/lib/markdown2/tests/test_markdown_wikilinks.nit @@ -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 = """

foo

\n""" + assert md_to_html(md) == html + end + + fun test_wikilinks2 is test do + var md = """[[foo | bar baz]]\n""" + var html = """

foo

\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 = """

This is a link and this is another one.

\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 = """

very: complex

\n""" + assert md_to_html(md) == html + end + + fun test_wikilink_bad1 is test do + var md = """Not a [wikilink]].\n""" + var html = """

Not a [wikilink]].

\n""" + assert md_to_html(md) == html + end + + fun test_wikilink_bad2 is test do + var md = """Not a [[wikilink].\n""" + var html = """

Not a [[wikilink].

\n""" + assert md_to_html(md) == html + end + + fun test_wikilink_bad3 is test do + var md = """Not a ![[wikilink]].\n""" + var html = """

Not a ![[wikilink]].

\n""" + assert md_to_html(md) == html + end + + fun test_wikilink_bad4 is test do + var md = """Not a [wikilink].\n""" + var html = """

Not a [wikilink].

\n""" + assert md_to_html(md) == html + end + + fun test_link is test do + var md = """A standard [link](url).\n""" + var html = """

A standard link.

\n""" + assert md_to_html(md) == html + end + + fun test_image is test do + var md = """A standard ![image](url).\n""" + var html = """

A standard image.

\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 = """

A standard link definition.

\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 = """

wikilinks are not

\n

link definition: url

\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