# PowerPoint editing between upload and activities

Assessment date: 2 November 2026.

## Scope and result

The requested first integration is one authoring stage: upload PowerPoint, edit its slide content using the GitHub editor's UI/UX, generate images, then continue into the existing activity and SCORM workflow. This does not require replacing the learning workspace or introducing animated learner playback in the first batch.

A fresh temporary checkout was created at `out/research/ppt-live-editor-stage1/`, from `https://github.com/ymankh/ppt-live-editor.git`, pinned to commit `ece43d6986cc1b417c5db2bbe5a92b70b330073b`. The existing root ignore rule `**/out/` covers the checkout, dependencies, generated files and research tests. The older research checkout was left intact. No host application code, dependencies, database or existing project data was changed.

Recommendation: reuse the frontend workspace and native document engine, connect them to Laravel through adapters, and rasterize the saved native document when the user continues. Do not feed edited content back through an unmodified original-source renderer: it would ignore native edits. The current importer cannot support unrestricted editing of every PowerPoint file without additional compatibility work.

## Exact upstream flow

Paths below are relative to the temporary checkout's `frontend/src/`.

1. `features/home/Home.tsx::upload()` calls `importProject(file)`, saves the document, loads the editor store and navigates to the editor.
2. `features/export/export.ts::importProject()` dispatches `.pptx` files to `importPptx(file)`.
3. `features/export/importPptx.ts` reads OOXML using JSZip and creates a native `Presentation` containing slides and supported elements. It assigns new native IDs; these are not our course-slide identities.
4. `features/editor/Editor.tsx` and `Workspace.tsx` mount the toolbar, slide rail, editable canvas, inspector and notes. Commands operate on `store/editor.ts`.
5. `features/persistence/repository.ts` saves whole native documents and assets to its own API. These concrete calls must be replaced with our authenticated project API; importing the repository unchanged would also bring automatic IndexedDB migration and unrelated project-library behavior.
6. `features/export/raster.tsx::rasterizeSlide()` mounts the shared slide renderer, resolves images, waits for fonts/images and captures PNG/JPEG. This is the useful handoff for our image-based course player.

The upstream code edits a translated presentation model, not arbitrary objects inside the original uploaded PPTX in place. Its PPTX exporter creates a new file from that model; it is not a lossless source patcher.

## Components to bring across

| Upstream modules | Use in the upload editing stage | Adaptation |
| --- | --- | --- |
| `features/editor/`, `features/slides/`, `features/canvas/` | Same workspace layout, menus, inspector, layers, gestures, slide rail | Replace application navigation, identity, persistence and continue action; scope keyboard handlers and styles |
| `features/commands/`, `store/editor.ts`, `store/view.ts` | Commands, selection, undo/redo, transient gestures, save status | Project-specific store ownership; revision-aware saves; flush/cancel timers on project changes |
| `types/model.ts`, `lib/defaults.ts`, geometry and units helpers | Native editable document and geometry | Add our format/engine discriminator and source-slide/course-slide identity mapping |
| `features/renderer/`, `features/text/`, `features/theme/` | Rich text, object rendering, themes and notes | Preserve presentation dimensions and mixed Arabic/English text |
| `features/export/importPptx.ts`, `pptxFonts.ts` | Initial supported PPTX import | Compatibility inventory, resource limits, cancellation, stable source mapping, no silent omissions |
| `features/images/`, `features/fonts/`, localization | Image controls, font resolution and Arabic UI | Map to project-private Laravel asset/font APIs and our language preference |
| `features/export/raster.tsx`, relevant asset helpers | Edited slide images and thumbnails | Capture an immutable saved revision and publish output only when complete |
| Existing UI primitives and necessary CSS | Preserve the GitHub interaction and appearance | Contain CSS/reset/theme behavior within the editor; adapt mobile panels |

Do not bring across the ASP.NET backend, hardcoded local identity, standalone project library/router or automatic browser-project migration. Its presenter and PPTX/PDF export can be assessed separately; they are not needed to complete this first image-based stage. Preserve editable animation metadata if retained, but do not present raster output as retaining object animations.

## Host application connection points

| Existing source | Current behavior | Required connection |
| --- | --- | --- |
| `documents_generator_tools_backend/app/Http/Controllers/Api/PowerPointToScormConversionController.php::store()` | Validates/stores original PPTX, creates a conversion with status `preparing` | Keep this entry point and original source; expose authorized import bytes or a server-produced import document |
| `documents_generator_tools_frontend/app/tools/powerpoint-to-scorm/studio/editor-project.tsx` | Shows `PreparationEditor` while preparing and provides existing learning tools when ready | Mount the new editing workspace for opted-in projects between upload and image generation |
| `documents_generator_tools_frontend/app/tools/powerpoint-to-scorm/preparation-editor.tsx` | Font/preparation and render workflow | Connect font readiness and the explicit generate-images/continue action |
| `documents_generator_tools_backend/app/Http/Controllers/Api/PreparationController.php::render()` | Captures revision, source/font/correction snapshot and queues original-PPTX rendering | Add an explicit native-edit branch with native document hash/revision; retain existing source rendering for legacy projects |
| `documents_generator_tools_backend/app/Jobs/RenderPreparedPresentation.php` | Publishes matching render generation and retains successful output on failure | Apply the same generation/access/quota protections to native document raster output |
| `documents_generator_tools_backend/app/Services/CourseSlideService.php` | Stable course-slide IDs/tracking keys and legacy anchors | Map native slide IDs once; adding, deleting and reordering must reconcile records rather than recreate them |
| `documents_generator_tools_backend/app/Services/ScormPackageBuilder.php` | Packages active slide image assets and learning resources | Accept the committed native image generation through existing slide contracts; keep revision guards |

The existing `SlideLayoutController` saves a restricted set of geometry/format corrections and rejects unsupported keys. It is not a suitable endpoint for saving whole editable presentations or replacing text. Use a separate native-document contract rather than weakening that existing validation.

## Proposed first-batch contract

These are proposed names and boundaries, not existing endpoints or fields.

- A versioned document envelope with engine name/version, document revision, source hash, logical dimensions, native presentation, native-to-course-slide mapping and compatibility findings.
- Authenticated load/save operations using expected revision and rejecting stale writes. Validate document schema, owned asset references, dimensions, element counts and resource sizes server-side.
- Import must happen once per source/version, not on every reopen: re-import generates new IDs and would discard edits. Save the editable result before continuing.
- Preserve the original PPTX separately. Never overwrite `source.pptx` as a side effect of saving native edits.
- The continue action flushes pending edits, waits for assets/fonts, captures the saved revision and queues an image generation. Block packaging if the current native document differs from the successful image revision.
- Prefer a queued browser-render worker using the shared renderer, with project-scoped access to assets and explicit network restrictions. A browser-side capture can prove the concept, but production continuation should not depend on keeping a tab open while generating a large deck.
- Stage generated files in a new generation path. Publish all images, thumbnails and slide mapping together only if document revision, generation and workspace authorization still match. Retain previous output if rendering fails.
- Render outputs must honor dimensions, transparency policy, image resolution, skipped slides, order and visible/hidden element state. Test how animation state is flattened into static artwork.
- Slide deletion after activities exist must follow existing remove/restore rules. Reordering must not move activities to another slide. Duplicating a slide must explicitly decide whether attachments are copied through existing services.

For the first batch, the user-facing flow is:

`Upload → edit slide content → save and generate images → existing activities/media/H5P → preview → Build SCORM`.

Returning to editing retains the same native document and course-slide identity map. Modified slides make images/package outdated; successful regeneration updates artwork without reattaching learning content by slide number.

## Import compatibility findings

The importer supports direct text boxes, supported shapes, raster/SVG pictures, connectors, tables, some chart types and notes. The current version adds run-level text/font handling, Arabic complex-script fonts, theme-font references and some inherited font defaults.

It still filters the slide shape tree to `sp`, `pic`, `cxnSp` and `graphicFrame`. Group containers (`grpSp`) are skipped. SmartArt and embedded media have no native counterpart in this importer. Full master/layout object inheritance and source PowerPoint animations are not reconstructed. These are content-preservation gaps, not just missing buttons in the UI.

Two local research probes were added only inside the ignored clone:

- Direct text imports as editable content; changing it survives native-document JSON serialization.
- A grouped textbox imports as an empty slide without an error. This reproduces actual silent content loss on a minimal synthetic PPTX.

The second probe characterizes an existing defect; a passing probe is not acceptance of that behavior for production. Before rollout, unsupported content must produce compatibility findings, preserve source artwork, or be supported by importer work. A background preserves appearance but does not make original text inside it editable. Do not label all content editable.

## Compatibility and extraction sequence

1. Confirm rights to reuse the editor code. No application `LICENSE`, `COPYING` or `NOTICE` was found in the checkout. The bundled Amiri font's OFL is not an application license.
2. Extract the workspace into a scoped, lazy-loaded module on an isolated implementation branch, initially backed by test data and an injected repository. Keep the GitHub UI/UX intact while removing unrelated standalone app behavior.
3. Connect upload/import and versioned Laravel saving behind an opt-in flag. Use new uploads first; do not auto-migrate old projects.
4. Connect generation of edited images to existing course-slide records, then enter the current learning workflow. Keep old rendering endpoints and existing project behavior available.
5. Validate supported imports, unsupported-content reporting, save/reopen, reorder/add/remove/duplicate, attachment identities, Arabic/English fonts, denied access, stale edits, render failure and offline SCORM assets.
6. Only then offer an explicit upgrade path for old projects, with a recovery snapshot or a separate copy and clear import findings. An image-only legacy slide cannot be restored to editable native objects without an editable source.

The host uses React 19.2.6 / TypeScript 5.9.3 / Vite 8.0.13; the clone lockfile builds with its own newer toolchain and many additional dependencies. Reconcile required dependencies in the implementation branch; do not replace our package manifest or copy `node_modules`. Upstream store/save queues and root theme changes need adaptation to avoid interference with other project tabs and application pages.

## Verification performed

- Fresh shallow Git clone and pinned SHA recorded above.
- Git ignore coverage verified against root `.gitignore` line 14 (`**/out/`).
- `npm ci --no-audit --no-fund`: passed inside the clone only; 800 packages installed.
- `npm run build`: passed (TypeScript build and Vite production build).
- `npm test`: passed, 18 files / 126 supplied tests.
- `npx vitest run src/features/export/researchImport.test.ts`: passed, 2 local research probes described above.
- `npm run e2e`: passed, all 7 supplied browser tests against the clone's isolated ASP.NET/SQLite API and Vite frontend. Coverage includes authoring/transform/reorder/export/restore, history/persistence/presenting, raster artwork, pointer/keyboard layer reordering, Arabic settings and panel resizing. The first attempt could not launch because the required Playwright Chromium binary was absent; after `npx playwright install chromium`, the rerun passed in 20.8 seconds. These tests use the clone's `.cache/playwright/folio.db`, not the host application's database.
- Parent `git status` confirms the only new host-workspace file from this assessment is this document. Existing H5P changes were left untouched; no cloned files are tracked by the parent repository.

The automated import fixtures do not establish fidelity for the user's real presentations. No host migrations, host dependency installation, host application tests, real-user-file acceptance, integrated Laravel save/render or Moodle runtime checks have been performed in this assessment.
