Browse Source

Add github wiki plugin and update readme

Rhys Tyers 7 years ago
parent
commit
7b28675cc0
6 changed files with 223 additions and 0 deletions
  1. 2 0
      Readme.rst
  2. 43 0
      github-wiki/ReadMe.md
  3. 1 0
      github-wiki/__init__.py
  4. 13 0
      github-wiki/wiki.js
  5. 98 0
      github-wiki/wiki.py
  6. 66 0
      github-wiki/wikiarticle.html

+ 2 - 0
Readme.rst

@@ -100,6 +100,8 @@ Gallery                   Allows an article to contain an album of pictures
 
 Gist directive            This plugin adds a ``gist`` reStructuredText directive.
 
+GitHub wiki               Converts a flat github wiki into a structured read only wiki on your site
+
 GitHub activity           On the template side, you just have to iterate over the ``github_activity`` variable
 
 Global license            Allows you to define a ``LICENSE`` setting and adds the contents of that license variable to the article's context

+ 43 - 0
github-wiki/ReadMe.md

@@ -0,0 +1,43 @@
+# GitHub Wiki
+A plugin to convert a flat GitHub wiki into a structured 'read-only' wiki on your pelican site.
+
+## Usage
+
+The plugin looks for a GitHub style wiki (flat collection of md files) at `content\wiki`. You can clone a wiki with:
+
+    git clone https://github.com/YOUR_USERNAME/YOUR_REPOSITORY.wiki.git
+
+And you can also do clever things to set this up as a submodule of your main pelican site repo.
+
+The plugin needs a `wikiarticle.html` template in your theme templates folder. An example template file is provided. 
+
+The resulting wiki will be available at `output\wiki`. 
+
+## Structure
+
+By default the generated wiki will also be flat with no heirarchy to the pages. This plugin allows you to automatically generate a virtual file structure.
+
+In order to provide a structure to the wiki each page can be given the `Path:` metadata.
+
+    Path: foo/bar/baz
+
+This will allow a correctly set up template to generate breadcrumbs and a structured menu where this page will be under the `foo/bar/baz`. Note: The plugin does not actually make this folder structure in the output (this is to make is easier to associate the 
+generated pages with their original wiki pages). 
+
+If a page has the same name and location in the structure as a virtual folder (i.e For the path given above, a file called `bar.md` with the path `Path: foo`) then the breadcrumbs and menu can link to that page as though it were the index of that vritual folder.
+
+## Template
+
+The template is given the following variables.
+
+- `content`: The template has the usual `content` variable available for the converted html of the wiki page. 
+- `breadcrumbs`: A list of tuples describing a 'path' to the current wiki page. The first value is the name of a parent page (in order). The second value is either 'a' or 'p'. 'a' means that the parent page exists and can be linked to, 'p' means the parent page 
+doesn't 
+exist and is just there for descriptibe purposes.
+- `links`: A list of tuples describing a site map of the wiki. The first value is the name of the page, the second value is either 'indexdir' or 'noindexdir' if the page has or does not have subpages respectively, and the third value is the level of the page 
+within the wiki (how many parents it has).
+
+Also provided is a simple javascript file to make the structured menu in the example template openable/closable. 
+
+Though you cannot edit this 'wiki' directly from your site an example of how to emulate wiki editing behaviour is shown in the example template. You can link directly to the github edit page for the wiki page you're on allowing your Github contributers to very 
+easily edit pages. Combined with hooks to redeploy your wiki this can emulate a real wiki quite well.

+ 1 - 0
github-wiki/__init__.py

@@ -0,0 +1 @@
+from .wiki import *

+ 13 - 0
github-wiki/wiki.js

@@ -0,0 +1,13 @@
+window.addEventListener("load", function() {
+  document.querySelector(".wiki-nav-button").addEventListener('click', function(event) {
+    document.querySelector(".wiki-links").classList.toggle('nodisplay');
+    event.target.text = event.target.text == "Expand Menu" ? "Collapse Menu" : "Expand Menu";
+  }, false);
+  var expanders = document.querySelectorAll(".wiki-dir-expander");
+  for (i = 0; i < expanders.length; ++i) {
+    expanders[i].addEventListener('click', function(event) {
+      event.target.parentElement.nextSibling.nextSibling.classList.toggle("nodisplay");
+      event.target.text = event.target.text == "+" ? "-" : "+";
+    }, false);
+  };
+}, false);

+ 98 - 0
github-wiki/wiki.py

@@ -0,0 +1,98 @@
+from pelican import signals, utils
+from collections import namedtuple, OrderedDict
+import os
+import re
+import logging
+
+def add_to_structure(structure, path_list):
+    folders = structure["folders"]
+    articles = structure["articles"]
+    subdir = path_list[0]
+    rest = path_list[1:]
+
+    if len(rest) > 1:
+        if subdir in folders:
+            folders[subdir] = add_to_structure(folders[subdir], rest)
+        else:
+            folders[subdir] = add_to_structure({"folders":{},"articles":[]}, rest)
+    else:
+       if subdir in folders:
+           folders[subdir]["articles"] += rest
+       else:
+           folders[subdir] = { "folders": {}, "articles": rest }
+
+    return { "folders": folders, "articles": articles }
+
+def parse_wiki_pages(generator):
+    settings = generator.settings
+    readers = generator.readers
+    contentpath = settings.get("PATH", "content")
+
+    root = os.path.realpath(
+        os.path.abspath(os.path.join(contentpath, "wiki", "")))
+
+    wikilist = []
+    structure = {"folders":{}, "articles":[]}
+    for (dirname, dirnames, filenames) in os.walk(root):
+        for filename in filenames:
+            if ".git" not in dirname and ".git" not in filename:
+                parsedfile = readers.read_file(dirname, filename)
+                metadata = parsedfile.metadata
+                try:
+                    path = metadata["path"]
+                    org = metadata["path"].split("/")
+                except KeyError:
+                    path = ""
+                    org = []
+                org.append(filename)
+                structure = add_to_structure(structure, org)
+                wikilist.append((path,filename,parsedfile))
+
+    structure = { "articles": structure["folders"]['']["articles"], "folders":structure["folders"] }
+
+    del(structure["folders"][""])
+    wikilist.sort()
+    generator.context['wikilist'] = wikilist
+    generator.context['wiki'] = structure
+
+
+def parse_dict(structure, level, nice_list):
+    folders = OrderedDict(sorted(structure["folders"].items(), key=lambda t: t[0]))
+    articles = sorted(structure["articles"])
+    for key in folders.keys():
+        if key + ".md" in articles:
+            nice_list.append((key, "indexdir", level))
+            articles.remove(key + ".md")
+        else:
+            nice_list.append((key, "noindexdir", level))
+        nice_list = parse_dict(folders[key], level + 1, nice_list)
+    for item in articles:
+        nice_list.append((item, "article", level))
+    return nice_list
+
+def generate_wiki_pages(generator, writer):
+    wiki_list = generator.context['wikilist']
+    structure = generator.context['wiki']
+    template = generator.get_template('wikiarticle')
+    nice_list = parse_dict(structure, 0, [])
+
+    for page in wiki_list:
+        filename = os.path.join('wiki', page[1].replace('.md', '.html'))
+        content = page[2].content
+        metadata = page[2].metadata
+        path = page[0]
+        breadcrumbs = []
+        for name in path.split('/'):
+            name_match = [item[1] for item in nice_list if item[0] == name]
+            if len(name_match) > 0 and name_match[0] == "indexdir":
+                breadcrumbs.append((name, "a"))
+            else:
+                breadcrumbs.append((name, "p"))
+        file = page[1]
+        writer.write_file(filename, template, generator.context,
+                          meta=metadata, content=content, file=file, path=path, links=nice_list, breadcrumbs=breadcrumbs)
+
+
+def register():
+    signals.article_generator_finalized.connect(parse_wiki_pages)
+    signals.article_writer_finalized.connect(generate_wiki_pages)

+ 66 - 0
github-wiki/wikiarticle.html

@@ -0,0 +1,66 @@
+{% extends "base.html" %}
+{% block title %}{{ meta.title }} - {{ SITENAME }}{% endblock %}
+
+{% block head %}<script src="{{ SITEURL }}/theme/js/wiki.js"></script>{% endblock %}
+
+{% block banner %}{{ meta.title }}{% endblock banner %}
+
+{% block content %}
+
+<div class="article-content">
+
+  <h1 class="article-title">{{ meta.title }}</h1>
+
+  <nav><a class="wiki-nav-button">Expand Menu</a> / <a class="wiki-crumbs" href="{{ SITEURL }}/wiki/Home.html">Home</a>
+  {% set total_path = SITEURL + "/wiki" %}
+  {% for page, type in breadcrumbs %}
+    {% set total_path = total_path + "/" + page %}
+    {% if type == "a" %}
+      / <a class="wiki-crumbs" href="{{ total_path }}">{{ page }}</a>
+    {% elif type == "p" %}
+      / <p class="wiki-crumbs">{{ page }}</p>
+    {% endif %}
+  {% endfor %}</nav>
+  <nav class="wiki-nav">
+    <ul class="wiki-links nodisplay">
+    {% set vars = {'level': 0} %}
+    {% for link in links %}
+      {% if link[0] != "_Footer.md" %}
+        {% set linklevel = link[2] %}
+        {% if linklevel > vars.level %}
+          {% if vars.update({'level':linklevel}) %} {% endif %}
+          <ul class="nodisplay">
+        {% elif linklevel < vars.level %}
+          {% for i in range(vars.level - linklevel) %}
+            </ul>
+          {% endfor %}
+          {% if vars.update({'level':linklevel}) %} {% endif %}
+        {% endif %}
+        {% if not loop.last %}
+          {% if links[loop.index][2] > vars.level %}
+            {% if link[1] == "indexdir" %}
+              <li class="wiki-link"><a href="{{ SITEURL }}/wiki/{{ link[0].replace('.md','.html') }}">{{ link[0].replace('.md','') }}</a> <a class="wiki-dir-expander">+</a></li>
+            {% else %}
+              <li class="wiki-link">{{ link[0].replace('.md','') }} <a class="wiki-dir-expander">+</a></li>
+            {% endif %}
+          {% else %}
+            <li class="wiki-link"><a href="{{ SITEURL }}/wiki/{{ link[0].replace('.md','.html') }}">{{ link[0].replace('.md','') }}</a></li>
+          {% endif %}
+        {% else %}
+          <li class="wiki-link"><a href="{{ SITEURL }}/wiki/{{ link[0].replace('.md','.html') }}">{{ link[0].replace('.md','') }}</a></li>
+        {% endif %}
+      {% endif %}
+    {% endfor %}
+    </ul>
+  </nav>
+
+  {{ content }}
+  
+  <p>
+    <a href="https://github.com/YOUR_USER/YOUR_REPO/wiki/{{ file.replace(".md","") }}/_edit">Edit page.</a><br>
+    <a href="https://github.com/YOUR_USER/YOUR_REPO/wiki/_new">Add new page.</a>
+  </p>
+  
+</div>
+
+{% endblock %}