Ir al contenido
Código en GitHub (se abre en una pestaña nueva)

Documentación · Referencia · El formato de un proyecto

2. sitio.yml

La configuración del sitio: nombre, dirección, idiomas, despliegue y el resto de claves.

Versión 0.16

formato: 1
nombre: Librería La Esquina
url: https://www.ejemplo.com
idioma: es
zonaHoraria: Europe/Madrid

despliegue:
  destino: sftp
  servidor: sftp.ejemplo.com
  usuario: esquina
  ruta: /home/esquina/www
  huella: SHA256:OgR5PWmWkjC9MJd/4ChYsOklVAXnzl8AMwJFqb0rAgY
  # la contraseña va en .secretos.yml, nunca aquí

sitio.yml es obligatorio y tiene que llevar al menos nombre y url. url es la dirección del dominio del sitio, con http:// o https:// y sin ruta: https://www.ejemplo.com, con o sin la barra final. Un sitio dentro de una subcarpeta (https://ejemplo.com/sub/) no está soportado y es un error (decisión 130). Las plantillas ven sitio.url sin la barra final, así que una dirección completa se escribe {{ sitio.url }}{{ pagina.url }}. Si falta el fichero o alguno de esos dos campos, el build se detiene con un error: sin ellos no se pueden generar ni el sitemap ni el feed.

formato es la versión de este formato para la que está escrito el proyecto: un número entero, 1. No hay versión menor, porque dentro de una versión mayor el formato solo crece (§12): un proyecto escrito para el formato 1 sigue significando lo mismo en cualquier Ehundu posterior que entienda el 1 (el HTML puede variar en lo que deciden Twig o CommonMark, §12, regla 3). Uno que use algo añadido en una versión menor necesita un motor que lo tenga: uno anterior ignora los campos que no conoce. Si falta, es 1, y sin avisar, así que los proyectos escritos antes de que existiera la clave no cambian. Un valor que no es un entero mayor que cero ("2" entre comillas, 0) detiene el build con un error: tomarlo por 1 podría hacer pasar por bueno un proyecto de otro formato. Si es mayor que la versión que entiende esta versión de Ehundu, el build se detiene con un error que lo dice (ehundu compilar, servir y desplegar): compilar a ciegas un formato distinto daría un sitio mal hecho sin que nadie lo notara. Es lo primero que se comprueba, antes que nombre y url.

nombre es un texto: nombre: 2024, sin comillas, es un número y detiene el build (en el front matter, en cambio, un número se admite como texto, §4).

zonaHoraria es la zona en la que se leen y se escriben todas las fechas del sitio, con su nombre estándar (Europe/Madrid, America/Mexico_City). Si falta, es UTC. Una zona que no existe detiene el build.

Qué detiene el build en sitio.yml y qué solo se avisa. Detienen el build nombre, url, zonaHoraria, idiomas y formato mal escritos: un valor que se tomara por otro cambiaría, sin que nadie lo note, qué se lee o qué sale en todo el sitio. Con idioma, generador, feed, enlacesExternos, encabezados e imagenes, que solo ajustan un añadido, se avisa y se usa su valor por defecto, o se ignora la sección.

Claves reservadas. Las que el motor lee de sitio.yml son formato, nombre, url, idioma, idiomas, zonaHoraria, despliegue, generador, feed, enlacesExternos, encabezados e imagenes. Cualquier otra clave llega a las plantillas como sitio.<clave> (§7.2), y es del sitio. Una clave nueva que un motor posterior reserve se anuncia en una versión menor, y ese motor avisa a los sitios que ya la usaban como propia (§12, regla 5).

Una sección vacía. Una sección sin valor (encabezados:) es lo mismo que no ponerla. Un mapa vacío (encabezados: {}) la pone con todo por defecto: en encabezados activa los id del nivel 2 al 6, y en enlacesExternos no cambia nada; en imagenes y en feed, que necesitan anchos o coleccion, se avisa y se ignora.

idioma es el código del idioma del sitio: dos o tres letras minúsculas, como es, eu o en. Lo usan fecha() (§7.3) y el feed, y las plantillas lo ven también en pagina.idioma. Si falta, es es (o el primero de idiomas, si el sitio los declara, §15.1); si no es un código así, se avisa y se usa es. Un sitio en varios idiomas los declara en idiomas.

La sección feed pide un feed.xml y dice de qué colección sale (§10.2).

La sección enlacesExternos ajusta cómo salen los enlaces a otros dominios que se escriben en Markdown (§8):

enlacesExternos:
  aviso: (abre en ventana nueva)
  clase: visually-hidden
  noreferrer: sí

Sin ella, esos enlaces llevan target="_blank" y rel="noopener" y nada más. Todos sus campos son opcionales:

  • aviso es un texto que se añade dentro del enlace, detrás del suyo, en un <span>, para que los lectores de pantalla avisen de que se abre otra pestaña. El motor pone un espacio delante; los paréntesis, si se quieren, van en el texto. Un enlace que solo envuelve una imagen (una figura, §8) no lo lleva. Un sitio con varios idiomas (§15.1) da un texto por idioma, con su código como clave:

    aviso:
      es: (abre en ventana nueva)
      eu: (leiho berrian irekitzen da)
    

    Un idioma sin texto no lleva aviso, y se avisa de ello. Un texto suelto en un sitio con varios idiomas se usa en todos y se avisa también, porque casi nunca es lo que se quiere. Un código que el sitio no declara se avisa y se ignora.

  • clase es la clase del <span>, y por defecto visually-hidden. El motor no trae CSS: el sitio tiene que definirla de modo que oculte el texto a la vista y no a los lectores de pantalla (el .visually-hidden o .sr-only de siempre). Si no lo hace, el aviso se ve.

  • noreferrer, con sí, añade noreferrer a rel (rel="noopener noreferrer"): el sitio de destino no sabe de qué página viene la visita. Por defecto, no.

Un valor que no vale en cualquiera de ellos se avisa y se ignora. Cambiar esta sección rehace todas las páginas, como cualquier otro cambio de sitio.yml.

La sección encabezados da un id a los encabezados del Markdown, para enlazar a un apartado de una página y para construir un índice con ellos (§7.2, §8):

encabezados:
  niveles: [2]
  enlace: ¶
  clase: ancla
  etiqueta: Enlace a «{texto}»

Sin ella, los encabezados salen sin id. Todos sus campos son opcionales:

  • niveles es la lista de niveles de encabezado que reciben id, del 1 al 6. Por defecto, del 2 al 6: el 1 suele ser el título de la página, y lo escribe la plantilla.
  • enlace es el texto de un enlace permanente al apartado, que se añade al final del encabezado. Sin él, no hay enlace.
  • clase es la clase de ese enlace, y por defecto ancla. El motor no trae CSS: si el sitio quiere que el enlace solo se vea al pasar el ratón, lo define él.
  • etiqueta es el nombre accesible del enlace (aria-label), y {texto} se sustituye por el texto del encabezado. Un sitio con varios idiomas (§15.1) da un texto por idioma, con las mismas reglas que aviso de enlacesExternos. Sin ella, el enlace no lleva aria-label y un lector de pantalla solo lee su símbolo.

Un valor que no vale en cualquiera de ellos se avisa y se ignora. Una clase o una etiqueta válidas sin enlace no tienen a qué aplicarse, y se ignoran sin aviso; si no valen, se avisa igual. Con niveles: [] ningún encabezado recibe id. Cambiar esta sección rehace todas las páginas.

La sección imagenes dice qué variantes de ancho tienen las imágenes del sitio, para que variantes() (§7.3), el atajo imagen y las figuras del Markdown (§8) escriban el srcset. El motor no las genera (§9): las busca, con el nombre <tronco>-<ancho>.<formato>, en publico/.

imagenes:
  anchos: [480, 960, 1600]
  formatos: [avif, webp]
  sizes: "(min-width: 60rem) 50rem, 100vw"

Sin ella, las imágenes salen sin srcset. Con ella:

  • anchos es la lista de anchos, en píxeles, que tienen las imágenes del sitio. Es obligatoria: la sección sin ella se avisa y se ignora entera. Un valor que no es un entero positivo se avisa y se ignora; los repetidos se juntan, y se usan de menor a mayor.
  • formatos es la lista de formatos, de más a menos preferido, porque el navegador usa el primero que entiende. Valen avif, webp, jpg, jpeg y png, que son también la extensión de los ficheros. Por defecto, [webp]. Un formato que no vale se avisa y se ignora. El de reserva es el último de la lista que tenga alguna variante de la imagen en publico/: el que se usa en el <img>, y el único que verían los PDF (§10.3), que solo leen bien JPEG, PNG y SVG. Un sitio con PDF que muestran el cuerpo de una página con figuras acaba la lista en jpg o png.
  • sizes es el valor de sizes que llevan las imágenes del atajo imagen y las figuras del Markdown cuando no dicen otro. Por defecto, 100vw, que nunca pide menos imagen de la que hace falta.

El tronco de una imagen es su ruta sin la extensión: el de img/foto.jpg es img/foto, y sus variantes son img/foto-480.avif, img/foto-480.webp, img/foto-960.avif… Quien las genera (un editor al subir la imagen, o un programa aparte) deja un fichero por cada ancho y cada formato, y no amplía nunca: si el original es más estrecho que un ancho, el fichero de ese ancho sale con el ancho del original. El número del nombre es el ancho que se pidió; el que cuenta en el srcset es el que tiene el fichero, que el motor lee (dimensiones(), §7.3). Si dos anchos pedidos dan el mismo ancho real, entra solo el menor, para no repetir la imagen.

Cambiar esta sección rehace todas las páginas, y una página depende de cada fichero de variantes que mira, como de cualquier otro de publico/.

generador marca las páginas como hechas con Ehundu. Por defecto, el motor añade <meta name="generator" content="Ehundu"> al <head> de cada página HTML, y esta clave la quita:

generador: no
  • Dónde. En cada página que escribe el motor y que tiene un </head> (sin distinguir mayúsculas), en el primero. La etiqueta va justo antes, en su propia línea y con la sangría de </head> más dos espacios; si </head> no está al principio de su línea, va pegada a él. Lo que no tiene </head> no cambia: un fragmento, un .txt, un XML, una página con plantilla: false que no es un documento. Tampoco cambian el PDF de una página, el sitemap ni el feed.
  • Si la plantilla ya la pone. Una página que ya tiene una etiqueta <meta> con name="generator" no se toca: manda la plantilla.
  • Sin versión. El contenido es siempre Ehundu. Con la versión, cada actualización del motor cambiaría todas las páginas de todos los sitios y obligaría a volver a subirlas (decisión 127).
  • Valores. no o false la quita; sí, true o no poner la clave son lo mismo: la etiqueta sale. Otro valor se avisa y se ignora. Cambiar la clave rehace todas las páginas, como cualquier otro cambio de sitio.yml.

La sección despliegue dice adónde publica ehundu desplegar (ver despliegue.md). Destinos del formato 1: carpeta, ftp, sftp y s3; se podrán añadir otros (§12, regla 5). Sus campos:

Campo Destinos Significado
destino todos carpeta, ftp, sftp o s3
ruta todos la carpeta de destino; en carpeta, una ruta local fuera del proyecto, relativa a él si no es absoluta; en s3, la carpeta dentro del cubo
servidor ftp, sftp, s3 el servidor; en s3, la dirección del servicio (s3.fr-par.scw.cloud)
puerto ftp, sftp si no es el de siempre (21 y 22)
usuario ftp, sftp, s3 el usuario; en s3, el identificador de la clave de acceso
huella sftp la huella de la clave del servidor, como la da ssh-keygen -l
cifrado ftp no para FTP sin cifrar; por defecto, FTPS
region s3 la región del cubo (fr-par)
cubo s3 el nombre del cubo

Los secretos van en .secretos.yml, con la misma forma y solo con ellos:

despliegue:
  clave: 'la-contraseña'                   # en s3, la clave secreta
  clavePrivada: '~/.ssh/id_ed25519'        # sftp, en lugar de clave
  frase: 'la-de-la-clave-privada'          # si la tiene

clavePrivada es la ruta de un fichero con la clave (relativa al proyecto, absoluta o que empieza por ~/), no su contenido. Los secretos van entre comillas simples, y una comilla simple dentro se escribe doble ('l''arte'). Sin comillas, YAML lee algunas contraseñas de otra forma sin avisar: lo que va detrás de # es un comentario y se pierde, 1e3 es el número 1000, y una que empieza por !, *, @ o % ni siquiera se lee. Si .secretos.yml no es YAML válido, el error dice el fichero, la línea y qué pasa, pero nunca enseña la línea.

Un secreto en sitio.yml detiene el despliegue: ese fichero se comparte y se versiona. .secretos.yml no se versiona nunca ni se publica. Un programa que incruste el motor puede darle los secretos directamente, sin fichero; los suyos ganan. Un campo que no corresponde al destino, o que no existe, avisa y se ignora.

Ver este documento en GitHub (se abre en una pestaña nueva)