view libervia/pages/_browser/template.py @ 1304:70e3341d25bf

pages: take care of None/null when exposing a variable
author Goffi <goffi@goffi.org>
date Thu, 16 Jul 2020 09:08:50 +0200
parents 8aba2a2078ca
children c07112ef01cd
line wrap: on
line source

"""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