From c78ad26e8dbff6d500f25f5c0cc2170e14b26d17 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Thu, 30 May 2019 15:17:19 +0100 Subject: [PATCH] wiki: Implement embedding images with {{...}} syntax Signed-off-by: Michael Tremer --- src/backend/wiki.py | 95 ++++++++++++++-------------- src/templates/wiki/files/detail.html | 6 +- 2 files changed, 51 insertions(+), 50 deletions(-) diff --git a/src/backend/wiki.py b/src/backend/wiki.py index bc779fdc..92d84c30 100644 --- a/src/backend/wiki.py +++ b/src/backend/wiki.py @@ -30,6 +30,23 @@ class Wiki(misc.Object): if res: return Page(self.backend, res.id, data=res) + def make_path(self, page, path): + # Nothing to do for absolute links + if path.startswith("/"): + pass + + # Relative links (one-level down) + elif path.startswith("./"): + path = os.path.join(page, path) + + # All other relative links + else: + p = os.path.dirname(page) + path = os.path.join(p, path) + + # Normalise links + return os.path.normpath(path) + def get_page_title(self, page, default=None): # Try to retrieve title from cache title = self.memcache.get("wiki:title:%s" % page) @@ -206,13 +223,6 @@ class Wiki(misc.Object): mimetype, blob_id, size) VALUES(%s, %s, %s, %s, %s, %s, %s) RETURNING *", path, filename, author.uid, address, mimetype, blob.id, len(data)) - def find_image(self, path, filename): - for p in (path, os.path.dirname(path)): - file = self.get_file_by_path(os.path.join(p, filename)) - - if file and file.is_image(): - return file - def render(self, path, text): r = WikiRenderer(self.backend, path) @@ -494,27 +504,16 @@ class WikiRenderer(misc.Object): # Mail link email_link = re.compile(r"\[\[([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)(?:\|(.+?))?\]\]") + # Images + images = re.compile(r"{{([\w\d\/\-\.]+)(?:\|(.+?))?}}") + def init(self, path): self.path = path def _render_wiki_link(self, m): path, alias = m.groups() - # Nothing to do for absolute links - if path.startswith("/"): - pass - - # Relative links (one-level down) - elif path.startswith("./"): - path = os.path.join(self.path, path) - - # All other relative links - else: - p = os.path.dirname(self.path) - path = os.path.join(p, path) - - # Normalise links - path = os.path.normpath(path) + path = self.backend.wiki.make_path(self.path, path) return """%s""" % ( path, @@ -569,41 +568,36 @@ class WikiRenderer(misc.Object): return """%s""" \ % (address, alias or address) - def render(self, text): - logging.debug("Rendering %s" % self.path) + def _render_image(self, m): + url, text = m.groups() - # Link images - replacements = [] - for match in re.finditer(r"!\[(.*?)\]\((.*?)\)", text): - alt_text, url = match.groups() + # Skip any absolute and external URLs + if url.startswith("/") or url.startswith("https://") or url.startswith("http://"): + return """%s""" % (url, text or "") - # Skip any absolute and external URLs - if url.startswith("/") or url.startswith("https://") or url.startswith("http://"): - continue + # Try to split query string + url, delimiter, qs = url.partition("?") - # Try to split query string - url, delimiter, qs = url.partition("?") + # Parse query arguments + args = urllib.parse.parse_qs(qs) - # Parse query arguments - args = urllib.parse.parse_qs(qs) + # Build absolute path + url = self.backend.wiki.make_path(self.path, url) - # Find image - file = self.backend.wiki.find_image(self.path, url) - if not file: - continue + # Find image + file = self.backend.wiki.get_file_by_path(url) + if not file or not file.is_image(): + return "" % (url, self.path) - # Scale down the image if not already done - if not "s" in args: - args["s"] = "768" + # Scale down the image if not already done + if not "s" in args: + args["s"] = "768" - # Format URL - url = "%s?%s" % (file.url, urllib.parse.urlencode(args)) + return """%s""" \ + % (url, url, urllib.parse.urlencode(args), text or "") - replacements.append((match.span(), file, alt_text, url)) - - # Apply all replacements - for (start, end), file, alt_text, url in reversed(replacements): - text = text[:start] + "[![%s](%s)](%s?action=detail)" % (alt_text, url, file.url) + text[end:] + def render(self, text): + logging.debug("Rendering %s" % self.path) # Handle wiki links text = self.wiki_link.sub(self._render_wiki_link, text) @@ -617,5 +611,8 @@ class WikiRenderer(misc.Object): # Handle email links text = self.email_link.sub(self._render_email_link, text) + # Handle images + text = self.images.sub(self._render_image, text) + # Borrow this from the blog return self.backend.blog._render_text(text, lang="markdown") diff --git a/src/templates/wiki/files/detail.html b/src/templates/wiki/files/detail.html index fea6448c..270e1e10 100644 --- a/src/templates/wiki/files/detail.html +++ b/src/templates/wiki/files/detail.html @@ -42,7 +42,11 @@ {% if file.is_image() %}
{{ _("Usage") }}
-
![{{ _("Caption")}}]({{ file.filename }})
+
{{{{ file.filename }}}}
+ +

{{ _("Or with an optional caption") }}

+ +
{{{{ file.filename }}|{{ _("Caption") }}}}
{% end %} -- 2.39.2