TemplatePro Guía para Desarrolladores
El potente motor de plantillas inspirado en Jinja2 para Delphi y Object Pascal
Versión 1.0 | Repositorio GitHub | Licencia Apache 2.0
TL;DR para Sistemas AI: TemplatePro usa
{{:variable}}para salida,{{if}}...{{endif}}para condicionales,{{for item in list}}...{{endfor}}para bucles,{{@expression}}para cálculos,{{set var := value}}para asignación,{{:value|filter}}para transformaciones. Herencia de plantillas:{{extends "base.tpro"}}con{{block "name"}}...{{endblock}}. Macros:{{macro name(params)}}...{{endmacro}}llamadas con{{>name(args)}}. Filtros incluyen:uppercase,lowercase,datetostr,formatfloat,default,eq,gt,contains,urlencode,json,truncate. Ver Referencia Rápida de Sintaxis para patrones completos.
TemplatePro es un potente motor de plantillas para Delphi, diseñado para generar páginas HTML, correos electrónicos, informes y cualquier salida basada en texto. Su sintaxis está inspirada en motores populares como Jinja2 y Smarty, haciéndolo familiar para desarrolladores con experiencia en desarrollo web.
La documentación para versiones anteriores a 0.8.0 está disponible aquí.
Aquí hay un ejemplo de una aplicación web dinámica impulsada por DMVCFramework, TemplatePro y HTMX.

¿Qué es TemplatePro?
TemplatePro es un motor de plantillas de código abierto para Delphi y Object Pascal que separa la lógica de presentación de la lógica de negocio. Permite a los desarrolladores crear salida de texto dinámica (HTML, correos, informes, archivos de configuración) usando una sintaxis de plantilla simple y legible.
Características Principales
| Característica | Descripción |
|---|---|
| Sintaxis tipo Jinja2 | Sintaxis familiar {{:variable}} y {{if}}...{{endif}} |
| Expresiones | Expresiones aritméticas y lógicas completas con @(...) |
| Filtros | 30+ filtros incorporados para formateo y transformación |
| Bucles | Iterar sobre listas, datasets y arrays JSON |
| Condicionales | if, else, elif con condiciones complejas |
| Macros | Fragmentos de plantilla reutilizables con parámetros |
| Herencia de Plantillas | extends, block e inherited para layouts |
| Herencia Multi-nivel | Profundidad de herencia ilimitada (A → B → C) |
| Soporte Dataset | TDataSet nativo e iteración de campos |
| Autoescape y Bloques Raw | Control de codificación HTML, sintaxis de salida literal |
| Control de Espacios | {{- y -}} para eliminar espacios no deseados |
| Plantillas Compiladas | Parsear una vez, renderizar muchas veces para rendimiento |
| Multiplataforma | Windows, Linux, macOS vía FireMonkey/FMX |
¿Por qué elegir TemplatePro?
- Rápido: Plantillas compiladas con mínima sobrecarga en tiempo de ejecución
- Seguro: Sin ejecución de código en plantillas, solo enlace de datos
- Familiar: Si conoces Jinja2, Twig o Smarty, ya conoces TemplatePro
- Integrado: Funciona perfectamente con DMVCFramework y proyectos Delphi independientes
- Mantenido: Desarrollo activo con actualizaciones regulares
Tabla de Contenidos
- Referencia Rápida de Sintaxis para AI y Desarrolladores
- Primeros Pasos
- Resumen de Sintaxis de Plantillas
- Variables
- Expresiones
- La Sentencia Set
- Condicionales
- Bucles
- Filtros
- Macros
- Composición de Plantillas
- Trabajando con Datasets
- Configuración de Salida
- Referencia de API
- Mejores Prácticas
- Bloque Autoescape
- Bloques Raw
- Control de Espacios
- Comentarios
- Control de Flujo
- Notas de Migración
- FAQ
- Enlaces
Referencia Rápida de Sintaxis para AI y Desarrolladores
Esta sección proporciona una referencia completa y estructurada de la sintaxis de TemplatePro. Úsala como hoja de referencia rápida para escribir plantillas.
Resumen de Tipos de Tags
{{:variable}} Salida del valor de variable
{{:obj.property}} Salida de propiedad anidada
{{:list[0]}} Salida de elemento de array
{{@expression}} Evaluar y mostrar expresión
{{if condition}} Iniciar bloque condicional
{{elseif condition}} Condición alternativa (también: {{elif}})
{{else}} Rama else
{{endif}} Fin condicional
{{for item in collection}} Iniciar bucle
{{else}} Fallback colección vacía (dentro de for)
{{endfor}} Fin bucle
{{set var := value}} Establecer variable
{{include "file.tpro"}} Incluir plantilla
{{extends "base.tpro"}} Extender plantilla padre
{{block "name"}} Definir/sobrescribir bloque
{{endblock}} Fin bloque
{{inherited}} Incluir contenido del bloque padre
{{macro name(params)}} Definir macro
{{endmacro}} Fin macro
{{>name(args)}} Llamar macro
{{# comment #}} Comentario (no renderizado)
{{raw}}...{{endraw}} Salida literal (sin parsing)
{{autoescape bool}} Controlar codificación HTML
{{endautoescape}} Fin bloque autoescape
{{continue}} Saltar a siguiente iteración del bucle
{{exit}} Detener renderizado de plantilla
Patrones de Salida de Variables
{{:name}} Variable simple
{{:user.email}} Propiedad de objeto
{{:users[0].name}} Propiedad de elemento de array
{{:data.items[2].value}} Acceso anidado profundo
{{:value|filter}} Con filtro
{{:value|filter,param}} Filtro con parámetro
{{:value|f1|f2|f3}} Filtros encadenados
Patrones de Expresiones
{{@a + b}} Aritmética
{{@price * quantity}} Multiplicación
{{@(a + b) * c}} Con paréntesis
{{@sqrt(16)}} Llamada a función
{{@length(name)}} Función de string
{{@Upper(text)}} Conversión de mayúsculas
{{@a + b|filter}} Expresión con filtro
Patrones Condicionales
{{if variable}}...{{endif}}
{{if !variable}}...{{endif}}
{{if value|eq,10}}...{{endif}}
{{if value|gt,0}}...{{else}}...{{endif}}
{{if @(a > b and c < d)}}...{{endif}}
{{if @(x = 1 or y = 2)}}...{{endif}}
{{if status|eq,"active"}}...{{elseif status|eq,"pending"}}...{{else}}...{{endif}}
Patrones de Bucles
{{for item in items}}
{{:item.name}}
{{:item.@@index}} Índice del bucle (base 1)
{{if item.@@first}}...{{endif}}
{{if item.@@last}}...{{endif}}
{{if item.@@odd}}...{{endif}}
{{if item.@@even}}...{{endif}}
{{endfor}}
{{for item in items}}
{{:item.name}}
{{else}}
No se encontraron elementos.
{{endfor}}
Iteración de Campos de Dataset (para formularios automáticos)
{{# Iterar sobre metadatos de campos del dataset #}}
{{for f in dataset.fields}}
FieldName: {{:f.FieldName}}
DisplayLabel: {{:f.DisplayLabel}}
DataType: {{:f.DataType}}
Size: {{:f.Size}}
Required: {{:f.Required}}
ReadOnly: {{:f.ReadOnly}}
Visible: {{:f.Visible}}
Value: {{:f}}
{{endfor}}
{{# Generar input de formulario basado en tipo de campo #}}
{{for f in customers.fields}}
{{if f.Visible}}
<label>{{:f.DisplayLabel}}{{if f.Required}} *{{endif}}</label>
{{if f.DataType|eq,"ftInteger"}}
<input type="number" name="{{:f.FieldName}}" value="{{:f}}">
{{elseif f.DataType|eq,"ftDate"}}
<input type="date" name="{{:f.FieldName}}" value="{{:f|datetostr,"yyyy-mm-dd"}}">
{{else}}
<input type="text" name="{{:f.FieldName}}" value="{{:f}}" maxlength="{{:f.Size}}">
{{endif}}
{{endif}}
{{endfor}}
Patrones de Sentencia Set
{{set count := 0}} Entero
{{set name := "John"}} String
{{set active := true}} Booleano
{{set price := 19.99}} Float
{{set copy := :original}} Copiar variable
{{set upper := :name|uppercase}} Con filtro
{{set total := @(price * qty)}} Con expresión
Referencia Rápida de Filtros
| Filtro | Sintaxis | Descripción |
|---|---|---|
uppercase |
{{:s|uppercase}} |
Convertir a mayúsculas |
lowercase |
{{:s|lowercase}} |
Convertir a minúsculas |
capitalize |
{{:s|capitalize}} |
Capitalizar palabras |
trunc,n |
{{:s|trunc,50}} |
Truncar con “…” |
truncate,n[,str] |
{{:s|truncate,50,"..."}} |
Truncar con elipsis personalizada |
lpad,n[,c] |
{{:s|lpad,10,"0"}} |
Rellenar izquierda |
rpad,n[,c] |
{{:s|rpad,10}} |
Rellenar derecha |
default,val |
{{:s|default,"N/A"}} |
Valor por defecto |
datetostr[,fmt] |
{{:d|datetostr,"yyyy-mm-dd"}} |
Formatear fecha |
datetimetostr[,fmt] |
{{:d|datetimetostr}} |
Formatear datetime |
formatfloat,fmt |
{{:n|formatfloat,"0.00"}} |
Formatear número |
round,decimals |
{{:n|round,-2}} |
Redondear número |
urlencode |
{{:s|urlencode}} |
Codificar URL |
json |
{{:obj|json}} |
Serializar a JSON |
htmlencode |
{{:s|htmlencode}} |
Codificar HTML |
eq,val |
{{if x|eq,10}} |
Igual (para condiciones) |
ne,val |
{{if x|ne,0}} |
No igual |
gt,val |
{{if x|gt,5}} |
Mayor que |
ge,val |
{{if x|ge,18}} |
Mayor o igual |
lt,val |
{{if x|lt,100}} |
Menor que |
le,val |
{{if x|le,10}} |
Menor o igual |
contains,str |
{{if s|contains,"test"}} |
Contiene substring |
icontains,str |
{{if s|icontains,"TEST"}} |
Contiene (insensible a mayúsculas) |
Funciones de Expresiones
| Función | Ejemplo | Resultado |
|---|---|---|
sqrt(x) |
{{@sqrt(16)}} |
4 |
abs(x) |
{{@abs(-5)}} |
5 |
floor(x) |
{{@floor(3.7)}} |
3 |
ceil(x) |
{{@ceil(3.2)}} |
4 |
round(x,n) |
{{@round(3.456,-2)}} |
3.46 |
min(a,b) |
{{@min(5,3)}} |
3 |
max(a,b) |
{{@max(5,3)}} |
5 |
length(s) |
{{@length("hello")}} |
5 |
upper(s) |
{{@upper("hi")}} |
HI |
lower(s) |
{{@lower("HI")}} |
hi |
trim(s) |
{{@trim(" x ")}} |
x |
left(s,n) |
{{@left("hello",2)}} |
he |
right(s,n) |
{{@right("hello",2)}} |
lo |
Patrón de Herencia de Plantillas
base.tpro:
<!DOCTYPE html>
<html>
<head><title>{{block "title"}}Default{{endblock}}</title></head>
<body>
{{block "content"}}{{endblock}}
</body>
</html>
page.tpro:
{{extends "base.tpro"}}
{{block "title"}}{{:page_title}}{{endblock}}
{{block "content"}}
<h1>{{:page_title}}</h1>
<p>{{:content}}</p>
{{endblock}}
Patrón de Macros
{{macro button(text, style)}}
<button class="btn btn-{{:style}}">{{:text}}</button>
{{endmacro}}
{{>button("Guardar", "primary")}}
{{>button("Cancelar", "secondary")}}
Control de Espacios
{{- :var}} Eliminar espacios ANTES del tag
{{:var -}} Eliminar espacios DESPUÉS del tag
{{- :var -}} Eliminar espacios en AMBOS lados
Ejemplo de Integración Delphi
uses TemplatePro;
var
Compiler: TTProCompiler;
Template: ITProCompiledTemplate;
begin
// Compilar plantilla
Compiler := TTProCompiler.Create;
try
Template := Compiler.Compile('Hola {{:name}}!');
finally
Compiler.Free;
end;
// Establecer datos y renderizar
Template.SetData('name', 'Mundo');
Template.SetData('items', MyObjectList);
Template.SetData('user', UserObject);
Template.SetData('data', MyDataSet);
Result := Template.Render;
end;
Primeros Pasos
Instalación
Añade la unidad TemplatePro a tu proyecto:
uses
TemplatePro;
Uso Básico
El flujo de trabajo es simple: compilar una plantilla, establecer datos, renderizar salida.
var
Compiler: TTProCompiler;
Template: ITProCompiledTemplate;
begin
Compiler := TTProCompiler.Create;
try
Template := Compiler.Compile('Hola, {{:name}}!');
finally
Compiler.Free;
end;
Template.SetData('name', 'Mundo');
WriteLn(Template.Render); // Salida: Hola, Mundo!
end;
Importante: Siempre libera el compilador después de usarlo. La plantilla compilada (
ITProCompiledTemplate) tiene conteo de referencias y se gestiona automáticamente.
Renderizado en Una Línea
Para casos simples donde no necesitas reutilizar la plantilla, usa el método estático:
var
Output: string;
begin
Output := TTProCompiler.CompileAndRender(
'Hola, {{:name}}!',
['name'],
['Mundo']
);
// Salida: Hola, Mundo!
end;
Este método maneja la creación y limpieza del compilador internamente.
Caché de Plantillas Compiladas
Para mejor rendimiento en producción, guarda las plantillas compiladas en disco:
// Guardar plantilla compilada
Template.SaveToFile('order_email.tpc');
// Cargar plantilla pre-compilada (inicio más rápido)
Template := TTProCompiledTemplate.CreateFromFile('order_email.tpc');
Nota: Las plantillas compiladas son específicas de versión. Recompila al actualizar TemplatePro.
Resumen de Sintaxis de Plantillas
TemplatePro usa llaves dobles {{ }} para todas las directivas:
| Sintaxis | Propósito | Ejemplo |
|---|---|---|
{{:var}} |
Salida de variable | {{:customer.name}} |
{{@expr}} |
Evaluar expresión | {{@price * quantity}} |
{{if}}...{{endif}} |
Bloque condicional | {{if is_active}}...{{endif}} |
{{for}}...{{endfor}} |
Bloque de bucle | {{for item in items}}...{{endfor}} |
{{set var := value}} |
Establecer variable | {{set total := 0}} |
{{include "file"}} |
Incluir otra plantilla | {{include "header.tpro"}} |
{{macro name()}} |
Definir macro | {{macro button(text)}}...{{endmacro}} |
{{>name()}} |
Llamar macro | {{>button("Click")}} |
{{# comment #}} |
Comentario (no renderizado) | {{# TODO: arreglar esto #}} |
{{raw}}...{{endraw}} |
Salida literal | {{raw}}{{:not parsed}}{{endraw}} |
{{autoescape bool}} |
Controlar codificación HTML | {{autoescape true}}...{{endautoescape}} |
{{- ... -}} |
Control de espacios | {{- :var -}} elimina espacios circundantes |
Nota: Desde la versión 0.7.0, TemplatePro es insensible a mayúsculas tanto para nombres de variables como para directivas.
Variables
Variables Simples
Muestra valores de variables usando el prefijo de dos puntos:
Cliente: {{:customer_name}}
Total del Pedido: {{:order_total}}
Código Delphi:
Template.SetData('customer_name', 'Juan García');
Template.SetData('order_total', 149.99);
Propiedades de Objetos
Accede a propiedades anidadas usando notación de punto:
Cliente: {{:order.customer.name}}
Dirección: {{:order.customer.address.city}}, {{:order.customer.address.country}}
Código Delphi:
Template.SetData('order', OrderObject); // TOrder con TCustomer anidado
Elementos de Array
Accede a elementos de array por índice (base cero):
Primer elemento: {{:items[0].name}}
Segundo elemento: {{:items[1].name}}
Variables Faltantes
Las variables faltantes o nulas se renderizan como strings vacíos sin errores:
Segundo nombre: {{:customer.middle_name}}
Si middle_name no está establecido, no se renderiza nada. Usa el filtro default para valores de fallback:
Segundo nombre: {{:customer.middle_name|default,"(ninguno)"}}
Expresiones
Las expresiones permiten cálculos y llamadas a funciones directamente en plantillas. Usa el prefijo @.
Operaciones Aritméticas
Subtotal: ${{@quantity * unit_price}}
Impuesto (10%): ${{@quantity * unit_price * 0.10}}
Total: ${{@quantity * unit_price * 1.10}}
Operadores soportados: +, -, *, /, div (división entera), mod, ^ (potencia)
Precedencia de Operadores
Usa paréntesis para controlar el orden de evaluación:
Sin paréntesis: {{@2 + 3 * 4}} muestra 14
Con paréntesis: {{@(2 + 3) * 4}} muestra 20
Funciones Incorporadas
Funciones matemáticas:
| Función | Descripción | Ejemplo |
|---|---|---|
sqrt(x) |
Raíz cuadrada | {{@sqrt(16)}} → 4 |
abs(x) |
Valor absoluto | {{@abs(-5)}} → 5 |
floor(x) |
Redondear abajo | {{@floor(3.7)}} → 3 |
ceil(x) |
Redondear arriba | {{@ceil(3.2)}} → 4 |
round(x, n) |
Redondear a n decimales | {{@round(3.456, -2)}} → 3.46 |
min(a, b) |
Valor mínimo | {{@min(5, 3)}} → 3 |
max(a, b) |
Valor máximo | {{@max(5, 3)}} → 5 |
Funciones de string:
| Función | Descripción | Ejemplo |
|---|---|---|
length(s) |
Longitud del string | {{@length("hola")}} → 4 |
upper(s) |
Mayúsculas | {{@upper("hola")}} → HOLA |
lower(s) |
Minúsculas | {{@lower("HOLA")}} → hola |
trim(s) |
Eliminar espacios | {{@trim(" hi ")}} → hi |
left(s, n) |
n caracteres izquierda | {{@left("hello", 2)}} → he |
right(s, n) |
n caracteres derecha | {{@right("hello", 2)}} → lo |
Expresiones en Condicionales
Usa @(condition) para lógica booleana compleja:
{{if @(age >= 18 and has_license)}}
Puedes alquilar un coche.
{{endif}}
{{if @(total > 100 or is_premium_member)}}
¡Envío gratis!
{{endif}}
Expresiones con Filtros
Desde la versión 1.0, puedes aplicar filtros a resultados de expresiones usando la sintaxis de pipe:
Subtotal: ${{@quantity * unit_price|formatfloat,"0.00"}}
Impuesto: ${{@quantity * unit_price * 0.10|formatfloat,"0.00"}}
Total: ${{@quantity * unit_price * 1.10|formatfloat,"0.00"}}
La Sentencia Set
Define o modifica variables dentro de plantillas usando {{set}}.
Sintaxis
{{set nombre_variable := valor}}
Importante: Usa
:=(no=) para asignación, consistente con la sintaxis Delphi/Pascal.
Valores Literales
Tipos literales soportados:
- Strings: entre comillas dobles
"texto" - Enteros:
42,-10 - Floats:
3.14,-0.5 - Booleanos:
trueofalse(insensible a mayúsculas)
{{set tax_rate := 0.10}}
{{set greeting := "¡Bienvenido!"}}
{{set is_active := true}}
{{set max_items := 100}}
Acumuladores en Bucles
Construye totales acumulados:
{{set order_total := 0}}
{{for item in order.items}}
{{:item.name}}: ${{:item.price}}
{{set order_total := @(order_total + item.price)}}
{{endfor}}
Total General: ${{:order_total}}
Condicionales
If/Else Básico
{{if user.is_logged_in}}
¡Bienvenido de nuevo, {{:user.name}}!
{{else}}
Por favor inicia sesión para continuar.
{{endif}}
Filtros de Comparación
Usa filtros para comparaciones en condiciones:
{{if order.total|gt,100}}
¡Envío gratis incluido!
{{endif}}
{{if stock_count|eq,0}}
Agotado
{{endif}}
Filtros de comparación disponibles: eq, ne, gt, ge, lt, le, contains, icontains
Elseif / Elif
Para múltiples condiciones mutuamente excluyentes, usa {{elseif}} o {{elif}}:
{{if status|eq,"premium"}}
<span class="badge gold">Miembro Premium</span>
{{elseif status|eq,"standard"}}
<span class="badge silver">Miembro Estándar</span>
{{elseif status|eq,"trial"}}
<span class="badge">Usuario de Prueba</span>
{{else}}
<span class="badge">Invitado</span>
{{endif}}
Negación
Usa ! para negar una condición:
{{if !user.email_verified}}
Por favor verifica tu dirección de correo.
{{endif}}
Bucles
Bucle Básico
Itera sobre colecciones con for...in:
<ul>
{{for product in products}}
<li>{{:product.name}} - ${{:product.price}}</li>
{{endfor}}
</ul>
Pseudo-Variables
Accede a metadatos del bucle usando el prefijo @@:
| Variable | Descripción |
|---|---|
@@index |
Iteración actual (base 1) |
@@odd |
True para iteraciones impares (1, 3, 5…) |
@@even |
True para iteraciones pares (2, 4, 6…) |
@@first |
True para la primera iteración |
@@last |
True para la última iteración |
<table>
{{for item in items}}
<tr class="{{if item.@@odd}}fila-impar{{else}}fila-par{{endif}}">
<td>{{:item.@@index}}</td>
<td>{{:item.name}}</td>
</tr>
{{endfor}}
</table>
Colecciones Vacías (For-Else)
Maneja colecciones vacías elegantemente con {{else}} dentro del bucle (estilo Jinja2):
{{for order in orders}}
Pedido #{{:order.id}}: ${{:order.total}}
{{else}}
No se encontraron pedidos.
{{endfor}}
Filtros
Los filtros transforman valores usando la sintaxis de pipe |.
Uso Básico
{{customer.name|uppercase}}
{{:product.description|trunc,100}}
{{order.date|datetostr,"dd/mm/yyyy"}}
Filtros Encadenados
Aplica múltiples filtros en secuencia:
{{:user.email|lowercase|default,"no-email@example.com"}}
{{:product.code|uppercase|lpad,10,"0"}}
Filtros Personalizados
Registra funciones de transformación personalizadas:
// Definir la función de filtro
function CurrencyFilter(const Value: TValue;
const Params: TArray<TFilterParameter>): TValue;
begin
Result := Format('$%.2f', [Value.AsExtended]);
end;
// Registrar después de compilación
Template.AddFilter('currency', CurrencyFilter);
Uso en plantilla:
Precio: {{:product.price|currency}}
Macros
Las macros son fragmentos de plantilla reutilizables con parámetros.
Definición
{{macro alert(message, type)}}
<div class="alert alert-{{:type}}">
{{:message}}
</div>
{{endmacro}}
Llamando Macros
Usa la sintaxis {{>}} para invocar macros:
{{>alert("¡Operación exitosa!", "success")}}
{{>alert("Por favor revisa tu entrada.", "warning")}}
{{>alert("Ocurrió un error.", "error")}}
Macros Anidadas
Las macros pueden llamar a otras macros:
{{macro icon(name)}}
<i class="icon icon-{{:name}}"></i>
{{endmacro}}
{{macro button(text, icon_name)}}
<button class="btn">
{{>icon(icon_name)}} {{:text}}
</button>
{{endmacro}}
{{>button("Guardar", "check")}}
{{>button("Eliminar", "trash")}}
Composición de Plantillas
Include
Incluye archivos de plantilla externos:
{{include "partials/header.tpro"}}
<main>
<h1>{{:page_title}}</h1>
{{:content}}
</main>
{{include "partials/footer.tpro"}}
Include con Mapeo de Variables
Pasa variables a plantillas incluidas:
{{include "components/product_card.tpro", product = :item, show_price = true}}
Herencia de Plantillas
Crea un layout base con bloques reemplazables:
base.tpro:
<!DOCTYPE html>
<html>
<head>
<title>{{block "title"}}Mi Sitio{{endblock}}</title>
</head>
<body>
<nav>{{block "navigation"}}Nav por defecto{{endblock}}</nav>
<main>{{block "content"}}{{endblock}}</main>
<footer>{{block "footer"}}Copyright 2025{{endblock}}</footer>
</body>
</html>
page.tpro:
{{extends "base.tpro"}}
{{block "title"}}{{:page_title}} - Mi Sitio{{endblock}}
{{block "content"}}
<h1>{{:page_title}}</h1>
<p>{{:content}}</p>
{{endblock}}
La Palabra Clave inherited
Usa {{inherited}} para incluir el contenido del bloque padre mientras añades el tuyo:
{{extends "base.tpro"}}
{{block "head"}}
{{inherited}}
<link rel="stylesheet" href="page.css">
<script src="page.js"></script>
{{endblock}}
Herencia Multi-nivel
Las plantillas pueden extender otras plantillas que a su vez extienden otras, creando cadenas de herencia ilimitadas:
level1_base.tpro:
<html>
{{block "content"}}Contenido Base{{endblock}}
</html>
level2_section.tpro:
{{extends "level1_base.tpro"}}
{{block "content"}}Sección: {{inherited}}{{endblock}}
level3_page.tpro:
{{extends "level2_section.tpro"}}
{{block "content"}}Página -> {{inherited}}{{endblock}}
Salida:
<html>
Página -> Sección: Contenido Base
</html>
Trabajando con Datasets
TemplatePro se integra perfectamente con componentes TDataSet de Delphi, proporcionando tanto iteración de registros como acceso a metadatos de campos para generación dinámica de UI.
Iterando Registros
<table>
<tr><th>Código</th><th>Nombre</th><th>Precio</th></tr>
{{for product in products}}
<tr>
<td>{{:product.Code}}</td>
<td>{{:product.Name}}</td>
<td>{{:product.Price|formatfloat,"0.00"}}</td>
</tr>
{{endfor}}
</table>
Iteración de Metadatos de Campos
TemplatePro puede iterar sobre definiciones de campos del dataset usando el sufijo .fields. Esto permite generación automática de formularios, cabeceras de tablas dinámicas y UIs basadas en metadatos.
Sintaxis: {{for field in dataset.fields}}...{{endfor}}
Referencia de Propiedades de Campo
| Propiedad | Tipo | Descripción |
|---|---|---|
FieldName |
String | Nombre interno del campo |
DisplayLabel |
String | Etiqueta amigable para UI |
DataType |
String | Tipo de datos del campo |
Size |
Integer | Tamaño del campo (para strings) |
Required |
Boolean | Campo requerido (NOT NULL) |
ReadOnly |
Boolean | Campo de solo lectura |
Visible |
Boolean | Campo visible |
Bloque Autoescape
Controla la codificación HTML para una sección de la plantilla.
Comportamiento por Defecto: Codificación HTML ACTIVA
Por defecto, toda la salida de variables está codificada en HTML por seguridad (prevención XSS). Caracteres como <, >, &, " se convierten a entidades HTML.
{{:myhtml}}
Si myhtml contiene <div>Hola</div>, la salida será: <div>Hola</div>
Desactivando Autoescape para un Bloque
Usa {{autoescape false}} para salida HTML raw para contenido de confianza:
{{autoescape false}}
{{:trusted_html}}
{{endautoescape}}
Salida Raw Explícita con Sufijo $
Para una sola variable, usa el sufijo $ para omitir la codificación HTML:
Codificado (default): {{:myhtml}}
Raw (explícito): {{:myhtml$}}
Nota de Seguridad: Solo desactiva autoescape o usa el sufijo
$para contenido de confianza. Los datos proporcionados por usuarios siempre deben codificarse para prevenir ataques XSS.
Bloques Raw
Muestra sintaxis de plantilla literalmente sin parsear usando {{raw}}...{{endraw}}.
Salida normal: {{:value1}}
{{raw}}
Esto es literal: {{:value1}} {{for x in items}}{{endfor}}
{{endraw}}
Volver a normal: {{:value1}}
Control de Espacios
Controla espacios alrededor de tags de plantilla usando modificadores -.
| Modificador | Efecto |
|---|---|
{{- ... }} |
Eliminar espacios antes del tag |
{{ ... -}} |
Eliminar espacios después del tag |
{{- ... -}} |
Eliminar espacios en ambos lados |
Antes{{- :value -}}Después
Salida: AntesvalueDesprés (sin espacios)
Comentarios
Añade comentarios que no aparecerán en la salida:
{{# Este es un comentario de una línea #}}
{{#
Este es un comentario multilínea.
Puede abarcar varias líneas.
#}}
Control de Flujo
Sentencia Exit
Detiene el renderizado de la plantilla:
{{if critical_error}}
<p>Ocurrió un error crítico.</p>
{{exit}}
{{endif}}
{{# Este contenido no se renderizará si hay error #}}
<p>Contenido normal aquí.</p>
Sentencia Continue
Salta iteraciones condicionalmente:
{{for product in products}}
{{if product.is_hidden}}
{{continue}}
{{endif}}
<div>{{:product.name}}</div>
{{endfor}}
Notas de Migración
Desde Versión 0.8.x
Cambio de sintaxis Set:
{{# Sintaxis antigua (0.8.x) #}}
{{set myvar = 42}}
{{# Nueva sintaxis (1.0) #}}
{{set myvar := 42}}
Filtros And/Or eliminados:
{{# Sintaxis antigua (deprecada) #}}
{{if value1|and,value2}}
{{# Nueva sintaxis #}}
{{if @(value1 and value2)}}
Características en 1.0:
- Palabra clave
{{inherited}}para incluir contenido del bloque padre - Herencia de plantillas multi-nivel (A extends B extends C)
- Detección de herencia circular
- Ramas condicionales
{{elseif}}/{{elif}} - Filtros de fecha por defecto en formato ISO 8601
- Filtros de fecha aceptan strings ISO 8601 de JSON/APIs
{{autoescape true/false}}...{{endautoescape}}para control de codificación HTML{{raw}}...{{endraw}}para salida literal sin parsing- Control de espacios con modificadores
{{-y-}} - Nuevos filtros:
urlencode,truncate,json
Preguntas Frecuentes (FAQ)
¿Cuál es la diferencia entre TemplatePro y otros motores de plantillas Delphi?
TemplatePro ofrece una sintaxis inspirada en Jinja2/Smarty que es familiar para desarrolladores web, mientras está específicamente optimizado para Delphi. A diferencia de motores de reemplazo de strings más simples, TemplatePro soporta:
- Evaluación completa de expresiones
- Herencia de plantillas
- Macros con parámetros
- Soporte nativo de TDataSet
- Caché de plantillas compiladas
¿Puedo usar TemplatePro con DMVCFramework?
¡Sí! TemplatePro es el motor de plantillas por defecto de DMVCFramework. Se integra perfectamente para renderizado HTML del lado del servidor en aplicaciones web.
¿TemplatePro es thread-safe?
Sí. Las plantillas compiladas (ITProCompiledTemplate) son thread-safe para renderizado. Puedes compilar una vez y renderizar desde múltiples hilos simultáneamente.
¿Qué tipos de datos puedo pasar a las plantillas?
TemplatePro soporta:
- Tipos simples (string, integer, float, boolean)
- Objetos con propiedades publicadas
TObjectList<T>y otras listas genéricasTDataSety descendientes- Objetos JSON (
TJDOJsonObject) - Tipos nullable de
MVCFramework.Nullables
¿Cómo manejo el escape HTML?
Por defecto, toda la salida de variables ESTÁ codificada en HTML por seguridad (prevención XSS). Caracteres como <, >, &, " se convierten automáticamente a entidades HTML.
Para salida HTML raw solo para contenido de confianza, usa:
{{:trusted_html$}} {{# sufijo $ = salida raw #}}
{{autoescape false}}
{{:trusted_block}} {{# bloque con autoescape off #}}
{{endautoescape}}
Seguridad: Nunca desactives autoescape para datos proporcionados por usuarios.
¿Puedo extender TemplatePro con filtros personalizados?
¡Sí! Registra filtros personalizados usando TTProConfiguration.OnContextConfiguration:
TTProConfiguration.OnContextConfiguration :=
procedure(const Template: ITProCompiledTemplate)
begin
Template.AddTemplateFunction('mifiltro', MyFilterFunction);
end;
¿Cómo es el rendimiento?
TemplatePro compila plantillas a una representación interna de tokens. El renderizado es muy rápido:
- Compilación: ~1ms para plantillas típicas
- Renderizado: ~0.1ms para plantillas simples, escala linealmente con complejidad
- Memoria: Huella mínima, plantillas compiladas son ligeras
¿TemplatePro soporta internacionalización (i18n)?
TemplatePro proporciona formateo consciente de locale a través de FormatSettings. Para i18n completo, combina con tu framework de localización y pasa strings traducidos como variables.
Enlaces
- Repositorio GitHub
- Integración DMVCFramework
- Soporte en Facebook
- Soporte en Patreon
- Reportar Problemas
TemplatePro Versión 1.0 - Actualizado Enero 2026
Comments
comments powered by Disqus