mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
feat(studio,core): populate hfId in DomEditSelection + widen MutationTarget (R7, T5a) (#1296)
## Summary - Adds `hfId` field to `resolveDomEditSelection` — reads `data-hf-id` off the live element and stores it in `DomEditSelection.hfId` - `DomEditSelection extends PatchTarget` which already declares `hfId?: string`, so this is a single new line at the return site - Widens `MutationTarget` in `files.ts` to include `hfId?: string` (type hygiene — the value already survives through `parseMutationBody`'s by-reference pass, so this is documentation not a behaviour change) ## Why R7 / Task 5a. The full hf-id write-back and patch-engine infrastructure (R1 + R7 Tasks 0–4, PRs #1269–#1292) is server-complete. The only missing piece was: the Studio client never read `data-hf-id` off a hit-tested element, so `target.hfId` was always `undefined` and the `hfId`-first lookup branches in both patch engines were unreachable in production. This PR fixes the selection side — the commit wire (#1297) completes the path. ## Test plan - [ ] `packages/studio/src/components/editor/domEditingLayers.test.ts` — two new tests with jsdom environment: - `resolveDomEditSelection` on an element with `data-hf-id` → `selection.hfId` is populated - element without `data-hf-id` → `selection.hfId` is `undefined` - [ ] All 65 studio test files pass, all 72 core test files pass 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
@@ -84,7 +84,12 @@ function resolveFileMutationContext(c: RouteContext, adapter: StudioApiAdapter,
|
|||||||
return resolveProjectPath(c, adapter, (id) => `/projects/${id}/file-mutations/${operation}/`);
|
return resolveProjectPath(c, adapter, (id) => `/projects/${id}/file-mutations/${operation}/`);
|
||||||
}
|
}
|
||||||
|
|
||||||
type MutationTarget = { id?: string | null; selector?: string; selectorIndex?: number };
|
type MutationTarget = {
|
||||||
|
id?: string | null;
|
||||||
|
hfId?: string;
|
||||||
|
selector?: string;
|
||||||
|
selectorIndex?: number;
|
||||||
|
};
|
||||||
|
|
||||||
/** Write `next` to `absPath` only if it differs from `original`, returning a standardized change response. */
|
/** Write `next` to `absPath` only if it differs from `original`, returning a standardized change response. */
|
||||||
function writeIfChanged(
|
function writeIfChanged(
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { resolveDomEditSelection } from "./domEditingLayers";
|
||||||
|
|
||||||
|
const opts = { activeCompositionPath: "index.html", isMasterView: true, skipSourceProbe: true };
|
||||||
|
|
||||||
|
describe("resolveDomEditSelection — hfId from data-hf-id", () => {
|
||||||
|
it("populates hfId from the element data-hf-id attribute", async () => {
|
||||||
|
const el = document.createElement("div");
|
||||||
|
el.id = "hero";
|
||||||
|
el.setAttribute("data-hf-id", "hf-x7k2");
|
||||||
|
document.body.appendChild(el);
|
||||||
|
|
||||||
|
const selection = await resolveDomEditSelection(el, opts);
|
||||||
|
document.body.removeChild(el);
|
||||||
|
|
||||||
|
expect(selection?.hfId).toBe("hf-x7k2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("leaves hfId undefined when element has no data-hf-id", async () => {
|
||||||
|
const el = document.createElement("div");
|
||||||
|
el.id = "no-hfid-el";
|
||||||
|
document.body.appendChild(el);
|
||||||
|
|
||||||
|
const selection = await resolveDomEditSelection(el, opts);
|
||||||
|
document.body.removeChild(el);
|
||||||
|
|
||||||
|
expect(selection?.hfId).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -369,6 +369,7 @@ export async function resolveDomEditSelection(
|
|||||||
return {
|
return {
|
||||||
element: current,
|
element: current,
|
||||||
id: current.id || undefined,
|
id: current.id || undefined,
|
||||||
|
hfId: current.getAttribute("data-hf-id") ?? undefined,
|
||||||
selector,
|
selector,
|
||||||
selectorIndex,
|
selectorIndex,
|
||||||
sourceFile,
|
sourceFile,
|
||||||
|
|||||||
Reference in New Issue
Block a user