mirror of
https://github.com/svemagie/blog-eleventy-indiekit.git
synced 2026-05-15 06:58:50 +02:00
fix: generate sitemap.xml in eleventy.after hook instead of template
The @quasibit/eleventy-plugin-sitemap shortcode triggers TemplateContentPrematureUseError on paginated templates in Eleventy 3.x. Move sitemap generation to eleventy.after hook which scans the output directory for index.html files after all templates are rendered. Remove the plugin import/registration and the sitemap.njk template.
This commit is contained in:
+49
-30
@@ -2,7 +2,7 @@ import pluginWebmentions from "@chrisburnell/eleventy-cache-webmentions";
|
|||||||
import pluginRss from "@11ty/eleventy-plugin-rss";
|
import pluginRss from "@11ty/eleventy-plugin-rss";
|
||||||
import embedEverything from "eleventy-plugin-embed-everything";
|
import embedEverything from "eleventy-plugin-embed-everything";
|
||||||
import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";
|
import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";
|
||||||
import sitemap from "@quasibit/eleventy-plugin-sitemap";
|
|
||||||
import markdownIt from "markdown-it";
|
import markdownIt from "markdown-it";
|
||||||
import markdownItAnchor from "markdown-it-anchor";
|
import markdownItAnchor from "markdown-it-anchor";
|
||||||
import syntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
|
import syntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
|
||||||
@@ -352,12 +352,6 @@ export default function (eleventyConfig) {
|
|||||||
return eleventyConfig.htmlTransformer.transformContent(this.outputPath, content, this);
|
return eleventyConfig.htmlTransformer.transformContent(this.outputPath, content, this);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sitemap generation
|
|
||||||
eleventyConfig.addPlugin(sitemap, {
|
|
||||||
sitemap: {
|
|
||||||
hostname: siteUrl,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wrap <table> elements in <table-saw> for responsive tables
|
// Wrap <table> elements in <table-saw> for responsive tables
|
||||||
eleventyConfig.addTransform("table-saw-wrap", function (content, outputPath) {
|
eleventyConfig.addTransform("table-saw-wrap", function (content, outputPath) {
|
||||||
@@ -674,29 +668,6 @@ export default function (eleventyConfig) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Exclude pages from sitemap by URL pattern
|
|
||||||
// Usage: collections.all | excludeFromSitemap
|
|
||||||
eleventyConfig.addFilter("excludeFromSitemap", (items) => {
|
|
||||||
const excludePatterns = [
|
|
||||||
/^\/replies\//,
|
|
||||||
/^\/feed\.(xml|json)$/,
|
|
||||||
/\/feed\.(xml|json)$/,
|
|
||||||
/^\/categories\//,
|
|
||||||
/^\/digest/,
|
|
||||||
/^\/webmention-debug\//,
|
|
||||||
/^\/404\.html$/,
|
|
||||||
/^\/sitemap\.xml$/,
|
|
||||||
/^\/dashboard/,
|
|
||||||
/^\/homepage/,
|
|
||||||
/^\/search\//,
|
|
||||||
/^\/graph\//,
|
|
||||||
];
|
|
||||||
return items.filter((item) => {
|
|
||||||
const url = item.url || "";
|
|
||||||
return !excludePatterns.some((pattern) => pattern.test(url));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Slugify filter
|
// Slugify filter
|
||||||
eleventyConfig.addFilter("slugify", (str) => {
|
eleventyConfig.addFilter("slugify", (str) => {
|
||||||
if (!str) return "";
|
if (!str) return "";
|
||||||
@@ -1426,6 +1397,54 @@ export default function (eleventyConfig) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sitemap generation — scan output HTML files, exclude URL patterns
|
||||||
|
if (!incremental) {
|
||||||
|
const sitemapOutputDir = directories?.output || dir.output;
|
||||||
|
const excludePatterns = [
|
||||||
|
/^\/replies\//,
|
||||||
|
/\/feed\.(xml|json)$/,
|
||||||
|
/^\/categories\//,
|
||||||
|
/^\/digest/,
|
||||||
|
/^\/webmention-debug\//,
|
||||||
|
/^\/404\.html$/,
|
||||||
|
/^\/dashboard/,
|
||||||
|
/^\/homepage/,
|
||||||
|
/^\/search\//,
|
||||||
|
/^\/graph\//,
|
||||||
|
/^\/sitemap\.xml$/,
|
||||||
|
];
|
||||||
|
try {
|
||||||
|
const walkHtml = (base, prefix = "") => {
|
||||||
|
const entries = [];
|
||||||
|
for (const entry of readdirSync(resolve(base, prefix), { withFileTypes: true })) {
|
||||||
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
entries.push(...walkHtml(base, rel));
|
||||||
|
} else if (entry.name === "index.html") {
|
||||||
|
const urlPath = prefix ? `/${prefix}/` : "/";
|
||||||
|
entries.push(urlPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entries;
|
||||||
|
};
|
||||||
|
const allUrls = walkHtml(sitemapOutputDir)
|
||||||
|
.filter((url) => !excludePatterns.some((p) => p.test(url)))
|
||||||
|
.sort();
|
||||||
|
const xmlLines = [
|
||||||
|
'<?xml version="1.0" encoding="UTF-8"?>',
|
||||||
|
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
|
||||||
|
];
|
||||||
|
for (const url of allUrls) {
|
||||||
|
xmlLines.push(` <url><loc>${siteUrl}${url}</loc></url>`);
|
||||||
|
}
|
||||||
|
xmlLines.push("</urlset>");
|
||||||
|
writeFileSync(resolve(sitemapOutputDir, "sitemap.xml"), xmlLines.join("\n"));
|
||||||
|
console.log(`[sitemap] Generated sitemap.xml with ${allUrls.length} URLs`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("[sitemap] Generation failed:", err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Pagefind indexing — run exactly once per process lifetime
|
// Pagefind indexing — run exactly once per process lifetime
|
||||||
if (!pagefindDone) {
|
if (!pagefindDone) {
|
||||||
pagefindDone = true;
|
pagefindDone = true;
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
permalink: /sitemap.xml
|
|
||||||
layout: null
|
|
||||||
eleventyExcludeFromCollections: true
|
|
||||||
---
|
|
||||||
{% set sitemapItems = collections.all | excludeFromSitemap %}
|
|
||||||
{% sitemap sitemapItems %}
|
|
||||||
Reference in New Issue
Block a user