📜 ⬆️ ⬇️

Template engine. Framing designs

One gets the impression that the template syntax standard is what we use as a frame for control structures (parentheses, percentiles, question marks). This is not true. The characters in which we enclose a particular pattern entry are just a way to relate data to logic. It is difficult to establish some kind of standard. But the reproduction logic of a particular structure must be specified in advance, and it is then that we can make templates compatible with each other for different programming languages.

But today we still talk about these same brackets. Do not forget about the sigils for variables.

There are a lot of examples of restriction of template constructs. Angular, curly, square, parentheses in combinations with each other and with symbols such as % ,? , $ , # ... In general, you know that there are a lot of special characters, and there are even more combinations of them.

<...>


To visually distinguish template designs from html tags, it is better to use non- angle brackets. But in constructions like HTML :: Template there is a charm which is valued in certain circles. Need to somehow limit such a group of people? I do not think.
')

[...]


Square brackets would be nice to use in control structures, for example, to specify the array slice. In this case, in combination with [% ...%], some control structures (for example, an array slice) will lose visibility:
[% myobj => data.source [3..5] %] 

(...)


We used to use parentheses for semantic merging and phrasing. I think this will be one of the most unfortunate options. In addition, for sure in conditional operators we will have to make complex expressions, and there will be a situation similar to the example above.

{...}


If you pay attention, in most programming languages ​​code blocks are highlighted with just such curly braces. So why not follow the tradition and not adopt this approach to patterns? It would seem that everything is trivial, and why everyone has not come to this conclusion for a long time. They came, but each in its own way. Let's say the use of constructions as in the example below is not entirely universal.
 <p>{title}</p> {if expr} <span>true</span> {else} <span>false</span> {endif} 

We can simply run into a situation where {title} will appear in the template text, at a time when we do not need to consider this as a template construct. Today, template implementations offer various solutions to this problem, for example, Django:
 {% if expr %} <span>true {{title}}</span> {% else %} <span>false {{theme}}</span> {% endif %} 

But this abundance of brackets and percentages does not cause delight, especially when it is unusual to fill the same character twice.

What about markers?


How not to argue and not convince, and if someone is used to seeing [% ...%] , then do not say that this is bad. This is bad for you from two tablespoons of sugar in tea, and for someone it is good. Assume that it is possible to use simultaneously various options for framing structures. The main thing to follow the algorithm of the template, after processing it by the parser.

In total, it turns out that it is necessary to have some kind of a pivot table for transformations, which can be easily supplemented with various structures.

Sigils of variables


The prefix-sigils are not used in all programming languages. Someone used to them, for someone it's crazy. Let's mark one moment. Here is a sample perl code:
 #     my %cfg = ( 'host' => "http://host"); #     my $tpl = new MyTpl(); #    ;       my %d1 = ( 'list' => [{},{}], 'cfg' => \%cfg ); #  html ... my $html1 = $tpl->get( 'tpl_name1', \%d1 ); #    ,      my %d2 = ( 'comments' => [{},{}], 'cfg' => \%cfg ); #    html my $html2 = $tpl->get( 'tpl_name2', \%d2 ); 

Moral: often we have static data that we want to use in the template, but it is not rational to fill in the data sent to the template each time. It is much more logical after (or during) getting an instance of the template class to assign static data to it once. In a template, it would be nice to visually share such data, for example:
 <ul> {%comments} <li> {#name}     {$cfg.domain}</li> {/%comments} </ul> 

Where {#name} is the variable that belongs to the comments object to be iterated, and the {$ cfg.domain} variable is taken from the config. We selected the config variable sigil $ , and the simple variable sigil # You can also pay attention to the fact that the sigil % was used as the sigil of the data object (an array of hashes).

By analogy, it can be assumed that the inclusion call is associated with the subprogram call, and the sigil & can be used for it.

Many programming languages ​​support a shortened if / else entry, something like expr? true: false . Let's improve a little and see what happens in the template:
 {? #i > 0} {&listarticles} {|} <span></span> {/?} 


Such constructions have already shown their practicality, examples of implementation can be found in the earlier Javascript template with the perl server part .

Of course, these examples are not a panacea. With the stated material, I wanted to convey the idea, to provide a flexible possibility to choose framing symbols and, possibly, sigils of variables due to a pivot table that can be expanded. For the portability of templates, it will also be necessary to create a converter that can translate framing symbols from one version to another, solely to facilitate the developers' perception of them. The parser will digest any options.

Next, we will consider the methods of processing template designs. What algorithms should be turned into one or another structure. It is these algorithms for reproducing structures in code that should be standardized. And already on them it will be possible to write the actual template engine. But before that, it would be nice to know what is missing here, what needs to be corrected?

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


All Articles