All checks were successful
Zola / build-and-deploy (push) Successful in 17s
- <html lang="es"> en lugar de "en" - <title> con sufijo del sitio, canonical, meta robots y author - Open Graph completo (url, type, locale, image, article:*) y Twitter Card - JSON-LD: WebSite + Person en portada, BlogPosting en cada post - rel="me" hacia Mastodon/GitHub/X - Imagen para redes (og-image.png) y favicon - Títulos de página como <h1> (antes <div>); listados y modal de búsqueda en <h2> - Notas sueltas con noindex y fuera del sitemap; sin paginación duplicada - Páginas de etiquetas y 404 en español, con títulos propios - alt/width/height/lazy en los badges de la portada - MathJax solo cuando un post lo pida ([extra] mathjax = true) - Descripción en /posts y etiquetas en "Hola Mundo" - Limpieza de ficheros de respaldo del editor + .gitignore Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
396 lines
16 KiB
HTML
396 lines
16 KiB
HTML
{% import "macros/macros.html" as post_macros %}
|
|
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<meta name="base" content="{{ config.base_url }}" />
|
|
|
|
{% if config.extra.fediverse %}
|
|
<meta name="fediverse:creator"
|
|
content="{{ config.extra.fediverse_creator }}" />
|
|
{% endif %}
|
|
|
|
{% if page.extra.meta %}
|
|
<!-- the meta data config goes here -->
|
|
{% for data in page.extra.meta %}
|
|
<meta {% for key, value in data %} {% if key == "property" and value == "og:title" %} {% set_global page_has_og_title = true -%} {% endif %}
|
|
{% if key == "property" and value == "og:description" %} {% set_global page_has_og_description = true -%} {% endif %}
|
|
{% if key == "name" and value == "description" %} {% set_global page_has_description = true -%} {% endif %}
|
|
{{ key }}
|
|
None="{{ value }}"
|
|
{% endfor %} />
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
{# ===== SEO ===== #}
|
|
{% set is_404 = current_path is not defined %}
|
|
{% set current_path = current_path | default(value="/") %}
|
|
{% set site_name = config.extra.site_name | default(value=config.title) %}
|
|
{% set author = config.extra.author | default(value=site_name) %}
|
|
|
|
{# Título #}
|
|
{% if is_404 %}
|
|
{% set_global seo_title = "Página no encontrada | " ~ site_name %}
|
|
{% elif current_path == "/" %}
|
|
{% set_global seo_title = site_name ~ " — " ~ config.description | trim_end_matches(pat=".") %}
|
|
{% elif term %}
|
|
{% set_global seo_title = "Entradas sobre «" ~ term.name ~ "» | " ~ site_name %}
|
|
{% elif taxonomy %}
|
|
{% set_global seo_title = "Etiquetas | " ~ site_name %}
|
|
{% elif page.title %}
|
|
{% set_global seo_title = page.title ~ " | " ~ site_name %}
|
|
{% elif section.title %}
|
|
{% set_global seo_title = section.title ~ " | " ~ site_name %}
|
|
{% else %}
|
|
{% set_global seo_title = site_name %}
|
|
{% endif %}
|
|
|
|
{# Descripción #}
|
|
{% if page.description %}
|
|
{% set_global seo_description = page.description %}
|
|
{% elif section.description %}
|
|
{% set_global seo_description = section.description %}
|
|
{% elif term %}
|
|
{% set_global seo_description = "Artículos de " ~ site_name ~ " sobre " ~ term.name ~ "." %}
|
|
{% elif taxonomy %}
|
|
{% set_global seo_description = "Todas las etiquetas del blog de " ~ site_name ~ "." %}
|
|
{% else %}
|
|
{% set_global seo_description = config.description %}
|
|
{% endif %}
|
|
|
|
{# URL canónica #}
|
|
{% if page.permalink %}
|
|
{% set_global seo_url = page.permalink %}
|
|
{% elif section.permalink %}
|
|
{% set_global seo_url = section.permalink %}
|
|
{% elif term %}
|
|
{% set_global seo_url = term.permalink %}
|
|
{% else %}
|
|
{% set_global seo_url = current_url | default(value=config.base_url) %}
|
|
{% endif %}
|
|
|
|
{# Imagen para redes sociales #}
|
|
{% if page.extra.image %}
|
|
{% set_global seo_image = get_url(path=page.extra.image) %}
|
|
{% elif section.extra.image %}
|
|
{% set_global seo_image = get_url(path=section.extra.image) %}
|
|
{% elif config.extra.og_image %}
|
|
{% set_global seo_image = get_url(path=config.extra.og_image) %}
|
|
{% else %}
|
|
{% set_global seo_image = "" %}
|
|
{% endif %}
|
|
|
|
{% set is_article = page.date and page.components and page.components | first == "posts" %}
|
|
|
|
<title>{{ seo_title }}</title>
|
|
{% if not is_404 %}<link rel="canonical" href="{{ seo_url | safe }}" />{% endif %}
|
|
<meta name="author" content="{{ author }}" />
|
|
{% set is_nota = page.components and page.components | first == "notas" %}
|
|
{% if page.extra.noindex or section.extra.noindex or is_404 or is_nota %}
|
|
<meta name="robots" content="noindex, follow" />
|
|
{% else %}
|
|
<meta name="robots" content="index, follow, max-image-preview:large" />
|
|
{% endif %}
|
|
|
|
{% if not page_has_description %}
|
|
<meta name="description" content="{{ seo_description }}" />
|
|
{% endif %}
|
|
|
|
{# Open Graph #}
|
|
<meta property="og:site_name" content="{{ site_name }}" />
|
|
<meta property="og:locale" content="{{ config.extra.locale | default(value='es_ES') }}" />
|
|
<meta property="og:url" content="{{ seo_url | safe }}" />
|
|
{% if not page_has_og_title %}
|
|
<meta property="og:title" content="{% if page.title %}{{ page.title }}{% else %}{{ seo_title }}{% endif %}" />
|
|
{% endif %}
|
|
{% if not page_has_og_description %}
|
|
<meta property="og:description" content="{{ seo_description }}" />
|
|
{% endif %}
|
|
{% if seo_image %}
|
|
<meta property="og:image" content="{{ seo_image | safe }}" />
|
|
<meta property="og:image:alt" content="{{ seo_title }}" />
|
|
{% endif %}
|
|
{% if is_article %}
|
|
<meta property="og:type" content="article" />
|
|
<meta property="article:published_time" content="{{ page.date | date(format='%Y-%m-%d') }}" />
|
|
{% if page.updated %}
|
|
<meta property="article:modified_time" content="{{ page.updated | date(format='%Y-%m-%d') }}" />
|
|
{% endif %}
|
|
<meta property="article:author" content="{{ author }}" />
|
|
{% if page.taxonomies.tags %}
|
|
{% for tag in page.taxonomies.tags %}
|
|
<meta property="article:tag" content="{{ tag }}" />
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% else %}
|
|
<meta property="og:type" content="website" />
|
|
{% endif %}
|
|
|
|
{# Twitter / X #}
|
|
<meta name="twitter:card" content="{% if seo_image %}summary_large_image{% else %}summary{% endif %}" />
|
|
{% if config.extra.twitter_handle %}
|
|
<meta name="twitter:site" content="{{ config.extra.twitter_handle }}" />
|
|
<meta name="twitter:creator" content="{{ config.extra.twitter_handle }}" />
|
|
{% endif %}
|
|
|
|
{# Verificación de identidad (Mastodon, IndieWeb) #}
|
|
{% set_global same_as = [] %}
|
|
{% for social in config.extra.socials | default(value=[]) %}
|
|
{% if social.url is not starting_with("mailto:") %}
|
|
{% set_global same_as = same_as | concat(with=social.url) %}
|
|
<link rel="me" href="{{ social.url }}" />
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
{# Datos estructurados (schema.org) #}
|
|
{% if current_path == "/" and not is_404 %}
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "WebSite",
|
|
"name": {{ site_name | json_encode | safe }},
|
|
"url": {{ config.base_url | json_encode | safe }},
|
|
"description": {{ config.description | json_encode | safe }},
|
|
"inLanguage": {{ config.default_language | json_encode | safe }},
|
|
"author": {
|
|
"@type": "Person",
|
|
"name": {{ author | json_encode | safe }},
|
|
"url": {{ config.base_url | json_encode | safe }},
|
|
"sameAs": {{ same_as | json_encode | safe }}
|
|
}
|
|
}
|
|
</script>
|
|
{% elif is_article %}
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "BlogPosting",
|
|
"headline": {{ page.title | json_encode | safe }},
|
|
"description": {{ seo_description | json_encode | safe }},
|
|
"url": {{ page.permalink | json_encode | safe }},
|
|
"mainEntityOfPage": {{ page.permalink | json_encode | safe }},
|
|
"datePublished": {{ page.date | date(format="%Y-%m-%d") | json_encode | safe }},
|
|
"dateModified": {{ page.updated | default(value=page.date) | date(format="%Y-%m-%d") | json_encode | safe }},
|
|
"inLanguage": {{ page.lang | json_encode | safe }},
|
|
"wordCount": {{ page.word_count }},
|
|
{% if page.taxonomies.tags %}"keywords": {{ page.taxonomies.tags | join(sep=", ") | json_encode | safe }},{% endif %}
|
|
{% if seo_image %}"image": {{ seo_image | json_encode | safe }},{% endif %}
|
|
"author": {
|
|
"@type": "Person",
|
|
"name": {{ author | json_encode | safe }},
|
|
"url": {{ config.base_url | json_encode | safe }}
|
|
},
|
|
"publisher": {
|
|
"@type": "Person",
|
|
"name": {{ author | json_encode | safe }}
|
|
}
|
|
}
|
|
</script>
|
|
{% endif %}
|
|
{# ===== /SEO ===== #}
|
|
|
|
{# Favicon #}
|
|
{% if config.extra.favicon %}
|
|
<link rel="icon"
|
|
type="image/png"
|
|
href="{{ get_url(path=config.extra.favicon) }}" />
|
|
{% endif %}
|
|
|
|
{# Font from cdn or disk #}
|
|
{% if config.extra.use_cdn | default(value=false) %}
|
|
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
|
|
<link rel="stylesheet"
|
|
href="https://cdn.jsdelivr.net/npm/jetbrains-mono@1.0.6/css/jetbrains-mono.min.css" />
|
|
<link rel="stylesheet"
|
|
href="https://cdn.jsdelivr.net/npm/@fontsource/space-grotesk@4.5.8/index.min.css" />
|
|
{% else %}
|
|
<link href={{ get_url(path="fonts.css") }} rel="stylesheet" />
|
|
{% endif %}
|
|
|
|
{# Syntax theme #}
|
|
{% if config.markdown.highlight_code and config.markdown.highlight_theme == "css" %}
|
|
<link rel="stylesheet"
|
|
type="text/css"
|
|
href="/syntax-theme-dark.css"
|
|
media="(prefers-color-scheme: dark)" />
|
|
<link rel="stylesheet"
|
|
type="text/css"
|
|
href="/syntax-theme-light.css"
|
|
media="(prefers-color-scheme: light)" />
|
|
{% endif %}
|
|
|
|
{# Analytics #}
|
|
{% if config.extra.analytics.enabled %}
|
|
{% if config.extra.analytics.umami.website_id %}
|
|
{% set website_id = config.extra.analytics.umami.website_id %}
|
|
{% set host_url = config.extra.analytics.umami.host_url | default(value="https://api-gateway.umami.dev/") %}
|
|
|
|
<script defer
|
|
src="/js/imamu.js"
|
|
data-website-id="{{ website_id }}"
|
|
data-host-url="{{ host_url }}"></script>
|
|
{% endif %}
|
|
|
|
{% if config.extra.analytics.goatcounter.user %}
|
|
{% set user = config.extra.analytics.goatcounter.user %}
|
|
{% set host = config.extra.analytics.goatcounter.host | default(value="goatcounter.com") %}
|
|
|
|
<script data-goatcounter="https://{{ user }}.{{ host }}/count"
|
|
async
|
|
src="{{ get_url(path="js/count.js") }}"></script>
|
|
<noscript>
|
|
{# EasyList blocks '.com/count?', so we have to use '.com//count' #}
|
|
<img src="https://{{ user }}.{{ host }}//count?p={{ current_path }}&t={{ page.title | default(value=config.title) }}" />
|
|
</noscript>
|
|
{% endif %}
|
|
|
|
{% if config.extra.analytics.google.tracking_id %}
|
|
{% set tracking_id = config.extra.analytics.google.tracking_id %}
|
|
|
|
<!-- Google tag (gtag.js) -->
|
|
<script async
|
|
src="https://www.googletagmanager.com/gtag/js?id={{ tracking_id }}"></script>
|
|
<script>
|
|
window.dataLayer = window.dataLayer || [];
|
|
|
|
function gtag() {
|
|
dataLayer.push(arguments);
|
|
}
|
|
gtag('js', new Date());
|
|
gtag('config', '{{ tracking_id }}');
|
|
</script>
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
{# Fancy Codeblock #}
|
|
{% if config.extra.fancy_code %}
|
|
<script defer src={{ get_url(path="js/codeblock.js") }}></script>
|
|
{% endif %}
|
|
|
|
{# Table of contents #}
|
|
{% if config.extra.toc | default(value=false) %}
|
|
<script defer src={{ get_url(path="js/toc.js") }}></script>
|
|
{% endif %}
|
|
|
|
{# Dynamic Note #}
|
|
{% if config.extra.dynamic_note | default(value=false) %}
|
|
<script defer src={{ get_url(path="js/note.js") }}></script>
|
|
{% endif %}
|
|
|
|
{% if page.extra.mathjax | default(value=config.extra.mathjax | default(value=false)) %}
|
|
{% if config.extra.mathjax_dollar_inline_enable | default(value=false) %}
|
|
<script>
|
|
MathJax = {
|
|
tex: {
|
|
inlineMath: [
|
|
['$', '$'],
|
|
['\\(', '\\)']
|
|
]
|
|
}
|
|
};
|
|
</script>
|
|
{% endif %}
|
|
<script type="text/javascript" id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">
|
|
</script>
|
|
{% endif %}
|
|
|
|
{# RSS #}
|
|
{% if config.generate_feeds %}
|
|
{% for feed_filenames in config.feed_filenames %}
|
|
{% if feed_filenames == "atom.xml" %}
|
|
<link rel="alternate"
|
|
type="application/atom+xml"
|
|
title="{{ config.title }}"
|
|
href="{{ get_url(path='atom.xml', trailing_slash=false) }}" />
|
|
{% elif feed_filenames == "rss.xml" %}
|
|
<link rel="alternate"
|
|
type="application/rss+xml"
|
|
title="{{ config.title }}"
|
|
href="{{ get_url(path='rss.xml', trailing_slash=false) }}" />
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
|
|
{% set theme = config.extra.theme | default(value="toggle") %}
|
|
{% if theme == "dark" %}
|
|
<link rel="stylesheet"
|
|
type="text/css"
|
|
href="{{ get_url(path='theme/dark.css') }}" />
|
|
{% elif theme == "light" %}
|
|
<link rel="stylesheet"
|
|
type="text/css"
|
|
href="{{ get_url(path='theme/light.css') }}" />
|
|
{% elif theme == "auto" %}
|
|
<link rel="stylesheet"
|
|
type="text/css"
|
|
href="{{ get_url(path='theme/light.css') }}" />
|
|
<link rel="stylesheet"
|
|
type="text/css"
|
|
href="{{ get_url(path='theme/dark.css') }}"
|
|
media="(prefers-color-scheme: dark)" />
|
|
{% elif theme == "toggle" %}
|
|
<link rel="stylesheet"
|
|
type="text/css"
|
|
href="{{ get_url(path='theme/light.css') }}" />
|
|
<link id="darkModeStyle"
|
|
rel="stylesheet"
|
|
type="text/css"
|
|
href="{{ get_url(path='theme/dark.css') }}" />
|
|
{% endif %}
|
|
|
|
<!-- Set the correct theme in the script -->
|
|
|
|
{% if theme == "auto" or theme == "toggle" %}
|
|
<script src={{ get_url(path="js/themetoggle.js") }}></script>
|
|
|
|
{% if theme == "auto" %}
|
|
<script>
|
|
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
setTheme("dark");
|
|
} else {
|
|
setTheme("light");
|
|
}
|
|
</script>
|
|
{% else %}
|
|
<script>
|
|
setTheme(getSavedTheme());
|
|
</script>
|
|
{% endif %}
|
|
{% endif %}
|
|
|
|
|
|
<link rel="stylesheet"
|
|
type="text/css"
|
|
media="screen"
|
|
href="{{ get_url(path='main.css') }}" />
|
|
|
|
{% if config.extra.stylesheets %}
|
|
{% for stylesheet in config.extra.stylesheets %}
|
|
<link rel="stylesheet" href="{{ get_url(path=stylesheet) }}" />
|
|
{% endfor %}
|
|
{% endif %}
|
|
|
|
{# Search #}
|
|
{%- if config.build_search_index -%}
|
|
{%- if config.search.index_format -%}
|
|
{%- set search_index_format = config.search.index_format -%}
|
|
{%- elif config.extra.index_format -%}
|
|
{# Necessary to support Zola 0.17.X, as it doesn't have access to config.search.index_format #}
|
|
{# See: https://github.com/getzola/zola/issues/2165 #}
|
|
{%- set search_index_format = config.extra.index_format -%}
|
|
{%- else -%}
|
|
{%- set search_index_format = "elasticlunr_json" -%}
|
|
{%- endif -%}
|
|
|
|
{%- if search_index_format == "elasticlunr_javascript" -%}
|
|
<script defer
|
|
src="{{ get_url(path='search_index.' ~ lang ~ '.js', cachebust=true) | safe }}"></script>
|
|
{%- endif -%}
|
|
|
|
{# Main search script #}
|
|
<script defer
|
|
src="{{ get_url(path='js/searchElasticlunr.min.js', cachebust=true) | safe }}"></script>
|
|
{%- endif -%}
|
|
</head>
|