Skip to content

feat: MS Office-style pptx editor with live editing and i18n - #287

Draft
baseballyama wants to merge 2 commits into
mainfrom
feat/pptx-editor
Draft

feat: MS Office-style pptx editor with live editing and i18n#287
baseballyama wants to merge 2 commits into
mainfrom
feat/pptx-editor

Conversation

@baseballyama

Copy link
Copy Markdown
Collaborator

Summary

Adds a PowerPoint/Google-Slides-style editor at the SvelteKit /editor route (Svelte 5), built on the @office-kit/pptx public API, and fixes a library bug it surfaced: you could not type text into a freshly-inserted shape. The editor is designed around a capability-coverage guarantee — all 147 mutating public exports are reachable — and is fully localized (English / Japanese).

Motivation

Goal: an MS-Office-compatible editing UI that can express everything the library can author, with a mechanism that guarantees feature coverage rather than hand-wiring a subset. A generated manifest + registry + enforcement test provides that guarantee. A second round of work brought direct manipulation up to (and past) Google Slides, then added i18n. While testing text entry with a real mouse, setShapeText was found to throw on shapes authored without a text body — fixed here.

No pre-existing issue; this is net-new tooling plus the bug fix it exposed.

Changes

  • Library fix (@office-kit/pptx, patch): setShapeText / appendShapeText now create the <p:txBody> on demand (via a shared ensureTxBody helper) instead of throwing has no <p:txBody>. Picture / table shapes still throw. Changeset included.
  • New /editor route (site/, not published): ribbon, command palette (Ctrl+K, all 147 capabilities), auto-generated properties panel + argument dialogs, slide navigator.
  • Direct manipulation: live per-frame move/resize/rotate (one undo per gesture), smart-guide snapping, marquee + multi-select group move, double-click / type-to-edit inline text, keyboard (arrow-nudge, Ctrl+D/C/X/V/A, Delete), zoom/fit, right-click context menu, inline SVG icon set.
  • i18n: English / Japanese with a live language switcher (persisted); command/category labels use the manifest's labelJa / labelEn.
  • Coverage tests (run in the library's pnpm test): test/editor-capability-coverage.test.ts fails if the manifest drifts from the mutating-export set; test/editor-command-smoke.test.ts drives the registry end-to-end.

Testing

  • pnpm vitest run — 1240 passed; the 59 failures are pre-existing and all schema-valid assertions that need the missing references/ecma-376-5th XSD submodule (unrelated to this change; 0 new failures).
  • New regression test test/fn-set-shape-text-creates-txbody.test.ts (setShapeText/appendShapeText on a body-less shape + save/load round-trip).
  • tsc --noEmit clean; svelte-check clean (0/0); oxlint clean.
  • Manual (real mouse via Playwright): insert shape → double-click → type (incl. Japanese) → commits & renders; type-to-edit; drag-move; handle-resize; Ctrl+Z restore; language switch flips all chrome + manifest labels reactively; context menu localized. No console errors.

Repro for the fix:

pnpm vitest run test/fn-set-shape-text-creates-txbody.test.ts

Breaking changes

None. setShapeText / appendShapeText calls that previously threw now succeed; nothing that worked before changes behavior.

Checklist

  • I have read CLAUDE.md and followed the project's conventions.
  • I have added or updated tests for the change.
  • I have added or updated documentation where user-visible behavior changed.
  • If this is a breaking change, I have added a changeset / CHANGELOG entry and flagged it above.
  • I have re-read my own diff and removed dead code, debug prints, and stale comments.
  • If I used an LLM to draft this PR, I have verified each change myself, the PR represents real work that warrants a maintainer's review, and I am willing to defend each line in review.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HQKrXTQDSr6XQ4Pb75Yirv

… has none

A preset shape authored without `text` (e.g. `addSlideShape` with no `text`)
has no `<p:txBody>`, so setting text on it later threw
`shape "…" has no <p:txBody>`. PowerPoint always gives an autoshape a text body
so you can click in and type; these functions now create the body on demand via
a shared `ensureTxBody` helper and populate it, matching that behavior. Picture
/ table shapes still throw, since they are not text-bearing.

This surfaced through the editor: inserting a shape and typing into it failed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HQKrXTQDSr6XQ4Pb75Yirv
Copilot AI review requested due to automatic review settings July 6, 2026 02:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

A PowerPoint-style editor at the SvelteKit `/editor` route (Svelte 5), built on
the public API. Its defining constraint is *capability coverage*: a generated
manifest enumerates all 147 mutating public exports, the command registry binds
each to the real library function by name, and a test in the library's own
`pnpm test` fails if the manifest drifts — so no authoring function is silently
left unreachable.

Reachability layers: Ctrl+K command palette (all 147) → auto-generated
properties panel → PowerPoint-style ribbon → direct manipulation on the canvas.

Direct manipulation aims to match / surpass Google Slides: shapes move for real
each frame (one undo per gesture), smart-guide snapping, marquee + multi-select,
resize / rotate handles, double-click or type-to-edit inline text, arrow-nudge,
Ctrl+D/C/X/V, zoom / fit, and a right-click context menu. A consistent inline
SVG icon set replaces emoji.

Fully localized (English / Japanese) with a live language switcher; command and
category labels come from the manifest's built-in `labelJa` / `labelEn`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HQKrXTQDSr6XQ4Pb75Yirv
@baseballyama
baseballyama marked this pull request as draft July 24, 2026 06:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants