rophako/rophako/model/wiki.py

155 lines
4.1 KiB
Python

# -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import
"""Wiki models."""
from flask import url_for
import time
import re
import hashlib
import rophako.jsondb as JsonDB
from rophako.utils import render_markdown
from rophako.log import logger
def render_page(content):
"""Render the Markdown content of a Wiki page, and support inter-page
linking with [[double braces]].
For simple links, just use the [[Page Name]]. To have a different link text
than the page name, use [[Link Text|Page Name]]."""
html = render_markdown(content)
# Look for [[double brackets]]
links = re.findall(r'\[\[(.+?)\]\]', html)
for match in links:
label = page = match
if "|" in match:
label, page = match.split("|", 2)
# Does the page exist?
output = '''<a href="{url}">{label}</a>'''
if not JsonDB.exists("wiki/pages/{}".format(page)):
output = '''<a href="{url}" class="wiki-broken">{label}</a>'''
html = html.replace("[[{}]]".format(match),
output.format(
url=url_for("wiki.view_page", name=name_to_url(page)),
label=label,
)
)
return html
def get_page(name):
"""Get a Wiki page. Returns `None` if the page isn't found."""
name = name.strip("/") # Remove any surrounding slashes.
path = "wiki/pages/{}".format(name)
if not JsonDB.exists(path):
return None
# TODO: case insensitive page names...
db = JsonDB.get(path)
return db
def list_pages():
"""Get a list of all existing wiki pages."""
return JsonDB.list_docs("wiki/pages", recursive=True)
def edit_page(name, author, body, note, history=True):
"""Write to a page."""
name = name.strip("/") # Remove any surrounding slashes.
# Get the old page first.
page = get_page(name)
if not page:
# Initialize the page.
page = dict(
revisions=[],
)
# The new revision to be added.
rev = dict(
id=hashlib.md5(str(int(time.time())).encode("utf-8")).hexdigest(),
time=int(time.time()),
author=author,
body=body,
note=note or "Updated the page.",
)
# Updating the history?
if history:
page["revisions"].insert(0, rev)
else:
# Replacing the original item.
if len(page["revisions"]):
page["revisions"][0] = rev
else:
page["revisions"].append(rev)
# Write it.
logger.info("Write to Wiki page {}".format(name))
JsonDB.commit("wiki/pages/{}".format(name), page)
return True
def delete_history(name, revision):
"""Delete a revision entry from the history."""
name = name.strip("/")
# Get page first.
page = get_page(name)
if not page:
return None
# Revise history.
history = list()
for rev in page["revisions"]:
if rev["id"] == revision:
logger.info("Delete history ID {} from Wiki page {}".format(revision, name))
continue
history.append(rev)
# Empty history = delete the page.
if len(history) == 0:
logger.info("Deleted last history item; Remove Wiki page {}".format(name))
return delete_page(name)
page["revisions"] = history
JsonDB.commit("wiki/pages/{}".format(name), page)
return True
def delete_page(name):
"""Completely delete a wiki page."""
name = name.strip("/")
path = "wiki/pages/{}".format(name)
if JsonDB.exists(path):
logger.info("Delete Wiki page {}".format(name))
JsonDB.delete(path)
return True
def name_to_url(name):
"""Convert a Wiki page name into a URL safe version.
All non-alphanumerics are replaced with dashes, multiple dashes in a row
are flattened down to one, and any preceeding or trailing dashes are also
stripped off."""
name = re.sub(r'[^A-Za-z0-9/]', '-', name).replace('--', '-').strip('-')
return name
def url_to_name(url):
"""Convert a URL to a page name, for 404'd links.
Turns a link like /wiki/New-Page-Name into 'New Page Name'"""
return url.replace("-", " ")