Files
Archivum/RENDERING_IMPROVEMENTS.md
Bjorn Blomberg cd588197b9
All checks were successful
build-and-push / build (push) Successful in 15m15s
feat: Authentik OIDC SSO, allow/deny RBAC, admin console & Gitea CI
Authentication & RBAC
- Add confidential OIDC client (Authentik) with /auth/oidc/login +
  /auth/oidc/callback: discovery, code exchange, id_token verify (go-oidc),
  groups claim → role (Archivum-admin → admin, else user). Sessions carry groups.
- Rework ACL into an allow/deny model (new `effect` column + migration).
  db.EffectiveAccess resolves user + all groups over the path and its ancestors:
  default deny, explicit deny always beats allow.
- Enforce ACL for ALL non-admin users (not just guest) across list/read/save/
  delete/move/create/history/diff/images/upload. Admins bypass.
- Seed built-in Archivum-admin / Archivum-reader groups; login allow-list on
  users & groups; public (guest) user access is ACL-configurable.

Admin API & UI
- New GraphQL ops: oidcConfig/updateOidcConfig, group CRUD, membership,
  setUserRole/setUserLogin/setGroupLogin, userGroups, loginOptions.
- Rebuilt AdminView: SSO config, user/group management + membership, login
  toggles, and an allow/deny access-control matrix per path.
- LoginView: "Sign in with Authentik" + public-user option; OIDC callback route.

Rendering/editor
- Fix bug where inline marks (bold/italic/code/strike/link) were dropped on
  TipTap→AsciiDoc save. Add RENDERING_IMPROVEMENTS.md with proposals.

CI / build
- .gitea/workflows/build.yaml: build on the Pi5 runner, push
  localhost:5000/archivum:{latest,<sha>}. Add .dockerignore; bump Go image to 1.25.
- Docs: ARCHITECTURE.md, README.md, docs/AUTHENTIK_SETUP.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 21:58:50 +02:00

121 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Förbättringsförslag — rendering & editor
Genomgång av renderings- och editorlagret (`frontend/src/bridge/*`,
`components/editor/*`) med konkreta, prioriterade förslag. En bekräftad bugg är
redan åtgärdad i denna gren (se punkt 0).
---
## 0. ÅTGÄRDAD bugg: inline-formatering tappades vid sparning
I `asciidoc-bridge.ts → renderTextNodes` byggdes den markerade strängen
(`*fet*`, `_kursiv_`, `` `kod` ``, länkar) men **lades aldrig till utdata** — i
stället lades den *omarkerade* texten till i ett andra `if`-block. Följd: all
inline-formatering försvann tyst varje gång ett dokument sparades från den
visuella editorn. Nu appliceras och skrivs marks korrekt (en enda gång).
> Rekommendation: lägg ett litet round-trip-test (`adoc → toTipTap → fromTipTap`)
> som CI-steg så att den här klassen av regressioner fångas automatiskt.
---
## 1. Round-trip-modellen är den största risken
Idag är flödet vid varje sparning:
```
.adoc ──asciidoctor.convert──▶ HTML ──generateJSON──▶ TipTap-JSON
▲ │
└─────────── fromTipTap (handskriven) ◀──────────────────┘
```
Två lossy konverteringar i rad. Allt som TipTap-schemat inte känner till
(attribut, `ifdef`/`ifeval`, `:attribut:`-definitioner, block-roller, kommentarer,
tabellformat, korsreferenser) går förlorat så fort man öppnar och sparar i den
visuella vyn.
**Förslag (välj en):**
- **A. Källan är sanningen.** Behandla `.adoc` som master. Visuella editorn får
bara redigera dokument som är "rena" (kan round-trippa förlustfritt), annars
öppnas källeditorn. Visa en varning "det här dokumentet innehåller avancerad
AsciiDoc — redigera i källvyn".
- **B. Patch-baserad sparning.** Spara bara de block som faktiskt ändrats i den
visuella vyn i stället för att reserialisera hela dokumentet.
- **C. Byt serialisering.** Använd en riktig AST (t.ex. `downdoc`/`@asciidoctor`
reducer) i stället för den handskrivna `TipTapToAsciidoc`-klassen.
Minst arbete/störst nytta på kort sikt: **A** + en tydlig indikator i UI.
---
## 2. Konkreta serialiseringsluckor i `fromTipTap`
| Nod / mark | Problem | Förslag |
|------------|---------|---------|
| Kombinerade marks (fet+kursiv) | Ger `*_text_*` — bräckligt intill andra tecken | Använd oконstruerad syntax (`**`, `__`) vid behov |
| Tabeller (`convertTable`) | Ingen header-rad (`[%header]`), inga kolumn-specar, colspan/align tappas | Detektera `tableHeader`, skriv `[options="header"]`, `cols=` |
| Listor (`convertListItem`) | Blandning av stycke + nästlad lista i samma item blir fel; principallista använder nivå-räkning som spretar | Rendera item-innehåll block för block med `+`-continuation för flerstycke |
| `blockquote` | Attribution/citat-källa tappas | Stöd `[quote, author, source]` |
| `admonition` | Bara 5 typer, alltid versalt block-format | Bevara ursprunglig form (inline `NOTE:` vs `[NOTE]`-block) |
| Bild | `role`/alignment/`link=` tappas | Utöka `AsciidocImage`-attribut och serialisering |
---
## 3. Renderingspipelinen (adoc → HTML)
- **Regex-omskrivning av admonitions** (`htmlContent.replace(/<div class="admonitionblock…`)
är känslig för nästlat innehåll och flera stycken. En admonition med en lista
eller ett kodblock inuti går sönder. → Rendera i stället admonitions via en
Asciidoctor-**converter/extension** i stället för att patcha HTML i efterhand.
- **`include::`** hanteras med regex och blir en platshållare. Riktiga includes
(t.ex. återanvändbara fragment) renderas aldrig. → Implementera en
include-resolver på backend (den har redan fil-I/O) och rendera server-side,
eller hämta fragmentet via API innan `convert`.
- **Passthrough (`+++`)**: fotnötter injiceras som rå-HTML före parsing. Fungerar,
men kringgår sanering. Låg risk internt, men värt en `DOMPurify` på
renderad HTML om publika/gäst-användare någonsin ska se opålitligt innehåll.
---
## 4. Prestanda / bundle
`DocumentView`-chunken är **~2,8 MB** (880 kB gzip). Två tunga poster:
- **`lowlight` med `all`** (`createLowlight(all)`) drar in *alla* språkgrammatiker.
→ Byt till `common` eller registrera bara de språk ni faktiskt använder
(go, js, ts, bash, python, yaml…). Sparar hundratals kB.
- **`asciidoctor.js`** är stort och laddas i varje dokumentvy. → Lazy-load
(`import()` först när ett dokument öppnas) — delvis redan gjort via
route-splitting, men Asciidoctor kan brytas ut ytterligare. Överväg
server-side-rendering av HTML (backend har redan Go; ett litet
`asciidoctor`-anrop eller cache av renderad HTML per commit-hash skulle ta bort
klientkostnaden helt och göra läsvyn snabb även på Pi5/mobil).
---
## 5. Editor-UX (presentation)
- **Synk mellan Visual och Source.** Gör "source of truth"-valet (punkt 1)
synligt: en toggle med en varningsikon när dokumentet inte kan round-trippa.
- **Live-förhandsvisning i källeditorn.** CodeMirror till vänster, renderad HTML
till höger (delad vy) — vanligt och uppskattat för teknisk dokumentation.
- **Innehållsförteckning / rubriknavigering.** Generera en TOC från rubrikerna
(finns redan `id` på `CustomHeading`) och visa i sidopanelen.
- **Bildhantering.** Uppladdning finns; lägg till drag-and-drop och inklistring
från urklipp direkt i editorn.
- **Autospar / utkast.** Spara utkast lokalt (IndexedDB) så inget tappas vid
session-timeout (sessioner ligger bara i minnet på servern).
- **Diff-vy i redigering.** `HistoryPanel`/`DiffViewer` finns — koppla en
"jämför med sparad version"-knapp direkt i editorn.
---
## Prioriteringsordning (rekommenderad)
1. ✅ Fixa marks-buggen (klar).
2. Lägg round-trip-test i CI.
3. Byt `lowlight` `all` → `common`/whitelist (snabb, stor bundle-vinst).
4. Inför "source of truth"-indikator + öppna källvyn för avancerade dokument.
5. Server-side- eller cachead HTML-rendering (störst läs-prestandavinst).
6. Robustare tabell-/list-serialisering.