alejandrogs.es/templates/partials/header.html
alejandrogs73 00dc194e86
All checks were successful
Zola / build-and-deploy (push) Successful in 17s
SEO: metadatos, datos estructurados y encabezados semánticos
- <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>
2026-09-25 12:10:08 +02:00

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>