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:
            - 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 . He is certainly not completely finished yet, but you need to get a feedback.

    So, let's try on five,

    !doctype/ html
            | Page Title
        h1 {'class': ' '.join(['main', 'content'], 'ng-app': 'Application'} "Page Header"
            - yield from options['content_block']()
        div.footer "Backslant © 2015"

    What we have here - doctypeends 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 h1arguments are passed to regular python dict, within which any code that can be in the dictionary declaration.

    Further interesting - yield fromfrom a certain challenge content_blockthat lies in some options. What can I say - optionsthis kwargs, since we do not have declarations of template parameters here. Maybe in vain, by the way, what not.

    So, aboutcontent_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, and calls its render, and passes the callback there.

    And this will be

    - from . import base
    :call base.render(*options)
            - for i in range(10):
                    - yield 'Paragraph {}'.format(i)
            p "Index page"

    Here we use a little sugar instead of honestly declaring just a function and passing it on. :calliterates over its child nodes, checks that they are all function declarations, and stuff them into the parameters. And :content_blockjust declares a function with no arguments with a name content_block, and with the same name :callwill 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'):

    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 yieldand 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 sendknows 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 yieldandyield 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

    Also popular now: