Skip to content

feat(exporters): add layout-aware editable PPTX beta - #441

Open
L4b0R wants to merge 1 commit into
OpenCoworkAI:mainfrom
L4b0R:feat/editable-pptx-phase1
Open

L4b0R wants to merge 1 commit into
OpenCoworkAI:mainfrom
L4b0R:feat/editable-pptx-phase1

Conversation

@L4b0R

@L4b0R L4b0R commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Add an opt-in, layout-aware editable PPTX Beta alongside the existing image-first PPTX export. Chromium executes HTML/JSX and measures the rendered document; a small slide model writes native text lines, basic shapes and independent images. Unsupported regions degrade locally with warnings instead of silently losing content or flattening an otherwise editable slide.

This is one phase-one export feature, including desktop wiring, package compatibility fixes, regression coverage and its authoring/acceptance contract. It does not replace the image-first default, change the legacy heading/bullet library mode, or promise arbitrary CSS fidelity.

Included

  • Separate translated PPTX (editable, beta) menu action; validated IPC/store forwarding and export warnings independent of research-source warnings.
  • Explicit/hidden slide discovery, preview-scale normalization, measured rich-text lines and actual platform-font resolution.
  • Isolated decoration capture and CSS stacking order, keeping background grids below editable foreground text.
  • Conservative single-poster detection and source-proportioned portrait pages; ordinary deck sizing remains unchanged.
  • Model/geometry validation and XML sanitization; persistent PptxGenJS 4.0.1 patch for font-attribute escaping and dangling slide-master ContentTypes declarations in both CJS and ESM.
  • Public synthetic regressions and authoring contract / Beta acceptance matrix.

Type of change

  • New feature
  • Bug fix (export fidelity/package compatibility within the feature)
  • Documentation
  • Breaking change

Linked issue

Refs #284 as follow-up context for editable PPTX fidelity. That issue is already closed; this PR does not reopen it or claim to resolve its other export-format concerns.

Validation

Local environment: Windows, Node 24.11.1, pinned pnpm 10.33.4, installed system Chromium. Upstream CI uses Node 22/Linux and remains a separate check.

  • Root lint and typecheck.
  • Complete repository test command; all 10 Turbo test tasks succeeded (unchanged packages may use local Turbo cache).
  • Exporter coverage: 179 passing tests, 3 existing skips; includes 39 native browser cases. Seven new representative cases cover SVG/table local rasterization, transforms, clip-path, group opacity, missing fonts and ignored controls.
  • Desktop suite: 168 files, 2,284 passing tests, 1 existing skip.
  • Frozen/offline lockfile validation and desktop production build; native exporter/model stay in lazy chunks.
  • Git pre-commit and pre-push checks, without bypassing hooks; staged-file/private-source audit and diff whitespace check.
  • Installed Windows PowerPoint: private six-slide deck and portrait poster opened, rendered, saved as copies, and reopened; 171 / 55 objects and all text retained. Private source, outputs and validation scripts are not committed.

Beta boundaries

  • Gradients, shadows and unsupported composites may remain local pictures; native chart datasets and native tables are not included.
  • Multiline text uses separate editable line objects, not automatic paragraph reflow.
  • Fonts are not embedded; browser/Office metrics and destination fonts can differ.
  • macOS PowerPoint, WPS and other Office versions are not verified. Browser tests skip if no system browser is present; a skipped run is not a compatibility pass.
  • No repair-free/fidelity guarantee for arbitrary HTML/CSS. Image-first export remains the safer appearance-first choice.

Dependency and design checks

No new production dependencies, bundled browser/model/font runtimes, or startup loading. The only new direct dev dependency is MIT-licensed @xmldom/xmldom@0.8.13, used to validate generated package XML in tests. The existing PptxGenJS dependency is repaired through a tracked pnpm patch; maintenance/removal instructions are included.

  • Compatibility — green: opt-in API/UI path; defaults and legacy behavior retained and regression-tested.
  • Upgradeability — green: no persisted-state migration; version-scoped dependency patch with maintenance instructions.
  • Lean scope — green: reuse system Chromium/PptxGenJS and existing IPC; no new runtime dependency or bundled runtime.
  • Elegance — green: DOM extraction → minimal in-memory model → writer, with localized fallback and explicit warnings; no general renderer/plugin framework.

Checklist

  • Reviewed relevant public issue/context.
  • Added/updated tests.
  • Added a changeset for the user-visible feature.
  • Updated public behavior, fallback and compatibility documentation.

Screenshot

Actual toolbar and menu rendered with synthetic preview state; no user design content, private paths or live desktop capture.

Editable PPTX remains a separate Beta option

Signed-off-by: HUANG <15866338256@163.com>
@github-actions github-actions Bot added docs Documentation area:desktop apps/desktop (Electron shell, renderer) area:exporters packages/exporters (PDF/PPTX/ZIP) area:build Turbo/Vite/Biome/tsconfig toolchain labels Sep 27, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Minor] MIME allowlist mismatch between the DOM extractor and the model writer can hard-fail native PPTX export — packages/exporters/src/pptx-dom.ts promotes an <img> to an independent image when currentSrc/src matches /^data:image\/(png|jpe?g);base64,/i (so image/jpg is accepted, and matching is case-insensitive), but packages/exporters/src/pptx-model.ts checkElement validates image data with /^data:image\/(png|jpeg|gif);base64,[A-Za-z0-9+/]+={0,2}$/ (no jpg, case-sensitive, and it advertises gif which the extractor never produces). A design containing <img src="data:image/jpg;base64,..." /> (or an uppercase image/PNG data URL) passes extraction as a native image and is then rejected by checkElement, so the whole native export throws instead of degrading to a warned raster fallback. If the workspace asset pipeline inlines .jpg files as image/jpg, this would hit every jpg image in a deck.
    Suggested fix: align the writer with the extractor, e.g. ^data:image\/(png|jpe?g|gif);base64,[A-Za-z0-9+/]+={0,2}$ with the i flag, and add a packages/exporters/src/pptx-model.test.ts case for a jpg data URL.

  • [Nit] The new mode is not recorded in the local action log — apps/desktop/src/renderer/src/store/slices/generation.ts still calls recordAction({ type: 'design.export', data: { format } }), so history cannot distinguish an image-first PPTX export from the native beta. Suggest adding renderMode to data when present.

Questions

  • apps/desktop/src/main/preview-runtime.ts removes three // @ts-expect-error browser context directives, yet this PR changes no tsconfig. Is this forced by the new /// <reference lib="dom" /> in packages/exporters/src/pptx-dom.ts, which adds the DOM lib program-wide for consumers that type-check exporters from source? If so, the Electron main-process program now has DOM globals typed, which removes a useful guard against accidentally using DOM APIs in apps/desktop/src/main/**. If intentional, a one-line note in the PR body would help reviewers.

Summary

  • Review mode: initial
  • No Blockers or Majors found. The feature is genuinely opt-in (separate PPTX (editable, beta) menu action), the image-first default and legacy editable mode are preserved and covered by tests, parseRequest validates renderMode before any save dialog or exporter call, and conversion fallbacks surface as user-visible exportWarnings rather than silent drops (packages/exporters/src/pptx-model.ts addNativeSlides validates the whole deck before mutating the presentation, and unresolved rasters throw descriptively).
  • Linked issue: the PR uses Refs #284 and explicitly does not claim to close it, so no completion-claim validation applies.
  • Constraints: only a test-only devDependency (@xmldom/xmldom@0.8.13, MIT) is added; no direct provider SDK imports; heavy exporter deps stay dynamically imported; the pptxgenjs@4.0.1 repair is version-scoped, tracked in patches/ and pinned by lockfile patch hash with maintenance instructions in patches/README.md; no console.* in packages/exporters/**.
  • Residual risk: fidelity and Office compatibility are explicitly Beta. The browser suites use skipIf(!chromePath), so a skipped run is not a compatibility pass (the README says so). Also note packages/exporters/src/pptx-native.browser.test.ts reads apps/desktop/resources/templates/design-skills/slide-deck.jsx across packages, so moving that resource will break the exporters suite.

Testing

  • Not run (automation). Suggested additions: a packages/exporters/src/pptx-model.test.ts case asserting a data:image/jpg;base64,... image is accepted after aligning the regex, plus a browser case covering a jpg data-URL image in an otherwise native slide.

Open-CoDesign Bot

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:build Turbo/Vite/Biome/tsconfig toolchain area:desktop apps/desktop (Electron shell, renderer) area:exporters packages/exporters (PDF/PPTX/ZIP) docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant