]> git.ipfire.org Git - ipfire.org.git/blobdiff - src/backend/wiki.py
wiki: Add watchlist
[ipfire.org.git] / src / backend / wiki.py
index fc46927f06211bb23153c6212c8f6cb688fe6098..3dc8a71f17aaa5ac36a93275235b7d97c461ac7e 100644 (file)
@@ -138,6 +138,18 @@ class Wiki(misc.Object):
                """
                self.db.execute("REFRESH MATERIALIZED VIEW wiki_search_index")
 
+       def get_watchlist(self, account):
+               pages = self._get_pages(
+                       "WITH pages AS (SELECT * FROM wiki_current \
+                                       LEFT JOIN wiki ON wiki_current.id = wiki.id) \
+                       SELECT * FROM wiki_watchlist watchlist \
+                               LEFT JOIN pages ON watchlist.page = pages.page \
+                               WHERE watchlist.uid = %s",
+                       account.uid,
+               )
+
+               return sorted(pages)
+
        # ACL
 
        def check_acl(self, page, account):
@@ -204,9 +216,18 @@ class Wiki(misc.Object):
 
 
 class Page(misc.Object):
+       # Wiki links
+       wiki_link = re.compile(r"\[\[([\w\d\/\-\.]+)(?:\|(.+?))?\]\]")
+
+       # External links
+       external_link = re.compile(r"\[\[((?:ftp|git|https?|rsync|sftp|ssh|webcal)\:\/\/.+?)(?:\|(.+?))?\]\]")
+
        # Interwiki links e.g. [[wp>IPFire]]
        interwiki_link = re.compile(r"\[\[(\w+)>(.+?)(?:\|(.+?))?\]\]")
 
+       # Mail link
+       email_link = re.compile(r"\[\[([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)(?:\|(.+?))?\]\]")
+
        def init(self, id, data=None):
                self.id = id
                self.data = data
@@ -276,6 +297,26 @@ class Page(misc.Object):
                if self.data.author_uid:
                        return self.backend.accounts.get_by_uid(self.data.author_uid)
 
+       def _render_wiki_link(self, m):
+               path, alias = m.groups()
+
+               # Allow relative links
+               if not path.startswith("/"):
+                       path = os.path.join(self.page, path)
+
+               # Normalise links
+               path = os.path.normpath(path)
+
+               return """<a href="%s">%s</a>""" % (
+                       path,
+                       alias or self.backend.wiki.get_page_title(path),
+               )
+
+       def _render_external_link(self, m):
+               url, alias = m.groups()
+
+               return """<a class="link-external" href="%s">%s</a>""" % (url, alias or url)
+
        def _render_interwiki_link(self, m):
                wiki = m.group(1)
                if not wiki:
@@ -313,6 +354,12 @@ class Page(misc.Object):
 
                return " ".join(s)
 
+       def _render_email_link(self, m):
+               address, alias = m.groups()
+
+               return """<a class="link-external" href="mailto:%s">%s</a>""" \
+                       % (address, alias or address)
+
        def _render(self, text):
                logging.debug("Rendering %s" % self)
 
@@ -349,46 +396,17 @@ class Page(misc.Object):
                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:]
 
+               # Handle wiki links
+               text = self.wiki_link.sub(self._render_wiki_link, text)
+
                # Handle interwiki links
                text = self.interwiki_link.sub(self._render_interwiki_link, text)
 
-               # Add wiki links
-               patterns = (
-                       (r"\[\[([\w\d\/\-\.]+)(?:\|(.+?))\]\]", r"\1", r"\2", None, True),
-                       (r"\[\[([\w\d\/\-\.]+)\]\]", r"\1", r"\1", self.backend.wiki.get_page_title, True),
-
-                       # External links
-                       (r"\[\[((?:ftp|git|https?|rsync|sftp|ssh|webcal)\:\/\/.+?)(?:\|(.+?))\]\]",
-                               r"\1", r"\2", None, False),
-
-                       # Mail
-                       (r"\[\[([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)\]\]",
-                               r"\1", r"\1", None, False),
-               )
-
-               for pattern, link, title, repl, internal in patterns:
-                       replacements = []
-
-                       for match in re.finditer(pattern, text):
-                               l = match.expand(link)
-                               t = match.expand(title)
-
-                               if internal:
-                                       # Allow relative links
-                                       if not l.startswith("/"):
-                                               l = os.path.join(self.page, l)
-
-                                       # Normalise links
-                                       l = os.path.normpath(l)
-
-                               if callable(repl):
-                                       t = repl(l) or t
-
-                               replacements.append((match.span(), t or l, l))
+               # Handle external links
+               text = self.external_link.sub(self._render_external_link, text)
 
-                       # Apply all replacements
-                       for (start, end), t, l in reversed(replacements):
-                               text = text[:start] + "[%s](%s)" % (t, l) + text[end:]
+               # Handle email links
+               text = self.email_link.sub(self._render_email_link, text)
 
                # Borrow this from the blog
                return self.backend.blog._render_text(text, lang="markdown")