5255cdce06
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 15376d4ac2 |
#135 Seiten-Einbettung ![[Seite]] (Transklusion) im Lesemodus
Obsidian-Syntax `![[slug]]` (optional `![[slug|Anzeige]]`) als Seiten- Einbettung. Im Lese- und öffentlichen Modus wird der Inhalt der Zielseite inline gerendert; im Editier-Modus zeigt die NodeView eine Platzhalter- Karte (Titel + Öffnen-Link). Shared (Vorbild plugin_block): - Neuer Block-Atom-Node `transclusion` (targetSlug + optional displayText). - Markdown: Block-Regel für eine reine `![[…]]`-Zeile (vor `paragraph` registriert; mitten im Absatz greift sie bewusst nicht), Token→Node- Mapping, Serializer — Round-Trip stabil. - html.ts: Platzhalter `<div class="dt-transclusion" data-transclusion>`. - extractWikilinkSlugs erfasst jetzt auch Transklusionen → Einbettung zählt als Backlink/Graph-Kante. Backend (zentraler Render-Pfad): - PublicService expandiert Platzhalter zur gerenderten Body-HTML der Zielseite: SELBER Pond, read-permission-geprüft, Tiefe ≤2 + Zyklen- Guard (visited); Fehlend/unlesbar/zyklisch → neutraler Wikilink. Medien werden EINMAL über den ganzen Baum aufgelöst (kein Doppel-Processing). - Neuer authentifizierter Endpoint GET /read/:pondSlug/:pageSlug (nicht @Public) liefert dieselbe gerenderte HTML — für die NodeView im authentifizierten Lesemodus, auch bei nicht-öffentlichen Seiten. Web: - NodeView `transclusion.tsx`: Editier-Modus → Karte; Lesemodus → holt /read/:pond/:slug und rendert den (server-sanitisierten) Inhalt inline. - WikilinkAutocomplete unterstützt `![[` → fügt einen Transklusions-Block ein (statt Wikilink). - CSS für Karte (.dt-transclusion-card) und Embed (.dt-embed), i18n de+en. Tests: shared Round-Trip-Unit (5), public-DB-Test um Embed-Expansion (zyklus-sicher, Fehlend→Link) erweitert — grün. typecheck/lint/i18n grün. Visuelle Editor-Verifikation folgt auf dem Test-Stage. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0155v2aT8AG1kZDQEZiCLBWC |
|||
| f014a61480 |
#133 Kommentare fest inline im Lesemodus (Slide-in-Panel ablösen)
Kommentare erscheinen jetzt fest im Lesefluss zwischen Backlinks und lokalem Graph statt in einem ein-/ausblendbaren Panel. Der Kopfleisten-Toggle (Icon + Unread-Badge) entfällt. Frontend: - CommentsPanel → CommentsSection (Inline-Sektion, ohne Panel-Chrome/ Close-Knopf; markiert beim Sichtbarwerden als gelesen). Neue Read-only-Variante PublicComments für die anonyme öffentliche Ansicht. - Umzug auf die äußere Ebene in PageEditorPage (view-Modus, zwischen BacklinksPanel und LocalGraphPanel). Das Schreibrecht (collab rw) wird per onWriteAccess aus dem inneren PageEditor hochgereicht, damit die äußere Ebene den Composer bei commentPolicy=editors korrekt zeigt/ verbirgt. - Deep-Link ?comments=1 scrollt jetzt zur Inline-Sektion statt ein Panel zu öffnen. Resolve/Unresolve-Knöpfe zusätzlich an mayComment gekoppelt (früher nur an isRoot) — Leser sehen keine 403-Knöpfe mehr; Read-only blendet alle Aktions-Controls aus. - CSS comments-panel* → comments-section*; tote Unread-Badge-Regeln raus. Backend: - GET /public/:pondSlug/:pageSlug/comments (@Public), read-only. Nutzt den vorhandenen resolve()-Pfad (erzwingt ggf. anonymen Lesezugriff → nicht öffentliche Seiten 404en) und CommentsService.list. PublicModule importiert CommentsModule. Tests: public.e2e.db.test.ts um anonymen Kommentar-Lesezugriff + 404-Fälle ergänzt (grün gegen frische Test-DB); comments.spec.ts auf die Inline-UI umgestellt. typecheck/lint/i18n:check grün. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0155v2aT8AG1kZDQEZiCLBWC |
|||
| 9e8ebfe49c |
Degrade plugin content gracefully in HTML, PDF, and office exports (#79)
All checks were successful
CI / Lint, typecheck, test (push) Successful in 2m57s
CD / Promote to Int (push) Successful in 9s
CI / Auth e2e pack (push) Successful in 5m2s
CI / Import/export fidelity gate (push) Successful in 46s
CI / Build container images (push) Has been skipped
CD / Build and push images (push) Successful in 3m10s
CD / Deploy to Test (push) Successful in 14s
CD / Smoke tests against Test (push) Successful in 1m12s
Completes M7: exports and the public read view no longer show raw plugin placeholders (ADR 0008/0009). - PluginFallbackRenderer (api): replaces each plugin-block placeholder in content-cache HTML with its best static form — the block's stored SVG snapshot (block data is author-controlled, so it passes the same DOMPurify sanitizer as uploaded SVG files before entering host HTML), else the manifest fallback from the stored snapshot (text, or an image inlined as a data URI so network-isolated renderers work; tombstone-safe for uninstalled plugins), else the literal '[plugin content]' marker. - Office exports (docx/odt): the export markdown is degraded before pandoc — GFM knows neither the dorfteich-plugin fence nor the section fenced div, so blocks become their fallback text and sections plain quoted blocks (shared replacePluginNodesForExport, AST-level so nesting and embedded blocks inside sections survive). - PDF export applies the HTML fallback pass before building the Gotenberg document — resolving the TODO left in #67. - Public read view: the same fallback pass plus the pond's active section-style CSS inlined as a <style> block, so public pages show styled sections and static plugin content without any plugin runtime. - Covered in export.service.db.test (snapshot SVG sanitized — hostile <script> stripped; manifest text; tombstone text; quoted sections and no fence artifacts in the pandoc input) and shared export-fallbacks tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1 |
|||
| fc41c91003 |
Add public read access and server-rendered page HTML (#56)
All checks were successful
CD / Build and push images (push) Successful in 3m13s
CI / Lint, typecheck, test (push) Successful in 2m30s
CI / Auth e2e pack (push) Successful in 3m21s
CI / Build container images (push) Has been skipped
CD / Deploy to Test (push) Successful in 9s
CD / Smoke tests against Test (push) Successful in 1m13s
CD / Promote to Int (push) Successful in 11s
Anonymous visitors read what `public` grants allow, via the SPA and a server-rendered HTML endpoint for crawlers / PDF export (ADR 0005/0009). - api `public/`: `GET /public/:pondSlug/:pageSlug` returns a self-contained HTML document (content cache + minimal chrome + canonical link, no session-dependent content), and `…/content` returns JSON for the SPA. Both are `@Public()` and resolve the `public` subject through the shared resolver (PermissionService) — denied or missing → 404, so non-public pages never reveal their existence (security.md). Cached image nodes (`data-file-id`) are resolved to `/api/v1/media/:fileId` for the static render. - media: `GET /media/:fileId` is `@Public()` too, so embedded images on a public page stream to anonymous visitors; the attachment guard still gates on the `public` grant (non-public → 404). - web: a lightweight read-only `PublicPageView` at `/public/:pondSlug/:pageSlug` (outside the auth guard) renders the server HTML — deliberately without importing the collaborative editor, so anonymous readers load no editor bundle. New `public` i18n namespace (de+en). - tests: `public.e2e.db.test.ts` (HTML + JSON served for a public page; a non-public page never resolves; removing the grant 404s both) and a browser `public` pack (anonymous reads a public page and its image via the SPA; a non-public page shows "not found") with its own CI step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1 |