mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 23:03:09 +00:00
fix(slideshow): finish remaining split-PR review findings (#1594)
* fix(slideshow): address split-PR review findings on #1585 Genuinely-open findings from the #1580/#1590/#1591/#1592 reviews (the rest were already fixed on this branch: CSP handlers, manifest version, UUID ids, float keys, presenter 1s-timer): core (#1580): - isManifest rejects a non-object/array manifest (e.g. [42,null]) explicitly - resolveSlideshow flags duplicate slideSequence ids instead of silent overwrite player (#1590): - present() window.open uses noopener,noreferrer (audience syncs via channel) - BroadcastChannel name is per-deck (keyed on pathname) to avoid same-origin cross-talk between decks - add observedAttributes + attributeChangedCallback so runtime sound/mode toggles re-render studio (#1591/#1592): - persistSlideshowManifest no-op gate (skip write when HTML is unchanged) - surface persist failures (console.error) instead of silent .catch(()=>{}) - confirm before deleting a branch sequence (data-loss + dangling hotspots) + tests for the collision + non-object-manifest rejection. 20 core / 106 player / 53 studio pass; tsc/lint/fmt/fallow clean; deck still renders. * fix(slideshow): finish remaining split-PR review findings The larger items from the #1580/#1590/#1591/#1592 reviews (the rest landed in #1585): core (#1580): - dedup isSceneLikeCompositionId — shared slideshow/sceneId.ts, used by both the lint rule and the runtime scene-window computation (no more mirror-and-drift) player (#1590 / #1592): - onKey: when multiple decks share a page, drop the unfocused-convenience so a key drives only the focused deck - slow-iframe recovery: if the scene timeline posts after the wait times out (empty scenes), re-init once so sceneId slides resolve instead of being dropped studio (#1591): - persistSlideshowManifest validates the built island round-trips before writing - reorderBranchSlide helper + BranchTree up/down controls (parallel to main-line reorder), with a branch-position indicator + tests for reorderBranchSlide. core 228 / player 106 / studio (panel) 46 pass; tsc/lint/fmt/fallow clean. * fix(player,cli): use fileURLToPath for path resolution (Windows CI) new URL(...).pathname yields a leading-slash drive path ("/D:/...") on Windows, which broke: - packages/player/vitest.config.ts — the @hyperframes/core/slideshow alias resolved to a nonexistent path, failing the player slideshow tests on the Windows render-verification CI (passed on macOS/Linux where pathname is clean) - packages/cli/src/utils/compositionServer.ts helperDir — same bug in the play/present bundle-path resolution fileURLToPath converts file:// URLs to correct OS paths on all platforms. Player slideshow tests pass; present serves + resolves bundles. * fix(producer): fileURLToPath for the renders dir (Windows) DEFAULT_RENDERS_DIR used new URL(import.meta.url).pathname, which is "/D:/..." on Windows and resolves to a bogus path — affects the Windows render pipeline. Last of the .pathname -> fileURLToPath fixes (repo-wide src sweep now clean).
This commit is contained in:
@@ -20,6 +20,7 @@ import type { SlideshowManifest } from "@hyperframes/core/slideshow";
|
||||
import {
|
||||
SLIDESHOW_ISLAND_TYPE,
|
||||
SLIDESHOW_MANIFEST_VERSION,
|
||||
parseSlideshowManifest,
|
||||
slideshowIslandRegex,
|
||||
} from "@hyperframes/core/slideshow";
|
||||
import type { Composition } from "@hyperframes/sdk";
|
||||
@@ -64,6 +65,18 @@ export async function persistSlideshowManifest(args: PersistSlideshowArgs): Prom
|
||||
const { manifest, sdkSession, originalContent, targetPath, deps, label, coalesceKey } = args;
|
||||
|
||||
const islandHtml = buildSlideshowIslandHtml(manifest);
|
||||
|
||||
// Write-time validation: confirm the island we just built round-trips to a
|
||||
// valid manifest before touching disk, so a malformed edit can't corrupt the
|
||||
// composition. parseSlideshowManifest throws on a structurally-invalid island.
|
||||
try {
|
||||
if (!parseSlideshowManifest(islandHtml)) {
|
||||
throw new Error("built island did not parse back to a manifest");
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(`refusing to persist invalid slideshow manifest: ${(err as Error).message}`);
|
||||
}
|
||||
|
||||
const current = sdkSession.serialize();
|
||||
|
||||
// Strip ALL existing islands (handles the case where two stale islands
|
||||
@@ -78,6 +91,10 @@ export async function persistSlideshowManifest(args: PersistSlideshowArgs): Prom
|
||||
after = stripped + "\n" + islandHtml;
|
||||
}
|
||||
|
||||
// No-op gate: if the rewritten HTML is byte-identical to the current serialized
|
||||
// HTML, skip the write — avoids a spurious disk write and a no-op undo entry.
|
||||
if (after === current) return;
|
||||
|
||||
await persistSdkSerialize(after, targetPath, originalContent, deps, {
|
||||
label: label ?? "Edit slideshow",
|
||||
...(coalesceKey ? { coalesceKey } : {}),
|
||||
|
||||
Reference in New Issue
Block a user