Merge: nitiwiki: introduce wikilinks
authorJean Privat <jean@pryen.org>
Mon, 11 May 2015 23:22:25 +0000 (19:22 -0400)
committerJean Privat <jean@pryen.org>
Mon, 11 May 2015 23:22:25 +0000 (19:22 -0400)
Nitiwiki now understand the wikilink format using double brackets.

Examples:
`[[foo]]`: link to the page named `foo`
`[[foo/bar]]`: link to the page named `bar` in `foo`
`[[/foo/bar]]`: link to the page located exactly here

It's also possible to add a custom name:
`[[foo|My cute custom name <3]]`: link to the page named `foo`

And to use anchors:
`[[foo#bar]]`: link to the page named `foo`

nitiwiki will display warnings if a link seems broken.

Pull-Request: #1317
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>

34 files changed:
contrib/nitiwiki/Makefile
contrib/nitiwiki/README.md
contrib/nitiwiki/src/nitiwiki.nit
contrib/nitiwiki/src/wiki_base.nit
contrib/nitiwiki/src/wiki_html.nit
contrib/nitiwiki/src/wiki_links.nit [new file with mode: 0644]
contrib/nitiwiki/tests/nitiwiki.args
contrib/nitiwiki/tests/nitiwiki_render.args [deleted file]
contrib/nitiwiki/tests/nitiwiki_status.args [deleted file]
contrib/nitiwiki/tests/res/nitiwiki_render.res [deleted file]
contrib/nitiwiki/tests/res/wiki1_nitiwiki_render.res [new file with mode: 0644]
contrib/nitiwiki/tests/res/wiki1_nitiwiki_status.res [new file with mode: 0644]
contrib/nitiwiki/tests/res/wiki2_nitiwiki_render.res [new file with mode: 0644]
contrib/nitiwiki/tests/res/wiki2_nitiwiki_status.res [moved from contrib/nitiwiki/tests/res/nitiwiki_status.res with 68% similarity]
contrib/nitiwiki/tests/wiki1_nitiwiki_render.args [new file with mode: 0644]
contrib/nitiwiki/tests/wiki1_nitiwiki_status.args [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/assets/css/main.css [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/config.ini [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/pages/contact.md [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/pages/index.md [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/pages/other_page.md [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/pages/sec1/index.md [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/pages/sec2/config.ini [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/pages/sec2/index.md [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/pages/sec2/sub-sec21/index.md [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/pages/sec2/sub-sec22/index.md [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/pages/sec2/sub-sec22/other.md [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/templates/footer.html [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/templates/header.html [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/templates/menu.html [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2/templates/template.html [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2_nitiwiki_render.args [new file with mode: 0644]
contrib/nitiwiki/tests/wiki2_nitiwiki_status.args [new file with mode: 0644]
lib/markdown/markdown.nit

index 2bff3fc..b2b3fed 100644 (file)
@@ -4,8 +4,7 @@ nitiwiki:
        mkdir -p bin
        ../../bin/nitc src/nitiwiki.nit -o bin/nitiwiki
 
-check: tests
-tests: nitiwiki
+check: nitiwiki
        cd tests; make
 
 doc:
index abe84ad..1c764d4 100644 (file)
@@ -128,6 +128,55 @@ For more details on each option see `WikiConfig`.
 
 To add content in your wiki simply add markdown files (with `.md` extension) into the `pages/` folder.
 
+#### Write content
+
+Nitiwiki only support content written in
+[markdown format](http://daringfireball.net/projects/markdown/).
+
+#### Link wiki articles
+
+In nitiwiki, linking to a section or an article is done using the *wikilinks*.
+
+Wikilinks provide easy linking between pages of the wiki.
+To create a wikilink, just put the name of the page to link to in double brackets.
+For example `[[WikiLink]]`.
+
+If you ever need to write something like `[[WikiLink]]` without creating a wikilink,
+just prefix it with a `\\`, like `\\[[WikiLink]]`.
+
+There are some special linking precedence that come into play when linking between
+sections and sub-sections.
+
+Nitiwiki will chose the first entry that match the given wikilinks in that order:
+1. Looks in the current section
+2. Looks in the current section children recursively
+3. Looks in the current section parents until root
+
+To link to or from a subpage, you can use a regular wikilink that does not
+contain the name of the parent directory of the subpage.
+Nikiwiki descends the directory hierarchy looking for a page that matches your link.
+
+For example, if `FooBar/SubPage` links to `OtherPage`, nikiwiki will first prefer
+pointing the link to `FooBar/SubPage/OtherPage` if it exists, next to
+`FooBar/OtherPage` and finally to `OtherPage` in the root of the wiki.
+
+You can also specify a link that contains a relative section name,
+like `FooBar/OtherPage` to specify what page to link to.
+
+You can also use `/` at the start of a link, to specify exactly which page to link to,
+when there are multiple pages with similar names and the link goes to the wrong page by default.
+For example, linking from `FooBar/SubPage` to `/OtherPage` will link to the `OtherPage`
+in the root of the wiki, even if there is a `FooBar/OtherPage`.
+
+It's also possible to write a wikilink that uses something other than the page
+name as the link text.
+For example `[[Contact|Contact me!]]` links to the `Contact` page, but the link
+will appear like this: `Contact me!`.
+
+You can link to an anchor inside a page, using something like `[[WikiLink#foo]]`.
+
+#### Render the wiki in HTML
+
 Once you have done your changes, use:
 
        nitiwiki --status
index 200f971..803da02 100644 (file)
@@ -157,7 +157,11 @@ if opt_rsync.value then
 end
 
 # --status
-if opt_status.value or args.is_empty then
+if opt_status.value or
+       (not opt_clean.value and
+        not opt_fetch.value and
+        not opt_render.value and
+        not opt_rsync.value) then
        wiki.parse
        wiki.status
 end
index 1527d4c..56cbbcb 100644 (file)
@@ -16,7 +16,6 @@
 module wiki_base
 
 import template::macro
-import markdown
 import opts
 import ini
 
@@ -72,6 +71,9 @@ class Nitiwiki
                end
        end
 
+       # Render output.
+       fun render do end
+
        # Show wiki status.
        fun status do
                print "nitiWiki"
@@ -105,7 +107,7 @@ class Nitiwiki
                end
        end
 
-       # Display msg if `level >= verbose_level`
+       # Display msg if `level <= verbose_level`
        fun message(msg: String, level: Int) do
                if level <= verbose_level then print msg
        end
@@ -163,6 +165,7 @@ class Nitiwiki
        # `path` is used to determine the ancestor sections.
        protected fun new_article(path: String): WikiArticle do
                if entries.has_key(path) then return entries[path].as(WikiArticle)
+               message("Found article `{path}`", 2)
                var article = new WikiArticle.from_source(self, path)
                var section = new_section(path.dirname)
                section.add_child(article)
@@ -447,7 +450,7 @@ class WikiSection
        private fun try_load_config do
                var cfile = wiki.expand_path(wiki.config.root_dir, src_path, wiki.config_filename)
                if not cfile.file_exists then return
-               wiki.message("Custom config for section {name}", 2)
+               wiki.message("Custom config for section {name}", 1)
                config = new SectionConfig(cfile)
        end
 
@@ -512,18 +515,13 @@ class WikiArticle
        # Page content.
        #
        # What you want to be displayed in the page.
-       var content: nullable Writable = null
-
-       # Headlines ids and titles.
-       var headlines = new ArrayMap[String, HeadLine]
+       var content: nullable Writable = null is writable
 
-       # Create a new articleu sing a markdown source file.
+       # Create a new article using a markdown source file.
        init from_source(wiki: Nitiwiki, md_file: String) do
                src_full_path = md_file
                init(wiki, md_file.basename(".md"))
-               var md_proc = new MarkdownProcessor
-               content = md_proc.process(md)
-               headlines = md_proc.emitter.decorator.headlines
+               content = md
        end
 
        redef var src_full_path: nullable String = null
@@ -538,8 +536,8 @@ class WikiArticle
        # Extract the markdown text from `source_file`.
        #
        # REQUIRE: `has_source`.
-       var md: String is lazy do
-               assert has_source
+       var md: nullable String is lazy do
+               if not has_source then return null
                var file = new FileReader.open(src_full_path.to_s)
                var md = file.read_all
                file.close
index 3427016..461e9e5 100644 (file)
 # HTML wiki rendering
 module wiki_html
 
-import wiki_base
+import wiki_links
 
 redef class Nitiwiki
 
        # Render HTML output looking for changes in the markdown sources.
-       fun render do
+       redef fun render do
+               super
                if not root_section.is_dirty and not force_render then return
                var out_dir = expand_path(config.root_dir, config.out_dir)
                out_dir.mkdir
@@ -47,10 +48,6 @@ redef class Nitiwiki
 end
 
 redef class WikiEntry
-
-       # Url to `self` once generated.
-       fun url: String do return wiki.config.root_url.join_path(breadcrumbs.join("/"))
-
        # Get a `<a>` template link to `self`
        fun tpl_link: Writable do
                return "<a href=\"{url}\">{title}</a>"
@@ -103,17 +100,6 @@ redef class WikiSection
                end
        end
 
-       # The index page for this section.
-       #
-       # If no file `index.md` exists for this section,
-       # a summary is generated using contained articles.
-       var index: WikiArticle is lazy do
-               for child in children.values do
-                       if child isa WikiArticle and child.is_index then return child
-               end
-               return new WikiSectionIndex(wiki, "index", self)
-       end
-
        redef fun tpl_link do return index.tpl_link
 
        # Render the section hierarchy as a html tree.
@@ -173,26 +159,13 @@ redef class WikiArticle
                end
        end
 
-       redef fun url do
-               if parent == null then
-                       return wiki.config.root_url.join_path("{name}.html")
-               else
-                       return parent.url.join_path("{name}.html")
-               end
-       end
-
-       # Is `self` an index page?
-       #
-       # Checks if `self.name == "index"`.
-       fun is_index: Bool do return name == "index"
-
        redef fun render do
+               super
                if not is_dirty and not wiki.force_render then return
                wiki.message("Render article {name}", 2)
                var file = out_full_path
                file.dirname.mkdir
                tpl_page.write_to_file file
-               super
        end
 
 
@@ -317,15 +290,7 @@ class WikiSitemap
 end
 
 # A `WikiArticle` that contains the section index tree.
-class WikiSectionIndex
-       super WikiArticle
-
-       # The section described by `self`.
-       var section: WikiSection
-
-       redef fun title do return section.title
-
-       redef fun url do return section.url
+redef class WikiSectionIndex
 
        redef var is_dirty = false
 
diff --git a/contrib/nitiwiki/src/wiki_links.nit b/contrib/nitiwiki/src/wiki_links.nit
new file mode 100644 (file)
index 0000000..bbbfea0
--- /dev/null
@@ -0,0 +1,295 @@
+# 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.
+
+# Wiki internal links handling.
+module wiki_links
+
+import wiki_base
+intrude import markdown
+
+redef class Nitiwiki
+       # Looks up a WikiEntry by its `name`.
+       #
+       # Rules are:
+       # 1. Looks in the current section
+       # 2. Looks in the current section children
+       # 3. Looks in the current section parent
+       # 4. Looks up to wiki root
+       #
+       # Returns `null` if no article can be found.
+       fun lookup_entry_by_name(context: WikiEntry, name: String): nullable WikiEntry do
+               var section = context.parent
+               var res = section.lookup_entry_by_name(name)
+               if res != null then return res
+               while section != null do
+                       if section.name == name then return section
+                       if section.children.has_key(name) then return section.children[name]
+                       section = section.parent
+               end
+               return null
+       end
+
+       # Looks up a WikiEntry by its `title`.
+       #
+       # Rules are:
+       # 1. Looks in the current section
+       # 2. Looks in the current section children
+       # 3. Looks in the current section parent
+       # 4. Looks up to wiki root
+       #
+       # Returns `null` if no article can be found.
+       fun lookup_entry_by_title(context: WikiEntry, title: String): nullable WikiEntry do
+               var section = context.parent
+               var res = section.lookup_entry_by_title(title)
+               if res != null then return res
+               while section != null do
+                       if section.title == title then return section
+                       for child in section.children.values do
+                               if child.title == title then return child
+                       end
+                       section = section.parent
+               end
+               return null
+       end
+
+       # Looks up a WikiEntry by its `path`.
+       #
+       # Path can be relative from `context` like `context/entry`.
+       # Or absolute like `/entry1/entry2`.
+       #
+       # Returns `null` if no article can be found.
+       fun lookup_entry_by_path(context: WikiEntry, path: String): nullable WikiEntry do
+               var entry = context.parent
+               var parts = path.split_with("/")
+               if path.has_prefix("/") then
+                       entry = root_section
+                       if parts.is_empty then return root_section.index
+                       parts.shift
+               end
+               while not parts.is_empty do
+                       var name = parts.shift
+                       if name.is_empty then continue
+                       if not entry.children.has_key(name) then return null
+                       entry = entry.children[name]
+               end
+               return entry
+       end
+end
+
+redef class WikiEntry
+
+       # Url to `self` once generated.
+       fun url: String do return wiki.config.root_url.join_path(breadcrumbs.join("/"))
+
+       redef fun render do
+               super
+               if not is_dirty and not wiki.force_render then return
+       end
+
+       # Search in `self` then `self.children` if an entry has the name `name`.
+       fun lookup_entry_by_name(name: String): nullable WikiEntry do
+               if children.has_key(name) then return children[name]
+               for child in children.values do
+                       var res = child.lookup_entry_by_name(name)
+                       if res != null then return res
+               end
+               return null
+       end
+
+       # Search in `self` then `self.children` if an entry has the title `title`.
+       fun lookup_entry_by_title(title: String): nullable WikiEntry do
+               for child in children.values do
+                       if child.title == title then return child
+               end
+               for child in children.values do
+                       var res = child.lookup_entry_by_title(title)
+                       if res != null then return res
+               end
+               return null
+       end
+end
+
+redef class WikiSection
+
+       # The index page for this section.
+       #
+       # If no file `index.md` exists for this section,
+       # a summary is generated using contained articles.
+       var index: WikiArticle is lazy do
+               for child in children.values do
+                       if child isa WikiArticle and child.is_index then return child
+               end
+               return new WikiSectionIndex(wiki, "index", self)
+       end
+end
+
+redef class WikiArticle
+
+       # Headlines ids and titles.
+       var headlines = new ArrayMap[String, HeadLine]
+
+       # Is `self` an index page?
+       #
+       # Checks if `self.name == "index"`.
+       fun is_index: Bool do return name == "index"
+
+       redef fun url do
+               if parent == null then
+                       return wiki.config.root_url.join_path("{name}.html")
+               else
+                       return parent.url.join_path("{name}.html")
+               end
+       end
+
+       redef fun render do
+               super
+               if not is_dirty and not wiki.force_render or not has_source then return
+               var md_proc = new NitiwikiMdProcessor(wiki, self)
+               content = md_proc.process(md.as(not null))
+               headlines.recover_with(md_proc.emitter.decorator.headlines)
+       end
+end
+
+# A `WikiArticle` that contains the section index tree.
+class WikiSectionIndex
+       super WikiArticle
+
+       # The section described by `self`.
+       var section: WikiSection
+
+       redef fun title do return section.title
+
+       redef fun url do return section.url
+end
+
+# A MarkdownProcessor able to parse wiki links.
+class NitiwikiMdProcessor
+       super MarkdownProcessor
+
+       # Wiki used to resolve links.
+       var wiki: Nitiwiki
+
+       # Article parsed by `self`.
+       #
+       # Used to contextualize links.
+       var context: WikiArticle
+
+       init do
+               emitter = new MarkdownEmitter(self)
+               emitter.decorator = new NitiwikiDecorator(wiki, context)
+       end
+
+       redef fun token_at(text, pos) do
+               var token = super
+               if not token isa TokenLink then return token
+               if pos + 1 < text.length then
+                       var c = text[pos + 1]
+                       if c == '[' then return new TokenWikiLink(pos, c)
+               end
+               return token
+       end
+end
+
+private class NitiwikiDecorator
+       super HTMLDecorator
+
+       # Wiki used to resolve links.
+       var wiki: Nitiwiki
+
+       # Article used to contextualize links.
+       var context: WikiArticle
+
+       fun add_wikilink(v: MarkdownEmitter, link: Text, name, comment: nullable Text) do
+               var wiki = v.processor.as(NitiwikiMdProcessor).wiki
+               var target: nullable WikiEntry = null
+               var anchor: nullable String = null
+               if link.has("#") then
+                       var parts = link.split_with("#")
+                       link = parts.first
+                       anchor = parts.subarray(1, parts.length - 1).join("#")
+               end
+               if link.has("/") then
+                       target = wiki.lookup_entry_by_path(context, link.to_s)
+               else
+                       target = wiki.lookup_entry_by_name(context, link.to_s)
+                       if target == null then
+                               target = wiki.lookup_entry_by_title(context, link.to_s)
+                       end
+               end
+               v.add "<a "
+               if target != null then
+                       if name == null then name = target.title
+                       link = target.url
+               else
+                       wiki.message("Warning: unknown wikilink `{link}` (in {context.src_path.as(not null)})", 0)
+                       v.add "class=\"broken\" "
+               end
+               v.add "href=\""
+               append_value(v, link)
+               if anchor != null then append_value(v, "#{anchor}")
+               v.add "\""
+               if comment != null and not comment.is_empty then
+                       v.add " title=\""
+                       append_value(v, comment)
+                       v.add "\""
+               end
+               v.add ">"
+               if name == null then name = link
+               v.emit_text(name)
+               v.add "</a>"
+       end
+end
+
+# A NitiWiki link token.
+#
+# Something of the form `[[foo]]`.
+#
+# Allowed formats:
+#
+# * `[[Wikilink]]`
+# * `[[Wikilink/Bar]]`
+# * `[[Wikilink#foo]]`
+# * `[[Wikilink/Bar#foo]]`
+# * `[[title|Wikilink]]`
+# * `[[title|Wikilink/Bar]]`
+# * `[[title|Wikilink/Bar#foo]]`
+class TokenWikiLink
+       super TokenLink
+
+       redef fun emit_hyper(v) do
+               v.decorator.as(NitiwikiDecorator).add_wikilink(v, link.as(not null), name, comment)
+       end
+
+       redef fun check_link(v, out, start, token) do
+               var md = v.current_text
+               var pos = start + 2
+               var tmp = new FlatBuffer
+               pos = md.read_md_link_id(tmp, pos)
+               if pos < start then return -1
+               var name = tmp.write_to_string
+               if name.has("|") then
+                       var parts = name.split_once_on("|")
+                       self.name = parts.first
+                       self.link = parts[1]
+               else
+                       self.name = null
+                       self.link = name
+               end
+               pos += 1
+               pos = md.skip_spaces(pos)
+               if pos < start then return -1
+               pos += 1
+               return pos
+       end
+end
diff --git a/contrib/nitiwiki/tests/nitiwiki_render.args b/contrib/nitiwiki/tests/nitiwiki_render.args
deleted file mode 100644 (file)
index 6f7050e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-nitiwiki --config wiki1/config.ini --clean --render -v
diff --git a/contrib/nitiwiki/tests/nitiwiki_status.args b/contrib/nitiwiki/tests/nitiwiki_status.args
deleted file mode 100644 (file)
index aa96d13..0000000
+++ /dev/null
@@ -1 +0,0 @@
-nitiwiki --config wiki1/config.ini --clean --status
diff --git a/contrib/nitiwiki/tests/res/nitiwiki_render.res b/contrib/nitiwiki/tests/res/nitiwiki_render.res
deleted file mode 100644 (file)
index 25f17ab..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-Render section out
-Render section out/sec1
-Render section out/sec2
-Render auto-index for section out/sec2
-Render section out/sec2/sub-sec21
-Render section out/sec2/sub-sec22
diff --git a/contrib/nitiwiki/tests/res/wiki1_nitiwiki_render.res b/contrib/nitiwiki/tests/res/wiki1_nitiwiki_render.res
new file mode 100644 (file)
index 0000000..adf25a7
--- /dev/null
@@ -0,0 +1 @@
+Render section out
diff --git a/contrib/nitiwiki/tests/res/wiki1_nitiwiki_status.res b/contrib/nitiwiki/tests/res/wiki1_nitiwiki_status.res
new file mode 100644 (file)
index 0000000..936a764
--- /dev/null
@@ -0,0 +1,10 @@
+nitiWiki
+name: wiki1
+config: wiki1/config.ini
+url: http://localhost/
+
+There is modified files:
+ + pages
+ + /pages/index.md
+
+Use nitiwiki --render to render modified files
diff --git a/contrib/nitiwiki/tests/res/wiki2_nitiwiki_render.res b/contrib/nitiwiki/tests/res/wiki2_nitiwiki_render.res
new file mode 100644 (file)
index 0000000..46cf17c
--- /dev/null
@@ -0,0 +1,20 @@
+Custom config for section sec2
+Render section out
+Warning: unknown wikilink `not found` (in /pages/index.md)
+Warning: unknown wikilink `Not Found` (in /pages/index.md)
+Warning: unknown wikilink `/not/found` (in /pages/index.md)
+Warning: unknown wikilink `not/found` (in /pages/index.md)
+Warning: unknown wikilink `not found` (in /pages/index.md)
+Warning: unknown wikilink `not found` (in /pages/index.md)
+Warning: unknown wikilink `not found` (in /pages/index.md)
+Render section out/sec1
+Render section out/sec2
+Warning: unknown wikilink `not found` (in /pages/sec2/index.md)
+Warning: unknown wikilink `Not Found` (in /pages/sec2/index.md)
+Warning: unknown wikilink `/not/found` (in /pages/sec2/index.md)
+Warning: unknown wikilink `not/found` (in /pages/sec2/index.md)
+Warning: unknown wikilink `not found` (in /pages/sec2/index.md)
+Warning: unknown wikilink `not found` (in /pages/sec2/index.md)
+Warning: unknown wikilink `not found` (in /pages/sec2/index.md)
+Render section out/sec2/sub-sec21
+Render section out/sec2/sub-sec22
@@ -1,17 +1,21 @@
 nitiWiki
-name: wiki1
-config: wiki1/config.ini
+name: wiki2
+config: wiki2/config.ini
 url: http://localhost/
 
 There is modified files:
  + pages
+ + /pages/contact.md
  + /pages/index.md
+ + /pages/other_page.md
  + pages/sec1
  + /pages/sec1/index.md
  + pages/sec2
+ + /pages/sec2/index.md
  + pages/sec2/sub-sec21
  + /pages/sec2/sub-sec21/index.md
  + pages/sec2/sub-sec22
  + /pages/sec2/sub-sec22/index.md
+ + /pages/sec2/sub-sec22/other.md
 
 Use nitiwiki --render to render modified files
diff --git a/contrib/nitiwiki/tests/wiki1_nitiwiki_render.args b/contrib/nitiwiki/tests/wiki1_nitiwiki_render.args
new file mode 100644 (file)
index 0000000..a7633a0
--- /dev/null
@@ -0,0 +1 @@
+../bin/nitiwiki --config wiki1/config.ini --clean --render -v
diff --git a/contrib/nitiwiki/tests/wiki1_nitiwiki_status.args b/contrib/nitiwiki/tests/wiki1_nitiwiki_status.args
new file mode 100644 (file)
index 0000000..d4b6826
--- /dev/null
@@ -0,0 +1 @@
+../bin/nitiwiki --config wiki1/config.ini --clean --status
diff --git a/contrib/nitiwiki/tests/wiki2/assets/css/main.css b/contrib/nitiwiki/tests/wiki2/assets/css/main.css
new file mode 100644 (file)
index 0000000..b3c3af5
--- /dev/null
@@ -0,0 +1,3 @@
+dummy { margin: 0 }
+
+a.broken { font-style: italic; color: red }
diff --git a/contrib/nitiwiki/tests/wiki2/config.ini b/contrib/nitiwiki/tests/wiki2/config.ini
new file mode 100644 (file)
index 0000000..ba285d6
--- /dev/null
@@ -0,0 +1,2 @@
+wiki.name=wiki2
+wiki.root_dir=wiki2
diff --git a/contrib/nitiwiki/tests/wiki2/pages/contact.md b/contrib/nitiwiki/tests/wiki2/pages/contact.md
new file mode 100644 (file)
index 0000000..09f7129
--- /dev/null
@@ -0,0 +1 @@
+# Contact
diff --git a/contrib/nitiwiki/tests/wiki2/pages/index.md b/contrib/nitiwiki/tests/wiki2/pages/index.md
new file mode 100644 (file)
index 0000000..9ad0a4d
--- /dev/null
@@ -0,0 +1,63 @@
+# Test wikilinks
+
+## Link to entries by name
+
+* Link to [[sec1]]
+* Link to [[sec2]]
+* Link to [[contact]]
+* Link to [[other_page]]
+* Link to [[other]]
+* Link to [[not found]]
+
+## Link to entries by title
+
+* Link to [[Sec1]]
+* Link to [[Section 2]]
+* Link to [[Contact]]
+* Link to [[Other Page]]
+* Link to [[Other]]
+* Link to [[Not Found]]
+
+## Link to entries by absolute path
+
+* Link to [[/index]]
+* Link to [[/sec1]]
+* Link to [[/sec1/index]]
+* Link to [[/sec1/]]
+* Link to [[/sec2/sub-sec22]]
+* Link to [[/sec2/sub-sec22/]]
+* Link to [[/sec2/sub-sec22/index]]
+* Link to [[/sec2/sub-sec22/other]]
+* Link to [[/not/found]]
+
+## Link to entries by relative path
+
+* Link to [[sec1]]
+* Link to [[sec1/index]]
+* Link to [[sec1/]]
+* Link to [[sec2/sub-sec22]]
+* Link to [[sec2/sub-sec22/]]
+* Link to [[sec2/sub-sec22/index]]
+* Link to [[sec2/sub-sec22/other]]
+* Link to [[not/found]]
+
+## Link with custom text
+
+* Link to [[1Fooi|Other Page]]
+* Link to [[2 Foo bar|/sec2/sub-sec22/index]]
+* Link to [[3|sec2/sub-sec22/other]]
+* Link to [[foo>bar>bar|other_page]]
+* Link to [[5|not found]]
+
+## Link with anchors
+
+* Link to [[Other Page#Foo]]
+* Link to [[/sec2/sub-sec22/index#2 Foo bar]]
+* Link to [[sec2/sub-sec22/other#3]]
+* Link to [[other_page#4]]
+* Link to [[not found#5_lol]]
+* Link to [[1|Other Page#Foo]]
+* Link to [[2|/sec2/sub-sec22/index#2 Foo bar]]
+* Link to [[3|sec2/sub-sec22/other#3]]
+* Link to [[4|other_page#4foobar#baz]]
+* Link to [[5|not found#5]]
diff --git a/contrib/nitiwiki/tests/wiki2/pages/other_page.md b/contrib/nitiwiki/tests/wiki2/pages/other_page.md
new file mode 100644 (file)
index 0000000..a1ca7d9
--- /dev/null
@@ -0,0 +1 @@
+# Other Page
diff --git a/contrib/nitiwiki/tests/wiki2/pages/sec1/index.md b/contrib/nitiwiki/tests/wiki2/pages/sec1/index.md
new file mode 100644 (file)
index 0000000..7c2fd43
--- /dev/null
@@ -0,0 +1 @@
+# Section 1
diff --git a/contrib/nitiwiki/tests/wiki2/pages/sec2/config.ini b/contrib/nitiwiki/tests/wiki2/pages/sec2/config.ini
new file mode 100644 (file)
index 0000000..dcde4cc
--- /dev/null
@@ -0,0 +1 @@
+section.title=Section 2
diff --git a/contrib/nitiwiki/tests/wiki2/pages/sec2/index.md b/contrib/nitiwiki/tests/wiki2/pages/sec2/index.md
new file mode 100644 (file)
index 0000000..c81eb7d
--- /dev/null
@@ -0,0 +1,58 @@
+# Test wikilinks
+
+## Link to entries by name
+
+* Link to [[sec1]]
+* Link to [[sec2]]
+* Link to [[contact]]
+* Link to [[other_page]]
+* Link to [[not found]]
+
+## Link to entries by title
+
+* Link to [[Sec1]]
+* Link to [[Section 2]]
+* Link to [[Contact]]
+* Link to [[Other Page]]
+* Link to [[Not Found]]
+
+## Link to entries by absolute path
+
+* Link to [[/index]]
+* Link to [[/sec1]]
+* Link to [[/sec1/index]]
+* Link to [[/sec1/]]
+* Link to [[/sec2/sub-sec22]]
+* Link to [[/sec2/sub-sec22/]]
+* Link to [[/sec2/sub-sec22/index]]
+* Link to [[/sec2/sub-sec22/other]]
+* Link to [[/not/found]]
+
+## Link to entries by relative path
+
+* Link to [[sub-sec22]]
+* Link to [[sub-sec22/index]]
+* Link to [[sub-sec22/other]]
+* Link to [[sub-sec22/]]
+* Link to [[not/found]]
+
+## Link with custom text
+
+* Link to [[1Foo|Other Page]]
+* Link to [[2 Foo bar|/sec2/sub-sec22/index]]
+* Link to [[3|sub-sec22/other]]
+* Link to [[4foo>bar>baz|other_page]]
+* Link to [[5|not found]]
+
+## Link with anchors
+
+* Link to [[Other Page#Foo]]
+* Link to [[/sec2/sub-sec22/index#2 Foo bar]]
+* Link to [[sub-sec22/other#3]]
+* Link to [[other_page#4]]
+* Link to [[not found#5_lol]]
+* Link to [[1|Other Page#Foo]]
+* Link to [[2|/sec2/sub-sec22/index#2 Foo bar]]
+* Link to [[3|sub-sec22/other#3]]
+* Link to [[4|other_page#4foobar#baz]]
+* Link to [[5|not found#5]]
diff --git a/contrib/nitiwiki/tests/wiki2/pages/sec2/sub-sec21/index.md b/contrib/nitiwiki/tests/wiki2/pages/sec2/sub-sec21/index.md
new file mode 100644 (file)
index 0000000..4c40d90
--- /dev/null
@@ -0,0 +1 @@
+# Section 2-1
diff --git a/contrib/nitiwiki/tests/wiki2/pages/sec2/sub-sec22/index.md b/contrib/nitiwiki/tests/wiki2/pages/sec2/sub-sec22/index.md
new file mode 100644 (file)
index 0000000..03e06f2
--- /dev/null
@@ -0,0 +1 @@
+# Section 2-2
diff --git a/contrib/nitiwiki/tests/wiki2/pages/sec2/sub-sec22/other.md b/contrib/nitiwiki/tests/wiki2/pages/sec2/sub-sec22/other.md
new file mode 100644 (file)
index 0000000..10a1342
--- /dev/null
@@ -0,0 +1 @@
+# Other page
diff --git a/contrib/nitiwiki/tests/wiki2/templates/footer.html b/contrib/nitiwiki/tests/wiki2/templates/footer.html
new file mode 100644 (file)
index 0000000..7506b39
--- /dev/null
@@ -0,0 +1,10 @@
+<div class="row footer">
+       <div class="container-fluid">
+               <div class="well well-sm">
+                       <p><strong>%TITLE% &copy; %YEAR%</strong></p>
+                       <p class="text-muted"><em>last modification %GEN_TIME%</em></p>
+                       <p class="text-muted">Proudly powered by
+                               <a href="http://nitlanguage.org">nit</a>!</p>
+               </div>
+       </div>
+</div>
diff --git a/contrib/nitiwiki/tests/wiki2/templates/header.html b/contrib/nitiwiki/tests/wiki2/templates/header.html
new file mode 100644 (file)
index 0000000..1cb06bf
--- /dev/null
@@ -0,0 +1,9 @@
+<div class="container-fluid header">
+       <div class="container">
+               <div class="header">
+                       <a href="http://uqam.ca"><img src="%ROOT_URL%/%LOGO%" alt="logo" /></a>
+                       <h2>%SUBTITLE%</h2>
+                       <h1>%TITLE%</h1>
+               </div>
+       </div>
+</div>
diff --git a/contrib/nitiwiki/tests/wiki2/templates/menu.html b/contrib/nitiwiki/tests/wiki2/templates/menu.html
new file mode 100644 (file)
index 0000000..1ff832e
--- /dev/null
@@ -0,0 +1,20 @@
+<nav class="menu" role="navigation">
+       <div class="container">
+               <!-- Brand and toggle get grouped for better mobile display -->
+               <div class="navbar-header">
+                       <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
+                               <span class="sr-only">Toggle navigation</span>
+                               <span class="icon-bar"></span>
+                               <span class="icon-bar"></span>
+                               <span class="icon-bar"></span>
+                       </button>
+                       <a class="navbar-brand" href="%ROOT_URL%index.html">%TITLE%</a>
+               </div>
+               <!-- Collect the nav links, forms, and other content for toggling -->
+               <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+                       <ul class="nav navbar-nav">
+                       %MENUS%
+                       </ul>
+               </div><!-- /.navbar-collapse -->
+       </div>
+</nav>
diff --git a/contrib/nitiwiki/tests/wiki2/templates/template.html b/contrib/nitiwiki/tests/wiki2/templates/template.html
new file mode 100644 (file)
index 0000000..6b3b126
--- /dev/null
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+       <head>
+               <meta charset="utf-8">
+               <meta http-equiv="X-UA-Compatible" content="IE=edge">
+               <meta name="viewport" content="width=device-width, initial-scale=1">
+               <title>%TITLE%</title>
+
+               <link href="%ROOT_URL%/assets/vendors/bootstrap/bootstrap-3.2.0-dist/css/bootstrap.min.css" rel="stylesheet">
+               <link href="%ROOT_URL%/assets/css/main.css" rel="stylesheet">
+
+               <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
+               <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+               <!--[if lt IE 9]>
+               <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+               <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+               <![endif]-->
+       </head>
+       <body>
+               %HEADER%
+               %TOP_MENU%
+               <div class="container">
+                       <div class="row">
+                               %BODY%
+                       </div>
+                       %FOOTER%
+               </div>
+
+               <script src="%ROOT_URL%/vendors/jquery/jquery-1.11.1.min.js"></script>
+               <script src="%ROOT_URL%/vendors/bootstrap/bootstrap-3.2.0-dist/js/bootstrap.min.js"></script>
+       </body>
+</html>
diff --git a/contrib/nitiwiki/tests/wiki2_nitiwiki_render.args b/contrib/nitiwiki/tests/wiki2_nitiwiki_render.args
new file mode 100644 (file)
index 0000000..d4d6ee6
--- /dev/null
@@ -0,0 +1 @@
+../bin/nitiwiki --config wiki2/config.ini --clean --render -v
diff --git a/contrib/nitiwiki/tests/wiki2_nitiwiki_status.args b/contrib/nitiwiki/tests/wiki2_nitiwiki_status.args
new file mode 100644 (file)
index 0000000..d2da70b
--- /dev/null
@@ -0,0 +1 @@
+../bin/nitiwiki --config wiki2/config.ini --clean --status
index 10dbcc6..7b7d319 100644 (file)
@@ -244,7 +244,7 @@ class MarkdownProcessor
        #
        # Markdown allows link refs to be defined over two lines:
        #
-       #       [id]: http://example.com/longish/path/to/resource/here
+       #       [id]: http://example.com/longish/path/to/resource/here
        #               "Optional Title Here"
        #
        private var last_link_ref: nullable LinkRef = null
@@ -2000,7 +2000,7 @@ abstract class TokenLinkOrImage
                                comment = lr.title
                        end
                else
-               var tid = name.write_to_string.replace("\n", " ").to_lower
+                       var tid = name.write_to_string.replace("\n", " ").to_lower
                        if v.processor.link_refs.has_key(tid) then
                                var lr = v.processor.link_refs[tid]
                                link = lr.link