Merge: Add trails to nitiwiki
authorJean Privat <jean@pryen.org>
Thu, 12 Nov 2015 01:43:47 +0000 (20:43 -0500)
committerJean Privat <jean@pryen.org>
Thu, 12 Nov 2015 01:43:47 +0000 (20:43 -0500)
Wikilinks, with the directive `trail`, will register the target page as an element of a trail.
Each `trail` are chained together and will display navigational link `prev` for the previous page of the trail, `next` for the next page of the trail and `up` to go to the pages that has used the `trail` wikilink.

For instance, if the page `doc.md` has the following content:

~~~md
To use nitiwiki, first [[trail: install|install it]],
then [[trail: simple_wiki|create a first wiki]].

You can also do advanced things like:

* [[trail: github|editing pages with github]]
* [[trail: templating| adapting the templates]]
~~~

A trail will be made and will consist of the sequence of pages `install`, `simple_wiki`, `github` and `templating`.
On each one of these pages, there will be links for the previous, the next page and the `doc.md` pae.

If a page includes trail wikilinks and is also the target for trail wikilinks, then the two trails are merged and pages will be visitable in a depth-first order.
This nesting of trails can be used to have sections and sub-sections.

Demo is up: http://info.uqam.ca/~privat/nitlanguage/manual/

Pull-Request: #1830
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>

15 files changed:
contrib/nitiwiki/README.md
contrib/nitiwiki/examples/default/templates/template.html
contrib/nitiwiki/examples/nitiwiki/assets/css/main.css
contrib/nitiwiki/examples/nitiwiki/pages/section/a_last_page.md [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/pages/section/a_page.md [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/pages/section/another_page.md [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/pages/section/index.md [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/pages/section/sub_section/bar.md [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/pages/section/sub_section/foo.md [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/pages/section/sub_section/index.md [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/templates/template.html
contrib/nitiwiki/src/wiki_html.nit
contrib/nitiwiki/src/wiki_links.nit
contrib/nitiwiki/tests/res/wiki2_nitiwiki_render.res
contrib/nitiwiki/tests/res/wiki3_nitiwiki_render.res

index 77e0b56..f9c7c45 100644 (file)
@@ -174,6 +174,29 @@ will appear like this: `Contact me!`.
 
 You can link to an anchor inside a page, using something like `[[WikiLink#foo]]`.
 
+#### Trails of Pages
+
+Wikilinks, with the directive `trail`, will register the target page as an element of a trail.
+Each `trail` are chained together and will display navigational link `prev` for the previous page of the trail, `next` for the next page of the trail and `up` to go to the pages that has used the `trail` wikilink.
+
+For instance, if the page `doc.md` has the following content:
+
+~~~md
+To use nitiwiki, first [[trail: install|install it]],
+then [[trail: simple_wiki|create a first wiki]].
+
+You can also do advanced things like:
+
+* [[trail: github|editing pages with github]]
+* [[trail: templating| adapting the templates]]
+~~~
+
+A trail will be made and will consist of the sequence of pages `install`, `simple_wiki`, `github` and `templating`.
+On each one of these pages, there will be links for the previous page, the next page and the `doc.md` page.
+
+If a page includes trail wikilinks and is also the target for trail wikilinks, then the two trails are merged and pages will be visitable in a depth-first order.
+This nesting of trails can be used to have sections and sub-sections.
+
 #### Render the wiki in HTML
 
 Once you have done your changes, use:
@@ -243,7 +266,9 @@ The template file `template.html` represents the overall structure of your wiki
                        %HEADER%
                        %TOP_MENU%
                        <div>
+                               %TRAIL%
                                %BODY%
+                               %TRAIL%
                                %FOOTER%
                        </div>
                </body>
@@ -256,6 +281,7 @@ Additionnal macros:
 * `TOP_MENU`: Wiki top menu (see [Topmenu template](#Topmenu_template))
 * `HEADER`: Wiki header (see [Header template](#Header_template))
 * `BODY`: Wiki body content
+* `TRAIL`: content of the trail navigational links, if any (see [Trails of Pages](#Trails_of_Pages))
 
 ### Header template
 
index 692a999..f7061a0 100644 (file)
@@ -8,7 +8,9 @@
         %HEADER%
         %TOP_MENU%
         <div>
+            %TRAIL%
             %BODY%
+            %TRAIL%
             %FOOTER%
         </div>
     </body>
index c00394a..63dda7c 100644 (file)
@@ -28,3 +28,17 @@ footer {
 .summary li li li { font-size: 12px; font-weight: normal }
 
 .breadcrumb { margin-top: 20px; }
+
+.trail {
+       list-style-type: none;
+       color: #838183;
+       text-align: center;
+}
+
+.trail li{
+       display: inline;
+}
+
+.trail li+li:before{
+       content: " | ";
+}
diff --git a/contrib/nitiwiki/examples/nitiwiki/pages/section/a_last_page.md b/contrib/nitiwiki/examples/nitiwiki/pages/section/a_last_page.md
new file mode 100644 (file)
index 0000000..885663d
--- /dev/null
@@ -0,0 +1 @@
+# a last page
diff --git a/contrib/nitiwiki/examples/nitiwiki/pages/section/a_page.md b/contrib/nitiwiki/examples/nitiwiki/pages/section/a_page.md
new file mode 100644 (file)
index 0000000..bf5a54f
--- /dev/null
@@ -0,0 +1 @@
+# a page
diff --git a/contrib/nitiwiki/examples/nitiwiki/pages/section/another_page.md b/contrib/nitiwiki/examples/nitiwiki/pages/section/another_page.md
new file mode 100644 (file)
index 0000000..ec67b83
--- /dev/null
@@ -0,0 +1 @@
+# another page
diff --git a/contrib/nitiwiki/examples/nitiwiki/pages/section/index.md b/contrib/nitiwiki/examples/nitiwiki/pages/section/index.md
new file mode 100644 (file)
index 0000000..229d1f0
--- /dev/null
@@ -0,0 +1,7 @@
+
+# Example of trail
+
+* [[trail: a_page]]
+* [[trail: another_page]]
+* [[trail: sub_section]]
+* [[trail: a_last_page]]
diff --git a/contrib/nitiwiki/examples/nitiwiki/pages/section/sub_section/bar.md b/contrib/nitiwiki/examples/nitiwiki/pages/section/sub_section/bar.md
new file mode 100644 (file)
index 0000000..d93e603
--- /dev/null
@@ -0,0 +1 @@
+# bar
diff --git a/contrib/nitiwiki/examples/nitiwiki/pages/section/sub_section/foo.md b/contrib/nitiwiki/examples/nitiwiki/pages/section/sub_section/foo.md
new file mode 100644 (file)
index 0000000..c2a8392
--- /dev/null
@@ -0,0 +1 @@
+# foo
diff --git a/contrib/nitiwiki/examples/nitiwiki/pages/section/sub_section/index.md b/contrib/nitiwiki/examples/nitiwiki/pages/section/sub_section/index.md
new file mode 100644 (file)
index 0000000..040e564
--- /dev/null
@@ -0,0 +1,4 @@
+# A sub-section
+
+* [[trail: foo]]
+* [[trail: bar]]
index 7c43833..57196fa 100644 (file)
@@ -21,7 +21,9 @@
                %TOP_MENU%
                <div class="container">
                        <div class="row">
+                               %TRAIL%
                                %BODY%
+                               %TRAIL%
                        </div>
                        %FOOTER%
                </div>
index 2e96567..05c06f9 100644 (file)
@@ -95,6 +95,9 @@ redef class WikiSection
                        index.is_dirty = true
                        add_child index
                end
+               # Hack: Force the rendering of `index` first so that trails are collected
+               # TODO: Add first-pass analysis to collect global information before doing the rendering
+               index.render
                super
        end
 
@@ -209,6 +212,9 @@ redef class WikiArticle
                if tpl.has_macro("FOOTER") then
                        tpl.replace("FOOTER", tpl_footer)
                end
+               if tpl.has_macro("TRAIL") then
+                       tpl.replace("TRAIL", tpl_trail)
+               end
                return tpl
        end
 
@@ -293,6 +299,37 @@ redef class WikiArticle
                return tpl
        end
 
+       # Generate navigation links for the trail of this article, if any.
+       #
+       # A trail is generated if the article include or is included in a trail.
+       # See `wiki.trails` for details.
+       fun tpl_trail: Writable do
+               if not wiki.trails.has(self) then return ""
+
+               # Get the position of `self` in the trail
+               var flat = wiki.trails.to_a
+               var pos = flat.index_of(self)
+               assert pos >= 0
+
+               var res = new Template
+               res.add "<ul class=\"trail\">"
+               if pos > 0 then
+                       var target = flat[pos-1]
+                       res.add "<li>{target.a_from(self, "prev")}</li>"
+               end
+               var parent = wiki.trails.parent(self)
+               if parent != null then
+                       res.add "<li>{parent.a_from(self, "up")}</li>"
+               end
+               if pos < flat.length - 1 then
+                       var target = flat[pos+1]
+                       res.add "<li>{target.a_from(self, "next")}</li>"
+               end
+               res.add "</ul>"
+
+               return res
+       end
+
        # Generate the HTML footer for this article.
        fun tpl_footer: Writable do
                var file = footer_file
index efb9f78..03f21ca 100644 (file)
@@ -17,6 +17,7 @@ module wiki_links
 
 import wiki_base
 import markdown::wikilinks
+import ordered_tree
 
 redef class Nitiwiki
        # Looks up a WikiEntry by its `name`.
@@ -86,6 +87,12 @@ redef class Nitiwiki
                end
                return entry
        end
+
+       # Trails between pages
+       #
+       # Trails are represented as a forest of entries.
+       # This way it is possible to represent a flat-trail as a visit of a tree.
+       var trails = new OrderedTree[WikiEntry]
 end
 
 redef class WikiEntry
@@ -102,6 +109,17 @@ redef class WikiEntry
                return res
        end
 
+       # A relative hyperlink <a> to `self` from the page `context`.
+       #
+       # If `text` is not given, `title` will be used instead.
+       fun a_from(context: WikiEntry, text: nullable Text): Writable
+       do
+               var title = title.html_escape
+               if text == null then text = title else text = text.html_escape
+               var href = href_from(context)
+               return """<a href="{{{href}}}" title="{{{title}}}">{{{text}}}</a>"""
+       end
+
        redef fun render do
                super
                if not is_dirty and not wiki.force_render then return
@@ -233,6 +251,14 @@ class NitiwikiDecorator
                var name = token.name
                v.add "<a "
                if not link.has_prefix("http://") and not link.has_prefix("https://") then
+                       # Extract commands from the link.
+                       var command = null
+                       var command_split = link.split_once_on(":")
+                       if command_split.length > 1 then
+                               command = command_split[0].trim
+                               link = command_split[1].trim
+                       end
+
                        if link.has("#") then
                                var parts = link.split_with("#")
                                link = parts.first
@@ -249,6 +275,11 @@ class NitiwikiDecorator
                        if target != null then
                                if name == null then name = target.title
                                link = target.href_from(context)
+
+                               if command == "trail" then
+                                       if target isa WikiSection then target = target.index
+                                       wiki.trails.add(context, target)
+                               end
                        else
                                wiki.message("Warning: unknown wikilink `{link}` (in {context.src_path.as(not null)})", 0)
                                v.add "class=\"broken\" "
index 1bf4497..cdba310 100644 (file)
@@ -1,5 +1,4 @@
 Render section pages -> out
-Render article contact -> wiki2/out/contact.html
 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)
@@ -8,6 +7,7 @@ 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 article index -> wiki2/out/index.html
+Render article contact -> wiki2/out/contact.html
 Render article other_page -> wiki2/out/other_page.html
 Render section sec1 -> out/sec1
 Render article index -> wiki2/out/sec1/index.html
index 2199343..65466e3 100644 (file)
@@ -1,5 +1,5 @@
 Render section pages -> out
-Render article contact -> wiki3/out/contact.html
 Render article index -> wiki3/out/index.html
+Render article contact -> wiki3/out/contact.html
 Render article other_page -> wiki3/out/other_page.html
 Render article sitemap -> wiki3/out/sitemap.html