aboutsummaryrefslogtreecommitdiffstats
path: root/pysite
diff options
context:
space:
mode:
authorGravatar Gareth Coles <[email protected]>2018-06-07 13:15:20 +0100
committerGravatar Gareth Coles <[email protected]>2018-06-07 13:15:20 +0100
commite8b89a75ab0c8e234d67885ec52ce427e69c70e9 (patch)
tree653468ec98b8703ee7b7af4187534743f824d586 /pysite
parentDon't log DEBUG/TRACE (diff)
[RST] Add directive for UIKit buttons
Diffstat (limited to 'pysite')
-rw-r--r--pysite/rst/__init__.py4
-rw-r--r--pysite/rst/directives/__init__.py69
-rw-r--r--pysite/views/wiki/render.py2
3 files changed, 74 insertions, 1 deletions
diff --git a/pysite/rst/__init__.py b/pysite/rst/__init__.py
index 744dd269..54dbba9c 100644
--- a/pysite/rst/__init__.py
+++ b/pysite/rst/__init__.py
@@ -1,8 +1,10 @@
import re
from docutils.core import publish_parts
+from docutils.parsers.rst.directives import register_directive
from docutils.parsers.rst.roles import register_canonical_role
+from pysite.rst.directives import ButtonDirective
from pysite.rst.roles import icon_role, page_role, url_for_role
RST_TEMPLATE = """.. contents::
@@ -97,3 +99,5 @@ def render(rst: str, link_headers=True):
register_canonical_role("icon", icon_role)
register_canonical_role("page", page_role)
register_canonical_role("url_for", url_for_role)
+
+register_directive("button", ButtonDirective)
diff --git a/pysite/rst/directives/__init__.py b/pysite/rst/directives/__init__.py
index e69de29b..2df1d734 100644
--- a/pysite/rst/directives/__init__.py
+++ b/pysite/rst/directives/__init__.py
@@ -0,0 +1,69 @@
+import pprint
+
+from docutils import nodes
+from docutils.parsers.rst import Directive
+from docutils.parsers.rst.directives import unchanged, unchanged_required
+from flask import url_for
+from jinja2 import escape
+
+BUTTON_TYPES = ("default", "primary", "secondary", "danger", "darkish", "darker")
+
+ICON_WEIGHT_TABLE = {
+ "light": "fal",
+ "regular": "far",
+ "solid": "fas",
+ "branding": "fab"
+}
+ICON_WEIGHTS = tuple(ICON_WEIGHT_TABLE.values())
+
+
+class ButtonDirective(Directive):
+ has_content = True
+
+ option_spec = {
+ "icon": unchanged_required,
+ "text": unchanged_required,
+ "type": unchanged,
+ "url": unchanged,
+ }
+
+ def run(self):
+ pprint.pprint(self.__dict__) # DEBUG
+
+ icon = self.options.get("icon", "")
+ button_type = self.options.get("type", "primary")
+
+ text = self.options["text"]
+ url = self.options["url"]
+
+ if icon:
+ parts = [escape(x) for x in icon.split("/")]
+
+ if len(parts) != 2:
+ raise self.error("Icon specification must be in the form <type>/<name>")
+ elif parts:
+ weight = parts[0]
+
+ if weight not in ICON_WEIGHTS:
+ weight = ICON_WEIGHT_TABLE.get(weight)
+
+ if not weight:
+ raise self.error(
+ "Icon type must be one of light, regular, solid or "
+ "branding, or a font-awesome weight class"
+ )
+
+ icon_html = f"""<i class="uk-icon fa-fw {weight} fa-{parts[1]}"></i>"""
+ else:
+ icon_html = ""
+
+ if button_type not in BUTTON_TYPES:
+ self.error(f"Button type must be one of {', '.join(BUTTON_TYPES[:-1])} or {[-1]}")
+
+ if url.startswith("flask://"):
+ url = url_for(url.split("://", 1)[1])
+ elif url.startswith("wiki://"):
+ url = url_for("wiki.page", page=url.split("://", 1)[1])
+ html = f"""<a class="uk-button uk-button-{button_type}" href=\"{url}\">{icon_html} &nbsp;{text}</a>"""
+
+ return [nodes.raw(html, html, format="html", **{})]
diff --git a/pysite/views/wiki/render.py b/pysite/views/wiki/render.py
index 40e5d3f4..39bdd133 100644
--- a/pysite/views/wiki/render.py
+++ b/pysite/views/wiki/render.py
@@ -13,7 +13,7 @@ SCHEMA = Schema([{
"data": str
}])
-MESSAGE_REGEX = re.compile(r"<string>:(\d+): \([A-Z]+/\d\) (.*)")
+MESSAGE_REGEX = re.compile(r"<string>:(\d+): \([A-Z]+/\d\) (.*)", flags=re.S)
class RenderView(APIView):