M10: Presentation (.pptx) export (#1137) (#1162)

* feat: presentation (.pptx) export (#1137)

- Implement OpenXML PresentationML (.pptx) generator in crates/export/src/pptx.rs:
  - Generate [Content_Types].xml, _rels/.rels, core properties, presentation.xml
  - Build slide master, blank slide layout, and DrawingML theme
  - Render slides per page: largest text block as title shape, remaining paragraphs as body text box with font size, bold, italic, and color formatting
  - Embed images with proper DrawingML picture shapes and relationships
  - Generate DrawingML table shapes with column grid and span merging
- Wire OfficeFormat::Pptx into crates/engine/src/compare.rs and export_office
- Register export.pptx command and mark Presentation (.pptx) Ready in catalog
- Support pptx in automation doc_export_office tool
- Wire export.pptx into UI commands and file save dialog
- Add unit and integration tests across crates/export, engine, automation, and ui-egui
- Update create.export-pptx parity feature evidence and docs

* pptx export: saturating slide positions, matching cell-border tags, theme ea/cs fonts, package test

- Heights and the running vertical position use clamped/saturating arithmetic, so a hostile
  text size or image rectangle (1e300, NaN, inf) can't overflow i64; the item loop uses get().
- The table cells' a:lnR and a:lnT borders were closed with </a:lnL>, which made every slide
  with a table malformed XML; they now close with their own tags.
- The theme's major/minor fonts carry the schema-required a:ea and a:cs children.
- New test walks the produced zip entry by entry (sizes, inflation, central directory), checks
  every XML part's tags balance, the required parts, content-type overrides, relationship
  targets and that no placeholders are used; a hostile-sizes test covers the overflow.
- Test literals gain main's Block/Image rotation and size fields.
- Parity notes say what is still unverified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: KrzysztofC <krzysztofc@localhost-live.lan>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Krzysztof Cieślik
2026-10-11 21:55:25 -04:00
committed by GitHub
co-authored by Claude Opus 5.5 KrzysztofC Brandon Thomas
parent 0a447ee1ab
commit 84a75eae1b
36 changed files with 837 additions and 42 deletions
+21 -5
View File
@@ -6967,11 +6967,27 @@ title = "Export to PowerPoint (.pptx)"
area = "J"
tier = "P1"
milestone = "M10"
status = "planned"
commands = []
tools = []
evidence = []
notes = ""
status = "partial"
commands = ["export.pptx"]
tools = ["doc_export_office"]
evidence = [
"crates/export/src/pptx.rs::pptx_is_a_presentationml_package",
"crates/export/src/pptx.rs::pptx_slide_has_title_body_and_images_in_order",
"crates/export/src/pptx.rs::pptx_text_colour_and_formatting",
"crates/export/src/pptx.rs::pptx_empty_pages_produce_valid_slide",
"crates/export/src/pptx.rs::pptx_slide_dimensions_and_clamping",
"crates/export/src/pptx.rs::pptx_table_cell_with_largest_font_stays_in_table_and_not_in_title",
"crates/export/src/pptx.rs::pptx_opens_in_libreoffice",
"crates/export/src/pptx.rs::pptx_package_parts_are_complete_and_consistent",
"crates/export/src/pptx.rs::hostile_sizes_do_not_overflow_the_slide_position",
"crates/export/src/lib.rs::grid_text_becomes_a_real_table_in_every_format",
"crates/export/src/lib.rs::text_colour_survives_every_format",
"crates/engine/src/tests.rs::exporting_office_files_keeps_images",
"crates/engine/src/tests.rs::exporting_office_files_keeps_text_colour",
"crates/automation/tests/automation.rs::exporting_to_word_html_and_rtf",
"crates/ui-egui/tests/compare.rs::export_to_word_html_and_rtf",
]
notes = "PowerPoint presentation: each page becomes a slide, with the largest non-table text as slide title, remaining paragraphs as body text, images and detected tables in reading order; DrawingML formatting (font size, bold, italic, text fill colour, cell borders); wired into engine command export.pptx, automation tool doc_export_office, and Export dialog. Missing: content past the slide bottom is not paginated or shrunk across multiple slides (no normAutofit), all slides use the first page's dimensions, title is determined by largest font size rather than semantic structure, and there is no layout-preserving mode (Acrobat keeps positions). Not yet verified in PowerPoint or Keynote: pptx_opens_in_libreoffice only converts the file when LibreOffice is installed and passes silently otherwise (CI has none), so the package structure is checked by pptx_package_parts_are_complete_and_consistent instead."
[[feature]]
id = "create.export-png"