Reglen gjaldt kun de nyeste tekster; resten af sitet var fuld af dem. 72 steder rettet på tværs af sider, komponenter, layout, profildata og et blogindlæg. Valget pr. sted: ".." hvor der er en ægte pause eller en tør bemærkning (fejlbeskederne i /ubl, /nemhandel og /chat, påskeægget i sidekilden, "Øjebliksbillede.. verificér altid"), kolon hvor noget defineres (cookie-listen, kolofonens rækker, profilbemærkninger der forklarer en forkortelse) og komma hvor sætningen bare skal hænge sammen. Ét sted blev det til to sætninger, fordi indskuddet var for langt til et komma. Sidetitlen i Head.astro og de fire "docs.peppol.eu"-kildelinks brugte tankestregen som skilletegn; de bruger nu "·", som sitet i forvejen bruger mellem sidetitel og navn. Tilbage står én tankestreg i /ubl, og den bliver: den markerer et tomt felt i definitionslisten og er ikke en pause i en sætning. Claude-Session: https://claude.ai/code/session_0198n4owY35jQpwht1wCGzfh
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
// Lille cookie-popup: vises 1. gang man besøger siden, huskes derefter i localStorage.
|
||||
// Implicit samtykke — ved at bruge siden accepterer man cookies (samme tekst på /cookies).
|
||||
// Implicit samtykke: ved at bruge siden accepterer man cookies (samme tekst på /cookies).
|
||||
---
|
||||
<div
|
||||
id="cookie-banner"
|
||||
|
||||
@@ -17,10 +17,10 @@ const {
|
||||
publishedTime, modifiedTime, tags = [], jsonLd = [],
|
||||
} = Astro.props;
|
||||
|
||||
const pageTitle = title ? `${title} · ${SITE.name}` : `${SITE.title} — Datalog & Technical Solution Architect`;
|
||||
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
|
||||
// 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.
|
||||
const canonicalPath = Astro.url.pathname.replace(/\/$/, '') || '/';
|
||||
const canonical = new URL(canonicalPath, SITE.url).href;
|
||||
@@ -70,7 +70,7 @@ const graphs = [baseGraph, ...jsonLd];
|
||||
|
||||
{graphs.map((g) => <script type="application/ld+json" set:html={JSON.stringify(g)} />)}
|
||||
|
||||
<!-- Matomo (site 2) via first-party proxy /_a/ — neutrale navne, så content-blockers ikke matcher "matomo".
|
||||
<!-- Matomo (site 2) via first-party proxy /_a/: neutrale navne, så content-blockers ikke matcher "matomo".
|
||||
Lagt direkte i kilden fordi HTML-minify dropper det valgfrie </head> som NPMplus' sub_filter ellers injicerede på. -->
|
||||
<script is:inline>
|
||||
var _paq = (window._paq = window._paq || []);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Command palette (⌘K / Ctrl+K): naviger, søg i blog, skift tema, kopiér email.
|
||||
// Vanilla JS, ingen dependencies. Søgeindekset hentes lazy fra /search-index.json
|
||||
// første gang paletten åbnes. Script i head er guarded (kører én gang), markup
|
||||
// gen-renderes pr. side af ClientRouter — alt state læses on-open.
|
||||
// gen-renderes pr. side af ClientRouter, alt state læses on-open.
|
||||
---
|
||||
<div id="palette" class="palette-overlay" hidden>
|
||||
<div class="palette-box" role="dialog" aria-modal="true" aria-label="Kommandopalette">
|
||||
|
||||
@@ -15,7 +15,7 @@ og brugere logger ind centralt via **SSO (OIDC)**.
|
||||
|
||||
## Kode & CI/CD
|
||||
Jeg hoster min egen **Gitea** med tilhørende Actions-runnere, så projekter bygges og
|
||||
deployes automatisk ved push — inklusive den her side.
|
||||
deployes automatisk ved push.. inklusive den her side.
|
||||
|
||||
## Resten
|
||||
Medieservere, databaser, dokument-redigering, overvågning og en lang række småtjenester.
|
||||
|
||||
+21
-21
@@ -40,7 +40,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['Invoice', 'CreditNote'],
|
||||
anvendelse: 'Internationalt NES-fakturaprofil: kunde modtager faktura og kreditnota fra leverandør.',
|
||||
bemaerkninger: 'Obligatorisk profil. Den profil der ligger tættest på den gamle OIOXML-faktura — kun afløftede felter er tilladt. Bruges når fakturaafsender teknisk set ikke kan modtage en ApplicationResponse.',
|
||||
bemaerkninger: 'Obligatorisk profil. Den profil der ligger tættest på den gamle OIOXML-faktura, kun afløftede felter er tilladt. Bruges når fakturaafsender teknisk set ikke kan modtage en ApplicationResponse.',
|
||||
},
|
||||
|
||||
// ── Profiler for: Ordre til fakturering ────────────────────────────────────
|
||||
@@ -52,7 +52,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['Order', 'OrderResponseSimple', 'Invoice', 'CreditNote', 'Reminder', 'ApplicationResponse *'],
|
||||
anvendelse: 'Komplet simpel handel: simpel ordre efterfulgt af simpel fakturering. Dækker bestilling til betaling.',
|
||||
bemaerkninger: 'Samlepakken de fleste vælger, når de vil kunne både bestille og fakturere. Ingen ordreændring/-annullering — det kræver en OrdAdv-variant.',
|
||||
bemaerkninger: 'Samlepakken de fleste vælger, når de vil kunne både bestille og fakturere. Ingen ordreændring/-annullering, det kræver en OrdAdv-variant.',
|
||||
},
|
||||
|
||||
// ── Profiler for: Simple Ordrer ────────────────────────────────────────────
|
||||
@@ -64,7 +64,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['OrderResponse'],
|
||||
anvendelse: 'Enkeltdokument-profil til alene at kunne udveksle en ordrebekræftelse (OrderResponse) uden at tilmelde sig en fuld ordreproces.',
|
||||
bemaerkninger: 'Registerprofil af typen "single" — findes i Nemhandelsregistret, men er ikke beskrevet i OIOUBL Profiler-guiden (G26) v1.3. Verificér mod registret før brug.',
|
||||
bemaerkninger: 'Registerprofil af typen "single", findes i Nemhandelsregistret, men er ikke beskrevet i OIOUBL Profiler-guiden (G26) v1.3. Verificér mod registret før brug.',
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -84,7 +84,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['Order', 'OrderResponseSimple'],
|
||||
anvendelse: 'Som OrdSim, men leverandør skal altid sende ordresvar.',
|
||||
bemaerkninger: "R = 'Response required' — samme dokumenter som OrdSim, men svaret er obligatorisk.",
|
||||
bemaerkninger: "R = 'Response required': samme dokumenter som OrdSim, men svaret er obligatorisk.",
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -106,7 +106,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['Catalogue', 'CatalogueDeletion', 'ApplicationResponse'],
|
||||
anvendelse: 'Leverandør sender et produktkatalog til kunden og kan slette det igen. Kunden kan afvise med ApplicationResponse.',
|
||||
bemaerkninger: 'Simpleste katalogprofil — ingen prisopdatering, ingen katalogforespørgsel.',
|
||||
bemaerkninger: 'Simpleste katalogprofil, ingen prisopdatering, ingen katalogforespørgsel.',
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -116,7 +116,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['CataloguePricingUpdate', 'ApplicationResponse'],
|
||||
anvendelse: 'Leverandør opdaterer alene priserne i et allerede udvekslet katalog.',
|
||||
bemaerkninger: '"Catalogue Pricing Update Only" — forudsætter at kataloget er sendt via en anden katalogprofil.',
|
||||
bemaerkninger: '"Catalogue Pricing Update Only" forudsætter at kataloget er sendt via en anden katalogprofil.',
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -148,7 +148,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['Invoice', 'CreditNote', 'Reminder', 'ApplicationResponse'],
|
||||
anvendelse: 'Som BilSim, men kunden skal altid kvittere med et ApplicationResponse (accept/afvisning).',
|
||||
bemaerkninger: "R = 'Response required' — kunden skal kvittere. Bemærk: tilmelding til BilSimR giver ikke automatisk BilSim; begge skal registreres hver for sig.",
|
||||
bemaerkninger: "R = 'Response required': kunden skal kvittere. Bemærk: tilmelding til BilSimR giver ikke automatisk BilSim; begge skal registreres hver for sig.",
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -158,7 +158,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['Reminder'],
|
||||
anvendelse: 'Enkeltdokument-profil til alene at kunne modtage rykkere.',
|
||||
bemaerkninger: 'Registerprofil af typen "single" — ikke i OIOUBL Profiler-guiden (G26) v1.3. Praktisk fordi Reminder ikke findes i Peppol BIS Billing og derfor kun kan sendes i OIOUBL-profilerne.',
|
||||
bemaerkninger: 'Registerprofil af typen "single", ikke i OIOUBL Profiler-guiden (G26) v1.3. Praktisk fordi Reminder ikke findes i Peppol BIS Billing og derfor kun kan sendes i OIOUBL-profilerne.',
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -167,7 +167,7 @@ export const profiles: EProfile[] = [
|
||||
id: 'Procurement-PayBas-1.0',
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['Statement', 'ApplicationResponse'],
|
||||
anvendelse: 'Leverandør sender kontoudtog (Statement) til kunden — en samlet oversigt over udestående poster, ikke en faktura.',
|
||||
anvendelse: 'Leverandør sender kontoudtog (Statement) til kunden, en samlet oversigt over udestående poster, ikke en faktura.',
|
||||
bemaerkninger: 'G26 kalder profilen direkte "Statement". Trods "Pay"-navnet er der ingen betalingsdokumenter i profilen.',
|
||||
},
|
||||
{
|
||||
@@ -200,7 +200,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['CatalogueRequest', 'Catalogue', 'CatalogueItemSpecificationUpdate', 'CataloguePricingUpdate', 'CatalogueDeletion', 'ApplicationResponse'],
|
||||
anvendelse: 'Fuld katalogproces: forespørgsel, katalog, opdatering af både varebeskrivelser og priser samt sletning.',
|
||||
bemaerkninger: 'Den mest komplette katalogprofil — CatExt plus katalogforespørgsel.',
|
||||
bemaerkninger: 'Den mest komplette katalogprofil: CatExt plus katalogforespørgsel.',
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -292,7 +292,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['Order', 'OrderResponse', 'OrderResponseSimple', 'OrderChange', 'OrderCancellation', 'Invoice', 'CreditNote', 'Reminder', 'ApplicationResponse *'],
|
||||
anvendelse: 'Som OrdAdv-BilSim, men fakturasvar (ApplicationResponse) er påkrævet.',
|
||||
bemaerkninger: 'R sidder på fakturadelen — ordresvaret er stadig valgfrit.',
|
||||
bemaerkninger: 'R sidder på fakturadelen, ordresvaret er stadig valgfrit.',
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -302,7 +302,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['Order', 'OrderResponse', 'OrderResponseSimple', 'OrderChange', 'OrderCancellation', 'Invoice', 'CreditNote', 'Reminder', 'ApplicationResponse *'],
|
||||
anvendelse: 'Som OrdAdv-BilSim, men ordresvar er påkrævet.',
|
||||
bemaerkninger: 'R sidder på ordredelen — fakturasvaret er valgfrit.',
|
||||
bemaerkninger: 'R sidder på ordredelen, fakturasvaret er valgfrit.',
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -322,7 +322,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['OrderResponse', 'OrderResponseSimple', 'OrderChange', 'OrderCancellation', 'Invoice', 'CreditNote', 'Reminder', 'ApplicationResponse *'],
|
||||
anvendelse: 'Sælgerinitieret handel: leverandøren starter med en ordrebekræftelse (fx efter aftale i marken eller telefonisk), kunden kan ændre eller annullere, og der faktureres bagefter.',
|
||||
bemaerkninger: 'Bemærk: ingen Order i profilen — "Sel" = seller initiated, så processen starter med OrderResponse.',
|
||||
bemaerkninger: 'Bemærk: ingen Order i profilen, "Sel" = seller initiated, så processen starter med OrderResponse.',
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -332,7 +332,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['OrderResponse', 'OrderResponseSimple', 'OrderChange', 'OrderCancellation', 'Invoice', 'CreditNote', 'Reminder', 'ApplicationResponse *'],
|
||||
anvendelse: 'Som OrdSel-BilSim, men fakturasvar er påkrævet.',
|
||||
bemaerkninger: 'Ingen Order i profilen — processen starter hos sælger.',
|
||||
bemaerkninger: 'Ingen Order i profilen, processen starter hos sælger.',
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -362,7 +362,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['Order', 'OrderResponseSimple', 'Invoice', 'CreditNote', 'Reminder', 'ApplicationResponse *'],
|
||||
anvendelse: 'Simpel ordre og fakturering hvor både ordresvar og fakturasvar er påkrævet.',
|
||||
bemaerkninger: 'Begge R’er sat — modparten skal kvittere i begge led.',
|
||||
bemaerkninger: 'Begge R’er sat, modparten skal kvittere i begge led.',
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -384,7 +384,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['UtilityStatement', 'ApplicationResponse'],
|
||||
anvendelse: 'Forsyningsbranchen (el/vand/varme/gas): leverandør sender detaljeret forbrugs-/forsyningsspecifikation der ledsager fakturaen; kunden kan svare med ApplicationResponse.',
|
||||
bemaerkninger: 'Bruges som tillæg til en faktureringsprofil — UTS erstatter ikke fakturaen.',
|
||||
bemaerkninger: 'Bruges som tillæg til en faktureringsprofil, UTS erstatter ikke fakturaen.',
|
||||
},
|
||||
{
|
||||
standard: NH,
|
||||
@@ -415,7 +415,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'OIOUBL-2.x',
|
||||
dokumenter: ['DespatchAdvice'],
|
||||
anvendelse: 'Leverandør varsler en forsendelse, så kunden kan forberede modtagelse og afstemme leveringen mod ordren.',
|
||||
bemaerkninger: 'CEN BII-profil optaget i OIOUBL (G26 afsnit 3.3.15). Ikke placeret i en registerkategori her — bekræft gruppen i Nemhandelsregistrets dropdown før brug.',
|
||||
bemaerkninger: 'CEN BII-profil optaget i OIOUBL (G26 afsnit 3.3.15). Ikke placeret i en registerkategori her, bekræft gruppen i Nemhandelsregistrets dropdown før brug.',
|
||||
},
|
||||
|
||||
// ── Peppol BIS 3.0 ─────────────────────────────────────────────────────────
|
||||
@@ -426,7 +426,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0',
|
||||
dokumenter: ['Invoice', 'CreditNote'],
|
||||
anvendelse: 'Den centrale e-faktura/kreditnota-pakke i Peppol. CIUS af EN 16931. Bruges til EU-grænsehandel og DK/Peppol-fakturering.',
|
||||
bemaerkninger: 'Langt den mest brugte BIS3-profil. Invoice Response er en separat profil. Bemærk: Reminder findes ikke i Peppol — brug OIOUBL-profilerne til rykkere.',
|
||||
bemaerkninger: 'Langt den mest brugte BIS3-profil. Invoice Response er en separat profil. Bemærk: Reminder findes ikke i Peppol, brug OIOUBL-profilerne til rykkere.',
|
||||
},
|
||||
{
|
||||
standard: 'Peppol BIS 3.0',
|
||||
@@ -527,7 +527,7 @@ export const profiles: EProfile[] = [
|
||||
customization: 'urn:peppol:pint:billing-1@eu-1',
|
||||
dokumenter: ['Invoice', 'CreditNote'],
|
||||
anvendelse: 'Peppols internationale fakturamodel (PINT) tilpasset EU. Implementerer BIS Billing 3.0 som PINT-kompatibel uden ændringer; baner vej for grænseoverskridende fakturering mod lande med egne PINT-specs (AU/JP/MY/NZ/SG m.fl.).',
|
||||
bemaerkninger: 'v1.0.0 udgivet okt. 2025, nu v1.0.1. CIUS af EN 16931. NB: identifikator-format afviger fra BIS3 — verificér mod docs.peppol.eu/poac/eu/pint-eu inden brug.',
|
||||
bemaerkninger: 'v1.0.0 udgivet okt. 2025, nu v1.0.1. CIUS af EN 16931. NB: identifikator-format afviger fra BIS3, verificér mod docs.peppol.eu/poac/eu/pint-eu inden brug.',
|
||||
},
|
||||
{
|
||||
standard: 'Peppol BIS 4.0 / PINT',
|
||||
@@ -535,8 +535,8 @@ export const profiles: EProfile[] = [
|
||||
id: '(endnu ikke endeligt fastlagt)',
|
||||
customization: '(endnu ikke endeligt fastlagt)',
|
||||
dokumenter: ['Invoice', 'CreditNote (forventet)'],
|
||||
anvendelse: 'Næste generation der lægger BIS og PINT sammen til ét globalt faktura-format. Forventet 2026 — endnu ikke udgivet (pr. juni 2026).',
|
||||
bemaerkninger: "STATUS: under udarbejdelse pr. juni 2026 - ID'er og indhold ikke endeligt publiceret. Brug BIS Billing 3.0 / EU PINT i mellemtiden.",
|
||||
anvendelse: 'Næste generation der lægger BIS og PINT sammen til ét globalt faktura-format. Forventet 2026, endnu ikke udgivet (pr. juni 2026).',
|
||||
bemaerkninger: "STATUS: under udarbejdelse pr. juni 2026, ID'er og indhold ikke endeligt publiceret. Brug BIS Billing 3.0 / EU PINT i mellemtiden.",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ const { title, description, image, type, publishedTime, modifiedTime, tags, json
|
||||
|
||||
Hej, kildekode-læser. Du er min slags.
|
||||
Statisk Astro, ingen frameworks, self-hosted på Proxmox.
|
||||
Prøv Cmd/Ctrl+K — eller den gamle kode: op op ned ned venstre højre venstre højre B A.
|
||||
Prøv Cmd/Ctrl+K.. eller den gamle kode: op op ned ned venstre højre venstre højre B A.
|
||||
-->`} />
|
||||
<html lang={SITE.lang}>
|
||||
<head>
|
||||
|
||||
@@ -6,7 +6,7 @@ import Base from '../layouts/Base.astro';
|
||||
<p class="mt-4 max-w-2xl text-muted">
|
||||
En lille AI der har læst mit CV og denne side, og svarer på spørgsmål om mig.. fx
|
||||
<em>“hvad har Asger lavet med Peppol?”</em> eller <em>“hvilken stack kører hans homelab?”</em>.
|
||||
Den ved kun noget om mig — alt andet må du google selv.
|
||||
Den ved kun noget om mig.. alt andet må du google selv.
|
||||
</p>
|
||||
|
||||
<div id="chat-log" class="mt-8 space-y-3" aria-live="polite"></div>
|
||||
@@ -17,7 +17,7 @@ import Base from '../layouts/Base.astro';
|
||||
class="flex-1 rounded-xl border border-border bg-surface/60 px-4 py-2.5 outline-none focus:border-accent" />
|
||||
<button type="submit" class="rounded-xl bg-accent px-5 py-2.5 font-medium text-bg transition-transform hover:-translate-y-0.5">Send</button>
|
||||
</form>
|
||||
<p class="mt-3 text-xs text-muted/80">Svar genereres af en sprogmodel ud fra mit offentlige CV — tjek vigtige detaljer med mig direkte.</p>
|
||||
<p class="mt-3 text-xs text-muted/80">Svar genereres af en sprogmodel ud fra mit offentlige CV.. tjek vigtige detaljer med mig direkte.</p>
|
||||
|
||||
<script is:inline>
|
||||
(function () {
|
||||
@@ -27,7 +27,7 @@ import Base from '../layouts/Base.astro';
|
||||
function esc(s) {
|
||||
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||
}
|
||||
// Escape FØRST, linkificér så — rene URL'er og e-mails bliver klikbare, intet HTML slipper igennem.
|
||||
// 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,
|
||||
@@ -66,12 +66,12 @@ import Base from '../layouts/Base.astro';
|
||||
body: JSON.stringify({ messages: history.slice(-10) }),
|
||||
});
|
||||
var data = await r.json();
|
||||
if (!r.ok) { wait.textContent = data.error || 'Chatten er offline lige nu — prøv senere.'; track('afvist', q); return; }
|
||||
if (!r.ok) { wait.textContent = data.error || 'Chatten er offline lige nu.. prøv senere.'; track('afvist', q); return; }
|
||||
wait.innerHTML = linkify(data.reply);
|
||||
history.push({ role: 'assistant', content: data.reply });
|
||||
track('besvaret', q);
|
||||
} catch (_) {
|
||||
wait.textContent = 'Kunne ikke nå chatten — prøv igen om lidt.';
|
||||
wait.textContent = 'Kunne ikke nå chatten.. prøv igen om lidt.';
|
||||
track('fejl', q);
|
||||
} finally { btn.disabled = false; input.focus(); }
|
||||
});
|
||||
|
||||
@@ -2,20 +2,20 @@
|
||||
import Base from '../layouts/Base.astro';
|
||||
|
||||
const stack = [
|
||||
{ k: 'Generator', v: 'Astro 5 — statisk output, view transitions, content collections til bloggen' },
|
||||
{ k: 'Generator', v: 'Astro 5: statisk output, view transitions, content collections til bloggen' },
|
||||
{ k: 'Runtime', v: 'Bun (build og dev)' },
|
||||
{ k: 'CSS', v: 'Tailwind 4 med egne design-tokens; dark/light sat pre-paint uden flash' },
|
||||
{ k: 'Typografi', v: 'Inter Variable, self-hosted woff2 (ingen Google Fonts-kald)' },
|
||||
{ k: 'JS i browseren', v: 'Ingen frameworks. Lidt vanilla til tema-toggle, paletten og service workeren' },
|
||||
{ k: 'PWA', v: 'Workbox service worker — siden virker offline og kan installeres' },
|
||||
{ k: 'PWA', v: 'Workbox service worker, siden virker offline og kan installeres' },
|
||||
{ k: 'Kommentarer', v: 'Comentario, self-hosted, login via min egen Authentik' },
|
||||
{ k: 'Analytics', v: 'Matomo, self-hosted og first-party — ingen tredjeparts-trackere' },
|
||||
{ k: 'Analytics', v: 'Matomo, self-hosted og first-party, ingen tredjeparts-trackere' },
|
||||
{ k: 'Hosting', v: 'Alpine LXC med nginx på min egen Proxmox-node, bag NPMplus som edge' },
|
||||
{ k: 'CI/CD', v: 'Gitea Actions på egne runnere: push til master → build → atomisk swap af webroot' },
|
||||
{ k: 'Struktureret data', v: 'JSON-LD: Person, ProfilePage, FAQ, BlogPosting, BreadcrumbList — plus llms.txt til LLM’er' },
|
||||
{ k: 'Struktureret data', v: 'JSON-LD: Person, ProfilePage, FAQ, BlogPosting, BreadcrumbList, plus llms.txt til LLM’er' },
|
||||
];
|
||||
---
|
||||
<Base title="Kolofon" description="Hvordan denne side er bygget: Astro, Bun, Tailwind, self-hosted alt — og ingen JS-frameworks.">
|
||||
<Base title="Kolofon" description="Hvordan denne side er bygget: Astro, Bun, Tailwind, self-hosted alt, og ingen JS-frameworks.">
|
||||
<h1 class="text-4xl font-bold tracking-tight">Kolofon</h1>
|
||||
<p class="mt-4 max-w-2xl text-muted">
|
||||
Hele kæden fra commit til din skærm kører på udstyr jeg selv drifter. Ingen CDN’er,
|
||||
@@ -38,8 +38,8 @@ const stack = [
|
||||
<section class="mt-10">
|
||||
<h2 class="text-sm font-semibold uppercase tracking-widest text-accent">Sikkerhed</h2>
|
||||
<p class="mt-3 max-w-2xl text-sm text-muted">
|
||||
Fundet noget der ser forkert ud? Skriv til <a class="text-accent hover:underline" href="mailto:asger@weirsoe.dk">asger@weirsoe.dk</a>
|
||||
— der ligger også en <a class="text-accent hover:underline" href="/.well-known/security.txt">security.txt</a> (RFC 9116).
|
||||
Fundet noget der ser forkert ud? Skriv til <a class="text-accent hover:underline" href="mailto:asger@weirsoe.dk">asger@weirsoe.dk</a>.
|
||||
Der ligger også en <a class="text-accent hover:underline" href="/.well-known/security.txt">security.txt</a> (RFC 9116).
|
||||
Og ja, der er en <a class="text-accent hover:underline" href="/humans.txt">humans.txt</a> til de nysgerrige.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
@@ -15,13 +15,13 @@ import Base from '../layouts/Base.astro';
|
||||
<h3 class="font-semibold tracking-tight">Statistik & analyse</h3>
|
||||
<p class="mt-2 text-sm text-muted">
|
||||
Jeg bruger <strong class="text-text">Matomo</strong> til at se hvor mange der besøger siden,
|
||||
og hvordan den bruges, så jeg kan gøre den bedre. Matomo kører på mine egne servere — dine
|
||||
og hvordan den bruges, så jeg kan gøre den bedre. Matomo kører på mine egne servere, dine
|
||||
data bliver <strong class="text-text">ikke delt med tredjeparter</strong> og ikke solgt.
|
||||
</p>
|
||||
<ul class="mt-3 space-y-1 text-sm text-muted">
|
||||
<li><code class="rounded bg-surface-2 px-1.5 py-0.5">_pk_id</code> — et tilfældigt id der tæller dig som samme besøgende over tid (op til 1 år).</li>
|
||||
<li><code class="rounded bg-surface-2 px-1.5 py-0.5">_pk_ses</code> — markerer dit aktuelle besøg (udløber efter ca. 30 minutter).</li>
|
||||
<li><code class="rounded bg-surface-2 px-1.5 py-0.5">WEC_VID</code> — et tilsvarende besøgs-id på mine egne tjenester.</li>
|
||||
<li><code class="rounded bg-surface-2 px-1.5 py-0.5">_pk_id</code>: et tilfældigt id der tæller dig som samme besøgende over tid (op til 1 år).</li>
|
||||
<li><code class="rounded bg-surface-2 px-1.5 py-0.5">_pk_ses</code>: markerer dit aktuelle besøg (udløber efter ca. 30 minutter).</li>
|
||||
<li><code class="rounded bg-surface-2 px-1.5 py-0.5">WEC_VID</code>: et tilsvarende besøgs-id på mine egne tjenester.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -31,8 +31,8 @@ import Base from '../layouts/Base.astro';
|
||||
Husker dine valg på siden. Det er ikke sporing, og det forlader aldrig din browser.
|
||||
</p>
|
||||
<ul class="mt-3 space-y-1 text-sm text-muted">
|
||||
<li><code class="rounded bg-surface-2 px-1.5 py-0.5">theme</code> — dit valgte tema (lyst/mørkt/terminal).</li>
|
||||
<li><code class="rounded bg-surface-2 px-1.5 py-0.5">wec_cookie_ack</code> — husker at du har set denne cookie-besked, så den ikke dukker op igen.</li>
|
||||
<li><code class="rounded bg-surface-2 px-1.5 py-0.5">theme</code>: dit valgte tema (lyst/mørkt/terminal).</li>
|
||||
<li><code class="rounded bg-surface-2 px-1.5 py-0.5">wec_cookie_ack</code>: husker at du har set denne cookie-besked, så den ikke dukker op igen.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,7 @@ const faqs = [
|
||||
},
|
||||
{
|
||||
q: 'Hvem kan rådgive om Peppol og NemHandel i Danmark?',
|
||||
a: 'Det kan jeg. Jeg har arbejdet praktisk med både Peppol og NemHandel — hos CGI, der var leverandør til Erhvervsstyrelsen (ERST) på NemHandel, var jeg med til at udvikle ERST’s open source eDelivery-løsning bygget på Oxalis. I dag arbejder jeg som Technical Solution Architect hos Digisense A/S med løsningsarkitektur inden for elektronisk fakturering.',
|
||||
a: 'Det kan jeg. Jeg har arbejdet praktisk med både Peppol og NemHandel. Hos CGI, der var leverandør til Erhvervsstyrelsen (ERST) på NemHandel, var jeg med til at udvikle ERST’s open source eDelivery-løsning bygget på Oxalis. I dag arbejder jeg som Technical Solution Architect hos Digisense A/S med løsningsarkitektur inden for elektronisk fakturering.',
|
||||
},
|
||||
{
|
||||
q: 'Er Asger Weirsøe radioamatør?',
|
||||
@@ -84,10 +84,10 @@ const jsonLd = [profilePage, faqPage(faqs)];
|
||||
<h2 class="text-2xl font-bold tracking-tight">Mere end et CV</h2>
|
||||
<div class="mt-5 grid gap-4 sm:grid-cols-2">
|
||||
{[
|
||||
{ href: '/nemhandel', title: 'NemHandel-opslag', desc: 'Slå et CVR-nummer op og se om virksomheden er registreret i NemHandelsregisteret — og hvilke profilpakker den understøtter.' },
|
||||
{ href: '/nemhandel', title: 'NemHandel-opslag', desc: 'Slå et CVR-nummer op og se om virksomheden er registreret i NemHandelsregisteret, og hvilke profilpakker den understøtter.' },
|
||||
{ href: '/chat', title: 'Spørg mit CV', desc: 'En lille AI der har læst mit CV og svarer på spørgsmål om mig. Prøv den af.' },
|
||||
{ href: '/status', title: 'Homelab-status', desc: 'Live driftsstatus for de offentlige dele af mit homelab. Self-hosted, selvfølgelig.' },
|
||||
{ href: '/now', title: 'Now', desc: 'Hvad jeg roder med lige nu — plus et aktivitets-heatmap fra min egen Gitea.' },
|
||||
{ href: '/now', title: 'Now', desc: 'Hvad jeg roder med lige nu, plus et aktivitets-heatmap fra min egen Gitea.' },
|
||||
].map((c) => (
|
||||
<a href={c.href} class="group rounded-2xl border border-border bg-surface/60 p-5 transition-colors hover:border-accent">
|
||||
<h3 class="font-semibold tracking-tight group-hover:text-accent">{c.title} →</h3>
|
||||
@@ -95,7 +95,7 @@ const jsonLd = [profilePage, faqPage(faqs)];
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
<p class="mt-3 text-xs text-muted/80">Pro-tip: tryk <kbd class="rounded border border-border bg-surface-2 px-1.5 py-0.5 font-mono text-[0.7rem]">Ctrl/⌘ K</kbd> og hop direkte til alt — eller <code class="rounded bg-surface-2 px-1.5 py-0.5">curl asger.weirsøe.dk</code> i en terminal.</p>
|
||||
<p class="mt-3 text-xs text-muted/80">Pro-tip: tryk <kbd class="rounded border border-border bg-surface-2 px-1.5 py-0.5 font-mono text-[0.7rem]">Ctrl/⌘ K</kbd> og hop direkte til alt, eller <code class="rounded bg-surface-2 px-1.5 py-0.5">curl asger.weirsøe.dk</code> i en terminal.</p>
|
||||
</section>
|
||||
|
||||
<section class="mt-16">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
import Base from '../layouts/Base.astro';
|
||||
---
|
||||
<Base title="NemHandel-opslag" description="Slå et CVR-nummer op og se om virksomheden er registreret i NemHandelsregisteret — og hvilke profilpakker den understøtter.">
|
||||
<Base title="NemHandel-opslag" description="Slå et CVR-nummer op og se om virksomheden er registreret i NemHandelsregisteret, og hvilke profilpakker den understøtter.">
|
||||
<h1 class="text-4xl font-bold tracking-tight">NemHandel-opslag</h1>
|
||||
<p class="mt-4 max-w-2xl text-muted">
|
||||
Tast et CVR-nummer og se om virksomheden er registreret i NemHandelsregisteret, og hvilke
|
||||
@@ -66,7 +66,7 @@ import Base from '../layouts/Base.astro';
|
||||
' · <span class="font-mono text-xs">' + esc(d.participant_id || '') + '</span>' + (d.reg_date ? ' · reg. ' + esc(d.reg_date) : '') + '</p>' +
|
||||
'<p class="mt-4 text-xs font-semibold uppercase tracking-widest text-accent">Kan modtage</p>' +
|
||||
'<div class="mt-2 flex flex-wrap gap-2">' + (docs || '<span class="text-sm text-muted">ingen dokumenttyper</span>') + '</div>' +
|
||||
'<p class="mt-3 text-xs text-muted/80">Live fra Peppol Directory via egen proxy — intet gemt.</p></div>';
|
||||
'<p class="mt-3 text-xs text-muted/80">Live fra Peppol Directory via egen proxy, intet gemt.</p></div>';
|
||||
} catch (_) {
|
||||
box.innerHTML = '<div class="rounded-2xl border border-border bg-surface/60 p-5"><p class="text-sm text-muted">Kunne ikke nå Peppol-opslaget.</p></div>';
|
||||
}
|
||||
@@ -81,7 +81,7 @@ import Base from '../layouts/Base.astro';
|
||||
try {
|
||||
var r = await fetch('/api/nemhandel/' + encodeURIComponent(cvr));
|
||||
var data = await r.json();
|
||||
if (!r.ok) { err.textContent = data.error || 'Noget gik galt — prøv igen.'; err.hidden = false; return; }
|
||||
if (!r.ok) { err.textContent = data.error || 'Noget gik galt.. prøv igen.'; err.hidden = false; return; }
|
||||
document.getElementById('pep-name').textContent = data.name || 'Ukendt navn';
|
||||
document.getElementById('pep-cvr-line').textContent = 'CVR ' + data.cvr;
|
||||
var badge = document.getElementById('pep-badge');
|
||||
@@ -104,13 +104,13 @@ import Base from '../layouts/Base.astro';
|
||||
}
|
||||
res.hidden = false;
|
||||
} catch (_) {
|
||||
err.textContent = 'Kunne ikke nå opslagstjenesten — prøv igen om lidt.'; err.hidden = false;
|
||||
err.textContent = 'Kunne ikke nå opslagstjenesten.. prøv igen om lidt.'; err.hidden = false;
|
||||
} finally { btn.disabled = false; btn.textContent = 'Slå op'; }
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
<p class="mt-10 text-xs text-muted/80">
|
||||
Til nørderne: API’et er frit tilgængeligt — <code class="rounded bg-surface-2 px-1.5 py-0.5">curl https://asger.weirsøe.dk/api/nemhandel/<cvr></code> (rate-limited).
|
||||
Til nørderne: API’et er frit tilgængeligt: <code class="rounded bg-surface-2 px-1.5 py-0.5">curl https://asger.weirsøe.dk/api/nemhandel/<cvr></code> (rate-limited).
|
||||
</p>
|
||||
</Base>
|
||||
|
||||
+4
-4
@@ -2,14 +2,14 @@
|
||||
import Base from '../layouts/Base.astro';
|
||||
import { SITE } from '../consts';
|
||||
|
||||
// Hvad jeg roder med lige nu — opdateres manuelt, det er hele pointen med en /now-side.
|
||||
// Hvad jeg roder med lige nu, opdateres manuelt, det er hele pointen med en /now-side.
|
||||
const focus = [
|
||||
'Elektronisk fakturering hos Digisense: Peppol, NemHandel og løsningsarkitektur',
|
||||
'HD 1. del i Erhvervsøkonomi på AAU (eksamener til sommer)',
|
||||
'Homelab: crawlkit, denne side, og alt for mange LXC-containere',
|
||||
];
|
||||
|
||||
// Build-time: aktivitets-heatmap fra min Gitea (offentligt API). Fejler stille —
|
||||
// Build-time: aktivitets-heatmap fra min Gitea (offentligt API). Fejler stille,
|
||||
// siden bygger fint uden graf hvis Gitea er nede under build.
|
||||
type Beat = { timestamp: number; contributions: number };
|
||||
let perDay = new Map<string, number>();
|
||||
@@ -40,7 +40,7 @@ const level = (n: number) => (n === 0 ? 0 : n < 3 ? 1 : n < 6 ? 2 : n < 12 ? 3 :
|
||||
const total = [...perDay.values()].reduce((a, b) => a + b, 0);
|
||||
const updated = today.toLocaleDateString('da-DK', { year: 'numeric', month: 'long', day: 'numeric' });
|
||||
---
|
||||
<Base title="Now" description="Hvad jeg arbejder på lige nu — plus et aktivitets-heatmap fra min self-hostede Gitea.">
|
||||
<Base title="Now" description="Hvad jeg arbejder på lige nu, plus et aktivitets-heatmap fra min self-hostede Gitea.">
|
||||
<h1 class="text-4xl font-bold tracking-tight">Now</h1>
|
||||
<p class="mt-2 text-sm text-muted">Senest opdateret {updated} · à la <a class="text-accent hover:underline" href="https://nownownow.com/about" target="_blank" rel="noopener">nownownow.com</a></p>
|
||||
|
||||
@@ -56,7 +56,7 @@ const updated = today.toLocaleDateString('da-DK', { year: 'numeric', month: 'lon
|
||||
{weeks.length > 0 && (
|
||||
<section class="mt-10">
|
||||
<h2 class="text-sm font-semibold uppercase tracking-widest text-accent">Git-aktivitet</h2>
|
||||
<p class="mt-2 text-sm text-muted">{total} bidrag i mit eget Gitea det seneste år — de seneste {WEEKS} uger:</p>
|
||||
<p class="mt-2 text-sm text-muted">{total} bidrag i mit eget Gitea det seneste år, de seneste {WEEKS} uger:</p>
|
||||
<div class="mt-4 overflow-x-auto rounded-2xl border border-border bg-surface/60 p-4">
|
||||
<div class="heatmap" role="img" aria-label="Aktivitets-heatmap over git-bidrag">
|
||||
{weeks.map((w) => (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
// Gammel rute — omdøbt til /nemhandel. Redirect så eksisterende links ikke 404'er.
|
||||
// Gammel rute, omdøbt til /nemhandel. Redirect så eksisterende links ikke 404'er.
|
||||
---
|
||||
<!doctype html>
|
||||
<html lang="da">
|
||||
|
||||
@@ -7,7 +7,7 @@ const searchString = (p: (typeof profiles)[number]) =>
|
||||
.join(' ')
|
||||
.toLowerCase();
|
||||
|
||||
// Registerprofilerne af "single"-typen står ikke i G26 — dem henviser vi til registret for.
|
||||
// Registerprofilerne af "single"-typen står ikke i G26, dem henviser vi til registret for.
|
||||
const kunIRegistret = new Set(['Procurement-OrdRes-1.0', 'Procurement-BilSimReminderOnly-1.0']);
|
||||
|
||||
const kilde = (p: (typeof profiles)[number]) => {
|
||||
@@ -18,12 +18,12 @@ const kilde = (p: (typeof profiles)[number]) => {
|
||||
if (p.standard.includes('PINT'))
|
||||
return p.navn.includes('(kommende)')
|
||||
? { label: 'Peppol roadmap', url: 'https://docs.peppol.eu/poac/' }
|
||||
: { label: 'docs.peppol.eu \u2014 EU PINT Billing', url: 'https://docs.peppol.eu/poac/eu/pint-eu/' };
|
||||
: { label: 'docs.peppol.eu \u00b7 EU PINT Billing', url: 'https://docs.peppol.eu/poac/eu/pint-eu/' };
|
||||
if (p.navn.includes('Self-Billing'))
|
||||
return { label: 'docs.peppol.eu \u2014 Self-Billing 3.0', url: 'https://docs.peppol.eu/poacc/self-billing/3.0/' };
|
||||
return { label: 'docs.peppol.eu \u00b7 Self-Billing 3.0', url: 'https://docs.peppol.eu/poacc/self-billing/3.0/' };
|
||||
if (p.navn.includes('Billing 3.0'))
|
||||
return { label: 'docs.peppol.eu \u2014 BIS Billing 3.0', url: 'https://docs.peppol.eu/poacc/billing/3.0/' };
|
||||
return { label: 'docs.peppol.eu \u2014 BIS v3', url: 'https://docs.peppol.eu/poacc/upgrade-3/' };
|
||||
return { label: 'docs.peppol.eu \u00b7 BIS Billing 3.0', url: 'https://docs.peppol.eu/poacc/billing/3.0/' };
|
||||
return { label: 'docs.peppol.eu \u00b7 BIS v3', url: 'https://docs.peppol.eu/poacc/upgrade-3/' };
|
||||
};
|
||||
---
|
||||
<Base
|
||||
@@ -33,7 +33,7 @@ const kilde = (p: (typeof profiles)[number]) => {
|
||||
<h1 class="text-4xl font-bold tracking-tight">Profil-opslag</h1>
|
||||
<p class="mt-4 max-w-2xl text-muted">
|
||||
Browse og søg i e-dokumentprofilerne for <strong class="text-text">Nemhandel OIOUBL</strong> og
|
||||
<strong class="text-text">Peppol BIS/PINT</strong> — profil-/proces-id, customization-id, hvilke
|
||||
<strong class="text-text">Peppol BIS/PINT</strong>: profil-/proces-id, customization-id, hvilke
|
||||
dokumenter profilen indeholder og typisk anvendelse. Klik på et id for at kopiere det.
|
||||
</p>
|
||||
<p class="mt-3 max-w-2xl text-sm text-muted">
|
||||
@@ -132,7 +132,7 @@ const kilde = (p: (typeof profiles)[number]) => {
|
||||
Kilder: OIOUBL Profiler-guiden (G26) v1.3 (dokumentlister, tabel 1-3), Nemhandelsregistret
|
||||
(gruppering og profilnavne) og Peppol BIS/PINT (docs.peppol.eu). * = ApplicationResponse bruges kun
|
||||
til afvisning; det forretningsmæssige svar på en ordre er altid OrderResponse/OrderResponseSimple.
|
||||
Øjebliksbillede — verificér altid id'er mod den officielle dokumentation før brug.
|
||||
Øjebliksbillede.. verificér altid id'er mod den officielle dokumentation før brug.
|
||||
</p>
|
||||
|
||||
<style is:inline>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import Base from '../layouts/Base.astro';
|
||||
const STATUS_URL = 'https://status.weircon.dk/status/weircon';
|
||||
---
|
||||
<Base title="Status" description="Live driftsstatus for mit homelab — self-hosted Uptime Kuma, selvfølgelig.">
|
||||
<Base title="Status" description="Live driftsstatus for mit homelab.. self-hosted Uptime Kuma, selvfølgelig.">
|
||||
<h1 class="text-4xl font-bold tracking-tight">Status</h1>
|
||||
<p class="mt-4 max-w-2xl text-muted">
|
||||
Live status for de offentlige dele af mit homelab, målt af en self-hosted
|
||||
|
||||
+7
-7
@@ -13,12 +13,12 @@ const idx = profiles.map((p) => ({
|
||||
---
|
||||
<Base
|
||||
title="UBL-tjek & identifikator-afkoder"
|
||||
description="Træk en UBL/OIOUBL-faktura ind eller indsæt en CustomizationID/ProfileID — så afkoder den profilen, syntaksen og EN 16931-status. Alt sker lokalt i browseren; filen sendes aldrig nogen steder."
|
||||
description="Træk en UBL/OIOUBL-faktura ind eller indsæt en CustomizationID/ProfileID, så afkoder den profilen, syntaksen og EN 16931-status. Alt sker lokalt i browseren; filen sendes aldrig nogen steder."
|
||||
>
|
||||
<h1 class="text-4xl font-bold tracking-tight">UBL-tjek</h1>
|
||||
<p class="mt-4 max-w-2xl text-muted">
|
||||
Træk en <strong class="text-text">UBL/OIOUBL-faktura</strong> (eller andet UBL-dokument) ind — eller indsæt en
|
||||
<strong class="text-text">CustomizationID/ProfileID</strong> — så afkoder den profilen, syntaksen og
|
||||
Træk en <strong class="text-text">UBL/OIOUBL-faktura</strong> (eller andet UBL-dokument) ind, eller indsæt en
|
||||
<strong class="text-text">CustomizationID/ProfileID</strong>, så afkoder den profilen, syntaksen og
|
||||
EN 16931-status og kobler til <a href="/profiler" class="text-accent">profil-opslaget</a>.
|
||||
Alt sker <strong class="text-text">lokalt i din browser</strong>; intet sendes nogen steder.
|
||||
</p>
|
||||
@@ -54,7 +54,7 @@ const idx = profiles.map((p) => ({
|
||||
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) {
|
||||
return { '&': '&', '<': '<', '>': '>', '"': '"' }[c]; }); };
|
||||
|
||||
// Electronic Address Scheme (ISO 6523) — de gængse, DK/Norden i fokus.
|
||||
// Electronic Address Scheme (ISO 6523): de gængse, DK/Norden i fokus.
|
||||
var EAS = {
|
||||
'0088': 'GLN (GS1 Global Location Number)',
|
||||
'0184': 'DK:CVR (dansk CVR-nummer)',
|
||||
@@ -91,7 +91,7 @@ const idx = profiles.map((p) => ({
|
||||
if (blob.indexOf('pint') > -1) { standard = 'Peppol PINT'; notes.push('PINT (Peppol International)'); }
|
||||
if (blob.indexOf('billing:3.0') > -1) notes.push('Billing 3.0-proces');
|
||||
if (blob.indexOf('selfbilling') > -1) notes.push('Selvfakturering (køber udsteder)');
|
||||
if (blob.indexOf('oioubl') > -1) { standard = standard || 'OIOUBL (NemHandel)'; notes.push('OIOUBL — dansk UBL-tilpasning'); }
|
||||
if (blob.indexOf('oioubl') > -1) { standard = standard || 'OIOUBL (NemHandel)'; notes.push('OIOUBL, dansk UBL-tilpasning'); }
|
||||
if (/procurement-/i.test(p)) { standard = standard || 'OIOUBL (NemHandel)'; if (/r-|r$|simr|advr/i.test(p)) notes.push("'R' = svar påkrævet"); }
|
||||
|
||||
return { match: match, standard: match ? match.standard : standard, notes: notes };
|
||||
@@ -146,7 +146,7 @@ const idx = profiles.map((p) => ({
|
||||
(dec.notes.length ? '<div class="mt-3 flex flex-wrap gap-1.5">' + dec.notes.map(function (n) { return badge(n, ''); }).join('') + '</div>' : '') +
|
||||
(epHtml ? '<p class="mt-3 text-xs text-muted">Parter (EAS):</p><div class="mt-1 space-y-1">' + epHtml + '</div>' : '') +
|
||||
(dec.match ? '<p class="mt-3 text-xs"><a class="text-accent hover:underline" href="/profiler?q=' + encodeURIComponent(dec.match.id) + '">Se profilen i /profiler ↗</a></p>'
|
||||
: '<p class="mt-3 text-xs text-muted">Ingen eksakt match i profil-databasen — afkodet ud fra mønstre.</p>') +
|
||||
: '<p class="mt-3 text-xs text-muted">Ingen eksakt match i profil-databasen, afkodet ud fra mønstre.</p>') +
|
||||
'</div>';
|
||||
result.hidden = false; err.hidden = true;
|
||||
}
|
||||
@@ -171,7 +171,7 @@ const idx = profiles.map((p) => ({
|
||||
if (text.indexOf('<') === 0 || text.indexOf('<?xml') === 0) {
|
||||
var doc = new DOMParser().parseFromString(text, 'application/xml');
|
||||
if (doc.getElementsByTagName('parsererror').length) {
|
||||
err.textContent = 'Kunne ikke parse XML — er filen velformet?'; err.hidden = false; result.hidden = true; return;
|
||||
err.textContent = 'Kunne ikke parse XML.. er filen velformet?'; err.hidden = false; result.hidden = true; return;
|
||||
}
|
||||
renderXml(doc);
|
||||
} else {
|
||||
|
||||
@@ -5,9 +5,9 @@ const sections = [
|
||||
{
|
||||
title: 'Homelab',
|
||||
items: [
|
||||
{ name: 'Proxmox VE', note: 'Hypervisor på egen hardware. ~50 LXC-containere og et par KVM-VM’er — én tjeneste pr. container.' },
|
||||
{ name: 'Proxmox VE', note: 'Hypervisor på egen hardware. ~50 LXC-containere og et par KVM-VM’er, én tjeneste pr. container.' },
|
||||
{ name: 'NPMplus', note: 'Reverse proxy og TLS-terminering på kanten. Alt trafik ind går her igennem.' },
|
||||
{ name: 'Authentik', note: 'Self-hosted SSO (OIDC/LDAP). Én identitet til alle tjenester — bygget fra source.' },
|
||||
{ name: 'Authentik', note: 'Self-hosted SSO (OIDC/LDAP). Én identitet til alle tjenester, bygget fra source.' },
|
||||
{ name: 'Gitea + Gitea Actions', note: 'Egen git-hosting og CI/CD. Denne side deployes automatisk ved push.' },
|
||||
{ name: 'MariaDB / Redis / PostgreSQL', note: 'Databaser som dedikerede containere, host-pinned brugere og det hele.' },
|
||||
{ name: 'Matomo', note: 'Self-hosted analytics, first-party og uden tredjeparter.' },
|
||||
@@ -19,7 +19,7 @@ const sections = [
|
||||
items: [
|
||||
{ name: 'Linux + code-server', note: 'Udvikling foregår i en dedikeret LXC med VS Code i browseren.' },
|
||||
{ name: 'Java · Go · Python · TypeScript', note: 'Arbejdshestene. Java til Peppol/eDelivery-verdenen, Python/TS til alt det andet.' },
|
||||
{ name: 'Claude Code', note: 'LLM-drevne workflows — fra blogindlæg til Proxmox-administration.' },
|
||||
{ name: 'Claude Code', note: 'LLM-drevne workflows, fra blogindlæg til Proxmox-administration.' },
|
||||
{ name: 'Docker', note: 'Hvor det giver mening. Ellers foretrækker jeg native installationer i LXC.' },
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user