fix(html-export): presentatielogo op elke dia in de HTML-export #1486

Merged
brenno merged 2 commits from fix/html-export-logo into main 2026-08-13 20:39:31 +00:00
Owner

Wat & waarom

Bij het exporteren van een deck naar de zelfstandige HTML (dia-modus) kwam het stijlprofiel-logo niet mee. In de app, de beamer en de PDF/PPTX ligt datzelfde logo op elke dia; de HTML-dia-export kende alleen het documentlogo van de doorlopende documentmodus. Wie zijn deck als losse dia's naar HTML exporteerde, gaf de ontvanger dus een deck zonder logo — inconsistent met elk ander formaat.

Oorzaak

MarpHtmlService.build emitteerde het logo uitsluitend via _withDocumentChrome (kop/voetband), en dat pad draait alleen bij continuous: true. De dia-modus (continuous: false) stuurde geen enkel logo mee.

Oplossing

  • _presentationLogoCss (in marp_html_service_images.dart): legt het logo als ingesloten data:-URI op elke logo-dia via .slide.logo-safe::before. Een pseudo-element, want het renderscript wist de innerHTML van elke sectie voordat het de markdown erin zet — een echt <img> zou die reset niet overleven.
  • Hoek, maat en vrijgehouden strook komen uit dezelfde bron als de overlay in de app (kLogo*InsetFraction, logoSafeReserve uit rich_text_layout.dart), zodat de HTML precies toont wat de presentator/PDF al gaven.
  • _renderSections tagt een dia logo-safe, tenzij die met no-logo afziet van het logo — spiegelt hasLogo && slide.showLogo in MarkdownService.
  • De doorlopende documentmodus houdt zijn eigen kop/voetband-logo (_withDocumentChrome); geen dubbel logo.
  • Refactor: build liep hierdoor over de method-length-ratchet (129); het laden van de webbundels is uitgetild naar _loadExportBundles, waarna build weer 120 regels is.

Test

Bug krijgt een regressietest (test/marp_html_presentation_logo_test.dart) — eerst rood tegen de onherstelde code, nu groen. Pint: aanwezigheid + offline data:-URI, hoek/maat (rechtsonder én linksboven), per-dia no-logo-opt-out, en het uitblijven bij een logoloos thema, bij een niet-insluitbaar logo, en in de documentmodus.

Visueel gecontroleerd door de export echt te openen: LibreKAT (linksonder) en Vigilis (rechtsboven) tonen het logo correct; een no-logo-dia niet.

  • make check groen (9360 tests, dekking 86,9%, per-file-vloer 0 eronder)
  • make check-secrets schoon (gitleaks + trufflehog)
  • make sast schoon (semgrep, 0 bevindingen)

Documentatie

USER_GUIDE en KNOWN_LIMITATIONS documenteerden (sinds #1330) dat het logo bewust wordt weggelaten; die belofte is bijgewerkt naar de werkelijkheid. SOURCE_MAP beschrijft de nieuwe route. De .nl-doc-varianten zijn machinevertalingen (Engels leidend) en worden in batch geregenereerd.

Bewaker (stap 2c)

Expliciet overgeslagen: deze wijziging raakt niet het bestandsformaat, de opslag, een afhankelijkheid of uitgaand verkeer — het logo reist juist ingesloten en offline mee (CSP img-src ... data:). De docwijziging corrigeert alleen een verouderde beperking; geen nieuwe belofte of vastzetting.

Co-Authored-By: Claude Opus 4.8

## Wat & waarom Bij het exporteren van een deck naar de zelfstandige HTML (dia-modus) kwam het stijlprofiel-logo niet mee. In de app, de beamer en de PDF/PPTX ligt datzelfde logo op elke dia; de HTML-dia-export kende alleen het **documentlogo** van de doorlopende documentmodus. Wie zijn deck als losse dia's naar HTML exporteerde, gaf de ontvanger dus een deck zonder logo — inconsistent met elk ander formaat. ## Oorzaak `MarpHtmlService.build` emitteerde het logo uitsluitend via `_withDocumentChrome` (kop/voetband), en dat pad draait alleen bij `continuous: true`. De dia-modus (`continuous: false`) stuurde geen enkel logo mee. ## Oplossing - **`_presentationLogoCss`** (in `marp_html_service_images.dart`): legt het logo als ingesloten `data:`-URI op elke logo-dia via `.slide.logo-safe::before`. Een pseudo-element, want het renderscript wist de `innerHTML` van elke sectie voordat het de markdown erin zet — een echt `<img>` zou die reset niet overleven. - Hoek, maat en vrijgehouden strook komen uit dezelfde bron als de overlay in de app (`kLogo*InsetFraction`, `logoSafeReserve` uit `rich_text_layout.dart`), zodat de HTML precies toont wat de presentator/PDF al gaven. - **`_renderSections`** tagt een dia `logo-safe`, tenzij die met `no-logo` afziet van het logo — spiegelt `hasLogo && slide.showLogo` in `MarkdownService`. - De doorlopende documentmodus houdt zijn eigen kop/voetband-logo (`_withDocumentChrome`); geen dubbel logo. - **Refactor:** `build` liep hierdoor over de method-length-ratchet (129); het laden van de webbundels is uitgetild naar `_loadExportBundles`, waarna `build` weer 120 regels is. ## Test Bug krijgt een regressietest (`test/marp_html_presentation_logo_test.dart`) — eerst rood tegen de onherstelde code, nu groen. Pint: aanwezigheid + offline `data:`-URI, hoek/maat (rechtsonder én linksboven), per-dia `no-logo`-opt-out, en het uitblijven bij een logoloos thema, bij een niet-insluitbaar logo, en in de documentmodus. Visueel gecontroleerd door de export echt te openen: LibreKAT (linksonder) en Vigilis (rechtsboven) tonen het logo correct; een `no-logo`-dia niet. - [x] `make check` groen (9360 tests, dekking 86,9%, per-file-vloer 0 eronder) - [x] `make check-secrets` schoon (gitleaks + trufflehog) - [x] `make sast` schoon (semgrep, 0 bevindingen) ## Documentatie USER_GUIDE en KNOWN_LIMITATIONS documenteerden (sinds #1330) dat het logo bewust wordt weggelaten; die belofte is bijgewerkt naar de werkelijkheid. SOURCE_MAP beschrijft de nieuwe route. De .nl-doc-varianten zijn machinevertalingen (Engels leidend) en worden in batch geregenereerd. ## Bewaker (stap 2c) Expliciet overgeslagen: deze wijziging raakt niet het bestandsformaat, de opslag, een afhankelijkheid of uitgaand verkeer — het logo reist juist **ingesloten en offline** mee (CSP `img-src ... data:`). De docwijziging corrigeert alleen een verouderde beperking; geen nieuwe belofte of vastzetting. Co-Authored-By: Claude Opus 4.8
Het stijlprofiel-logo lag in de app, de beamer en de PDF/PPTX op elke dia,
maar de zelfstandige HTML-dia-export kende alleen het documentlogo van de
doorlopende documentmodus. Wie een deck als losse dia's naar HTML exporteerde,
gaf de ontvanger dus een deck zonder logo — inconsistent met elk ander formaat.

De export legt het logo nu als ingesloten data:-URI op elke dia die het toont,
via `.slide.logo-safe::before`. Een pseudo-element omdat het renderscript de
innerHTML van elke sectie wist voordat het de markdown erin zet; een echt
element zou die reset niet overleven. Hoek, maat en vrijgehouden strook komen
uit dezelfde bron (`kLogo*InsetFraction`, `logoSafeReserve`) als de overlay in
de app, zodat de HTML precies toont wat de presentator al zag. Een dia met
`no-logo` houdt hem weg, net als daar.

`build` liep hierdoor over de method-length-ratchet; het laden van de
webbundels is uitgetild naar `_loadExportBundles` zodat de methode weer krimpt.

Regressietest pint de aanwezigheid, de hoek/maat, de per-dia opt-out en het
uitblijven bij een logoloos thema of een niet-insluitbaar logo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs(html-export): logo reist nu mee in de HTML-export
All checks were successful
scans / scans (pull_request) Successful in 2m34s
static-gate / static-gate (pull_request) Successful in 9m43s
c94a7c3f1c
Werkt de nu-achterhaalde belofte bij dat het logo in de zelfstandige
HTML-export ontbreekt (#1330 documenteerde dat als bewust weggelaten). Het
logo reist voortaan wél mee; de overige on-slide-overlays (footer, watermerk,
TLP/PrivacyKat-badge) blijven het domein van de app-renderer.

- CHANGELOG: Fixed-entry.
- USER_GUIDE + KNOWN_LIMITATIONS: het logo uit de "weggelaten"-lijst gehaald.
- SOURCE_MAP: `_presentationLogoCss` en de `.slide.logo-safe::before`-route
  beschreven bij `marp_html_service.dart`.

De Nederlandse doc-varianten zijn machinevertalingen (Engels is leidend) en
worden in batch geregenereerd; die raak ik hier niet met de hand aan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brenno merged commit 416f5d149a into main 2026-08-13 20:39:31 +00:00
Sign in to join this conversation.
No description provided.