📜 ⬆️ ⬇️

Plim - the most complete port of Slim template engine on Python

Definitely, the first implementations of Haml and Slim were supposed to appear in Python. Or at least it would be more fair.
It’s hard to imagine a more “pythonic” approach to writing HTML markup than the one that was proposed by these languages ​​at one time. Indentation-based syntax, lack of closing characters, general conciseness - can these words be heard from the lips of an average programmer telling someone about Python for the first time?

But the reality turned out to be different, and my first acquaintance with Slim happened at that moment when, in one of my projects, I started using Chef and undertook to study Ruby about it. Since then and until very recently, I had been waiting for at least something in the Python world that in its quality would be close to the current implementation of Slim. But without waiting, he began to write his own.

Motivation


For Python, there are already quite a large number of packages that implement Haml-like markup languages. Here are just some of them:


Anyway, all these projects are inferior to the original Slim in the degree of their elaboration:
')
- some have inherent syntax flaws that can not be corrected, since the projects have an established audience with a large code base;
- others try to write cross-compilers for all existing “large” python-templating engines, as a result of which the syntax of each of them is equally poorly supported;
- for all others - too naive implementations. Even slimish-jinja2 (which, in theory, should support the entire syntax of Slim) is implemented very modestly . Please note that a very naive regular expression is used to parse tag attributes, which will work incorrectly with almost any python string containing the "=" character. This is clearly not the project that today can be implemented in your streamlined development process.

It turned out that even with such a voluminous list of packages, we have nothing to choose from when it comes to a production system. As a result of such a disappointing conclusion, it was decided to write our own, production-ready port of the original Slim template engine.

Implementation


Plim is the most complete implementation of the Slim syntax in Python, created on top of the Mako template engine. At its core, Plim is a simple preprocessor that knows nothing about the execution context (runtime), but which can correctly translate the slim markup into a correct mako template, which can then be compiled into a Python module and cached by the Mako engine.

By “the most complete implementation” is meant the support of most Slim control structures. However, you should immediately clarify that Plim is not an exact port of the language ! Some elements of the syntax were removed, others were significantly supplemented, and clarity and unambiguity were introduced in some constructions. But, nevertheless, most of the syntax has not undergone any changes, so when working with Plim you can use existing plugins to highlight the slim syntax .

To finally clarify the situation, below is a list of all the changes made to the syntax:

  1. Slim supports the following string indicators - "'", "=" "and" ==' ". In Plim, the apostrophe (single quote) has been replaced with a comma:
    , value =, value ==, value 

    This change was dictated by the fact that a single quote is a valid character at the beginning of an arbitrary Python expression. Therefore, the following plim expressions will have an ambiguous interpretation (which is always bad when it comes to automatic code translation):
     /      python-,       ,     ? ='' /     python-    ('u''' -   python-)       ,       ? ='u''' 


    At the same time, the comma character is not allowed at the beginning of any correct python string, so when using it we get an unambiguous interpretation of the expressions:
     /    runtime,    mako- ${'} -   .   . =,' /    .  mako-   -,      . =,u'' 

  2. Unlike Slim, Plim does not support square and curly braces to highlight tag attributes. You can only use parentheses.
    This restriction simplifies the logic of the algorithms of some components of the parser and introduces a certain level of standardization into the syntax, while at the same time not reducing its functionality:
     /         . p(title="Link Title") h1 class=(item.id == 1 and 'one' or 'unknown') Title /         mako-  python- a#idx-${item.id} href=item.get_link( **{'argument': 'value'}) = item.attrs['title'] 

  3. As you can see in the last example, Plim supports dynamic expressions in short form tags (# id.class). You can also transfer expressions in brackets to another line:
     /       #m${ c.message.id }.msg${ ( "test" ) } = do_something_real( 'with', 'the', real, arguments) 

  4. In Plim, all tags must use lower case letters. This restriction was introduced in order to be able to include in the language support for “implicit” literal strings, about which in the next paragraph of the list. But you can guess what it is by the following example:
     doctype 5 html head title Page Title body p | !  -   ,    . p !  -   ,      . 

  5. Unlike Slim, Plim has support for implicit text blocks. A text block will be considered an “implicit literal” if its first line starts with one of the following sequences of characters:
    • capital Latin letter;
    • Any letter from a range that is not in the ASCII character table;
    • any digit before which there are no "+" or "-" characters that are reserved;
    • any HTML character encoded in the & form. For example - & nbsp;
    • mako-expression starting with the "$ {" character sequence;
    • the opening bracket "[";
    • opening parenthesis "(";
    • any unicode character not in the range of codes U0021 - U007E (that is, outside the ASCII range 33 - 126, which is a reserved parser).

    Here is an example of using implicit text blocks:
     p | pipe is the explicit literal indicator. It is required if your line starts with the non-literal character. p I'm the implicit literal, because my first letter is in uppercase. p 1. Digits 2. are 3. the 4. implicit 5. literals 6. too. p ${raw_mako_expression} indicates the implicit literal line. p If subsequent lines do not start with implicit literal indicator, you must indent them | or you can use the "explicit" pipe. p       ,    ,     ASCII-,           . 

  6. You do not need to use the character "|" (pipe is an indicator of an explicit literal) in the style and script tags;
  7. Plim makes no distinction between control structures and filters.
    For example, in Slim you should write "-if", "-for", and so on - for any control design, but "coffee:" (without a minus at the beginning, but with a twist at the end) - for any of the available filters. In Plim, you use the same syntax: "-if", "-for" and "-coffee".
  8. Plim supports HTML tags! You should only remember to close them. Inside the tags, the same parsing rules are used as for the “clean” plim-markup. This functionality is especially useful when you are trying to implement something like the following example:
     - if edit_profile /       <div id="edit-profile"> - include new_or_edit_interface.html - if edit_profile /     </div> 

    Due to the HTML tag support, Plim did not implement the equivalent of the "/!" Instruction, with which Slim generated HTML comments. The decision about the uselessness of such a design in Plim was made due to the fact that HTML comments are currently used almost exclusively for Internet Explorer conditional hacks. Such an insignificant field of application does not justify the introduction of additional syntax constructions into a markup language, which has built-in support for “native” HTML comments.


As you can see, the changes were made as carefully as possible with respect to the original language and only in those places where, as I believed, there was an unnecessary “rigor” of the rules.

Bonuses


In addition to the basic syntax, Plim implements:


Meta information


Detailed and up-to-date documentation on all the language control structures can be found on the ReadTheDocs.org platform (English version, there is a pdf and epub ).

All suggestions and bug reports are welcome in the GitHub tracker .

PS The current version was tested only on branch 2.7. I'm not sure (there is no necessary environment for tests), but everything should work fine in 2.6. But 3.x is currently not supported exactly. But this is due only to the fact that some packages from the standard library in Py3K have changed their location.

Source: https://habr.com/ru/post/145856/


All Articles