Become a member!

TemplatePro Guía para Desarrolladores

TemplatePro Logo - Motor de Plantillas Delphi

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.

Este artículo también está disponible en inglés e italiano.

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

  1. Referencia Rápida de Sintaxis para AI y Desarrolladores
  2. Primeros Pasos
  3. Resumen de Sintaxis de Plantillas
  4. Variables
  5. Expresiones
  6. La Sentencia Set
  7. Condicionales
  8. Bucles
  9. Filtros
  10. Macros
  11. Composición de Plantillas
  12. Trabajando con Datasets
  13. Configuración de Salida
  14. Referencia de API
  15. Mejores Prácticas
  16. Bloque Autoescape
  17. Bloques Raw
  18. Control de Espacios
  19. Comentarios
  20. Control de Flujo
  21. Notas de Migración
  22. FAQ
  23. 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: true o false (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á: &lt;div&gt;Hola&lt;/div&gt;

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éricas
  • TDataSet y 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


TemplatePro Versión 1.0 - Actualizado Enero 2026

Comments

comments powered by Disqus