Files
hyperframes/packages/core/src/figma/assetSnippet.test.ts
T
Vance Ingalls 397c3ba7a8 feat(core): figma module foundations — types, parseFigmaRef, freeze, manifest, asset snippet (#1868)
## What

Foundations of the `@hyperframes/core/figma` module — the pure, transport-agnostic layer every later phase builds on:

- **`types.ts`** — `FigmaRef`, `FigmaProvenance`, `FigmaManifestRecord`, and the Motion model (`MotionDoc`/`MotionTrack`/`TimelineSpec`/`GsapTween`) shared across the stack.
- **`parseFigmaRef`** — normalizes any user input (full `/design|/file|/proto` URLs with `?node-id=1-2`, `fileKey:nodeId` shorthand, bare `fileKey`) into `{ fileKey, nodeId }`, including the URL-dash → API-colon node-id conversion.
- **`freeze.ts`** — `freezeBytes`/`freezeUrl`/`freezeLocalFile` with a 256 MB cap; every Figma asset is frozen to a local file before it can reach a composition (determinism: no render-time network).
- **`manifest.ts`** — the `.media/manifest.jsonl` ledger (same layout `media-use` writes, so a project has one shared media inventory without either skill depending on the other): append/read/find-by-node/next-id, with a pure type-guard (`isFigmaManifestRecord`) instead of `as`-casts.
- **`assetSnippet.ts`** — manifest record → composition `<img>` snippet with escaped attrs + `data-figma-id`.
- **publishConfig fix** — `./figma` added to `packages/core` `publishConfig.exports` (the packed-manifest CI gate requires every source export to have a dist mapping).

## Why

Design spec: `docs/superpowers/specs/2026-06-30-figma-asset-integration-design.md`. These functions are deliberately transport-agnostic — when the project reversed from MCP-first to a REST/MCP split (spec §2), nothing in this layer changed. That was the point.

## Tests

Unit tests per module (URL variants, freeze cap edges, manifest round-trip/malformed-line tolerance, snippet escaping). All colocated `*.test.ts`, vitest, no network.

---
Stack (1/6): this PR → #1869#1870#1871#1872#1873

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-03 14:12:24 -07:00

29 lines
994 B
TypeScript

// @vitest-environment node
import { describe, expect, it } from "vitest";
import { buildAssetSnippet } from "./assetSnippet";
import type { FigmaManifestRecord } from "./types";
const record: FigmaManifestRecord = {
id: "image_001",
type: "image",
path: ".media/images/image_001.png",
source: "figma",
description: 'Hero "banner"',
width: 240,
height: 57,
provenance: { source: "figma", fileKey: "FK", nodeId: "92:573", format: "png" },
};
describe("buildAssetSnippet", () => {
it("emits an img tag with src, dims, escaped alt, and data-figma-id", () => {
const { path, html } = buildAssetSnippet(record);
expect(path).toBe(".media/images/image_001.png");
expect(html).toContain('src=".media/images/image_001.png"');
expect(html).toContain('width="240"');
expect(html).toContain('height="57"');
expect(html).toContain('data-figma-id="92:573"');
expect(html).toContain("&quot;banner&quot;");
expect(html).not.toContain('"banner"');
});
});