Saltar a contenido

Presentación

Leaf es un potente lenguaje de plantillas con una sintaxis inspirada en Swift. Puedes usarlo para generar páginas HTML dinámicas destinadas a un portal web o generar correos electrónicos enriquecidos para enviar desde una API.

Esta guía te proporcionará una visión general de la sintaxis de Leaf y las etiquetas disponibles.

Sintaxis de la plantilla

Aquí tienes un ejemplo de cómo se usa una etiqueta básica de Leaf.

There are #count(users) users.

Las etiquetas de Leaf constan de cuatro elementos:

  • Token #: Esto indica al analizador de Leaf que comience a buscar una etiqueta.
  • Nombre count: identifica a la etiqueta.
  • Parámetro (users): Puede aceptar cero o más argumentos.
  • Cuerpo: Algunas etiquetas pueden tener un cuerpo opcional, que se suministra usando dos puntos y una etiqueta de cierre.

Dependiendo de la implementación de la etiqueta, puede haber muchos usos diferentes de estos cuatro elementos. Veamos algunos ejemplos de cómo se podrían usar las etiquetas incorporadas de Leaf:

#(variable)
#extend("template"): I'm added to a base template! #endextend
#export("title"): Welcome to Vapor #endexport
#import("body")
#count(friends)
#for(friend in friends): <li>#(friend.name)</li> #endfor

Leaf también admite muchas expresiones con las que estás familiarizado en Swift.

  • +
  • %
  • >
  • ==
  • ||
  • etc.
#if(1 + 1 == 2):
    Hello!
#endif

#if(index % 2 == 0):
    This is even index.
#else:
    This is odd index.
#endif

Contexto

En el ejemplo de Comenzando, usamos un diccionario [String: String] para pasar datos a Leaf. Sin embargo, puedes pasar cualquier cosa conformada con Encodable. Es preferible usar estructuras Encodable ya que [String: Any] no está soportado. Esto significa que no puedes pasar un array directamente, y en su lugar deberías envolverlo en una estructura:

struct WelcomeContext: Encodable {
    var title: String
    var numbers: [Int]
}
return req.view.render("home", WelcomeContext(title: "Hello!", numbers: [42, 9001]))

Esto expondrá title y numbers a nuestra plantilla de Leaf, que luego se pueden usar dentro de las etiquetas. Por ejemplo:

<h1>#(title)</h1>
#for(number in numbers):
    <p>#(number)</p>
#endfor

Uso

Aquí hay algunos ejemplos comunes del uso de Leaf.

Condiciones

Leaf puede evaluar una serie de condiciones usando su etiqueta #if. Por ejemplo, si proporcionas una variable, comprobará si esa variable existe en su contexto:

#if(title):
    The title is #(title)
#else:
    No title was provided.
#endif

También puedes escribir comparaciones, por ejemplo:

#if(title == "Welcome"):
    This is a friendly web page.
#else:
    No strangers allowed!
#endif

Si deseas usar otra etiqueta como parte de tu condición, debes omitir el # para la etiqueta interna. Por ejemplo:

#if(count(users) > 0):
    You have users!
#else:
    There are no users yet :(
#endif

También puedes usar declaraciones #elseif:

#if(title == "Welcome"):
    Hello new user!
#elseif(title == "Welcome back!"):
    Hello old user
#else:
    Unexpected page!
#endif

Bucles

Si proporcionas un array de elementos, Leaf puede recorrerlos y te permite manipular cada elemento individualmente usando su etiqueta #for.

Por ejemplo, podríamos actualizar nuestro código Swift para proporcionar una lista de planetas:

struct SolarSystem: Codable {
    let planets = ["Venus", "Earth", "Mars"]
}

return req.view.render("solarSystem", SolarSystem())

Luego podríamos recorrerlos en Leaf de la siguiente manera:

Planets:
<ul>
#for(planet in planets):
    <li>#(planet)</li>
#endfor
</ul>

Esto renderizaría una vista que se vería así:

Planets:
- Venus
- Earth
- Mars

Extendiendo plantillas

La etiqueta #extend de Leaf te permite copiar el contenido de una plantilla en otra. Al usar esto, siempre debes omitir la extensión .leaf del archivo de la plantilla.

Extender es útil para copiar un fragmento estándar de contenido, por ejemplo, un pie de página, un código publicitario o una tabla que se comparte en varias páginas:

#extend("footer")

Esta etiqueta también es útil para construir una plantilla sobre otra. Por ejemplo, podrías tener un archivo layout.leaf que incluya todo el código necesario para estructurar tu sitio web - estructura HTML, CSS y JavaScript - con algunos espacios en su lugar que representan dónde varía el contenido de la página.

Usando este enfoque, construirías una plantilla hija que completa con su contenido único, y luego extiende la plantilla padre que coloca el contenido de manera adecuada. Para hacer esto, puedes usar las etiquetas #export e #import para almacenar y luego recuperar contenido del contexto.

Por ejemplo, podrías crear una plantilla child.leaf de la siguiente manera:

#extend("master"):
    #export("body"):
        <p>Welcome to Vapor!</p>
    #endexport
#endextend

Llamamos #export para almacenar algo de HTML y hacerlo disponible para la plantilla que estamos extendiendo actualmente. Luego renderizamos master.leaf y usamos los datos exportados cuando sea necesario, junto con cualquier otra variable de contexto pasada desde Swift. Por ejemplo, master.leaf podría verse así:

<html>
    <head>
        <title>#(title)</title>
    </head>
    <body>#import("body")</body>
</html>

Aquí estamos usando #import para obtener el contenido pasado a la etiqueta #extend. Cuando se pasa ["title": "Hi there!"] desde Swift, child.leaf se renderizará de la siguiente manera:

<html>
    <head>
        <title>Hi there!</title>
    </head>
    <body><p>Welcome to Vapor!</p></body>
</html>

Otras etiquetas

#count

La etiqueta #count devuelve el número de elementos en un array. Por ejemplo:

Your search matched #count(matches) pages.

#lowercased

La etiqueta #lowercased convierte todas las letras de una cadena a minúsculas.

#lowercased(name)

#uppercased

La etiqueta #uppercased convierte todas las letras de una cadena a mayúsculas.

#uppercased(name)

#capitalized

La etiqueta #capitalized convierte a mayúsculas la primera letra de cada palabra de una cadena y el resto a minúsculas. Puedes ver String.capitalized para más información.

#capitalized(name)

#contains

La etiqueta #contains acepta un array y un valor como sus dos parámetros y devuelve verdadero si el array en el primer parámetro contiene el valor en el segundo parámetro.

#if(contains(planets, "Earth")):
    Earth is here!
#else:
    Earth is not in this array.
#endif

#date

La etiqueta #date formatea las fechas a una cadena legible. Por defecto utiliza el formato ISO8601.

render(..., ["now": Date()])
The time is #date(now)

Puede pasar una cadena de formateado de fecha personalizada como segundo argumento. Ve a DateFormatter de Swift para más información.

The date is #date(now, "yyyy-MM-dd")

#unsafeHTML

La etiqueta #unsafeHTML actúa como una etiqueta variable - p. ej. #(variable). Sin embargo, no escapa ningún HTML que variable pueda contener:

The time is #unsafeHTML(styledTitle)

Nota

Debes tener cuidado al usar esta etiqueta para asegurarte de que la variable proporcionada no exponga a sus usuarios a un ataque XSS.

#dumpContext

La etiqueta #dumpContext renderiza todo el contexto a una cadena legible por humanos. Usa esta etiqueta para depurar lo que se está proporcionando como contexto para el renderizado actual.

Hello, world!
#dumpContext