// Pinger IndexNow (Bing/Yandex/Seznam m.fl.) med de sider dette push faktisk ændrede. // // Vi sender bevidst IKKE hele sitemappet hver gang: IndexNow er til "det her ændrede sig // nu", og gentagne fuld-lister ser ud som støj. Kan vi ikke regne diffen ud, springer vi // over frem for at gætte. // // Kør efter `astro build` — dist/sitemap-0.xml bruges som facitliste over gyldige URL'er. // Google understøtter ikke IndexNow; det her hjælper kun de øvrige motorer. import { execFileSync } from 'node:child_process'; import fs from 'node:fs'; const HOST = 'asger.xn--weirse-fya.dk'; const KEY = 'b68b31655cb9c1a662d53905dd0b1b06'; const ORIGIN = `https://${HOST}`; const git = (args) => { try { return execFileSync('git', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim(); } catch { return null; } }; const sitemapUrls = () => { const xml = fs.readFileSync('dist/sitemap-0.xml', 'utf8'); return new Set([...xml.matchAll(/([^<]+)<\/loc>/g)].map((m) => m[1])); }; // src/pages/foo.astro -> /foo/ ; src/content/blog/bar.md -> /blog/bar/ const routeForFile = (f) => { let m = f.match(/^src\/pages\/(.+)\.astro$/); if (m) { if (m[1].includes('[')) return null; // dynamiske ruter kan vi ikke slå op if (m[1] === 'index') return '/'; return `/${m[1].replace(/\/index$/, '')}/`; } m = f.match(/^src\/content\/blog\/(.+)\.md$/); if (m) return `/blog/${m[1]}/`; return null; }; const changedFiles = () => { const { GITHUB_EVENT_BEFORE, GITHUB_SHA } = process.env; const zero = /^0*$/; if (GITHUB_EVENT_BEFORE && !zero.test(GITHUB_EVENT_BEFORE)) { const d = git(['diff', '--name-only', GITHUB_EVENT_BEFORE, GITHUB_SHA || 'HEAD']); if (d !== null) return d ? d.split('\n') : []; } const d = git(['diff', '--name-only', 'HEAD~1', 'HEAD']); return d ? d.split('\n') : null; }; const files = changedFiles(); if (files === null) { console.log('IndexNow: kan ikke bestemme hvad der ændrede sig (shallow clone?) — springer over.'); process.exit(0); } const valid = sitemapUrls(); const urls = [...new Set(files.map(routeForFile).filter(Boolean).map((r) => ORIGIN + r))].filter((u) => valid.has(u), ); // Layout/CSS/config-ændringer rammer hver side, men det er ikke en indholdsændring // værd at pinge om. Kun ruter med eget ændret kildefil ryger afsted. if (!urls.length) { console.log('IndexNow: ingen sider med ændret indhold i dette push — springer over.'); process.exit(0); } const body = { host: HOST, key: KEY, keyLocation: `${ORIGIN}/${KEY}.txt`, urlList: urls, }; console.log(`IndexNow: indsender ${urls.length} URL(er):`); for (const u of urls) console.log(' ', u); // `node scripts/indexnow.mjs --dry-run` viser hvad der ville blive sendt. if (process.argv.includes('--dry-run')) { console.log('IndexNow: --dry-run, sender ikke.'); process.exit(0); } const res = await fetch('https://api.indexnow.org/indexnow', { method: 'POST', headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify(body), }); // 200 = modtaget, 202 = modtaget men nøglen valideres stadig. Begge er fine. console.log(`IndexNow: HTTP ${res.status} ${res.statusText}`); if (![200, 202].includes(res.status)) { console.log(await res.text().catch(() => '')); console.log('IndexNow: afvist — men deployet er allerede ude, så vi fejler ikke buildet.'); }