refactor(core,studio): extract draft-marker constants + R7 code-review fixes (Task 4) (#1292)

* refactor(core,studio): extract draft-marker constants to core (R7, Task 4)

Create draftMarkers.ts in core with 5 shared CSS custom property names and the
gesture DOM attribute. PreviewAdapter imports from draftMarkers.ts instead of
hardcoding strings. Adds @hyperframes/core/studio-api/draft-markers export
subpath. Studio's manualEditsTypes.ts re-exports the shared constants from core
so all existing call sites are unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(core): address R7 code-review findings (C1–C14, P6–P7)

- previewAdapter: auto-revert previous gesture in applyDraft (C3); clearDraftProps
  on commitPreview not just revertDraft (C4); isVisible NaN→visible for JSDOM (P7);
  remove redundant GestureState.hfId field (C12); remove Array.from (C14);
  extract clearDraftProps/revertGesture helpers (C5/C6)
- hfIdPersist: replace string-equality change detection with attribute count to
  avoid false-positive writes on single-quoted HTML (C1); re-read disk before
  write for TOCTOU guard (C7); remove normalizeHfIds wrapper (C11)
- preview.ts: remove dead null-check on normalizedDisk after diskMain guard (C9);
  catch path re-reads disk fresh instead of using stale pre-request snapshot (C8)
- hfIds.test.ts: replace tautological second stability test with cross-document
  content-keyed id stability test (P6)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(core): follow-up R7 review fixes — CSS.escape fallback, invariant docs, new edge-case tests

- hfIdPersist: remove ensureHfIds re-export (P2); add JSDoc invariant note;
  improve TOCTOU comment; pass err to console.warn
- preview.ts: split import — ensureHfIds from parsers/hfIds.js (not re-export)
- previewAdapter: CSS.escape + inline fallback for non-browser environments;
  add JSDoc for atTime caller-seek contract; add 0.01 opacity-threshold comment
- previewAdapter.test: rename atTime test to clarify adapter-does-not-seek;
  add nested-hf-root-without-id test; add resize→move prop-leak test;
  add revertDraft-after-commit no-op test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(core): bundle-vs-disk id-stability test; comment double ensureHfIds (P3)

- preview.test: add "bundle returning untagged HTML gets same ids as disk" test —
  guards against id divergence when bundler reads a pre-write cache snapshot;
  content-keyed FNV1a minting ensures served ids == disk ids for same source HTML
- preview.ts: comment the second ensureHfIds call explaining it's intentional for
  adapter-injected elements and idempotent on the no-bundle path (P3 from miguel)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(core): wire-contract comment on mintHfId + fallow suppressions (R7)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vance Ingalls
2026-06-09 01:13:54 -07:00
committed by GitHub
co-authored by Claude Sonnet 4.6
parent 1a23938bef
commit 3d7d7c0291
11 changed files with 253 additions and 95 deletions
@@ -1,13 +1,15 @@
/* ── Public constants ──────────────────────────────────────────────── */
export const STUDIO_OFFSET_X_PROP = "--hf-studio-offset-x";
export const STUDIO_OFFSET_Y_PROP = "--hf-studio-offset-y";
export const STUDIO_WIDTH_PROP = "--hf-studio-width";
export const STUDIO_HEIGHT_PROP = "--hf-studio-height";
export {
STUDIO_OFFSET_X_PROP,
STUDIO_OFFSET_Y_PROP,
STUDIO_WIDTH_PROP,
STUDIO_HEIGHT_PROP,
STUDIO_MANUAL_EDIT_GESTURE_ATTR,
} from "@hyperframes/core/studio-api/draft-markers";
export const STUDIO_ROTATION_PROP = "--hf-studio-rotation";
/* ── Internal DOM attribute names ─────────────────────────────────── */
export const STUDIO_PATH_OFFSET_ATTR = "data-hf-studio-path-offset";
export const STUDIO_MANUAL_EDIT_GESTURE_ATTR = "data-hf-studio-manual-edit-gesture";
export const STUDIO_BOX_SIZE_ATTR = "data-hf-studio-box-size";
export const STUDIO_ROTATION_ATTR = "data-hf-studio-rotation";
export const STUDIO_ORIGINAL_TRANSLATE_ATTR = "data-hf-studio-original-translate";