Meldt ind: "kun den øverste sætning af det jeg markerede blev lavet om til monotype". Det førte til en anden fejl, der var værre. --- den meldte --- Monotype går uden om execCommand, fordi formatBlock pakker et <p> ind i <pre>'en i stedet for at lave den om. Den vej spurgte efter `currentBlock()`, og det er ét blok — markørens. Så af en markering over ti linjers terminaludskrift blev den første linje til kode og resten stod tilbage som brødtekst. `selectedBlocks()` læser hele markeringen, og de markerede blokke lægges sammen til ÉN blok. Ikke én pr. linje: en udskrift, man indsætter, er ét stykke kode, og tre blokke ved siden af hinanden ser næsten ens ud på skærmen og bliver til tre hegn i filen. Vejen ud af monotype tager nu også hele markeringen. `swapTag()` bytter tagget uden at røre markøren — tekstknuderne flytter med over, så den range browseren holder på stadig peger på noget i dokumentet, og formatBlock kan klare resten bagefter. --- den anden, som prøven fandt --- `watchForTrouble` meldte "ReferenceError: codeText is not defined" fra et rekursivt kald, jeg havde glemt at omdøbe. Ved siden af det lå en KOPI af "hvad er teksten i en blok", inde i editoren, med præcis den <br>-fejl, der blev rettet i #91: `textContent` på et <br> er den tomme streng. Den kopi bruges af farvelægningen, som maler resultatet TILBAGE ind i blokken. Så en kodeblok skrevet med shift+retur fik sine linjer skrevet sammen i det øjeblik, man klikkede væk fra den — på skærmen, ikke kun i filen, og uden at nogen havde rørt teksten. Målt mod den gamle kode: "echo enecho to". Kommentaren over kopien sagde ordret, at de to læsninger skulle være ét sted, FORDI en uenighed ville ende i noten. Den var sand, da den blev skrevet; kopien kom senere. `blockText` i richtext.js er nu det ene sted, eksporteret og brugt begge steder. Begge prøver er efterprøvet mod den gamle kode. Fuld chromium-suite kørt to gange: 94 bestået, 0 fejlet, begge gange. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
web
The SvelteKit PWA. Not written yet — this directory holds its place so the Docker build has something to copy, and so the frontend stage can tell "not built yet" apart from "the build failed".
The Dockerfile builds this directory when it finds a package.json here, and
otherwise emits a placeholder page. So adding the real app is exactly: put a
SvelteKit project in this directory whose npm run build produces build/.
What it needs to be
- SvelteKit,
adapter-static, output inbuild/. The Go binary embeds that directory at compile time and serves it, falling back toindex.htmlso client-side routes survive a reload. - A PWA: installable, offline reading of already-cached lists, swipe gestures for complete and schedule.
- Nordic minimalism. Dark by default, light available. One accent colour, everything else neutral. Runic mark for Verdande.
- Optimistic on every local action. No spinner ever appears for something the browser could already know the answer to.
Talking to the backend
Same origin — the Go binary serves both. /api/v1 for REST, /api/v1/ws for the
live sync. Session cookie is httpOnly, so the frontend never handles the token
itself.
During development, run the backend on 8080 and point the Vite dev server's proxy at it:
VERDANDE_DATA_DIR=./data VERDANDE_DEV=true go run ./cmd/verdande