GuíasSwift

Crea páginas web en Swift con la librería Plot

HTML desde Swift con arquitectura DSL

¿Aún sigues pensando que Swift sólo sirve para desarrollar apps para los sistemas de Apple? Vamos a analizar Plot, una de las 3 herramientas que ha creado el conocido programador, podcaster y blogger John Sundell para construir sitios web utilizando lenguaje Swift.

Generador de web estáticas

A finales del años pasado pasado, Sundell liberó Ink, Plot y Publish tres herramientas que permiten crear sitios web estáticos. Esto quiere decir que permiten generar el código HTML, añadir recursos y hojas de estilo y publicarlo en internet de forma bastante sencilla. Todas las librerías están escritas en Swift y son compatibles con el gestor de dependencias Swift Package Manager.

  • Ink: Parseador de markdown muy útil para webs con textos largos. Puedes redactar en tu editor favorito y generar el HTML con sólo unas líneas de código Swift.
  • Plot: Crea código HTML, XML y RSS con tipado seguro desde Swift. Puedes comprobar que el código es correcto antes de compilar.
  • Publish: Generador de sitios web estáticos. Después de utilizar las librerías anteriores, reúne todo el código, los recursos para test y puesta en producción.

Plot

El primer paso es la instalación. Gracias al soporte de SPM podemos incluir el paquete de con la URL https://github.com/johnsundell/plot.git mediante Xcode:

O como dependencia en el fichero Package.swift:

let package = Package( 
     ... 
     dependencies: [ 
          .package(url: "https://github.com/johnsundell/plot.git", from: "0.1.0") 
     ], 
     ... 
)

Con cualquiera de las dos opciones no hay que olvidarse nunca de añadir la dependencia en cada uno de los ficheros en los que vayamos a usar la librería.

import Plot

Ahora ya podemos utilizar todas las funciones, propiedades y tipos de la librería. Si no estás familiarizado con el desarrollo web, esta es una buena oportunidad para echarle un vistazo ya que necesitas conocer los elementos disponibles en el lenguaje HTML. Pero no te preocupes, si ya has aprendido Swift, esto será coser y cantar.

Primeros pasos

Empecemos con un ejemplo básico de lo que puede hacer la libería.

let html = HTML(
    .head(
        .title("Apple Coding"),
        .stylesheet("styles.css")
    ),
    .body(
        .div(
            .h1("Hola mundo"),
            .p("Descubre una nueva forma de crear páginas web")
        )
    )
)

Como se puede ver, Plot nos facilita una forma de escribir HTML pero sabiendo, desde el propio editor, que nuestra sintaxis es correcta y nos permite validar nuestro código mientras lo estamos escribiendo.

Cada elemento de HTML es un tipo de Swift y está soportado dentro del tipo del que puede depender. Es decir, puedo incluir un h1 o un p dentro de un div. Además, permite añadir dentro de ese div un conjunto de elementos a modo de array para que estén contenidos dentro del mismo a la hora de renderizar el HTML.

Los elementos de HTML también tienen atributos, y esta librería también nos permite añadirlos de una forma súper sencilla.

let html = HTML( 
    .body( 
        .a(
            .class("link"), 
            .href("https://applecoding.com"), 
            "Visítanos"
        ) 
    ) 
)

Ya tendríamos la sintaxis básica de la librería. Además, si no somos muy duchos en HTML o simplemente cometemos algún error, como estamos implementado código en Swift, el propio compilador nos mostrará los errores en su línea correspondiente.

Componentes y control de flujo

Las ventajas de utilizar un lenguaje como Swift a la hora de crear código HTML van más allá de el control de errores, también podemos crear nuestros propios componentes y agrupaciones de elementos para iterar sobre ellos y añadir controles de flujo.

Para crear un elemento debemos añadir un método estático mediante una extensión del tipo Node donde el Context sea HTML.BodyContext. Y que esta devuelva Self indicando que es un Node también.

extension Node where Context: HTML.BodyContext {
    static func nuevoArtículoAC(_ artículo: ArtículoAC) -> Self {
        return .article(
            .class("novedad"),
            .img(.src(artículo.imagen)),
            .h1(.text(artículo.título)),
            .span(
                .class("descripción"),
                .text(artículo.descripción)
            )
        )
    }
}

El tipo Node es el tipo básico de elemento al que le indicamos que nuestro elemento que puede ir dentro del body de HTML. De esta manera, además de definir el propio elemento, el compilador conoce dónde está permitido colocarlo. ArtículoAC es un tipo de Swift que creamos para poder añadir artículos; bien mediante el inicializador por defecto u obtenido los datos desde una fuente externa como un archivo o servicio web como haría cualquier aplicación Swift.

Ahora no tenemos más que añadirlo a nuestra página web, pero como seguramente tengamos más de un artículo, utilizaremos el control de flujo y no tendremos que añadirlos de forma individual.

let html = HTML(
    .body(
        .forEach(artículos) {
            .nuevoArtículoAC($0)
        }
    )
)

Esto nos ahorra un montón de trabajo, sobretodo cuando la lista de artículos sea grande. De manera similar podemos utilizar .if que acepta dos o tres parámetros (condición, ejecución si es true y no si es false) y .unwrap que recibe una variable y un closure a ejecutar donde el tipo ya no es opcional cuando el valor de la variable no es nulo.

Elementos personalizados

Con todo lo mencionado anteriormente es suficiente para la mayoría de los casos, pero es posible que alguna webs u otras aplicaciones que necesitan generar este tipo de plantillas, requieran sus propios elementos y sus correspondiente atributos de forma personalizada.

Plot tiene una solución muy sencilla donde basta con indicar el nombre y el texto o valor del elemento o atributo a implementar.

let html = HTML(
    .body( 
        .element(named: "elemento", text: "Mi elemento"), 
        .p( 
            .attribute(named: "atributo", value: "...es genial")  
        ) 
    )
)

Recogiendo los frutos

Hasta ahora únicamente hemos creado la variable html que debería contener nuestro código pero para comprobar cómo se visualiza nuestra web y para subir la página al servidor necesitamos extraer un String con el contenido.

let html = HTML(...) 

let nonIndentedString = html.render() 
let spacesIndentedString = html.render(indentedBy: .spaces(4)) 
let tabsIndentedString = html.render(indentedBy: .tabs(1))

Como se observa en el código anterior, es muy sencillo extraer el código como cadena de texto. Después guardarla en un fichero, enviarla a un servidor o al mecanismo de despliegue que tengamos implementado. Y lo mejor de todo, lo haremos con nuestro lenguaje de programación favorito.

Puedes encontrar más información en la documentación del proyecto, además puedes entrar directamente en el código y conocer más sobre el uso. Como comentamos al inicio, esta librería se complementa con Ink y Publish para poder hacer el ciclo completo de generación de contenido, renderizado HTML y puesta en producción.

La comunidad Swift

John Sundell ha compartido el proyecto de forma libre, así que puedes utilizar e incluso contribuir mejorando y añadiendo código tú mismo. La comunidad de Swift cada día es más grande y no sólo se reduce, como hemos comentado, al mundo Apple. Hay muchas librerías que permiten desarrollador código para muchos casos de uso y plataformas. Lo único que echamos en falta para cerrar el círculo es un indexador para Swift Package Manager donde puedas buscar el que se ajuste a tus necesidades. Esperamos que no tarde mucho en llegar. Un saludo y Good Apple Coding.

Arturo Rivas

Líder técnico especializado en mobile. Analista y desarrollador software. Apasionado de la tecnología, el deporte y la música.

Artículos relacionados

Botón volver arriba