diff libervia/pages/_browser/template.py @ 1298:8aba2a2078ca

browser: new template module: this module integrate integrate to render templates from the browser.
author Goffi <goffi@goffi.org>
date Fri, 19 Jun 2020 16:47:51 +0200
parents
children c07112ef01cd
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libervia/pages/_browser/template.py	Fri Jun 19 16:47:51 2020 +0200
@@ -0,0 +1,95 @@
+"""Integrate templating system using nunjucks"""
+
+from js_modules.nunjucks import nunjucks
+from browser import window, document
+import javascript
+
+
+safe = nunjucks.runtime.SafeString.new
+env = nunjucks.configure(
+    window.templates_root_url,
+    {
+        'autoescape': True,
+        'trimBlocks': True,
+        'lstripBlocks': True,
+    })
+
+nunjucks.installJinjaCompat()
+
+
+class Indexer:
+    """Index global to a page"""
+
+    def __init__(self):
+        self._indexes = {}
+
+    def next(self, value):
+        if value not in self._indexes:
+            self._indexes[value] = 0
+            return 0
+        self._indexes[value] += 1
+        return self._indexes[value]
+
+    def current(self, value):
+        return self._indexes.get(value)
+
+
+gidx = Indexer()
+# suffix use to avoid collision with IDs generated in static page
+SCRIPT_SUFF = "__script__"
+
+
+def _next_gidx(value):
+    """Use next current global index as suffix"""
+    next_ = gidx.next(value)
+    return f"{value}{SCRIPT_SUFF}" if next_ == 0 else f"{value}_{SCRIPT_SUFF}{next_}"
+
+env.addFilter("next_gidx", _next_gidx)
+
+
+def _cur_gidx(value):
+    """Use current current global index as suffix"""
+    current = gidx.current(value)
+    return f"{value}{SCRIPT_SUFF}" if not current else f"{value}_{SCRIPT_SUFF}{current}"
+
+env.addFilter("cur_gidx", _cur_gidx)
+
+
+def _tojson(value):
+    return safe(
+        window.JSON.stringify(value)
+        .replace('&', '&amp;')
+        .replace('<',  '&lt;')
+        .replace('>', '&gt;')
+        .replace('"', '&quot;')
+    )
+
+env.addFilter("tojson", _tojson)
+
+
+def _icon_use(name, cls=""):
+    kwargs = cls.to_dict()
+    cls = kwargs.get('cls')
+    return safe(
+        '<svg class="svg-icon{cls}" xmlns="http://www.w3.org/2000/svg" '
+        'viewBox="0 0 100 100">\n'
+        '    <use href="#{name}"/>'
+        '</svg>\n'.format(name=name, cls=(" " + cls) if cls else "")
+    )
+
+env.addGlobal("icon", _icon_use)
+
+
+class Template:
+
+    def __init__(self, tpl_name):
+        self._tpl = env.getTemplate(tpl_name, True)
+
+    def render(self, context):
+        return self._tpl.render(context)
+
+    def get_elt(self, context):
+        raw_html = self.render(context)
+        template_elt = document.createElement('template')
+        template_elt.innerHTML = raw_html
+        return template_elt.content.firstChild