feat(document): afbeeldingen renderen op het scherm, niet alleen in export (#1605) #1617

Merged
brenno merged 1 commit from feat/document-images-1605 into main 2026-08-20 17:29:39 +00:00
Owner

Samenvatting

Een afbeelding in een document (![alt](bron)) verscheen alleen in de HTML- en PDF-uitvoer — op het scherm stond een merkteken met de alt-tekst. Nu tekent OciDeck de afbeelding zelf in Visueel, Bron en Pagina's, met dezelfde pad-resolutie als slides.

Wat er verandert

  • DocumentImageScope (nieuwe InheritedWidget naast DocumentStyleScope) draagt de map van het document, zodat de lezer en het schrijfvlak een afbeeldingspad op dezelfde manier oplossen.
  • DocumentImage (nieuwe widget in parts/document_markdown_image.dart) tekent de afbeelding met begrensde decode (image_limits: 4096 px / 64 MiB), of valt terug op het merkteken als het pad niet oplost (fail-closed).
  • documentImageProvider resolveert asset:, mem: en lokaal-bestand via resolveSlideAssetPath (project-contained, met symlink-grens). Op web alleen mem: en asset: — een lokaal pad kan daar niet renderen.
  • ImageEmbedBuilder tekent de echte afbeelding i.p.v. het merkteken in de visuele editor, met fallback op het merkteken.
  • PagedDocumentView houdt de meet-boom gemonteerd voor documenten met afbeeldingen, zodat de asynchrone decode de paginering corrigeert zodra de hoogte binnenkomt. Zonder afbeeldingen blijft de eenmalige meting — geen overhead.
  • _parseImageLine herkent een regel die precies één afbeelding is (![alt](bron)) en maakt er een _Kind.image-blok van.

Beveiliging

  • Pad-resolutie is project-contained via resolveSlideAssetPath — een onvertrouwd document kan niet willekeurige bestanden buiten zijn map lezen.
  • Fail-closed: een ontbrekend of onoplosbaar pad toont het merkteken, niet een leeg vlak.
  • Decode-grenzen hergebruiken slides: 4096 px / 64 MiB.

Bewaker

Deze wijziging leest bestanden van schijf in een nieuwe context (documentweergave), maar hergebruikt de bestaande resolveSlideAssetPath-grens die slides al bewaken. Geen nieuwe trust boundary, geen nieuwe afhankelijkheid, geen wijziging aan het bestandsformaat. De belofte in de gids (web resolveert alleen mem:) is expliciet gedocumenteerd.

Testplan

  • document_reader_test.dart: nieuw test voor afbeeldingsblok-rendering in DocumentMarkdownView
  • document_visual_image_test.dart: bestaande tests groen
  • paged_document_view_test.dart: bestaande tests groen
  • shell_present_and_close_test.dart: bestaande tests groen
  • make check-static groen
  • flutter test --exclude-tags golden — 10240 tests groen
  • make check-secrets — geen leaks
  • make sast — 0 findings

Generated with Devin

## Samenvatting Een afbeelding in een document (`![alt](bron)`) verscheen alleen in de HTML- en PDF-uitvoer — op het scherm stond een merkteken met de alt-tekst. Nu tekent OciDeck de afbeelding zelf in Visueel, Bron en Pagina's, met dezelfde pad-resolutie als slides. ### Wat er verandert - **`DocumentImageScope`** (nieuwe `InheritedWidget` naast `DocumentStyleScope`) draagt de map van het document, zodat de lezer en het schrijfvlak een afbeeldingspad op dezelfde manier oplossen. - **`DocumentImage`** (nieuwe widget in `parts/document_markdown_image.dart`) tekent de afbeelding met begrensde decode (`image_limits`: 4096 px / 64 MiB), of valt terug op het merkteken als het pad niet oplost (fail-closed). - **`documentImageProvider`** resolveert `asset:`, `mem:` en lokaal-bestand via `resolveSlideAssetPath` (project-contained, met symlink-grens). Op web alleen `mem:` en `asset:` — een lokaal pad kan daar niet renderen. - **`ImageEmbedBuilder`** tekent de echte afbeelding i.p.v. het merkteken in de visuele editor, met fallback op het merkteken. - **`PagedDocumentView`** houdt de meet-boom gemonteerd voor documenten met afbeeldingen, zodat de asynchrone decode de paginering corrigeert zodra de hoogte binnenkomt. Zonder afbeeldingen blijft de eenmalige meting — geen overhead. - **`_parseImageLine`** herkent een regel die precies één afbeelding is (`![alt](bron)`) en maakt er een `_Kind.image`-blok van. ### Beveiliging - Pad-resolutie is project-contained via `resolveSlideAssetPath` — een onvertrouwd document kan niet willekeurige bestanden buiten zijn map lezen. - Fail-closed: een ontbrekend of onoplosbaar pad toont het merkteken, niet een leeg vlak. - Decode-grenzen hergebruiken slides: 4096 px / 64 MiB. ### Bewaker Deze wijziging leest bestanden van schijf in een nieuwe context (documentweergave), maar hergebruikt de bestaande `resolveSlideAssetPath`-grens die slides al bewaken. Geen nieuwe trust boundary, geen nieuwe afhankelijkheid, geen wijziging aan het bestandsformaat. De belofte in de gids (web resolveert alleen `mem:`) is expliciet gedocumenteerd. #### Testplan - [x] `document_reader_test.dart`: nieuw test voor afbeeldingsblok-rendering in `DocumentMarkdownView` - [x] `document_visual_image_test.dart`: bestaande tests groen - [x] `paged_document_view_test.dart`: bestaande tests groen - [x] `shell_present_and_close_test.dart`: bestaande tests groen - [x] `make check-static` groen - [x] `flutter test --exclude-tags golden` — 10240 tests groen - [x] `make check-secrets` — geen leaks - [x] `make sast` — 0 findings Generated with [Devin](https://devin.ai)
feat(document): afbeeldingen renderen op het scherm, niet alleen in export (#1605)
All checks were successful
scans / scans (pull_request) Successful in 2m2s
static-gate / static-gate (pull_request) Successful in 5m17s
29797db4bc
Een afbeelding in een document (`![alt](bron)`) verscheen alleen in de HTML- en
PDF-uitvoer — op het scherm stond een merkteken met de alt-tekst. Nu tekent
OciDeck de afbeelding zelf in Visueel, Bron en Pagina's, met dezelfde
pad-resolutie als slides: project-contained via resolveSlideAssetPath, met de
decode-grenzen uit image_limits (4096 px / 64 MiB).

De DocumentImageScope (een InheritedWidget naast DocumentStyleScope) draagt de
map van het document, zodat de lezer en het schrijfvlak het pad op dezelfde manier
oplossen. De ImageEmbedBuilder tekent de echte afbeelding i.p.v. het merkteken,
met fallback op het merkteken als het pad niet oplost (fail-closed).

De paginaweergave houdt de meetboom gemonteerd voor documenten met afbeeldingen,
zodat de asynchrone decode de paginering corrigeert zodra de hoogte binnenkomt.
Zonder afbeeldingen blijft de eenmalige meting — geen overhead.

Op web resolveert alleen mem: (sessie-geheugen) en asset: (gebundeld); een
lokaal bestandspad kan daar niet renderen. Die grens staat in de gids.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
brenno merged commit c2b25fb4ac into main 2026-08-20 17:29:39 +00:00
Sign in to join this conversation.
No description provided.