Commit Graph

8 Commits

Author SHA1 Message Date
Jörg Lohrer 10e455a078 spa: startseite + archiv + impressum + menü + assets für cutover
Startseite (+page.svelte) komplett überarbeitet:
  - Hero mit lokalem Profilbild (WebP aus static/, schneller als
    kind:0-roundtrip), Begrüßung "Hi Willkommen auf meinem Blog 🤗",
    About/Website aus kind:0
  - Social-Icons-Leiste (Nostr/Mastodon/Bluesky/LinkedIn/ORCID/Mail)
    als inline-SVG, monochrom via currentColor, hover färbt blau
  - Nostr-Icon von satscoffee/nostr_icons (outline, CC0), die anderen
    stilisiert als vereinfachte Brand-Icons
  - Neueste 5 Posts + Archiv-Link

Archiv-Route (/archiv/): alle Posts, nach Jahr gruppiert.

Impressum (/impressum/): static-page, rendert content/impressum.md
(via vite ?raw-import), bleibt aus nostr-feeds draußen. Frontmatter-
parser toleriert trailing-spaces auf --- zeilen.

Menü im Layout: sticky header mit brand + 3 links (Home, Archiv,
Impressum), aktiv-state via akzent-farbe. Footer mit © + Impressum
+ "Nostr-basiert"-hinweis.

Assets: profilbild und favicons aus dem hugo-static (repo-root) nach
app/static/ übernommen, favicon-links in app.html ergänzt.

NIP-05: .well-known/nostr.json in app/static angelegt mit CORS-header
via .htaccess, damit "joerglohrer@joerg-lohrer.de" nach cutover
verifizierbar bleibt.

E2E-Tests angepasst an neue hero/navigation-struktur, 29/29 unit + 4/4
e2e grün.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 15:35:05 +02:00
Jörg Lohrer 3b0f059cea spa(phase 5, tasks 26-32): reactions, replies, nip-07 kommentare, e2e
Neue Komponenten unter $lib/components/:
- Reactions.svelte: lädt kind:7-Aggregation via loadReactions, rendert
  Chips mit Emoji + Count. +/- werden zu 👍/👎 gemappt.
- ReplyItem.svelte: einzelner Kommentar mit Author-Npub-Prefix + Datum.
- ReplyList.svelte: lädt kind:1-Replies, merged mit optimistic-Props
  (dedup per id), sortiert chronologisch.
- ReplyComposer.svelte: Textarea + Senden-Button. Nutzt NIP-07-Wrapper
  (getPublicKey, signEvent), baut kind:1-Event mit a/e/p-Tags, pusht
  via pool.publish() zu allen Read-Relays. Fehlertolerant: zeigt
  Hinweis, wenn NIP-07-Extension fehlt.

Integration in PostView: Reactions, Composer, ReplyList unterhalb des
Artikel-Bodys. Optimistisches Reply-Pattern: Composer.onPublished
pushed signed event in PostView-local $state, ReplyList merged mit
fetched events.

Playwright-E2E:
- playwright.config.ts mit Dev-Server-Auto-Start
- home.test.ts: Profil + Beitragsliste sichtbar
- post.test.ts: Titel + Body + Legacy-URL-Redirect

Alle 3 E2E-Tests grün. npm run check: 600 files, 0 errors.
Deploy live auf svelte.joerg-lohrer.de (Phase 5 inklusive).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 17:51:57 +02:00
Jörg Lohrer ec9d361a13 spa(task 7 polish): scoped marked-instance, ssr-guard, erweiterte xss-tests
- Eigene `new Marked({...})`-Instanz statt globaler `marked.use()`-Mutation
  — schützt andere Module vor Konfigurationsleckage, schärft Spec §3
  ("lokale Ersetzbarkeit").
- SSR-Guard: `renderMarkdown` wirft in Non-DOM-Umgebungen eine
  Fehlermeldung statt stumm unsicher durchzulaufen. SPA hat `ssr=false`,
  Vitest läuft in jsdom — Guard ist Early-Fail für versehentliche
  Node-Aufrufe.
- `ADD_ATTR: ['target', 'rel']` entfernt — war ein No-Op, weil Marked
  diese Attribute nicht einfügt. Link-Attribut-Hardening kommt später,
  wenn externe Links tatsächlich `target="_blank"` bekommen sollen.
- Code-Block-Test prüft zusätzlich `class="hljs"` (Regression-Anker
  für Custom-Renderer).
- Erweiterte XSS-Matrix: onerror, onclick, iframe, data:text/html,
  vbscript:, svg+script — relevant für spätere Reply-Darstellung.

14/14 Tests grün.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 16:06:51 +02:00
Jörg Lohrer 2bcb2451b4 spa: markdown-renderer mit sanitize (tdd) 2026-04-15 16:03:04 +02:00
Jörg Lohrer 1fb77669e6 spa(task 5 polish): jsdoc auf naddr-helpers, coverage-lücken geschlossen
- JSDoc zu NaddrArgs, buildNaddr, buildHablaLink (Stil konsistent mit config.ts).
- Neue Tests: ohne relays (Default-`?? []`-Pfad), unterschiedliche Inputs
  erzeugen unterschiedliche Links (Guard gegen konstanten Rückgabewert).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:21:36 +02:00
Jörg Lohrer c539c4fee3 spa: naddr/habla-link-helper (tdd) 2026-04-15 15:18:41 +02:00
Jörg Lohrer 36dd76a88f spa(task 4 polish): decodeURIComponent crash-safe, edge-case-tests
- decodeURIComponent in try/catch (malformed URI encoding crasht
  den SPA-Boot-Path nicht mehr, returned stattdessen null).
- JSDoc präzisiert: erwartet nur Pfad ohne Query/Fragment.
- Neue Tests: malformed %E0 → null, leerer dtag → null,
  round-trip Legacy → canonical.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:17:38 +02:00
Jörg Lohrer 47decd9b70 spa: url-parser für legacy-hugo-urls (tdd) 2026-04-15 15:14:35 +02:00