aboutsummaryrefslogtreecommitdiffstats
path: root/pysite/views
diff options
context:
space:
mode:
Diffstat (limited to 'pysite/views')
-rw-r--r--pysite/views/wiki/edit.py10
-rw-r--r--pysite/views/wiki/search.py66
2 files changed, 74 insertions, 2 deletions
diff --git a/pysite/views/wiki/edit.py b/pysite/views/wiki/edit.py
index 2cd4181c..bb39ed2b 100644
--- a/pysite/views/wiki/edit.py
+++ b/pysite/views/wiki/edit.py
@@ -1,5 +1,7 @@
import datetime
import difflib
+import html
+import re
import requests
from flask import redirect, request, url_for
@@ -11,6 +13,8 @@ from pysite.decorators import csrf, require_roles
from pysite.mixins import DBMixin
from pysite.rst import render
+STRIP_REGEX = re.compile(r"<[^<]+?>")
+
class EditView(RouteView, DBMixin):
path = "/edit/<path:page>" # "path" means that it accepts slashes
@@ -55,11 +59,12 @@ class EditView(RouteView, DBMixin):
@csrf
def post(self, page):
rst = request.form.get("rst")
+ title = request.form["title"]
- if not rst:
+ if not rst or not not rst.strip():
raise BadRequest()
- if not rst.strip():
+ if not title or not title.strip():
raise BadRequest()
rendered = render(rst)
@@ -69,6 +74,7 @@ class EditView(RouteView, DBMixin):
"title": request.form["title"],
"rst": rst,
"html": rendered["html"],
+ "text": html.unescape(STRIP_REGEX.sub("", rendered["html"]).strip()),
"headers": rendered["headers"]
}
diff --git a/pysite/views/wiki/search.py b/pysite/views/wiki/search.py
new file mode 100644
index 00000000..1c920e15
--- /dev/null
+++ b/pysite/views/wiki/search.py
@@ -0,0 +1,66 @@
+import html
+import re
+
+from flask import redirect, request, url_for
+from werkzeug.exceptions import BadRequest
+
+from pysite.base_route import RouteView
+from pysite.decorators import csrf
+from pysite.mixins import DBMixin
+
+STRIP_REGEX = re.compile(r"<[^<]+?>")
+
+
+class SearchView(RouteView, DBMixin):
+ path = "/search" # "path" means that it accepts slashes
+ name = "search"
+ table_name = "wiki"
+ revision_table_name = "wiki_revisions"
+
+ def get(self):
+ return self.render("wiki/search.html")
+
+ @csrf
+ def post(self):
+ given_query = request.form.get("query")
+
+ if not given_query or not given_query.strip():
+ raise BadRequest()
+
+ query = f"({re.escape(given_query)})"
+
+ pages = self.db.filter(
+ self.table_name,
+ lambda doc: doc["text"].match(query)
+ )
+
+ if len(pages) == 1:
+ slug = pages[0]["slug"]
+ return redirect(url_for("wiki.page", page=slug), code=303)
+
+ for obj in pages:
+ text = obj["text"]
+
+ matches = re.finditer(query, text)
+ snippets = []
+
+ for match in matches:
+ start = match.start() - 50
+
+ if start < 0:
+ start = 0
+
+ end = match.end() + 50
+
+ if end > len(text):
+ end = len(text)
+
+ match_text = text[start:end]
+ match_text = re.sub(query, r"<strong>\1</strong>", html.escape(match_text))
+
+ snippets.append(match_text.replace("\n", "<br />"))
+
+ obj["matches"] = snippets
+
+ pages = sorted(pages, key=lambda d: d["title"])
+ return self.render("wiki/search_results.html", pages=pages, query=given_query)