From 2071c85c9a93fc08ea73cff53d601c29c1bc7f37 Mon Sep 17 00:00:00 2001 From: Vance Ingalls Date: Tue, 9 Jun 2026 14:18:14 -0700 Subject: [PATCH] feat(studio,core): populate hfId in DomEditSelection + widen MutationTarget (R7, T5a) (#1296) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 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) --- packages/core/src/studio-api/routes/files.ts | 7 ++++- .../editor/domEditingLayers.test.ts | 30 +++++++++++++++++++ .../src/components/editor/domEditingLayers.ts | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 packages/studio/src/components/editor/domEditingLayers.test.ts diff --git a/packages/core/src/studio-api/routes/files.ts b/packages/core/src/studio-api/routes/files.ts index fddd4321d..8cc7996a9 100644 --- a/packages/core/src/studio-api/routes/files.ts +++ b/packages/core/src/studio-api/routes/files.ts @@ -84,7 +84,12 @@ function resolveFileMutationContext(c: RouteContext, adapter: StudioApiAdapter, 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. */ function writeIfChanged( diff --git a/packages/studio/src/components/editor/domEditingLayers.test.ts b/packages/studio/src/components/editor/domEditingLayers.test.ts new file mode 100644 index 000000000..8a39e5441 --- /dev/null +++ b/packages/studio/src/components/editor/domEditingLayers.test.ts @@ -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(); + }); +}); diff --git a/packages/studio/src/components/editor/domEditingLayers.ts b/packages/studio/src/components/editor/domEditingLayers.ts index bb2570b58..e53e3360d 100644 --- a/packages/studio/src/components/editor/domEditingLayers.ts +++ b/packages/studio/src/components/editor/domEditingLayers.ts @@ -369,6 +369,7 @@ export async function resolveDomEditSelection( return { element: current, id: current.id || undefined, + hfId: current.getAttribute("data-hf-id") ?? undefined, selector, selectorIndex, sourceFile,