Last active
April 6, 2018 19:25
-
-
Save juancarlospaco/97a6a09d64b190a630ad to your computer and use it in GitHub Desktop.
Templar is a tiny Template Engine that Render and Runs native Python 3. Optionally it can Minify the rendered output, or load from a file or file-like object.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
"""Templar is a tiny Template Engine that Render and Runs native Python.""" | |
import re | |
class Templar(str): | |
"""Templar is a tiny Template Engine that Render and Runs native Python.""" | |
def __init__(self, template): | |
"""Init the Template class.""" | |
self.tokens = self.compile(template.strip()) | |
@classmethod | |
def from_file(cls, fl): | |
"""Load template from file.A str/file-like object supporting read().""" | |
return cls(str(open(fl).read() if isinstance(fl, str) else fl.read())) | |
def compile(self, t): | |
"""Parse and Compile all Tokens found on the template string t.""" | |
tokens = [] | |
for i, p in enumerate(re.compile("\{\%(.*?)\%\}", re.DOTALL).split(t)): | |
if not p or not p.strip(): | |
continue | |
elif i % 2 == 0: | |
tokens.append((False, p.replace("{\\%", "{%"))) | |
else: | |
lines = tuple(p.replace("%\\}", "%}").replace( | |
"{{", "spit(").replace("}}", "); ") .splitlines()) | |
mar = min(len(_) - len(_.lstrip()) for _ in lines if _.strip()) | |
al = "\n".join(line_of_code[mar:] for line_of_code in lines) | |
tokens.append((True, compile(al, "<t {}>".format(al), "exec"))) | |
return tokens | |
def render(__self, __namespace={}, mini=False, **kw): | |
"""Render template from __namespace dict + **kw added to namespace.""" | |
html = [] | |
__namespace.update(kw, **globals()) | |
def spit(*args, **kwargs): | |
for _ in args: | |
html.append(str(_)) | |
if kwargs: | |
for _ in tuple(kwargs.items()): | |
html.append(str(_)) | |
__namespace["spit"] = spit | |
for is_code, value in __self.tokens: | |
eval(value, __namespace) if is_code else html.append(value) | |
return re.sub('>\s+<', '> <', "".join(html)) if mini else "".join(html) | |
__call__ = render # shorthand | |
if __name__ in '__main__': | |
demo = """<html><body> | |
{% | |
def say_hello(arg): | |
{{"<tr> hello ", arg, " </tr>"}} | |
%} | |
<table> | |
{% [say_hello(i) for i in range(9) if i % 2] %} | |
</table> | |
{% {{ in_your_face }} {{ __doc__.title() }} %} | |
{% # this is a python comment %} </body></html>""" | |
templar_template = Templar(demo) | |
print(templar_template(in_your_face=9, mini=True)) | |
print(templar_template(in_your_face=2)) | |
print(isinstance(templar_template, str)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
{%
, end a code block with%}
, just like Django or Jinja2.{{
and}}
eg.{{foo}}
, just like Django and Mustache.globals()
are available so stuff like__doc__
and__name__
wil work.mini
Boolean argument (Off by Default).Output with Minification = True:
Output with Minification = False:
😸