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

Documentación · Referencia · El formato de un proyecto

5. URL

Cómo se decide la dirección de cada página, y los patrones.

Versión 0.16

Por defecto, la URL sale de la ruta dentro de contenido/, quitando la extensión (y el código de idioma, si lo hay: §15.2) y añadiendo barra final. Un index da la URL de su carpeta, en cualquier nivel:

contenido/servicios/encuadernacion.md  →  /servicios/encuadernacion/
contenido/blog/index.md                 →  /blog/
contenido/index.md                      →  /

La ruta se usa tal cual. Si da una mala URL (espacios, mayúsculas, tildes o ñ), el motor avisa: conviene renombrar el fichero o darle un url.

El campo url la sustituye. Tiene que empezar por /; si no, se avisa y se le añade. Lo que se escribe en salida/ depende de cómo acaba:

  • en /: un index.html dentro de esa carpeta (/contacto/ → contacto/index.html);
  • en un nombre con extensión, es decir, cuyo último tramo acaba en un punto seguido de letras o números: ese fichero tal cual (/404.html, /robots.txt, /v1.2; /foo.bar-baz no la tiene);
  • en otra cosa (/contacto): se avisa y se toma como /contacto/.

Una URL nunca escribe fuera de salida/. Si lleva tramos . o .., o caracteres que no caben en un nombre de fichero (\ ? # : * " < > |), se avisa y se usa la URL que sale de la ruta. Un url en blanco, o de solo espacios, también deja la de la ruta, y las barras repetidas se juntan en una (/x//y/ da /x/y/).

En un sitio en varios idiomas, las páginas que no son del predeterminado llevan delante el prefijo de su idioma, también cuando su URL se escribe en url (§15.3).

5.1 Patrones

url admite un patrón con valores del propio front matter:

url: "/blog/{{ titulo|slug }}/"

El vocabulario es cerrado: {{ campo }} pone el valor de un campo y {{ campo|slug }} lo pasa antes por el filtro slug. No hay más filtros, ni expresiones, ni condiciones. Dentro del patrón se aceptan también los alias ingleses (title, slugify).

Además de los campos, el patrón tiene {{ nombreDeFichero }}: el nombre del fichero de la página, sin carpeta, sin extensión y sin el código de idioma (contenido/blog/un-articulo.eu.md da un-articulo). Sirve para publicar las páginas de una carpeta sin la carpeta en la URL: con esto en el _datos.yml de contenido/posts/,

url: "/{{ nombreDeFichero }}/"

contenido/posts/mi-entrada.md sale como /mi-entrada/ y no como /posts/mi-entrada/, y una entrada nueva no tiene que escribir nada. No es un campo: el front matter y la cascada no lo cambian, y si una página tiene un campo con ese nombre, en el patrón manda el del fichero. Admite |slug, que conviene si los nombres de fichero pueden llevar mayúsculas o espacios, porque sin él se usan tal cual. Un index tiene index por nombre: quien quiera la URL de su carpeta, en una carpeta con este patrón, escribe su propio url.

Si el patrón usa un campo que la página no tiene, o que no es un texto o un número, si un slug sale vacío, o si entre las llaves hay otra cosa, se avisa y se usa la URL que sale de la ruta.

En una página con agrupar (§6.3) vale además {{ grupo }}, el valor del grupo de cada página que genera, y el patrón tiene que usarlo. En ella, {{ nombreDeFichero }} es el del fichero que genera las páginas.

En el url de paginar (§6.4) vale {{ numero }}, el número de cada página que genera, a partir del 2, y el patrón tiene que usarlo. Es el único patrón donde existe: el url de la propia página no lo tiene.

5.2 El filtro slug

Convierte un texto en un tramo de URL:

  • pasa a minúsculas y convierte las letras de la tabla de abajo, que quita tildes y diéresis (ü → u, ñ → n, ç → c, ș → s) y descompone algunas ligaduras (ß → ss, æ → ae, œ → oe);
  • & se convierte en la palabra y, con guiones alrededor (Tom&Jerry → tom-y-jerry), y el punto volado del catalán desaparece (col·legi → collegi); las marcas combinantes sueltas de un texto descompuesto (una n y una tilde aparte) se quitan antes de aplicar la tabla;
  • cualquier otro carácter que no sea una letra a a z o un número se convierte en guion, sin guiones repetidos ni en los extremos. Eso incluye las letras de otros alfabetos (griego, cirílico…), las del latino que la tabla no recoge (las del vietnamita, por ejemplo), los símbolos como € y el apóstrofo: abcβdef da abc-def y Don't da don-t.

Cómo elegir un buen libro: guía da como-elegir-un-buen-libro-guia.

La tabla de letras es esta, con lo que sale a la izquierda y las letras que lo dan a la derecha (cada una, también en mayúscula):

a   àáâãäåāăą
c   çćĉċč
d   ďđð
e   èéêëēĕėęě
g   ĝğġģ
h   ĥħ
i   ìíîïĩīĭįı
j   ĵ
k   ķ
l   ĺļľŀł
n   ñńņňʼn
o   òóôõöøōŏő
r   ŕŗř
s   śŝşšſș
t   ţťŧț
u   ùúûüũūŭůűų
w   ŵ
y   ýÿŷ
z   źżž
ss  ß
ae  æ
oe  œ
th  þ
ij  ij

La tabla y la conversión de & en y son parte del contrato y no cambian dentro de una versión mayor (decisión 134). Añadir una letra cambiaría la dirección de toda página cuyo título la lleve, que hoy sale con un guion. El mismo filtro fija el orden alfabético de los textos (§6.2), los grupos de agrupar (§6.3) y los id de los encabezados (§8): lo que se decide aquí vale también para ellos.

Para los títulos habituales en español da lo mismo que el filtro slugify de Eleventy. Difiere en la diéresis (Eleventy da ue: bilingüe → bilinguee), en & (Eleventy da and), en símbolos como € (Eleventy da e; aquí, un guion) y en el apóstrofo (Eleventy lo quita: Don't → dont; aquí, don-t). Al migrar, las páginas afectadas conservan su dirección con un url explícito.

5.3 Fragmentos y colisiones

url: false produce un fragmento: se lee, se puede consultar desde otras páginas y se puede editar desde un editor, pero no genera fichero.

Si dos páginas que se publican van al mismo fichero de salida, el build se detiene con un error que nombra las dos. Las mayúsculas no cuentan, porque en Windows y en macOS /Blog/ y /blog/ son la misma carpeta. Los fragmentos, los borradores y las páginas con publicar en el futuro no generan fichero, así que no chocan con nada.

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