fix(docx/odt): codeblok lekt niet meer door naar volgende inline code #2096

Merged
brenno merged 1 commit from fix/docx-odt-codeblock-stack-leak into main 2026-09-15 08:36:11 +00:00
Owner

Samenvatting

Een document met een (mermaid-)codeblok gevolgd door alinea's met inline code (enkele backticks) produceerde een ongeldig .docx/.odt dat niet te openen was.

Oorzaak: _visitCode pushte _Ctx.codeBlockBody op de visitor-stack en returnte false uit visitElementBefore. De markdown-package roept visitElementAfter dan niet meer aan (ast.dart:107), dus die placeholder bleef staan. pre's visitElementAfter popte daardoor _Ctx.codeBlockBody in plaats van _Ctx.codeBlock. Na het eerste codeblok stond _Ctx.codeBlock permanent op de stack → _inCodeBlock was voor altijd true → élke volgende inline `code` werd als een blok-level PreformattedText-alinea gerenderd, genest in een alinea die nooit sloot → </w:body> mismatch.

Oplossing: de _Ctx.codeBlockBody-push was dood (nooit gelezen, nooit opgeruimd). Verwijderd, plus de dode enum-waarde en de dode visitElementAfter-branch. Nu popt pre's visitElementAfter correct _Ctx.codeBlock en blijft de stack schoon.

Dezelfde bug bestond in de ODT-converter. LaTeX en EPUB hadden hem niet (die returnen true uit _visitCode, dus visitElementAfter wordt wél aangeroepen).

Reële impact: het document Information-Security-Policy-2.0-concept.docx (mermaid-blok op regel 163, inline code op regels 460/495/520) was niet te openen. Na de fix is de body welgevormd XML (xmllint: exit 0).

Dit raakt het exportformaat, maar alleen om output te herstellen die al kapot was — geen nieuw formaat, geen nieuwe afhankelijkheid, geen nieuwe belofte. De bewaker-stap is inhoudelijk een reparatie van uitwisselbaarheid, geen afweging ertegen.

Fixes #2095.

Testplan

  • Regressietest DOCX: codeblok gevolgd door inline code → geen geneste <w:p><w:p>, inline code is een run met SourceText
  • Regressietest ODT: codeblok gevolgd door inline code → inline code is een Source_Text span, geen Preformatted_Text-alinea
  • Echte document-body uit 2026-09-11_Information_Security_Policy_NEO_NL_v2.0.md is welgevormd XML (xmllint exit 0)
  • make check groen (format, analyze, conventions, dead-code, l10n, volledige suite, coverage, goldens)

Generated with Devin

## Samenvatting Een document met een (mermaid-)codeblok gevolgd door alinea's met inline code (enkele backticks) produceerde een ongeldig `.docx`/`.odt` dat niet te openen was. **Oorzaak:** `_visitCode` pushte `_Ctx.codeBlockBody` op de visitor-stack en returnte `false` uit `visitElementBefore`. De `markdown`-package roept `visitElementAfter` dan niet meer aan (ast.dart:107), dus die placeholder bleef staan. `pre`'s `visitElementAfter` popte daardoor `_Ctx.codeBlockBody` in plaats van `_Ctx.codeBlock`. Na het eerste codeblok stond `_Ctx.codeBlock` permanent op de stack → `_inCodeBlock` was voor altijd `true` → élke volgende inline `` `code` `` werd als een blok-level PreformattedText-alinea gerenderd, genest in een alinea die nooit sloot → `</w:body>` mismatch. **Oplossing:** de `_Ctx.codeBlockBody`-push was dood (nooit gelezen, nooit opgeruimd). Verwijderd, plus de dode enum-waarde en de dode `visitElementAfter`-branch. Nu popt `pre`'s `visitElementAfter` correct `_Ctx.codeBlock` en blijft de stack schoon. Dezelfde bug bestond in de ODT-converter. LaTeX en EPUB hadden hem niet (die returnen `true` uit `_visitCode`, dus `visitElementAfter` wordt wél aangeroepen). **Reële impact:** het document `Information-Security-Policy-2.0-concept.docx` (mermaid-blok op regel 163, inline code op regels 460/495/520) was niet te openen. Na de fix is de body welgevormd XML (xmllint: exit 0). Dit raakt het exportformaat, maar alleen om output te herstellen die al kapot was — geen nieuw formaat, geen nieuwe afhankelijkheid, geen nieuwe belofte. De bewaker-stap is inhoudelijk een reparatie van uitwisselbaarheid, geen afweging ertegen. Fixes #2095. #### Testplan - [x] Regressietest DOCX: codeblok gevolgd door inline code → geen geneste `<w:p><w:p>`, inline code is een run met `SourceText` - [x] Regressietest ODT: codeblok gevolgd door inline code → inline code is een `Source_Text` span, geen `Preformatted_Text`-alinea - [x] Echte document-body uit `2026-09-11_Information_Security_Policy_NEO_NL_v2.0.md` is welgevormd XML (xmllint exit 0) - [x] `make check` groen (format, analyze, conventions, dead-code, l10n, volledige suite, coverage, goldens) Generated with [Devin](https://devin.ai)
fix(docx/odt): codeblok lekt niet meer door naar volgende inline code
All checks were successful
scans / scans (pull_request) Successful in 3m9s
static-gate / static-gate (pull_request) Successful in 6m40s
6d4237c88c
_visitCode pushte _Ctx.codeBlockBody op de stack en returnte false uit
visitElementBefore. De markdown-package roept visitElementAfter dan niet
meer aan (ast.dart:107), dus die placeholder bleef staan. pre's
visitElementAfter popte daardoor _Ctx.codeBlockBody in plaats van
_Ctx.codeBlock — na het eerste codeblok stond _Ctx.codeBlock permanent
op de stack en werd élke volgende inline `code` als een
PreformattedText-blok gerenderd, genest in een alinea die nooit sloot.
Resultaat: ongeldig .docx/.odt dat niet te openen is.

De placeholder was dood: nooit gelezen, nooit opgeruimd. Verwijderd, plus
de dode enum-waarde en de dode visitElementAfter-branch. LaTeX en EPUB
hadden de bug niet (die returnen true uit _visitCode).

Fixes #2095.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
brenno merged commit 7d3ad1f023 into main 2026-09-15 08:36:11 +00:00
Sign in to join this conversation.
No description provided.