Skip to content

Commit e35a407

Browse files
feat(embed): #4 embed API v1 (#14)
* docs(plan): #4 embed API v1 implementation plan (Task 0) * feat(embed): protocol envelope types + validator (Task 1) * feat(embed): origin validator + allowedOrigins parser (Task 2) * feat(embed): URL param parser (Task 3) * feat(embed): chrome CSS-class application (Task 4) * feat(embed): theme CSS-class application (Task 5) * feat(embed): EmbedServer constructor + URL-param wire-up (Task 6) - New EmbedServer class in src/embed/server.ts - Detects embed mode from URL params or detectEmbedMode callback - Applies chrome (menu/toolbox/etc visibility) and theme from URL params on init - Attaches message listener only when embedMode is true - Provides dispose() for cleanup + _allowedOriginsForTest getter for unit tests - 4 passing tests covering constructor, listener attachment, chrome application, and theme application * fix(embed): drop unused _server vars in embed-server tests (TS6133) * feat(embed): EmbedServer call dispatch + Element-handle round-trip (Task 7) * feat(embed): EmbedServer event emission + ready() helper (Task 8) * feat(embed): EmbedServer dialog hook system (Task 9) * fix(embed): cover src/embed in tsconfig + .js import extensions + lint cleanup (Tasks 1-9 plan defects) * docs(plan): revise embed-api v1 plan with 6 defect fixes (.js imports, tsconfig include, lint patterns, exactOptional, unused vars, void-listener) * feat(embed): EmbedServer control-message handlers (Task 10) * feat(embed): wire EmbedServer into Editor.ts + svgCanvas event bridge (Task 11) * feat(embed): SvgEditEmbed constructor + ready awaiter (Task 12) * feat(embed): SvgEditEmbed Proxy + Promise correlation + queued-call flush (Task 13) * feat(embed): SvgEditEmbed event subscription (on/off/once) (Task 14) * feat(embed): SvgEditEmbed dialog handler API (Task 15) * feat(embed): SvgEditEmbed convenience methods (setTheme/setChrome/setDialogTimeout) (Task 16) * chore(build): emit dist/embed via tsc + package exports (Task 17) * test(embed): e2e fixture + helpers (Task 18) * test(embed): e2e init handshake (Task 19) Three fixes required to get e2e passing: 1. embed-host.html: change default editorSrc from /src/editor/index.html to /index.html so fixture resolves under vite preview (dist/editor as root) 2. scripts/copy-static.ts: copy tests/e2e/fixtures/embed-host.html and dist/embed/ into dist/editor so vite preview can serve both 3. src/embed/server.ts: default allowedOrigins to [window.location.origin] when no origins are configured, allowing same-origin host->editor calls (getZoom round-trip was silently rejected with empty allowedOrigins) * test(embed): e2e methods round-trip (Task 20) * test(embed): e2e events suite (Task 21) Also fix EditorStartup.ts: bind 'sourcechanged' alongside 'changed' so loadFromString/loadFromURL triggers the embed change event (setSvgString fires sourcechanged, not changed). * test(embed): e2e element-handles round-trip (Task 22) - Add getElem(id) method to svgCanvas that returns elements by ID - Extend getId() to accept an optional Element parameter - When called with an element, getId() returns its id or ELEMENT_NOT_FOUND if element is not in document - Implement element handle serialization/deserialization round-trip tests - Both tests pass on chromium and firefox (4 × 2 = 4 pass total) * test(embed): e2e chrome control (Task 23) * test(embed): e2e theme sync (Task 24) * test(embed): e2e dialog hooks (Task 25) * test(embed): e2e security model (Task 26) * test(embed): e2e versioning (Task 27) * docs(embed): EMBED_API.md + README quickstart (Task 28) * docs(changelog): #4 embed API v1 (Task 29) * fix(embed): chain to previous svgCanvas event handlers (Task 11 regression) svgCanvas.bind() REPLACES the existing handler — it does NOT append. The Task 11 wire-in clobbered the editor's own 'changed' + 'selected' bindings from EditorStartup.ts:212-214 (this.svgCanvas.bind('selected', this.selectedChanged.bind(this)) / this.svgCanvas.bind('changed', this.elementChanged.bind(this))). That broke the editor's reactive UI updates and caused 8 standalone e2e regressions in clipboard / group-transforms / text-tools. Fix: capture the previous handler from bind()'s return value and chain to it before scheduling the embed emit. Also fix the 'selected' handler's arg signature (svgCanvas.call invokes handlers with (window, arg) — selection array is args[1], not args[0]).
1 parent df69fae commit e35a407

37 files changed

Lines changed: 6105 additions & 6 deletions

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added (#4 embed API v1 — 2026-05-21)
11+
12+
- New `src/embed/` module — editor-side `EmbedServer` + host-side `SvgEditEmbed` proxy library + shared protocol/origin/url-params/chrome/theme helpers (8 TypeScript modules).
13+
- New `EMBED_API.md` (472 lines) — canonical host-facing contract documenting URL params, postMessage envelope shape, 8-event allowlist, dialog hooks, chrome control, theme sync, security model, versioning, error codes, raw-protocol reference for non-JS hosts, recommended iframe sandbox attributes.
14+
- `src/editor/Editor.ts` wire-in at line ~333 (after `window.svgEditor = this`) — instantiates `EmbedServer` with version + default dialog handlers wrapping existing `window.seAlert` / `window.seConfirm`; prompt returns default until #13 lands a real prompt-with-input component.
15+
- `src/editor/EditorStartup.ts` — fires `_embedServer.ready()` immediately after the `svgedit:ready` DOM event; bridges svgCanvas events `changed` + `sourcechanged` (debounced 200ms) → embed `change`, and `selected` → embed `selection-changed`.
16+
- `packages/svgcanvas/svgcanvas.ts` — added `getElem(id)` + extended `getId([elem])` to support host-side element-handle round-trip (Task 22 element-handles e2e suite requirement).
17+
- 7 unit-test suites (vitest + jsdom): protocol (5), origin (8), url-params (9), chrome (7), theme (5), server (20), client (16). Total 70 new unit tests.
18+
- 9 e2e suites (Playwright × 2 browsers): init handshake (6), methods round-trip (8), events (10), element-handles (4), chrome control (8), theme sync (6), dialog hooks (4), security (4), versioning (2). Total 52 new e2e tests.
19+
- `tsconfig.embed.json` + `npm run build:embed` step — emits `dist/embed/{client,protocol,origin,url-params,chrome,theme,server,index}.{js,d.ts}` for host consumption.
20+
- `package.json` `exports` field maps `svgedit/embed` to `dist/embed/index.js`.
21+
- `tsconfig.json` `include` array extended with `src/embed/**/*.ts` so ESLint's type-aware lint covers the new module.
22+
- `scripts/copy-static.ts` — copies the e2e fixture + dist/embed/ artifacts into vite-preview's served root so e2e suites can load the embed library + parent-page fixture.
23+
- Closes svgedit todo item #4. Closes 5 of 12 audit-input items (#3 dialog hooks, #5 extension-error event, #8 ready wire-up, #9 load-API doc, #10 read-API doc, #11 extension-injection doc); 6 remaining items tracked as follow-ups in the spec doc.
24+
1025
### Changed (fork-network detach — 2026-05-20)
1126
- Detached `bilbospocketses/svgedit` from the `SVG-Edit/svgedit` fork network (GitHub Settings → Danger Zone → Leave fork network). `gh repo view` confirms post-detach state: `isFork: false`, `parent: null`. The "forked from SVG-Edit/svgedit" badge on GitHub no longer shows; the repo is now standalone in GitHub's repository graph.
1227
- **Why:** Reflects the locked scope directive ("no upstream tracking, no PRs upstream", `project_svgedit.md`) at the repo-metadata level. Fork-network membership was vestigial signal — search-result inclusion in the 1,733-repo network, child-fork-aware rule logic, organisational-affinity behaviour — none of which applied to a repository whose declared lineage is one-way + one-time.

0 commit comments

Comments
 (0)