Synopse Open Source - Tag - templatesmORMot MVC / SOA / ORM and friends2024-02-02T17:08:25+00:00urn:md5:cc547126eb580a9adbec2349d7c65274DotclearMustache Logic-less templates for Delphi - part 3urn:md5:177e56c3d5bed092677caa99fb1f52322014-04-28T13:39:00+02:002014-04-28T15:55:54+02:00AB4327-GANDIOpen Source librariesblogBusinessRulesCrossPlatformDelphiDocumentationGoodPracticeHTMLinterfaceJavaScriptmORMotmultithreadMustacheMVCOpenSourceperformanceSOASourcesyntaxtemplatesUserInterfaceweb<p><em><a href="https://blog.synopse.info?post/post/2012/03/07/Interface-based-services">Mustache</a></em> is
a well-known <em>logic-less</em> template engine.<br />
There is plenty of Open Source implementations around (including in JavaScript,
which can be very convenient for AJAX applications on client side, for
instance).<br />
For <em>mORMot</em>, we created the first pure Delphi implementation of it,
with a perfect integration with other bricks of the framework.</p>
<p><img src="http://santateresaschool.org/v2/wp-content/uploads/2014/03/mustache-much-8.jpg" alt="" width="250" height="292/" /></p>
<p>In last part of this series of blog articles, we will introduce the
<em>Mustache</em> library included within <em>mORMot</em> source code
tree.<br />
You can <a href="https://blog.synopse.info?post/public/Documents/SynMustache.pdf">download this documentation
as one single pdf file</a>.</p> <p>Part of our <em>mORMot</em> framework, we implemented an optimized
<em>Mustache</em> template engine in the <code>SynMustache</code> unit:</p>
<ul>
<li>It is the first Delphi implementation of <em>Mustache</em>;</li>
<li>It has a separate parser and renderer (so you can compile your templates
ahead of time);</li>
<li>The parser features a shared cache of compiled templates;</li>
<li>It passes all official <a href="http://github.com/mustache/spec"><em>Mustache</em> specification tests</a> -
including all weird whitespace process;</li>
<li>External partials can be supplied as <code>TSynMustachePartials</code>
dictionaries;</li>
<li><code>{{.}}</code>, <code>{{-index}}</code> and <code>{{"some text}}</code>
pseudo-variables were added to the standard <em>Mustache</em> syntax;</li>
<li><code>{{#-first}}</code>, <code>{{#-last}}</code> and
<code>{{#-odd}}</code> pseudo-sections were added to the standard
<em>Mustache</em> syntax;</li>
<li>Internal partials can be defined via <code>{{<partial}}</code> - also a
nice addition to the standard <em>Mustache</em> syntax;</li>
<li>It allows the data context to be supplied as JSON or our <a href="https://blog.synopse.info?post/post/2014/02/25/TDocVariant-custom-variant-type"><em>TDocVariant</em> custom
type</a>;</li>
<li>Almost no memory allocation is performed during the rendering;</li>
<li>It is natively UTF-8, from the ground up, with optimized conversion of any
string data;</li>
<li>Performance has been tuned and grounded in <code>SynCommons</code>'s
optimized code;</li>
<li>Each parsed template is thread-safe and re-entrant;</li>
<li>It follows the <em><a href="https://blog.synopse.info?post/post/2011/11/27/SOLID-design-principles">Open/Close principle</a></em> so
that any aspect of the process can be customized and extended (e.g. for any
kind of data context);</li>
<li>It is perfectly integrated with the other bricks of our <em>mORMot</em>
framework, ready to implement dynamic web sites with true 10 design, and full
separation of concerns in the views written in <em>Mustache</em>, the
controllers being e.g. interface-based services;</li>
<li>API is flexible and easy to use.</li>
</ul>
<h3>Variables</h3>
<p>Now, let's see some code.</p>
<p>First, we define our needed variables:</p>
<pre>
<strong>var</strong> mustache: TSynMustache;
doc: <strong>variant</strong>;
</pre>
<p>In order to parse a template, you just need to call:</p>
<pre>
mustache := TSynMustache.Parse(
'Hello {{name}}'#13#10'You have just won {{value}} dollars!');
</pre>
<p>It will return a compiled instance of the template.<br />
The <code>Parse()</code> class method will use the shared cache, so you won't
need to release the <code>mustache</code> instance once you are done with it:
no need to write a <code>try ... finally mustache.Free; end</code> block.</p>
<p>You can use a <code>TDocVariant</code> to supply the context data (with
late-binding):</p>
<pre>
TDocVariant.New(doc);
doc.name := 'Chris';
doc.value := 10000;
</pre>
<p>As an alternative, you may have defined the context data as such:</p>
<pre>
doc := _ObjFast(['name','Chris','value',1000]);
</pre>
<p>Now you can render the template with this context:</p>
<pre>
html := mustache.Render(doc);
<em>// now html='Hello Chris'#13#10'You have just won 10000 dollars!'</em>
</pre>
<p>If you want to supply the context data as JSON, then render it, you may
write:</p>
<pre>
mustache := TSynMustache.Parse(
'Hello {{value.name}}'#13#10'You have just won {{value.value}} dollars!');
html := mustache.RenderJSON('{value:{name:"Chris",value:10000}}');
<em>// now html='Hello Chris'#13#10'You have just won 10000 dollars!'</em>
</pre>
<p>Note that here, the JSON is supplied with an extended syntax (i.e. field
names are unquoted), and that <code>TSynMustache</code> is able to identify a
dotted-named variable within the execution context.</p>
<p>As an alternative, you could use the following syntax to create the data
context as JSON, with a set of parameters, therefore easier to work with in
real code storing data in variables (for instance, any <code>string</code>
variable is quoted as expected by JSON, and converted into UTF-8):</p>
<pre>
mustache := TSynMustache.Parse(
'Hello {{name}}'#13#10'You have just won {{value}} dollars!');
html := mustache.RenderJSON('{name:?,value:?}',[],['Chris',10000]);
html='Hello Chris'#13#10'You have just won 10000 dollars!'
</pre>
<p>You can find in the <code>mORMot.pas</code> unit the
<code>ObjectToJSON()</code> function which is able to transform any
<code>TPersistent</code> instance into valid JSON content, ready to be supplied
to a <code>TSynMustache</code> compiled instance.<br />
If the object's published properties have some getter functions, they will be
called on the fly to process the data (e.g. returning 'FirstName Name' as
FullName by concatenating both sub-fields).</p>
<h3>Sections</h3>
<p>Sections are handled as expected:</p>
<pre>
mustache := TSynMustache.Parse('Shown.{{#person}}As {{name}}!{{/person}}end{{name}}');
html := mustache.RenderJSON('{person:{age:?,name:?}}',[10,'toto']);
<em>// now html='Shown.As toto!end'</em>
</pre>
<p>Note that the sections change the data context, so that within the
<code>#person</code> section, you can directly access to the data context
<code>person</code> member, i.e. writing directly <code>name</code></p>
<p>It supports also inverted sections:</p>
<pre>
mustache := TSynMustache.Parse('Shown.{{^person}}Never shown!{{/person}}end');
html := mustache.RenderJSON('{person:true}');
<em>// now html='Shown.end'</em>
</pre>
<p>To render a list of items, you can write for instance (using the
<code>.</code> pseudo-variable):</p>
<pre>
mustache := TSynMustache.Parse('{{#things}}{{.}}{{/things}}');
html := mustache.RenderJSON('{things:["one", "two", "three"]}');
<em>// now html='onetwothree'</em>
</pre>
<p>The <code>-index</code> pseudo-variable allows to numerate the list items,
when rendering:</p>
<pre>
mustache := TSynMustache.Parse(
'My favorite things:'#$A'{{#things}}{{-index}}. {{.}}'#$A'{{/things}}');
html := mustache.RenderJSON('{things:["Peanut butter", "Pen spinning", "Handstands"]}');
<em>// now html='My favorite things:'#$A'1. Peanut butter'#$A'2. Pen spinning'#$A+</em>
<em>// '3. Handstands'#$A,'-index pseudo variable'</em>
</pre>
<h3>Partials</h3>
<p>External partials (i.e. standard <em>Mustache</em> partials) can be defined
using <code>TSynMustachePartials</code>. You can define and maintain a list of
<code>TSynMustachePartials</code> instances, or you can use a one-time partial,
for a given rendering process, as such:</p>
<pre>
mustache := TSynMustache.Parse('{{>partial}}'#$A'3');
html := mustache.RenderJSON('{}',TSynMustachePartials.CreateOwned(['partial','1'#$A'2']));
<em>// now html='1'#$A'23','external partials'</em>
</pre>
<p>Here <code>TSynMustachePartials.CreateOwned()</code> expects the partials to
be supplied as name/value pairs.</p>
<p>Internal partials (one of the <code>SynMustache</code> extensions), can be
defined directly in the main template:</p>
<pre>
mustache := TSynMustache.Parse('{{<partial}}1'#$A'2{{name}}{{/partial}}{{>partial}}4');
html := mustache.RenderJSON('{name:3}');
<em>// now html='1'#$A'234','internal partials'</em>
</pre>
<h3>Internationalization</h3>
<p>You can define <code>{{"some text}}</code> pseudo-variables in your
templates, which text will be supplied to a callback, ready to be transformed
on the fly: it may be convenient for <em>i18n</em> of web applications.</p>
<p>By default, the text will be written directly to the output buffer, but you
can define a callback which may be used e.g. for text translation:</p>
<pre>
<strong>procedure</strong> TTestLowLevelTypes.MustacheTranslate(<strong>var</strong> English: <strong>string</strong>);
<strong>begin</strong>
<strong>if</strong> English='Hello' <strong>then</strong>
English := 'Bonjour' <strong>else</strong>
<strong>if</strong> English='You have just won' <strong>then</strong>
English := 'Vous venez de gagner';
<strong>end</strong>;
</pre>
<p>Of course, in a real application, you may assign one
<code>TLanguageFile.Translate(var English: string)</code> method, as defined in
the <code>mORMoti18n.pas</code> unit.</p>
<p>Then, you will be able to define your template as such:</p>
<pre>
mustache := TSynMustache.Parse(
'{{"Hello}} {{name}}'#13#10'{{"You have just won}} {{value}} {{"dollars}}!');
html := mustache.RenderJSON('{name:?,value:?}',[],['Chris',10000],<strong>nil</strong>,MustacheTranslate);
<em>// now html='Bonjour Chris'#$D#$A'Vous venez de gagner 10000 dollars!'</em>
</pre>
<p>All text has indeed been translated as expected.</p>
<p>Feedback is <a href="http://synopse.info/forum/viewtopic.php?id=1720">welcome on our forum, as
usual</a>!</p>Mustache Logic-less templates for Delphi - part 2urn:md5:933cfcf13ca723e4ff09e08550ceccfb2014-04-28T13:38:00+02:002014-04-28T15:55:39+02:00AB4327-GANDIOpen Source librariesblogBusinessRulesCrossPlatformDelphiDocumentationGoodPracticeHTMLinterfaceJavaScriptmORMotmultithreadMustacheMVCOpenSourceperformanceSOASourcesyntaxtemplatesUserInterfaceweb<p><em><a href="http://mustache.github.io/">Mustache</a></em> is a well-known
<em>logic-less</em> template engine.<br />
There is plenty of Open Source implementations around (including in JavaScript,
which can be very convenient for AJAX applications on client side, for
instance).<br />
For <em>mORMot</em>, we created the first pure Delphi implementation of it,
with a perfect integration with other bricks of the framework.</p>
<p><img src="http://santateresaschool.org/v2/wp-content/uploads/2014/03/mustache-much-8.jpg" alt="" width="250" height="292/" /></p>
<p>In this second part of this series of blog articles, we will introduce the
<em>Mustache</em> syntax.<br />
You can <a href="https://blog.synopse.info?post/public/Documents/SynMustache.pdf">download this documentation
as one single pdf file</a>.</p> <p>The <em>Mustache</em> template logic-less language has five types of
tags:</p>
<ol>
<li>Variables;</li>
<li>Sections;</li>
<li>Inverted Sections;</li>
<li>Comments;</li>
<li>Partials.</li>
</ol>
<p>All those tags will be identified with mustaches, i.e.
<code>{{...}}</code>.<br />
Anything found in a template of this form is interpreted as a template
marker.<br />
All other text is considered formatting text and is output verbatim at template
expansion time.</p>
<table>
<tbody>
<tr>
<td><strong>Marker</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td><code>{{variable}}</code></td>
<td>The <code>variable</code> name will be searched recursively within the
current context (possibly with dotted names), and, if found, will be written as
escaped HTML.<br />
If there is no such key, nothing will be rendered.</td>
</tr>
<tr>
<td><code>{{{variable}}}<br />
{{& variable}}</code></td>
<td>The <code>variable</code> name will be searched recursively within the
current context, and, if found, will be written directly, <em>without any HTML
escape</em>.<br />
If there is no such key, nothing will be rendered.</td>
</tr>
<tr>
<td><code>{{#section}}<br /></code>...<br />
<code>{{/section}}</code></td>
<td>Defines a block of text, aka <em>section</em>, which will be rendered
depending of the <code>section</code> variable value, as searched in the
current context:<br />
- If <code>section</code> equals <code>false</code> or is an <em>empty
list</em> <code>[]</code>, the whole block won't be rendered;<br />
- If <code>section</code> is non-<code>false</code> but not a list, it will be
used as the context for a single rendering of the block;<br />
- If <code>section</code> is a non-empty list, the text in the block will be
rendered once for each item in the list - the context of the block will be set
to the current item for each iteration.</td>
</tr>
<tr>
<td><code>{{^section}}<br /></code>...<br />
<code>{{/section}}</code></td>
<td>Defines a block of text, aka <em>inverted section</em>, which will be
rendered depending of the <code>section</code> variable <em>inverted</em>
value, as searched in the current context:<br />
- If <code>section</code> equals <code>false</code> or is an <em>empty
list</em>, the whole block <em>will</em> be rendered;<br />
- If <code>section</code> is non-<code>false</code> or a non-empty list, it
won't be rendered.</td>
</tr>
<tr>
<td><code>{{! comment}}</code></td>
<td>The comment text will just be ignored.</td>
</tr>
<tr>
<td><code>{{>partial}}</code></td>
<td>The <code>partial</code> name will be searched within the registered
<em>partials list</em>, then will be executed at run-time (so recursive
partials are possible), with the current execution context.</td>
</tr>
<tr>
<td><code>{{=...=}}</code></td>
<td>The delimiters (i.e. by default <code>{{ }}</code>) will be replaced by the
specified characters (may be convenient when double-braces may appear in the
text).</td>
</tr>
</tbody>
</table>
<p>In addition to those standard markers, the <em>mORMot</em> implementation of
<em>Mustache</em> features:</p>
<table>
<tbody>
<tr>
<td><strong>Marker</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td><code>{{.}}</code></td>
<td>This pseudo-variable refers to the context object itself instead of one of
its members. This is particularly useful when iterating over lists.</td>
</tr>
<tr>
<td><code>{{-index}}</code></td>
<td>This pseudo-variable returns the current item number when iterating over
lists, starting counting at 1</td>
</tr>
<tr>
<td><code>{{#-first}}<br /></code>...<br />
<code>{{/-first}}</code></td>
<td>Defines a block of text (pseudo-section), which will be rendered - or
<em>not</em> rendered for inverted <code>{{^-first}}</code> - for the
<em>first</em> item when iterating over lists</td>
</tr>
<tr>
<td><code>{{#-last}}<br /></code>...<br />
<code>{{/-last}}</code></td>
<td>Defines a block of text (pseudo-section), which will be rendered - or
<em>not</em> rendered for inverted <code>{{^-last}}</code> - for the
<em>last</em> item when iterating over lists</td>
</tr>
<tr>
<td><code>{{#-odd}}<br /></code>...<br />
<code>{{/-odd}}</code></td>
<td>Defines a block of text (pseudo-section), which will be rendered - or
<em>not</em> rendered for inverted <code>{{^-odd}}</code> - for the
<em>odd</em> item number when iterating over lists: it can be very usefull e.g.
to display a list with alternating row colors</td>
</tr>
<tr>
<td><code>{{<partial}}<br /></code>...<br />
<code>{{/partial}}</code></td>
<td>Defines an in-lined <em>partial</em> - to be called later via
<code>{{>partial}}</code> - within the scope of the current template</td>
</tr>
<tr>
<td><code>{{"some text}}</code></td>
<td>This pseudo-variable will supply the given text to a callback, which will
for instance transform its content (e.g. translate it), before writing it to
the output</td>
</tr>
</tbody>
</table>
<p>This set of markers will allow to easily write any kind of content, without
any explicit logic nor nested code.<br />
As a major benefit, the template content could be edited and verified without
the need of any <em>Mustache</em> compiler, since all those
<code>{{...}}</code> markers will identify very clearly the resulting
layout.</p>
<h3>Variables</h3>
<p>A typical Mustache template:</p>
<pre>
Hello {{name}}
You have just won {{value}} dollars!
Well, {{taxed_value}} dollars, after taxes.
</pre>
<p>Given the following hash:</p>
<pre>
{
"name": "Chris",
"value": 10000,
"taxed_value": 6000
}
</pre>
<p>Will produce the following:</p>
<pre>
Hello Chris
You have just won 10000 dollars!
Well, 6000 dollars, after taxes.
</pre>
<p>You can note that <code>variable</code> tags are escaped for HTML by
default. This is a mandatory security feature. In fact, all web applications
which create HTML documents can be vulnerable to Cross-Site-Scripting (XSS)
attacks unless data inserted into a template is appropriately sanitized and/or
escaped. With Mustache, this is done by default. Of course, you can override it
and force to <em>not-escape</em> the value, using <code>variable or &
variable</code>.</p>
<p>For instance:</p>
<table>
<tbody>
<tr>
<td><strong>Template</strong></td>
<td><strong>Context</strong></td>
<td><strong>Output</strong></td>
</tr>
<tr>
<td><code>* {{name}}<br />
* {{age}}<br />
* {{company}}<br />
* {{{company}}}</code></td>
<td><code>{<br />
"name": "Chris",<br />
"company": "<b>GitHub</b>"<br />
}</code></td>
<td><code>* Chris<br />
*<br />
* &lt;b&gt;GitHub&lt;/b&gt;<br />
* <b>GitHub</b></code></td>
</tr>
</tbody>
</table>
<p>Variables resolve names within the current context with an optional dotted
syntax, for instance:</p>
<table>
<tbody>
<tr>
<td><strong>Template</strong></td>
<td><strong>Context</strong></td>
<td><strong>Output</strong></td>
</tr>
<tr>
<td><code>* {{people.name}}<br />
* {{people.age}}<br />
* {{people.company}}<br />
* {{{people.company}}}</code></td>
<td><code>{<br />
"name": "Chris",<br />
"company": "<b>GitHub</b>"<br />
}</code></td>
<td><code>* Chris<br />
*<br />
* &lt;b&gt;GitHub&lt;/b&gt;<br />
* <b>GitHub</b></code></td>
</tr>
</tbody>
</table>
<h3>Sections</h3>
<p><em>Sections</em> render blocks of text one or more times, depending on the
value of the key in the current context.</p>
<p>In our "wining template" above, what happen if we do want to hide the tax
details?<br />
In most script languages, we may write an <code>if ...</code> block within the
template. This is what <em>Mustache</em> avoids. So we define a section, which
will be rendered on need.</p>
<p>The template becomes:</p>
<pre>
Hello {{name}}
You have just won {{value}} dollars!
{{#in_ca}}
Well, {{taxed_value}} dollars, after taxes.
{{/in_ca}}
</pre>
<p>Here, we created a new section, named <code>in_ca</code>.</p>
<p>Given the hash value of <code>in_ca</code> (and its presence), the section
will be rendered, or not:</p>
<table>
<tbody>
<tr>
<td><strong>Context</strong></td>
<td><strong>Output</strong></td>
</tr>
<tr>
<td><code>{<br />
"name": "Chris",<br />
"value": 10000,<br />
"taxed_value": 6000,<br />
"in_ca": true<br />
}</code></td>
<td><code>Hello Chris<br />
You have just won 10000 dollars!<br />
Well, 6000 dollars, after taxes.</code></td>
</tr>
<tr>
<td><code>{<br />
"name": "Chris",<br />
"value": 10000,<br />
"taxed_value": 6000,<br />
"in_ca": false<br />
}</code></td>
<td><code>Hello Chris<br />
You have just won 10000 dollars!</code></td>
</tr>
<tr>
<td><code>{<br />
"name": "Chris",<br />
"value": 10000,<br />
"taxed_value": 6000<br />
}</code></td>
<td><code>Hello Chris<br />
You have just won 10000 dollars!</code></td>
</tr>
</tbody>
</table>
<p>Sections also change the context of its inner block. It means that the
section variable content becomes the top-most context which will be used to
identify any supplied variable key.</p>
<p>Therefore, the following context will be perfectly valid: we can define
<code>taxed_value</code> as a member of <code>in_ca</code>, and it will be
rendered directly, since it is part of the new context.</p>
<table>
<tbody>
<tr>
<td><strong>Context</strong></td>
<td><strong>Output</strong></td>
</tr>
<tr>
<td><code>{<br />
"name": "Chris",<br />
"value": 10000,<br />
"in_ca": {<br />
"taxed_value": 6000<br />
}<br />
}<br />
<br /></code></td>
<td><code>Hello Chris<br />
You have just won 10000 dollars!<br />
Well, 6000 dollars, after taxes.</code></td>
</tr>
<tr>
<td><code>{<br />
"name": "Chris",<br />
"value": 10000,<br />
"taxed_value": 6000<br />
}</code></td>
<td><code>Hello Chris<br />
You have just won 10000 dollars!</code></td>
</tr>
<tr>
<td><code>{<br />
"name": "Chris",<br />
"value": 10000,<br />
"taxed_value": 3000,<br />
"in_ca": {<br />
"taxed_value": 6000<br />
}<br />
}<br /></code></td>
<td><code>Hello Chris<br />
You have just won 10000 dollars!<br />
Well, 6000 dollars, after taxes.</code></td>
</tr>
</tbody>
</table>
<p>In the latest context above, there are two <code>taxed_value</code>
variables.<br />
The engine will use the one defined by the context in the <code>in_ca</code>
section, i.e. <code>in_ca.taxed_value</code>; the one defined at the root
context level (which equals 3000) is just ignored.</p>
<p>If the variable pointed by the section name is a list, the text in the block
will be rendered once for each item in the list.<br />
The context of the block will be set to the current item for each
iteration.</p>
<p>In this way we can loop over collections.<br />
<em>Mustache</em> allows any depth of nested loops (e.g. any level of
master/details information).</p>
<table>
<tbody>
<tr>
<td><strong>Template</strong></td>
<td><strong>Context</strong></td>
<td><strong>Output</strong></td>
</tr>
<tr>
<td><code>{{#repo}}<br />
<b>name</b><br />
{{/repo}}</code></td>
<td><code>{<br />
"repo": [<br />
{"name": "resque"},<br />
{"name": "hub"},<br />
{"name": "rip"} <br />
]<br />
}</code></td>
<td><code><b>resque</b><br />
<b>hub</b><br />
<b>rip</b></code></td>
</tr>
<tr>
<td><code>{{#repo}}<br />
<b>.</b><br />
{{/repo}}</code></td>
<td><code>{<br />
"repo":<br />
["resque", "hub", "rip"]<br />
}</code></td>
<td><code><b>resque</b><br />
<b>hub</b><br />
<b>rip</b></code></td>
</tr>
</tbody>
</table>
<p>The latest template makes use of the <code>.</code> pseudo-variable, which
allows to render the current item of the list.</p>
<h3>Inverted Sections</h3>
<p>An inverted section begins with a caret (<code>^</code>) and ends as a
standard (non-inverted) section.<br />
They may render text once, based on the <em>inverse</em> value of the key. That
is, the text block will be rendered if the key doesn't exist, is false, or is
an empty list.</p>
<p>Inverted sections are usually defined after a standard section, to render
some message in case no information will be written in the non-inverted
section:</p>
<table>
<tbody>
<tr>
<td><strong>Template</strong></td>
<td><strong>Context</strong></td>
<td><strong>Output</strong></td>
</tr>
<tr>
<td><code>{{#repo}}<br />
<b>.</b><br />
{{/repo}}<br />
{{^repo}}<br />
No repos <img src="https://blog.synopse.info?pf=sad.svg" alt=":(" class="smiley" /><br />
{{/repo}}</code></td>
<td><code>{<br />
"repo":<br />
[]<br />
}</code></td>
<td><code>No repos <img src="https://blog.synopse.info?pf=sad.svg" alt=":(" class="smiley" /></code></td>
</tr>
</tbody>
</table>
<h3>Partials</h3>
<p>Partials are some kind of external sub-templates which can be included
within a main template, for instance to follow the same rendering at several
places.<br />
Just like functions in code, they do ease template maintainability and spare
development time.</p>
<p>Partials are rendered at runtime (as opposed to compile time), so recursive
partials are possible. Just avoid infinite loops.<br />
They also inherit the calling context, so can easily be re-used within a list
section, or together with plain variables.</p>
<p>In practice, partials shall be supplied together with the data context -
they could be seen as "template context".</p>
<p>For example, this "main" template uses a <code>> user</code> partial:</p>
<pre>
<h2>Names</h2>
{{#names}}
{{> user}}
{{/names}}
</pre>
<p>With the following template registered as "user":</p>
<pre>
<strong>{{name}}</strong>
</pre>
<p>Can be thought of as a single, expanded template:</p>
<pre>
<h2>Names</h2>
{{#names}}
<strong>{{name}}</strong>
{{/names}}
</pre>
<p>In <em>mORMot</em>'s implementations, you can also create some
<em>internal</em> partials, defined as <code><partial ... /partial</code>
pseudo-sections.<br />
It may decrease the need of maintaining multiple template files, and refine the
rendering layout.</p>
<p>For instance, the previous template may be defined at once:</p>
<pre>
<h2>Names</h2>
{{#names}}
{{>user}}
{{/names}}
{{<user}}
<strong>{{name}}</strong>
{{/user}}
</pre>
<p>The same file will define both the partial and the main template. </p>
<p>Note that we defined the internal partial after the main template, but we
may have defined it anywhere in the main template logic: internal partials
definitions are ignored when rendering the main template, just like
comments.</p>
<p><a href="https://blog.synopse.info?post/post/2014/04/28/Mustache-Logic-less-templates-for-Delphi-part-3">Next article
will detail the <em>Mustache</em> engine as implemented in <em>mORMot</em>'s
source code tree</a>.<br />
Now, a bit of practice!</p>Mustache Logic-less templates for Delphi - part 1urn:md5:5e26b8841fcba48a85895f3f787cd0172014-04-28T13:37:00+02:002014-04-28T15:55:15+02:00AB4327-GANDIOpen Source librariesblogBusinessRulesCrossPlatformDelphiDocumentationGoodPracticeHTMLinterfaceJavaScriptmORMotmultithreadMustacheMVCOpenSourceperformanceSOASourcesyntaxtemplatesUserInterfaceweb<p><em><a href="http://mustache.github.io/">Mustache</a></em> is a well-known
<em>logic-less</em> template engine.<br />
There is plenty of Open Source implementations around (including in JavaScript,
which can be very convenient for AJAX applications on client side, for
instance).<br />
For <em>mORMot</em>, we created the first pure Delphi implementation of it,
with a perfect integration with other bricks of the framework.</p>
<p><img src="http://santateresaschool.org/v2/wp-content/uploads/2014/03/mustache-much-8.jpg" alt="" width="250" height="292/" /></p>
<p>In this first part of this series of blog articles, we will introduce the
<em>Mustache</em> design.<br />
You can <a href="https://blog.synopse.info?post/public/Documents/SynMustache.pdf">download this documentation
as one single pdf file</a>.</p> <p>Generally speaking, a Template system can be used to separate output
formatting specifications, which govern the appearance and location of output
text and data elements, from the executable logic which prepares the data and
makes decisions about what appears in the output.</p>
<p>Most template systems (e.g. PHP, smarty, Razor...) feature in fact a full
scripting engine within the template content.<br />
It allows powerful constructs like variable assignment or conditional
statements in the middle of the HTML content. It makes it easy to modify the
look of an application within the template system exclusively, without having
to modify any of the underlying "application logic". They do so, however, at
the cost of separation, turning the templates themselves into part of the
application logic.</p>
<p><em>Mustache</em> inherits from Google's <em>ctemplate</em> library, and is
used in many famous applications, including the "main" <a href="http://code.google.com/p/ctemplate">Google web search</a>, or the Twitter web
site.<br />
The <em>Mustache</em> template system leans strongly towards preserving the
separation of logic and presentation, therefore ensures a perfect <a href="https://blog.synopse.info?post/post/2014/04/18/Introducing-mORMot-s-architecture-and-design-principles">MVC
design</a>, and ready to consume SOA services.</p>
<p><em>Mustache</em> is intentionally constrained in the features it supports
and, as a result, applications tend to require quite a bit of code to
instantiate a template: all the application logic will be defined within the
<em>Controller</em> code, not in the <em>View</em> source.<br />
This may not be to everybody's tastes. However, while this design limits the
power of the template language, it does not limit the power or flexibility of
the template system. This system supports arbitrarily complex text
formatting.</p>
<p>Finally, <em>Mustache</em> is designed with an eye towards efficiency.
Template instantiation is very quick, with an eye towards minimizing both
memory use and memory fragmentation. As a result, it sounds like a perfect
template system for our <em>mORMot</em> framework.</p>
<h3>Mustache principles</h3>
<p>There are two main parts to the <em>Mustache</em> template system:</p>
<ol>
<li>Templates (which are plain text files);</li>
<li>Data dictionaries (aka <em>Context</em>).</li>
</ol>
<p>For instance, given the following template:</p>
<pre>
<h1>{{header}}</h1>
<br />{{#items}}
{{#first}}
<li><strong>{{name}}</strong></li>
{{/first}}
{{#link}}
<li><a href="{{url}}">{{name}}</a></li>
{{/link}}
{{/items}}
<br />{{#empty}}
<p>The list is empty.</p>
{{/empty}}
</pre>
<p>and the following data context:</p>
<pre>
{
"header": "Colors",
"items": [
{"name": "red", "first": <strong>true</strong>, "url": "#Red"},
{"name": "green", "link": <strong>true</strong>, "url": "#Green"},
{"name": "blue", "link": <strong>true</strong>, "url": "#Blue"}
],
"empty": <strong>true</strong>
}
</pre>
<p>The <em>Mustache</em> engine will render this data as such:</p>
<pre>
<h1>Colors</h1>
<li><strong>red</strong></li>
<li><a href="#Green">green</a></li>
<li><a href="#Blue">blue</a></li>
<p>The list is empty.</p>
</pre>
<p>In fact, you did not see any "<code>if</code>" nor "<em>for</em>" loop in
the template, but <em>Mustache</em> conventions make it easy to render the
supplied data as the expected HTML output. It is up to the MVC
<em>Controller</em> to render the data as expected by the template, e.g. for
formatting dates or currency values.</p>
<p><a href="https://blog.synopse.info?post/post/2014/04/28/Mustache-Logic-less-templates-for-Delphi-part-2">Next article
will detail the Mustache syntax itself</a>.<br />
Stay tuned!</p>