From 288205630ee0839611c22b21734487220c9fb4a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asger=20Geel=20Weirs=C3=B8e?= Date: Sat, 31 Oct 2026 14:43:20 +0100 Subject: [PATCH] Ryd op i kommentarer --- .gitea/workflows/deploy.yml | 19 +++---------------- astro.config.mjs | 33 +++++---------------------------- scripts/indexnow.mjs | 13 ++----------- scripts/verify-approvals.mjs | 16 +++------------- src/components/Chat.astro | 3 --- src/components/Head.astro | 14 +++----------- src/components/Header.astro | 1 - src/layouts/Base.astro | 7 ++----- src/pages/index.astro | 2 -- src/pages/now.astro | 6 ++---- src/seo.ts | 13 ------------- src/styles/global.css | 10 +--------- 12 files changed, 21 insertions(+), 116 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index cee780e..f9bbf79 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -12,9 +12,7 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive - # Fuld historik: astro.config.mjs udleder sitemap-lastmod fra hver sides - # sidste commit, og IndexNow-steppet differ pushet. Begge er værdiløse - # med den default shallow clone (fetch-depth: 1). + # Fuld historik til sitemap-lastmod og IndexNow fetch-depth: 0 - name: Setup Node @@ -22,10 +20,7 @@ jobs: with: node-version: 22 - # The runner forces omit of optional deps, dropping @img/sharp-linux-x64 - # (sharp's platform binary) -> astro:assets MissingSharp. Clear the omit - # env and force-install the linux/glibc/x64 sharp binary per sharp's - # official cross-platform install, then verify it loads. + # Runneren udelader optional deps, så sharp-binæren installeres eksplicit - name: Install dependencies env: npm_config_omit: "" @@ -35,7 +30,6 @@ jobs: npm install --include=optional --os=linux --libc=glibc --cpu=x64 sharp node -e "console.log('sharp', require('sharp').versions.sharp)" - # Intet indlæg bygges uden godkendelse; se scripts/verify-approvals.mjs. - name: Verify blog approvals env: PUBLISH_KEY: ${{ secrets.PUBLISH_KEY }} @@ -44,11 +38,7 @@ jobs: - name: Build site run: npm run build - # tar over SSH (the runner image has no rsync). Build is unpacked into - # a .new dir on the web host and atomically swapped in, so the live web - # root is never left half-written. Host and path are repository secrets, - # not variables: run logs of a public repo are public, and Gitea prints - # variables in them but masks secrets. + # tar over SSH med atomisk swap (runner-imaget har ikke rsync) - name: Deploy dist/ over SSH env: DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} @@ -72,9 +62,6 @@ jobs: && mv $DEPLOY_PATH.new $DEPLOY_PATH \ && rm -rf $DEPLOY_PATH.old" - # Fortæl Bing/Yandex m.fl. med det samme hvilke sider der ændrede sig. - # Kører EFTER deploy, så nøglefilen og siderne er live når de kommer og tjekker. - # Google understøtter ikke IndexNow. Må aldrig vælte et ellers vellykket deploy. - name: Ping IndexNow continue-on-error: true env: diff --git a/astro.config.mjs b/astro.config.mjs index 0ee55e1..105fb99 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -9,13 +9,8 @@ import { fileURLToPath } from 'node:url'; const ROOT = path.dirname(fileURLToPath(import.meta.url)); -// ── lastmod til sitemap ──────────────────────────────────────────────────────── -// Google bruger kun lastmod hvis den er troværdig, så vi gætter aldrig: statiske -// sider får datoen for deres SIDSTE COMMIT, blogindlæg får updated/date fra -// frontmatter, og alt vi ikke kan datere præcist får slet ingen lastmod. -// NB: kræver fuld git-historik — deploy-workflowen bruger fetch-depth: 0. -// Er historikken shallow (eller mangler .git), falder vi stille tilbage til -// "ingen lastmod" i stedet for at udgive en forkert dato. +// lastmod til sitemap: sidste commit for statiske sider, frontmatter for blogindlæg. +// Kræver fuld git-historik (fetch-depth: 0); ellers ingen lastmod. const gitLastModified = (file) => { try { @@ -30,8 +25,6 @@ const gitLastModified = (file) => { } }; -// Shallow clone => hver fil ser ud til at være ændret i den ene commit vi har. -// Så er datoerne værdiløse, og vi dropper lastmod helt. const gitHistoryIsUsable = (() => { try { const n = execFileSync('git', ['rev-list', '--count', 'HEAD'], { @@ -145,14 +138,8 @@ export default defineConfig({ sitemap({ changefreq: 'weekly', priority: 0.7, - // /tarballz/ er ikke en Astro-side (genereres på webhosten), men oversigten må - // gerne indekseres; selve pakkefilerne er noindex der. customPages: ['https://asger.xn--weirse-fya.dk/tarballz/'], - // Tag-siderne er noindex (tynde lister), så de hører heller ikke i sitemap'et. - // /peppol er kun en omdirigering til /nemhandel og skal ikke indekseres. - // /cookies, /status og /chat er hjælpesider uden søgeværdi; de er noindex - // og står derfor heller ikke i sitemap'et (ellers melder Search Console - // "indsendt URL markeret som noindex"). + // noindex-sider og omdirigeringer filter: (page) => { const p = new URL(page).pathname.replace(/\/$/, ''); return !p.startsWith('/tags') && !p.startsWith('/peppol') @@ -163,18 +150,11 @@ export default defineConfig({ if (pathname === '/') item.priority = 1.0; const lastmod = lastmodByRoute.get(pathname); if (lastmod) item.lastmod = lastmod; - // Samme kanoniske form som og de interne links: - // uden afsluttende skråstreg. Slås lastmod op FØR strippet, fordi - // lastmodByRoute er nøglet på Astros egne ruter (som har skråstregen). - // Undtagen /tarballz/: den er ikke en Astro-side, og webhosten serverer - // den kun med skråstreg (uden skråstreg giver den en 301). + // Kanonisk form uden afsluttende skråstreg (undtagen /tarballz/) if (pathname !== '/' && pathname !== '/tarballz/') item.url = item.url.replace(/\/$/, ''); return item; }, }), - // Service worker → offline support + installable PWA. autoUpdate + outdated-cache - // cleanup so a redeploy never strands a visitor on a stale version. Reuses the - // existing public/site.webmanifest (manifest: false = don't generate another). AstroPWA({ registerType: 'autoUpdate', manifest: false, @@ -184,10 +164,7 @@ export default defineConfig({ cleanupOutdatedCaches: true, clientsClaim: true, skipWaiting: true, - // No SPA fallback. The default answers EVERY navigation it has not - // precached with the cached front page, so /tarballz/ (served by nginx - // outside the Astro build) and unknown URLs showed the home page instead - // of the real page or the 404. Every Astro page is precached anyway. + // Ingen fallback til forsiden, så /tarballz/ og 404 virker navigateFallback: null, }, devOptions: { enabled: false }, diff --git a/scripts/indexnow.mjs b/scripts/indexnow.mjs index 01e8753..f2424c0 100644 --- a/scripts/indexnow.mjs +++ b/scripts/indexnow.mjs @@ -1,11 +1,5 @@ -// 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. +// Pinger IndexNow med de sider der er ændret i dette push. +// Kør efter `astro build` (bruger dist/sitemap-0.xml). import { execFileSync } from 'node:child_process'; import fs from 'node:fs'; @@ -62,8 +56,6 @@ const urls = [...new Set(files.map(routeForFile).filter(Boolean).map((r) => ORIG 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); @@ -91,7 +83,6 @@ const res = await fetch('https://api.indexnow.org/indexnow', { 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(() => '')); diff --git a/scripts/verify-approvals.mjs b/scripts/verify-approvals.mjs index 8cbca88..c04f4c3 100644 --- a/scripts/verify-approvals.mjs +++ b/scripts/verify-approvals.mjs @@ -1,14 +1,5 @@ -// Spærre før build: intet blogindlæg går live uden at være godkendt. -// -// Hvert indlæg i src/content/blog skal bære et `godkendt:`-stempel i frontmatter. -// Stemplet er en HMAC-SHA256 over filens sti + indhold (uden selve stempel-linjen) -// + sha256 af hvert billede i indlæggets mappe (src/content/blog//), -// lavet med en nøgle som kun godkendelsestjenesten og denne workflow kender. Et -// indlæg der er lagt direkte i repoet, eller ændret efter godkendelse, har derfor -// intet eller et forkert stempel, og så stopper buildet før noget bliver deployet. -// -// Udkast hører ikke hjemme her: repoet er offentligt, så `draft: true` ville stadig -// udgive teksten via git. Udkast ligger i et privat repo indtil de er godkendt. +// Stopper buildet hvis et blogindlæg mangler et gyldigt `godkendt:`-stempel +// (HMAC-SHA256 over sti, indhold og billeder). // // PUBLISH_KEY= node scripts/verify-approvals.mjs import crypto from 'node:crypto'; @@ -21,8 +12,7 @@ if (!key) { process.exit(1); } -// Skal matche godkendelsestjenesten byte for byte. Et indlæg uden billeder har -// ingen @asset-linjer, så dets stempel er det samme som før billeder fandtes. +// Skal matche godkendelsestjenesten byte for byte. const canonical = (relPath, text, assets = []) => { const lines = text.replace(/\r\n/g, '\n').split('\n'); if (lines[0] === '---') { diff --git a/src/components/Chat.astro b/src/components/Chat.astro index 04a8ba5..09f2848 100644 --- a/src/components/Chat.astro +++ b/src/components/Chat.astro @@ -32,7 +32,6 @@ const t = lang === 'en' ? { function esc(s) { return s.replace(/&/g, '&').replace(//g, '>'); } - // Escape FØRST, linkificér så: rene URL'er og e-mails bliver klikbare, intet HTML slipper igennem. function linkify(text) { var html = esc(text); html = html.replace(/\b(https?:\/\/[^\s<]+[^\s<.,!?:;)])/g, @@ -41,8 +40,6 @@ const t = lang === 'en' ? { '$1'); return html; } - // Track spørgsmålet i Matomo FRA browseren, så det knyttes til den besøgendes - // egen visitor-profil (cookie/visitor-ID, IP, browser) i stedet for en server-IP. function track(action, q) { try { (window._paq = window._paq || []).push(['trackEvent', 'Chat', action, q]); } catch (_) {} } diff --git a/src/components/Head.astro b/src/components/Head.astro index e07dc59..f525299 100644 --- a/src/components/Head.astro +++ b/src/components/Head.astro @@ -11,8 +11,7 @@ interface Props { modifiedTime?: string; tags?: string[]; jsonLd?: unknown[]; - // Tynde oversigtssider (fx tags med 1-2 indlæg) skal ikke i Googles indeks, - // men links fra dem skal stadig følges. + // noindex, follow noindex?: boolean; // Sidens sprog (standard: dansk) og dens oversættelser, som hreflang-links. lang?: 'da' | 'en'; @@ -28,9 +27,7 @@ const xDefault = hreflang.find((a) => a.lang === 'da'); const pageTitle = title ? `${title} · ${SITE.name}` : `${SITE.title} · Datalog & Technical Solution Architect`; const desc = description ?? SITE.description; -// Kanonisk form er UDEN afsluttende skråstreg. Origin serverer begge former med -// 200, og de interne links peger alle på no-slash, så canonical og sitemap skal -// gøre det samme, ellers opdager Google to adskilte sæt af de samme sider. +// Kanonisk form er uden afsluttende skråstreg, som i sitemap og interne links. const canonicalPath = Astro.url.pathname.replace(/\/$/, '') || '/'; const canonical = new URL(canonicalPath, SITE.url).href; const ogImage = new URL(image ?? '/og.png', SITE.url).href; @@ -76,20 +73,15 @@ const graphs = [baseGraph, ...jsonLd]; - {graphs.map((g) => - {!PREVIEW && } @@ -76,7 +73,7 @@ const { title, description, image, type, publishedTime, modifiedTime, tags, json