mirror of
https://github.com/svemagie/blog-eleventy-indiekit.git
synced 2026-05-14 22:48:50 +02:00
fix: use eleventyComputed for OG slug to avoid Nunjucks race condition
Eleventy 3.x renders Nunjucks templates in parallel, causing page.url
to return wrong values in {% set %} tags. This caused OG images to be
mismatched between pages (e.g., bookmark showed note's OG image).
Move ogSlug and hasOgImage computation to eleventyComputed, which runs
during the sequential data cascade phase before parallel rendering.
The computed values are then available as plain template variables.
Refs: https://github.com/11ty/eleventy/issues/3183
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Computed data resolved during the data cascade (sequential, per-page).
|
||||||
|
*
|
||||||
|
* Eleventy 3.x renders Nunjucks templates in parallel, which causes
|
||||||
|
* `page.url` and `page.fileSlug` to return wrong values when read
|
||||||
|
* via {% set %} in templates. By computing OG-related values here,
|
||||||
|
* they are resolved before parallel rendering begins.
|
||||||
|
*
|
||||||
|
* See: https://github.com/11ty/eleventy/issues/3183
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { existsSync } from "node:fs";
|
||||||
|
import { resolve, dirname } from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
|
export default {
|
||||||
|
ogSlug: (data) => {
|
||||||
|
const url = data.page?.url;
|
||||||
|
if (!url) return "";
|
||||||
|
return url.replace(/\/$/, "").split("/").pop();
|
||||||
|
},
|
||||||
|
|
||||||
|
hasOgImage: (data) => {
|
||||||
|
const url = data.page?.url;
|
||||||
|
if (!url) return false;
|
||||||
|
const slug = url.replace(/\/$/, "").split("/").pop();
|
||||||
|
if (!slug) return false;
|
||||||
|
const ogPath = resolve(__dirname, "..", ".cache", "og", `${slug}.png`);
|
||||||
|
return existsSync(ogPath);
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -23,16 +23,15 @@
|
|||||||
<meta property="og:type" content="{% if page.url == '/' %}website{% else %}article{% endif %}">
|
<meta property="og:type" content="{% if page.url == '/' %}website{% else %}article{% endif %}">
|
||||||
<meta property="og:description" content="{{ ogDesc }}">
|
<meta property="og:description" content="{{ ogDesc }}">
|
||||||
<meta name="description" content="{{ ogDesc }}">
|
<meta name="description" content="{{ ogDesc }}">
|
||||||
{% set ogFileSlug = page.url | ogSlug %}
|
{# ogSlug and hasOgImage are pre-computed via eleventyComputed (race-condition safe) #}
|
||||||
{% set hasGeneratedOg = ogFileSlug | hasOgImage %}
|
|
||||||
{% if ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10 %}
|
{% if ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10 %}
|
||||||
<meta property="og:image" content="{% if 'http' in ogPhoto %}{{ ogPhoto }}{% else %}{{ site.url }}{% if ogPhoto[0] != '/' %}/{% endif %}{{ ogPhoto }}{% endif %}">
|
<meta property="og:image" content="{% if 'http' in ogPhoto %}{{ ogPhoto }}{% else %}{{ site.url }}{% if ogPhoto[0] != '/' %}/{% endif %}{{ ogPhoto }}{% endif %}">
|
||||||
{% elif image and image != "" and (image | length) > 10 %}
|
{% elif image and image != "" and (image | length) > 10 %}
|
||||||
<meta property="og:image" content="{% if 'http' in image %}{{ image }}{% else %}{{ site.url }}{% if image[0] != '/' %}/{% endif %}{{ image }}{% endif %}">
|
<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 %}
|
{% 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 %}">
|
<meta property="og:image" content="{% if 'http' in contentImage %}{{ contentImage }}{% else %}{{ site.url }}{% if contentImage[0] != '/' %}/{% endif %}{{ contentImage }}{% endif %}">
|
||||||
{% elif hasGeneratedOg %}
|
{% elif hasOgImage %}
|
||||||
<meta property="og:image" content="{{ site.url }}/og/{{ ogFileSlug }}.png">
|
<meta property="og:image" content="{{ site.url }}/og/{{ ogSlug }}.png">
|
||||||
{% else %}
|
{% else %}
|
||||||
<meta property="og:image" content="{{ site.url }}/images/og-default.png">
|
<meta property="og:image" content="{{ site.url }}/images/og-default.png">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -41,7 +40,7 @@
|
|||||||
<meta property="og:locale" content="{{ site.locale | default('en_US') }}">
|
<meta property="og:locale" content="{{ site.locale | default('en_US') }}">
|
||||||
|
|
||||||
{# Twitter Card meta tags #}
|
{# Twitter Card meta tags #}
|
||||||
{% set hasImage = hasGeneratedOg or (ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10) or (image and image != "" and (image | length) > 10) or (contentImage and contentImage != "" and (contentImage | length) > 10) %}
|
{% set hasImage = hasOgImage 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 %}">
|
<meta name="twitter:card" content="{% if hasImage %}summary_large_image{% else %}summary{% endif %}">
|
||||||
<meta name="twitter:title" content="{{ ogTitle }}">
|
<meta name="twitter:title" content="{{ ogTitle }}">
|
||||||
<meta name="twitter:description" content="{{ ogDesc }}">
|
<meta name="twitter:description" content="{{ ogDesc }}">
|
||||||
@@ -51,8 +50,8 @@
|
|||||||
<meta name="twitter:image" content="{% if 'http' in image %}{{ image }}{% else %}{{ site.url }}/{{ image }}{% endif %}">
|
<meta name="twitter:image" content="{% if 'http' in image %}{{ image }}{% else %}{{ site.url }}/{{ image }}{% endif %}">
|
||||||
{% elif contentImage and contentImage != "" and (contentImage | length) > 10 %}
|
{% elif contentImage and contentImage != "" and (contentImage | length) > 10 %}
|
||||||
<meta name="twitter:image" content="{% if 'http' in contentImage %}{{ contentImage }}{% else %}{{ site.url }}/{{ contentImage }}{% endif %}">
|
<meta name="twitter:image" content="{% if 'http' in contentImage %}{{ contentImage }}{% else %}{{ site.url }}/{{ contentImage }}{% endif %}">
|
||||||
{% elif hasGeneratedOg %}
|
{% elif hasOgImage %}
|
||||||
<meta name="twitter:image" content="{{ site.url }}/og/{{ ogFileSlug }}.png">
|
<meta name="twitter:image" content="{{ site.url }}/og/{{ ogSlug }}.png">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# Favicon #}
|
{# Favicon #}
|
||||||
|
|||||||
Reference in New Issue
Block a user