Backslant - slim style template engine
I wanted to make a template engine, so that as slim, tags would automatically close and so on. Beautifully so:
But this is not enough for me, I want not to have my own misunderstanding, I want just Python designs. And who wants to shoot himself in the leg and pile business logic into templates, then this is a problem for beginners, why should I be tormented by smearing the view code into folders like utils, template_tags and so on?
And also, by the way, you can get it burned - let the templates stretch through the new import mechanism in python 3. And if you need to insert something from another template, then let it also work.
And let each template be a generator!
Well said done, meet github.com/Deepwalker/backslant . He is certainly not completely finished yet, but you need to get a feedback.
So, let's try on five, base.bs:
What we have here -
While the lines begin with
The
Further interesting -
So, about
And this will be index.bs:
Here we use a little sugar instead of honestly declaring just a function and passing it on.
And then in the python code we can use:
Madly. What to add by syntax - you can declare a function, direct
From the unsupported
What's next is the generator. And the generator, as you know, also
Speed is the same as jinja2. You can probably try somehow overclocking yet, but basically the code consists of
So here. The syntax can still be finished, introduce some ideas.
Any ideas by the way? Let's discuss. In the meantime, you can look at the project, poke examples github.com/Deepwalker/backslant/tree/master/example
html
head
title
- yield "Плюшка!" + " Чашка чаю!"
But this is not enough for me, I want not to have my own misunderstanding, I want just Python designs. And who wants to shoot himself in the leg and pile business logic into templates, then this is a problem for beginners, why should I be tormented by smearing the view code into folders like utils, template_tags and so on?
And also, by the way, you can get it burned - let the templates stretch through the new import mechanism in python 3. And if you need to insert something from another template, then let it also work.
And let each template be a generator!
Well said done, meet github.com/Deepwalker/backslant . He is certainly not completely finished yet, but you need to get a feedback.
So, let's try on five, base.bs:
!doctype/ html
html
head
title
| Page Title
body
h1 {'class': ' '.join(['main', 'content'], 'ng-app': 'Application'} "Page Header"
div.content
- yield from options['content_block']()
div.footer "Backslant © 2015"
What we have here -
doctype
ends with /
, so the tag
should not be closed through . While the lines begin with
"
, you need to finish the grammar so that you can immediately after the tag body, later. The
h1
arguments are passed to regular python dict
, within which any code that can be in the dictionary declaration. Further interesting -
yield from
from a certain challenge content_block
that lies in some options
. What can I say - options
this kwargs
, since we do not have declarations of template parameters here. Maybe in vain, by the way, what not. So, about
content_block
- here we expect that we will be given a certain callback in the parameter, and we believe that there will be a generator there - we have all the generators templates. That means some kind of template wants to use our base.bs, and calls its render, and passes the callback there. And this will be index.bs:
- from . import base
:call base.render(*options)
:content_block
- for i in range(10):
p
- yield 'Paragraph {}'.format(i)
:footer_block
p "Index page"
Here we use a little sugar instead of honestly declaring just a function and passing it on.
:call
iterates over its child nodes, checks that they are all function declarations, and stuff them into the parameters. And :content_block
just declares a function with no arguments with a name content_block
, and with the same name :call
will send it to the arguments. And then in the python code we can use:
import backslant
sys.meta_path.insert(0, backslant.PymlFinder('./templates', hook='backslant_import'))
from backslant_import.home import index
for chunk in index.render(title='The Real Thing'):
print(chunk)
Madly. What to add by syntax - you can declare a function, direct
- def func(a=True)
and so on. for
, if
, elif
, else
- just pure python. Of course, you can and should use yield
and yield from
. You can import anything you want and use it as you like. From the unsupported
try: except: ...
. The current version of the parser is not very friendly, it is necessary to redo the parsing. What's next is the generator. And the generator, as you know, also
send
knows how, not only next
. It’s true that you can get from this, I don’t know, you can dream up. It can somehow feed data and give portions to the output. Speed is the same as jinja2. You can probably try somehow overclocking yet, but basically the code consists of
yield
andyield from
, compiled through ast
, nothing much to optimize. So here. The syntax can still be finished, introduce some ideas.
Any ideas by the way? Let's discuss. In the meantime, you can look at the project, poke examples github.com/Deepwalker/backslant/tree/master/example