A Python content management system designed for kirsle.net featuring a blog, comments and photo albums. https://rophako.kirsle.net/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

wiki.py 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. """Wiki models."""
  4. from flask import url_for
  5. import time
  6. import re
  7. import hashlib
  8. import rophako.jsondb as JsonDB
  9. from rophako.utils import render_markdown
  10. from rophako.log import logger
  11. def render_page(content):
  12. """Render the Markdown content of a Wiki page, and support inter-page
  13. linking with [[double braces]].
  14. For simple links, just use the [[Page Name]]. To have a different link text
  15. than the page name, use [[Link Text|Page Name]]."""
  16. html = render_markdown(content)
  17. # Look for [[double brackets]]
  18. links = re.findall(r'\[\[(.+?)\]\]', html)
  19. for match in links:
  20. label = page = match
  21. if "|" in match:
  22. label, page = match.split("|", 2)
  23. # Does the page exist?
  24. output = '''<a href="{url}">{label}</a>'''
  25. if not JsonDB.exists("wiki/pages/{}".format(page)):
  26. output = '''<a href="{url}" class="wiki-broken">{label}</a>'''
  27. html = html.replace("[[{}]]".format(match),
  28. output.format(
  29. url=url_for("wiki.view_page", name=name_to_url(page)),
  30. label=label,
  31. )
  32. )
  33. return html
  34. def get_page(name):
  35. """Get a Wiki page. Returns `None` if the page isn't found."""
  36. name = name.strip("/") # Remove any surrounding slashes.
  37. path = "wiki/pages/{}".format(name)
  38. if not JsonDB.exists(path):
  39. return None
  40. # TODO: case insensitive page names...
  41. db = JsonDB.get(path)
  42. return db
  43. def list_pages():
  44. """Get a list of all existing wiki pages."""
  45. return JsonDB.list_docs("wiki/pages", recursive=True)
  46. def edit_page(name, author, body, note, history=True):
  47. """Write to a page."""
  48. name = name.strip("/") # Remove any surrounding slashes.
  49. # Get the old page first.
  50. page = get_page(name)
  51. if not page:
  52. # Initialize the page.
  53. page = dict(
  54. revisions=[],
  55. )
  56. # The new revision to be added.
  57. rev = dict(
  58. id=hashlib.md5(str(int(time.time()))).hexdigest(),
  59. time=int(time.time()),
  60. author=author,
  61. body=body,
  62. note=note or "Updated the page.",
  63. )
  64. # Updating the history?
  65. if history:
  66. page["revisions"].insert(0, rev)
  67. else:
  68. # Replacing the original item.
  69. if len(page["revisions"]):
  70. page["revisions"][0] = rev
  71. else:
  72. page["revisions"].append(rev)
  73. # Write it.
  74. logger.info("Write to Wiki page {}".format(name))
  75. JsonDB.commit("wiki/pages/{}".format(name), page)
  76. return True
  77. def delete_history(name, revision):
  78. """Delete a revision entry from the history."""
  79. name = name.strip("/")
  80. # Get page first.
  81. page = get_page(name)
  82. if not page:
  83. return None
  84. # Revise history.
  85. history = list()
  86. for rev in page["revisions"]:
  87. if rev["id"] == revision:
  88. logger.info("Delete history ID {} from Wiki page {}".format(revision, name))
  89. continue
  90. history.append(rev)
  91. # Empty history = delete the page.
  92. if len(history) == 0:
  93. logger.info("Deleted last history item; Remove Wiki page {}".format(name))
  94. return delete_page(name)
  95. page["revisions"] = history
  96. JsonDB.commit("wiki/pages/{}".format(name), page)
  97. return True
  98. def delete_page(name):
  99. """Completely delete a wiki page."""
  100. name = name.strip("/")
  101. path = "wiki/pages/{}".format(name)
  102. if JsonDB.exists(path):
  103. logger.info("Delete Wiki page {}".format(name))
  104. JsonDB.delete(path)
  105. return True
  106. def name_to_url(name):
  107. """Convert a Wiki page name into a URL safe version.
  108. All non-alphanumerics are replaced with dashes, multiple dashes in a row
  109. are flattened down to one, and any preceeding or trailing dashes are also
  110. stripped off."""
  111. name = re.sub(r'[^A-Za-z0-9/]', '-', name).replace('--', '-').strip('-')
  112. return name
  113. def url_to_name(url):
  114. """Convert a URL to a page name, for 404'd links.
  115. Turns a link like /wiki/New-Page-Name into 'New Page Name'"""
  116. return url.replace("-", " ")