mirror of
https://github.com/svemagie/blog-eleventy-indiekit.git
synced 2026-04-02 16:44:56 +02:00
fix: use Eleventy transform to resolve OG images from outputPath
The Eleventy 3.x parallel rendering race condition (#3183) makes page.url unreliable in templates — it changes between lines during concurrent processing. All previous approaches (eleventyComputed, capturing page.url early with {% set %}) failed because the page object is shared and mutated by parallel renders. The transform approach works because outputPath is passed as a function parameter (not read from a shared object) and IS correct since files are written to the right location. The transform: - Derives the OG slug from outputPath pattern matching - Replaces __OG_IMAGE_PLACEHOLDER__ with the correct OG image URL - Replaces __TWITTER_CARD_PLACEHOLDER__ with the correct card type - Fixes og:url and canonical URL from outputPath
This commit is contained in:
@@ -1,14 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ site.locale | default('en') }}">
|
||||
<head>
|
||||
{# CRITICAL: Capture page.url IMMEDIATELY — Eleventy 3.x race condition (#3183)
|
||||
causes page.url to change mid-render during parallel processing.
|
||||
Nunjucks {% set %} captures the VALUE (not a reference), making it immune
|
||||
to later mutations of the shared page object. This MUST be the first
|
||||
statement in the template, before any filter calls that could yield. #}
|
||||
{% set _pageUrl = page.url %}
|
||||
{% set _ogSlug = (_pageUrl or "") | ogSlug %}
|
||||
{% set _hasOg = _ogSlug | hasOgImage %}
|
||||
{# OG image resolution handled by og-fix transform in eleventy.config.js
|
||||
to bypass Eleventy 3.x parallel rendering race condition (#3183).
|
||||
Template outputs __OG_IMAGE_PLACEHOLDER__ and __TWITTER_CARD_PLACEHOLDER__
|
||||
which the transform replaces using the correct slug derived from outputPath. #}
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="generator" content="Eleventy">
|
||||
@@ -25,11 +21,10 @@
|
||||
{% set ogPhoto = ogPhoto[0] %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<!-- debug:og _pageUrl={{ _pageUrl }} ogSlug={{ _ogSlug }} hasOg={{ _hasOg }} -->
|
||||
<meta property="og:title" content="{{ ogTitle }}">
|
||||
<meta property="og:site_name" content="{{ site.name }}">
|
||||
<meta property="og:url" content="{{ site.url }}{{ _pageUrl }}">
|
||||
<meta property="og:type" content="{% if _pageUrl == '/' %}website{% else %}article{% endif %}">
|
||||
<meta property="og:url" content="{{ site.url }}{{ page.url }}">
|
||||
<meta property="og:type" content="{% if page.url == '/' %}website{% else %}article{% endif %}">
|
||||
<meta property="og:description" content="{{ ogDesc }}">
|
||||
<meta name="description" content="{{ ogDesc }}">
|
||||
{% if ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10 %}
|
||||
@@ -38,18 +33,16 @@
|
||||
<meta property="og:image" content="{% if 'http' in image %}{{ image }}{% else %}{{ site.url }}{% if image[0] != '/' %}/{% endif %}{{ image }}{% endif %}">
|
||||
{% elif contentImage and contentImage != "" and (contentImage | length) > 10 %}
|
||||
<meta property="og:image" content="{% if 'http' in contentImage %}{{ contentImage }}{% else %}{{ site.url }}{% if contentImage[0] != '/' %}/{% endif %}{{ contentImage }}{% endif %}">
|
||||
{% elif _hasOg %}
|
||||
<meta property="og:image" content="{{ site.url }}/og/{{ _ogSlug }}.png">
|
||||
{% else %}
|
||||
<meta property="og:image" content="{{ site.url }}/images/og-default.png">
|
||||
<meta property="og:image" content="__OG_IMAGE_PLACEHOLDER__">
|
||||
{% endif %}
|
||||
<meta property="og:image:width" content="1200">
|
||||
<meta property="og:image:height" content="630">
|
||||
<meta property="og:locale" content="{{ site.locale | default('en_US') }}">
|
||||
|
||||
{# Twitter Card meta tags #}
|
||||
{% set hasImage = _hasOg or (ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10) or (image and image != "" and (image | length) > 10) or (contentImage and contentImage != "" and (contentImage | length) > 10) %}
|
||||
<meta name="twitter:card" content="{% if hasImage %}summary_large_image{% else %}summary{% endif %}">
|
||||
{% set hasExplicitImage = (ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10) or (image and image != "" and (image | length) > 10) or (contentImage and contentImage != "" and (contentImage | length) > 10) %}
|
||||
<meta name="twitter:card" content="{% if hasExplicitImage %}summary_large_image{% else %}__TWITTER_CARD_PLACEHOLDER__{% endif %}">
|
||||
<meta name="twitter:title" content="{{ ogTitle }}">
|
||||
<meta name="twitter:description" content="{{ ogDesc }}">
|
||||
{% if ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10 %}
|
||||
@@ -58,8 +51,8 @@
|
||||
<meta name="twitter:image" content="{% if 'http' in image %}{{ image }}{% else %}{{ site.url }}{% if image[0] != '/' %}/{% endif %}{{ image }}{% endif %}">
|
||||
{% elif contentImage and contentImage != "" and (contentImage | length) > 10 %}
|
||||
<meta name="twitter:image" content="{% if 'http' in contentImage %}{{ contentImage }}{% else %}{{ site.url }}{% if contentImage[0] != '/' %}/{% endif %}{{ contentImage }}{% endif %}">
|
||||
{% elif _hasOg %}
|
||||
<meta name="twitter:image" content="{{ site.url }}/og/{{ _ogSlug }}.png">
|
||||
{% else %}
|
||||
<meta name="twitter:image" content="__OG_IMAGE_PLACEHOLDER__">
|
||||
{% endif %}
|
||||
|
||||
{# Favicon #}
|
||||
@@ -102,17 +95,17 @@
|
||||
[x-show*="loading"], button[\\@click*="fetch"], button[\\@click*="loadMore"] { display: none !important; }
|
||||
</style>
|
||||
</noscript>
|
||||
<link rel="canonical" href="{{ site.url }}{{ _pageUrl }}">
|
||||
<link rel="canonical" href="{{ site.url }}{{ page.url }}">
|
||||
<link rel="alternate" type="application/rss+xml" href="/feed.xml" title="RSS Feed">
|
||||
<link rel="alternate" type="application/json" href="/feed.json" title="JSON Feed">
|
||||
{% if site.markdownAgents.enabled and _pageUrl and _pageUrl.startsWith('/articles/') %}
|
||||
<link rel="alternate" type="text/markdown" href="{{ _pageUrl }}index.md" title="Markdown version">
|
||||
{% if site.markdownAgents.enabled and page.url and page.url.startsWith('/articles/') %}
|
||||
<link rel="alternate" type="text/markdown" href="{{ page.url }}index.md" title="Markdown version">
|
||||
{% endif %}
|
||||
<link rel="authorization_endpoint" href="{{ site.url }}/auth">
|
||||
<link rel="token_endpoint" href="{{ site.url }}/auth/token">
|
||||
<link rel="micropub" href="{{ site.url }}/micropub">
|
||||
<link rel="microsub" href="{{ site.url }}/microsub">
|
||||
<link rel="self" href="{{ site.url }}{{ _pageUrl }}">
|
||||
<link rel="self" href="{{ site.url }}{{ page.url }}">
|
||||
<link rel="hub" href="https://websubhub.com/hub">
|
||||
<link rel="webmention" href="https://webmention.io/{{ site.webmentions.domain }}/webmention">
|
||||
<link rel="pingback" href="https://webmention.io/{{ site.webmentions.domain }}/xmlrpc">
|
||||
@@ -314,7 +307,7 @@
|
||||
</header>
|
||||
|
||||
<main class="container py-8" data-pagefind-body>
|
||||
{% if withSidebar and _pageUrl == "/" and homepageConfig and homepageConfig.sections %}
|
||||
{% if withSidebar and page.url == "/" and homepageConfig and homepageConfig.sections %}
|
||||
{# Homepage: builder controls its own layout and sidebar #}
|
||||
{{ content | safe }}
|
||||
{% elif withSidebar %}
|
||||
|
||||
Reference in New Issue
Block a user