TemplatePro Official Documentation
TemplatePro is a powerful and flexible template language designed to simplify the process of generating text-based outputs from structured data in Delphi applications. Whether you’re working with JSON, datasets, or custom objects, TemplatePro offers a wide range of syntactic elements that enable you to create dynamic and responsive templates with ease. In this article, we’ll explore the key syntactic elements of TemplatePro with examples to help you understand how to use this language effectively.
⭐ Updated to TemplatePro Language version 0.5. Check unit tests for more info about syntax and border cases.
Here’s a tipical utilization of a template:
program tproconsole;
{$APPTYPE CONSOLE}
{$R *.res}
uses
TemplatePro { TemplatePro compiler and executor },
System.Rtti { required by TValue },
System.SysUtils { required by try..except block }
;
//this is a custom filter
function AddSquareBrackets(const aValue: TValue; const aParameters: TArray<string>): TValue;
begin
Result := '[' + aValue.AsString + ']';
end;
procedure Main;
begin
var lCompiledTemplate: ITProCompiledTemplate := nil;
var lCompiler := TTProCompiler.Create();
try
var lTemplate := 'Simple variable: {{:variable1}}';
// template must be compiled before utilization
lCompiledTemplate := lCompiler.Compile(lTemplate);
// compiled template can be saved and retrieved from a file.
// A compiled template cannot be executed with and older/newer version of the
// compiler.
finally
lCompiler.Free;
end;
//then, on the compiled template, you can define variable,
//datasets, list of objects and json objects to use while rendering
//the compiled template.
//in this case we use only a simple variable
lCompiledTemplate.SetData('variable1', 'Daniele Teti');
//compiled template can also use "filters" defined
//as simple functions with a specific prototype.
//In this case we are going to use a simple filter wich adds
//square brackets to the input value.
lCompiledTemplate.AddFilter('brackets', AddSquareBrackets);
//the render method returns the result of
//the template execution as string
WriteLn(lCompiledTemplate.Render);
end;
begin
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Let’s introduce the TemplatePro language.
1. Variable Interpolation
At the core of TemplatePro is variable interpolation, allowing you to inject dynamic content directly into your templates. You can use the {{:variable}}
syntax to display the value of a variable.
Example:
Hello, {{:name}}!
Output (if name
is “Daniele”):
Hello, Daniele!
2. Looping with for .. in
The for .. in
loop is a powerful construct in TemplatePro that lets you iterate over collections such as json arrays, datasets or lists of objects. Inside the loop, you can access each item in the collection using a loop variable.
Basic Example:
{{for person in people}}
- {{:person.first_name}} {{:person.last_name}}
{{endfor}}
Output (for a list of people):
- Daniele Teti
- Peter Parker
- Bruce Banner
Nested Loop Example:
You can also nest loops to iterate over collections within collections.
{{for person in people}}
{{:person.first_name}} {{:person.last_name}}
{{for phone in person.phones}}
- {{:phone.type}}: {{:phone.number}}
{{endfor}}
{{endfor}}
Output:
Daniele Teti
- Mobile: 123-456-7890
- Work: 098-765-4321
Peter Parker
- Home: 555-555-5555
- Work: 444-444-4444
3. Conditional Statements: if
, else
, and endif
TemplatePro supports conditional statements that allow you to include or exclude parts of the template based on the value of a condition.
Simple Conditional Example:
{{if is_logged_in}}
Welcome back, {{:username}}!
{{else}}
Please log in to continue.
{{endif}}
Output (if is_logged_in
is true
and username
is “Daniele”):
Welcome back, Daniele!
Output (if is_logged_in
is false
):
Please log in to continue.
Conditional with negation example:
{{if !is_logged_in}}
You cannot see this content
{{endif}}
Output (if is_logged_in
is false
):
You cannot see this content
4. Filters
Filters in TemplatePro allow you to modify the output of variables before they are rendered. Filter parameters (if any) are passed using “,” notation (see next paragraph).
Built-in Filter Example:
Original: {{:name}}
Uppercase: {{:name|uppercase}}
Lowercase: {{:name|lowercase}}
Output (if name
is “Daniele Teti”):
Original: Daniele Teti
Uppercase: DANIELE TETI
Lowercase: daniele teti
Filters parameters (if any) can be passed comma separated (e.g. {{:value1|filter,par1,par2,“par3”}}).
TemplatePro offers a set of built-in filters:
Filter Name | Description |
---|---|
uppercase | returns the value in uppercase |
lowercase | returns the value in lowercase |
capitalize | returns the value capitalized a.k.a. first letter in each word in uppercase |
rpad,xx | returns the value padded to right with spaces. Total length is xx. |
rpad,xx,"-" | returns the value padded to right with “-” char. Total length is xx. |
lpad,xx | returns the value padded to left with spaces. Total length is xx. |
lpad,xx,"-" | returns the value padded to left with “-” char. Total length is xx. |
datetostr | returns the date value as string formatted using the system locale |
datetostr,“yyyy mm dd” | returns the date value as string formatted using the specified format |
datetimetostr | returns the datetime value as string formatted using the system locale |
datetimetostr,“yyyy mm dd hh:nn:ss” | returns the datetime value as string formatted using the specified format |
formatdatetime | alias to datetimetostr |
Custom Filter Example:
Filters can be added to the compiled template. Filters are not required in the compile fase, they are linked and executed only at run-time.
Having a function like the following:
function AddSquareBrackets(const aValue: TValue; const aParameters: TArray<string>): TValue;
begin
Result := '[' + aValue.AsString + ']';
end;
You can let the compiled template “see” it as shown below.
//other code
var lCompiledTemplate := lCompiler.Compile(lTemplate);
lCompiledTemplate.AddFilter('brackets', AddSquareBrackets);
And then use the custom filter “brackets” in the template as shown below.
Bracketed: {{:name|brackets}}
(Where brackets
is a custom filter that adds square brackets around the text.)
Output:
Bracketed: [Daniele Teti]
Filters cannnot be chained.
5. Working with JSON Objects
TemplatePro seamlessly integrates with JSON objects, allowing you to access nested properties using dot notation.
Simple JSON Example:
Company Name: {{:company.name}}
Country: {{:company.country}}
Output (for a JSON object with company.name
as “bit Time Professionals” and company.country
as “Italy”):
Company Name: bit Time Professionals
Country: Italy
Iterating Over JSON Arrays:
You can iterate over JSON arrays using the for .. in
loop.
{{for employee in company.employees}}
- {{:employee.first_name}} {{:employee.last_name}} ({{:employee.role}})
{{endfor}}
Output:
- Daniele Teti (Developer)
- Peter Parker (Developer)
- Bruce Banner (Scientist)
6. Using Functions
TemplatePro supports the use of functions to manipulate data within your templates. Functions can be invoked with parameters and are a great way to add logic to your templates. Currently functions are just filters applied to an empty string, so be warned that the first function parameter is always an empty string.
Basic Function Example:
Sum: {{""|sum,2,3}}
Greeting: {{""|concat,"Hello","World"}}
Output:
Sum: 5
Greeting: Hello, Daniele
7. Template Reuse with include
TemplatePro allows you to reuse templates by including them in other templates. This helps to maintain clean and modular code.
Example:
File header.tpro
Header content from header.tpro
File footer.tpro
Header content from footer.tpro
File main.tpro
{{include "header.tpro"}}
Content of the main template.
{{include "footer.tpro"}}
Output:
Header content from header.tpro
Content of the main template.
Footer content from footer.tpro
Included templates are linked into the main one and will be produced only one compiled template (just like many dcu are included in the output executable).
8. Escaping variables with $
Contents produced by TemplatePro are always HTML escaped.
If you need to include raw content without processing, you can use the $
modifier.
Example:
{{"<div>123</div>"|lowercase}}
{{"<div>123</div>"$|lowercase}}
Output:
<div>123</div>
<div>123</div>
9. Terminate template compiling with exit
exit
statement interrupts the template compiling. It acts like an artificial eof
.
Example:
{{for cust in customers}}
Customer name: {{:cust.Name}}
{{exit}}
{{endfor}}
Output (for first record of customers dataset has a field named “Name” with value “bit Time Professionals”):
Customer name: bit Time Professionals
Dataset (or the object list) is not looped completely because exit
interrupts loop at first iteration.
10. Escaping “double open curly brackets”
In case you have to emit a literal {{
just add another {
; TemplatePro understand that you want to emits a double parentheses.
Example:
TemplatePro uses {{{ as start tag and }} as end tag
Output:
TemplatePro uses {{ as start tag and }} as end tag
11. Comments
TemplatePro comments start with {{#
and terminate with }}
. Can span on multiple lines too.
Example:
This is content {{# but this
is a comment}} and this is another content
Output:
This is content and this is another content
Conclusion
TemplatePro is a versatile and powerful templating engine that offers a wide range of features to help you generate dynamic and efficient output in your Delphi applications. By mastering the various syntactic elements such as for loops, conditionals, filters, and functions, you can create templates that are both readable and maintainable.
The examples provided here are just a glimpse of what TemplatePro can do. I encourage you to explore the TemplatePro GitHub repository and experiment with the various features to see how they can be applied to your projects.
Happy templating!
Comments
comments powered by Disqus