Documentación · Referencia · El formato de un proyecto
8. Markdown
El Markdown, las figuras, los enlaces externos, los encabezados y los atajos.
Versión 0.16
CommonMark, más tablas, notas al pie, tachado (~~texto~~) y enlaces
automáticos: una dirección escrita tal cual (https://ejemplo.com,
www.ejemplo.com) se convierte en enlace, y también una de correo
(info@ejemplo.com pasa a mailto:) o una ftp://, que es un enlace externo.
Se admite HTML escrito a mano.
Las etiquetas vacías salen como en HTML5, sin barra final: <img …>, <br>.
También los bloques de código sangrados de CommonMark: un párrafo que empieza con cuatro espacios, o un tabulador, tras una línea en blanco, es código. Eleventy los desactiva, así que al migrar desde él se quita la sangría que no quería decir código.
Cerrado: el Markdown NO pasa por Twig. En su lugar hay atajos, con un vocabulario cerrado (§8.1).
Dos añadidos forman parte del contrato:
- Figuras. Una imagen sola en su párrafo, enlazada o no, es una figura, y
se construye igual que el atajo
imagen(§8.2). Su texto alternativo da a la vez elaltde la imagen, en texto plano, y el pie, con su Markdown convertido:llevaalt="El escaparate en otoño"y el pieEl <strong>escaparate</strong> en otoño. Los enlaces dentro del texto alternativo no llegan al pie (sale su texto), y el título entre comillas de la imagen en Markdown no se usa. Si la dirección empieza por/y es una imagen depublico/, lleva también su ancho y su alto, como el atajo, y, si el sitio declaraimagenes(§2) y la imagen tiene variantes, susrcset(§8.2). Un sitio que quiera otro marcado para sus figuras (una clase, unloading="lazy") lo da con su propia plantillaimagen. - Enlaces externos. Un enlace escrito en Markdown a otro dominio recibe
target="_blank"yrel="noopener". El dominio del sitio es el deurlensitio.yml, con y sinwww.: un enlace es a otro dominio si su dirección empieza porhttp://,https://u otro esquema con dominio, o por//, y ese dominio no es el del sitio, sin distinguir mayúsculas (un subdominio comoblog.ejemplo.comsí es otro). Una ruta, un ancla, unmailto:o untel:no lo son, y un enlace con un esquema inseguro (javascript:,vbscript:,file:, ydata:salvo en las imágenes) sale sin dirección. El HTML escrito a mano y los enlaces de las plantillas no se tocan. La secciónenlacesExternosdesitio.yml(§2) añadenoreferrery un aviso para los lectores de pantalla. Una imagen enlazada a otro dominio, sea una figura o el atajoimagenconenlace(§8.2), lleva tambiéntargetyrel, aunque no el aviso, que un enlace que solo envuelve una imagen no tiene (decisión 131).
Y un añadido opcional, que solo existe si el sitio lo pide con la sección
encabezados de sitio.yml (§2):
- Encabezados con
id. Los encabezados del Markdown de los niveles que se indiquen reciben unid: elslug(§5.2) de su texto plano, sin enlaces ni énfasis, y sin el texto alternativo de las imágenes ni los atajos en línea (## Con  imagendacon-imagen); el código en línea sí cuenta. Si ya hay otro igual en la página, se le añade-2,-3… hasta el primer número libre; y si elslugsale vacío, elidesseccion. Conenlace, el encabezado termina en un enlace permanente, pegado a su texto:<h2 id="un-apartado">Un apartado<a class="ancla" href="#un-apartado" aria-label="Enlace a «Un apartado»">¶</a></h2>. Solo cuentan los encabezados que escribe el Markdown del cuerpo: no los del HTML escrito a mano, ni los de dentro de un atajo que envuelve contenido (§8.1), ni los que pone una plantilla, que decide los suyos. Las plantillas leen la lista enpagina.encabezados(§7.2).
8.1 Atajos¶
Un atajo es una llamada con nombre y atributos con nombre dentro del Markdown:
[imagen fichero="img/escaparate.jpg" alt="Escaparate de la librería" pie="La tienda en otoño"]
Y con contenido, cuando lo envuelve:
[aviso tipo="importante"]
Las plazas son limitadas.
[/aviso]
Reglas:
- Solo se reconocen los nombres registrados: los que trae el motor y los que
define el sitio. Un nombre que no está registrado se deja como texto; si
lleva atributos, o es un cierre sin su apertura, además se avisa. Nunca se
rompe el build. Un
[algo]sin atributos que no está registrado es texto normal; uno registrado es siempre una llamada, lleve atributos o no (en «Adjunta el[archivo]firmado»,[archivo]es el atajo y avisa de que faltafichero; para escribirlo como texto,\[archivo]). Un atajo registrado cuyos atributos no se pueden leer (sin comillas, por ejemplo) se deja como texto y se avisa (decisión 147).[imagen](…),[imagen][ref]y[imagen]: …siguen siendo enlaces de Markdown. - Los atributos son siempre cadenas con nombre, entre comillas dobles o
simples:
nombre="valor"onombre='valor'. No hay expresiones, ni variables, ni condicionales, ni acceso a colecciones: eso es lógica y la lógica vive en las plantillas. - El nombre de un atajo empieza por una letra minúscula y lleva minúsculas,
números y guiones; el de un atributo empieza por una letra y lleva letras y
números, sin guiones ni guiones bajos (
pie,siFalta). El valor termina en la misma comilla con que empieza y no admite escape: uno que lleve comillas dobles y simples a la vez no se puede escribir. Se admiten espacios alrededor del=; si un atributo se repite, gana el último; y la apertura de un atajo que envuelve puede llevar hasta tres espacios de sangría. - Un atajo simple puede ir en medio del texto. Si va solo en su párrafo y lo
que produce es un bloque (una figura, un
div, un vídeo…), sustituye al párrafo entero, porque un bloque no cabe dentro de un<p>. Si produce texto, comodato, se queda dentro del párrafo. Es un bloque lo que empieza por una de estas etiquetas:address,article,aside,audio,blockquote,details,div,dl,fieldset,figure,footer,form,h1ah6,header,hr,iframe,nav,ol,p,picture,pre,section,table,ulyvideo. Con cualquier otra (main,dialog…) el atajo se queda dentro del<p>. Si el párrafo lleva más texto, o dos atajos en líneas seguidas, el bloque queda dentro del<p>y el HTML no es válido: conviene ponerlo en su propio párrafo. Un atajo que no inserta nada (porque avisa) deja un<p></p>vacío. - Un atajo que envuelve contenido lleva la apertura y el cierre cada uno en
su línea. Lo que hay entre ellos es Markdown y llega convertido a HTML. Un
atajo envuelve si en algún sitio de la página hay una línea
[/nombre]; si no hay ninguna,[nombre]es un atajo simple, sincontenido. Si hay cierres pero a una apertura le falta el suyo, se avisa y el atajo se cierra al final del texto. El primer[/nombre]cierra la apertura más externa: dos atajos del mismo nombre no se anidan (con nombres distintos, sí). - Los atajos se reconocen al convertir el Markdown, así que uno escrito dentro
de código, o empezado con
\[, se queda como texto. Su HTML se inserta después, sin que el convertidor lo toque. - Los atajos son cosa de quien desarrolla el sitio. El esquema (§11) no los declara: un editor no sabe qué atajos hay ni qué atributos llevan.
Cada atajo es una plantilla de Twig. Los del sitio están en
parciales/atajos/, con el nombre del atajo: parciales/atajos/aviso.twig.
El nombre solo lleva minúsculas sin tildes, números y guiones. La plantilla
recibe:
- sus atributos, como variables:
{{ tipo }}; contenido, el HTML de lo que envuelve, si envuelve algo;sitio,datosypagina, igual que cualquier plantilla (§7.2).
Por eso sitio, datos, pagina y contenido no se pueden usar como
nombres de atributo: se avisa y se ignoran. Y un atributo con el nombre de una
variable que el motor calcula para ese atajo (§8.2: src, alt, ancho,
href, peso, valor…) no llega a la plantilla: gana la del motor.
8.2 Atajos incluidos en el motor¶
Un sitio puede sustituir cualquiera de ellos con su propia plantilla del mismo
nombre en parciales/atajos/, que recibe las mismas variables. Un fichero que
sale de publico/ (con .. o barras invertidas) se avisa y no inserta nada.
-
imagen:[imagen fichero="img/escaparate.jpg" alt="…" pie="…"], conficherodentro depublico/. Da<figure>con la imagen y, si hay pie,<figcaption>. Sinpie, el pie es elalt; conpie="", no hay pie. Elpiedel atajo es texto, que se escapa; el de una figura del Markdown (§8) se convierte como Markdown.enlacehace la imagen enlazada. La imagen llevawidthyheightcuando se pueden leer del fichero (§7.3,dimensiones()), para que el navegador le reserve el sitio antes de cargarla. La plantilla recibesrc,alt,pie(ya en HTML),enlace,externo(si elenlacelleva a otro dominio, como los enlaces del Markdown de §8; sinenlace, falso),rel(el de ese enlace,noopenery, si el sitio lo pide,noreferrer; solo siexterno),anchoyalto(nullsi no se pueden leer). La plantilla de Ehundu ponetarget="_blank"yrelen un enlace externo; la del sitio que no useexternonirelqueda como la escribió. Se avisa si faltaalto si el fichero no existe; sinficherono se inserta nada.Si el sitio declara
imagenes(§2), el atajo busca las variantes de la imagen (variantes(), §7.3) y, si las hay, la plantilla recibe ademássrcset,sizesyfuentes, ysrc,anchoyaltoson los de la variante más ancha del último formato; la plantilla del motor escribe<picture>si hayfuentesy un<img srcset>si no.sizeses el del atributosizes="…"del atajo o, si no lo lleva, el de la sección. Una imagen sin ninguna variante sale como sinimagenesy sin aviso: no todas se procesan (un logotipo, una imagen pequeña). Si tiene unas variantes y le faltan otras, se avisa de cada fichero que falta. Una imagen con variantes no necesita el fichero que da nombre a su tronco: puede que enpublico/solo estén ellas, y entonces no se avisa de que no existe. Las imágenes que no son depublico/, o que son SVG, no se tocan. -
video:[video url="https://www.youtube.com/watch?v=…" titulo="…"]admite YouTube, que se inserta desdeyoutube-nocookie.compara no poner cookies hasta que se reproduce, y Vimeo, condnt=1. Confichero="video/visita.mp4"inserta un vídeo depublico/. La proporción es 16:9 salvo que se indique otra conproporcion="4:3", y se aplica conaspect-ratio(a la plantilla llega como16 / 9). Para YouTube valen las formaswatch?v=,embed/,shorts/yyoutu.be/; si hayurlyfichero, ganaurl.tituloes el nombre accesible del vídeo (Vídeosi falta). Con otra dirección, se avisa y no se inserta nada. La plantilla recibeinsercion(la dirección para eliframe) osrc(la del fichero),proporcionytitulo. -
archivo:[archivo fichero="docs/tarifas.pdf" texto="Tarifas 2025"]da<a href="/docs/tarifas.pdf">Tarifas 2025</a> (PDF, 1,2 MB), con el tipo y el peso leídos del fichero depublico/al compilar (en KB por debajo de 1 MB; los múltiplos son de 1024 y se redondea: 1.048.000 bytes salen como «1023 KB»).tipoes la extensión en mayúsculas. Sintexto, el nombre del fichero. Si el fichero no existe, se avisa y el enlace sale sin peso. La plantilla recibehref,texto,tipoypeso. -
dato:[dato clave="cliente.nombre"]escribe un valor dedatos/, escapado. Es lo que necesitan los textos legales, que repiten el nombre, la razón social o la dirección del titular. ConsiFalta="…"se escribe ese texto si el dato no existe o está vacío; sin él, se avisa y no se escribe nada. Una lista, un mapa o una fecha avisan y no se escriben;0yfalseno cuentan como vacío (se escriben0yno). La plantilla recibevalor.
Lo que escriben las plantillas de Ehundu va en castellano: el título Vídeo
de video, el peso de archivo con coma decimal (1,2 MB), y sí o no en
dato si el valor es un booleano. peso llega a la plantilla ya como texto, así
que una plantilla propia no puede darle otro formato; un sitio en otro idioma
sustituye el atajo con la suya (decisión 136).