@hyperframes/core 0.7.27 → 0.7.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/compiler/compositionScoping.d.ts.map +1 -1
  2. package/dist/compiler/compositionScoping.js +13 -0
  3. package/dist/compiler/compositionScoping.js.map +1 -1
  4. package/dist/compiler/inlineSubCompositions.d.ts.map +1 -1
  5. package/dist/compiler/inlineSubCompositions.js +10 -0
  6. package/dist/compiler/inlineSubCompositions.js.map +1 -1
  7. package/dist/figma/assetSnippet.d.ts +3 -0
  8. package/dist/figma/assetSnippet.d.ts.map +1 -0
  9. package/dist/figma/assetSnippet.js +18 -0
  10. package/dist/figma/assetSnippet.js.map +1 -0
  11. package/dist/figma/bindings.d.ts +38 -0
  12. package/dist/figma/bindings.d.ts.map +1 -0
  13. package/dist/figma/bindings.js +84 -0
  14. package/dist/figma/bindings.js.map +1 -0
  15. package/dist/figma/client.d.ts +67 -0
  16. package/dist/figma/client.d.ts.map +1 -0
  17. package/dist/figma/client.js +134 -0
  18. package/dist/figma/client.js.map +1 -0
  19. package/dist/figma/color.d.ts +3 -0
  20. package/dist/figma/color.d.ts.map +1 -0
  21. package/dist/figma/color.js +23 -0
  22. package/dist/figma/color.js.map +1 -0
  23. package/dist/figma/emitTimelineScript.d.ts +3 -0
  24. package/dist/figma/emitTimelineScript.d.ts.map +1 -0
  25. package/dist/figma/emitTimelineScript.js +42 -0
  26. package/dist/figma/emitTimelineScript.js.map +1 -0
  27. package/dist/figma/freeze.d.ts +16 -0
  28. package/dist/figma/freeze.d.ts.map +1 -0
  29. package/dist/figma/freeze.js +67 -0
  30. package/dist/figma/freeze.js.map +1 -0
  31. package/dist/figma/index.d.ts +21 -0
  32. package/dist/figma/index.d.ts.map +1 -0
  33. package/dist/figma/index.js +15 -0
  34. package/dist/figma/index.js.map +1 -0
  35. package/dist/figma/jsonl.d.ts +3 -0
  36. package/dist/figma/jsonl.d.ts.map +1 -0
  37. package/dist/figma/jsonl.js +22 -0
  38. package/dist/figma/jsonl.js.map +1 -0
  39. package/dist/figma/manifest.d.ts +17 -0
  40. package/dist/figma/manifest.d.ts.map +1 -0
  41. package/dist/figma/manifest.js +96 -0
  42. package/dist/figma/manifest.js.map +1 -0
  43. package/dist/figma/motionEase.d.ts +3 -0
  44. package/dist/figma/motionEase.d.ts.map +1 -0
  45. package/dist/figma/motionEase.js +45 -0
  46. package/dist/figma/motionEase.js.map +1 -0
  47. package/dist/figma/motionToGsap.d.ts +3 -0
  48. package/dist/figma/motionToGsap.d.ts.map +1 -0
  49. package/dist/figma/motionToGsap.js +61 -0
  50. package/dist/figma/motionToGsap.js.map +1 -0
  51. package/dist/figma/nodeDocument.d.ts +4 -0
  52. package/dist/figma/nodeDocument.d.ts.map +1 -0
  53. package/dist/figma/nodeDocument.js +26 -0
  54. package/dist/figma/nodeDocument.js.map +1 -0
  55. package/dist/figma/nodeToHtml.d.ts +31 -0
  56. package/dist/figma/nodeToHtml.d.ts.map +1 -0
  57. package/dist/figma/nodeToHtml.js +244 -0
  58. package/dist/figma/nodeToHtml.js.map +1 -0
  59. package/dist/figma/parseFigmaRef.d.ts +3 -0
  60. package/dist/figma/parseFigmaRef.d.ts.map +1 -0
  61. package/dist/figma/parseFigmaRef.js +31 -0
  62. package/dist/figma/parseFigmaRef.js.map +1 -0
  63. package/dist/figma/resolveBindings.d.ts +31 -0
  64. package/dist/figma/resolveBindings.d.ts.map +1 -0
  65. package/dist/figma/resolveBindings.js +77 -0
  66. package/dist/figma/resolveBindings.js.map +1 -0
  67. package/dist/figma/sanitizeSvg.d.ts +18 -0
  68. package/dist/figma/sanitizeSvg.d.ts.map +1 -0
  69. package/dist/figma/sanitizeSvg.js +52 -0
  70. package/dist/figma/sanitizeSvg.js.map +1 -0
  71. package/dist/figma/tokensToVariables.d.ts +40 -0
  72. package/dist/figma/tokensToVariables.d.ts.map +1 -0
  73. package/dist/figma/tokensToVariables.js +118 -0
  74. package/dist/figma/tokensToVariables.js.map +1 -0
  75. package/dist/figma/types.d.ts +81 -0
  76. package/dist/figma/types.d.ts.map +1 -0
  77. package/dist/figma/types.js +2 -0
  78. package/dist/figma/types.js.map +1 -0
  79. package/dist/generated/runtime-inline.js +1 -1
  80. package/dist/generated/runtime-inline.js.map +1 -1
  81. package/dist/hyperframe.runtime.iife.js +19 -19
  82. package/package.json +8 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitTimelineScript.js","sourceRoot":"","sources":["../../src/figma/emitTimelineScript.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * "Freeze" = write asset bytes to local disk permanently so renders never
3
+ * re-fetch from figma (design spec §5) — not Object.freeze.
4
+ */
5
+ export declare const MAX_FREEZE_BYTES: number;
6
+ export declare function exceedsFreezeCap(byteLength: number): boolean;
7
+ export declare function freezeBytes(bytes: Uint8Array, destPath: string): number;
8
+ /**
9
+ * Only figma-owned hosts may be frozen from a URL — render/CDN responses
10
+ * come from figma.com subdomains or figma's S3 buckets. Blocks SSRF via a
11
+ * crafted manifest/config URL (metadata endpoints, internal services).
12
+ */
13
+ export declare function isAllowedFreezeUrl(url: string): boolean;
14
+ export declare function freezeUrl(url: string, destPath: string): Promise<number>;
15
+ export declare function freezeLocalFile(srcPath: string, destPath: string): void;
16
+ //# sourceMappingURL=freeze.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freeze.d.ts","sourceRoot":"","sources":["../../src/figma/freeze.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,eAAO,MAAM,gBAAgB,QAAoB,CAAC;AAElD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAevE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUvD;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS9E;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAMvE"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * "Freeze" = write asset bytes to local disk permanently so renders never
3
+ * re-fetch from figma (design spec §5) — not Object.freeze.
4
+ */
5
+ import { copyFileSync, mkdirSync, rmSync, statSync, writeFileSync } from "node:fs";
6
+ import { dirname } from "node:path";
7
+ // ponytail: bound the write so a hostile/runaway source can't fill the disk.
8
+ export const MAX_FREEZE_BYTES = 256 * 1024 * 1024;
9
+ export function exceedsFreezeCap(byteLength) {
10
+ return byteLength > MAX_FREEZE_BYTES;
11
+ }
12
+ export function freezeBytes(bytes, destPath) {
13
+ if (bytes.length === 0)
14
+ throw new Error("freeze failed: empty bytes");
15
+ if (exceedsFreezeCap(bytes.length))
16
+ throw new Error(`freeze failed: ${bytes.length} bytes exceeds ${MAX_FREEZE_BYTES} cap`);
17
+ mkdirSync(dirname(destPath), { recursive: true });
18
+ // Exclusive create; on EEXIST remove and retry — never write through an
19
+ // existing file or planted symlink (CodeQL js/insecure-temporary-file).
20
+ try {
21
+ writeFileSync(destPath, bytes, { flag: "wx" });
22
+ }
23
+ catch (err) {
24
+ if (err.code !== "EEXIST")
25
+ throw err;
26
+ rmSync(destPath);
27
+ writeFileSync(destPath, bytes, { flag: "wx" });
28
+ }
29
+ return bytes.length;
30
+ }
31
+ /**
32
+ * Only figma-owned hosts may be frozen from a URL — render/CDN responses
33
+ * come from figma.com subdomains or figma's S3 buckets. Blocks SSRF via a
34
+ * crafted manifest/config URL (metadata endpoints, internal services).
35
+ */
36
+ export function isAllowedFreezeUrl(url) {
37
+ let parsed;
38
+ try {
39
+ parsed = new URL(url);
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ if (parsed.protocol !== "https:")
45
+ return false;
46
+ const host = parsed.hostname;
47
+ return host === "figma.com" || host.endsWith(".figma.com") || host.endsWith(".amazonaws.com");
48
+ }
49
+ export async function freezeUrl(url, destPath) {
50
+ if (!isAllowedFreezeUrl(url))
51
+ throw new Error(`freeze failed: refusing non-figma url ${url} (https + figma hosts only)`);
52
+ const res = await fetch(url);
53
+ if (!res.ok)
54
+ throw new Error(`freeze failed: HTTP ${res.status}`);
55
+ const declared = Number(res.headers.get("content-length") ?? 0);
56
+ if (exceedsFreezeCap(declared))
57
+ throw new Error(`freeze failed: content-length ${declared} exceeds ${MAX_FREEZE_BYTES} cap`);
58
+ return freezeBytes(new Uint8Array(await res.arrayBuffer()), destPath);
59
+ }
60
+ export function freezeLocalFile(srcPath, destPath) {
61
+ const size = statSync(srcPath).size;
62
+ if (exceedsFreezeCap(size))
63
+ throw new Error(`freeze failed: ${size} bytes exceeds ${MAX_FREEZE_BYTES} cap`);
64
+ mkdirSync(dirname(destPath), { recursive: true });
65
+ copyFileSync(srcPath, destPath);
66
+ }
67
+ //# sourceMappingURL=freeze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freeze.js","sourceRoot":"","sources":["../../src/figma/freeze.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export type * from "./types";
2
+ export { createFigmaClient, FigmaClientError } from "./client";
3
+ export type { FigmaClient, FigmaClientErrorCode, FigmaClientOptions, FigmaFetch, FigmaFileVersion, FigmaNodeDocument, FigmaStyleMeta, FigmaVariablePayload, FigmaVariablesResult, RenderedNode, RenderNodeOptions, } from "./client";
4
+ export { parseFigmaRef } from "./parseFigmaRef";
5
+ export { MAX_FREEZE_BYTES, exceedsFreezeCap, freezeBytes, freezeUrl, freezeLocalFile, } from "./freeze";
6
+ export { mediaDir, manifestPath, typeDirPath, isFigmaManifestRecord, readManifest, appendRecord, findByFigmaNode, nextId, } from "./manifest";
7
+ export { buildAssetSnippet } from "./assetSnippet";
8
+ export { sanitizeSvg } from "./sanitizeSvg";
9
+ export { appendBinding, upsertBindings, findBindingByFigmaId, readBindings, readLibraryMap, recordLibraryFile, } from "./bindings";
10
+ export type { FigmaBindingRecord } from "./bindings";
11
+ export { figmaColorToCss } from "./color";
12
+ export { resolveBindings } from "./resolveBindings";
13
+ export type { BindingSite, ResolvedBindingSite, ResolveBindingsResult } from "./resolveBindings";
14
+ export { nodeToHtml, slugify } from "./nodeToHtml";
15
+ export type { NodeToHtmlResult, RasterizeRequest } from "./nodeToHtml";
16
+ export { tokensToVariables } from "./tokensToVariables";
17
+ export type { CompositionVariableEntry, FigmaTokenSidecarEntry, FigmaTokensSidecar, TokenSource, TokensToVariablesResult, } from "./tokensToVariables";
18
+ export { mapEase } from "./motionEase";
19
+ export { motionToGsap } from "./motionToGsap";
20
+ export { emitTimelineScript } from "./emitTimelineScript";
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/figma/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,SAAS,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC/D,YAAY,EACV,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,YAAY,EACZ,iBAAiB,GAClB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,eAAe,GAChB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,MAAM,GACP,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EACL,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,WAAW,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACjG,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EACV,wBAAwB,EACxB,sBAAsB,EACtB,kBAAkB,EAClB,WAAW,EACX,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,15 @@
1
+ export { createFigmaClient, FigmaClientError } from "./client.js";
2
+ export { parseFigmaRef } from "./parseFigmaRef.js";
3
+ export { MAX_FREEZE_BYTES, exceedsFreezeCap, freezeBytes, freezeUrl, freezeLocalFile, } from "./freeze.js";
4
+ export { mediaDir, manifestPath, typeDirPath, isFigmaManifestRecord, readManifest, appendRecord, findByFigmaNode, nextId, } from "./manifest.js";
5
+ export { buildAssetSnippet } from "./assetSnippet.js";
6
+ export { sanitizeSvg } from "./sanitizeSvg.js";
7
+ export { appendBinding, upsertBindings, findBindingByFigmaId, readBindings, readLibraryMap, recordLibraryFile, } from "./bindings.js";
8
+ export { figmaColorToCss } from "./color.js";
9
+ export { resolveBindings } from "./resolveBindings.js";
10
+ export { nodeToHtml, slugify } from "./nodeToHtml.js";
11
+ export { tokensToVariables } from "./tokensToVariables.js";
12
+ export { mapEase } from "./motionEase.js";
13
+ export { motionToGsap } from "./motionToGsap.js";
14
+ export { emitTimelineScript } from "./emitTimelineScript.js";
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/figma/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAc/D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,eAAe,GAChB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,MAAM,GACP,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EACL,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAQxD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Parse a .jsonl file into values, skipping blank/malformed lines. */
2
+ export declare function readJsonlValues(path: string): unknown[];
3
+ //# sourceMappingURL=jsonl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl.d.ts","sourceRoot":"","sources":["../../src/figma/jsonl.ts"],"names":[],"mappings":"AAEA,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAevD"}
@@ -0,0 +1,22 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ /** Parse a .jsonl file into values, skipping blank/malformed lines. */
3
+ export function readJsonlValues(path) {
4
+ if (!existsSync(path))
5
+ return [];
6
+ const out = [];
7
+ for (const line of readFileSync(path, "utf8").split(/\r?\n/)) {
8
+ const trimmed = line.trim();
9
+ if (trimmed.length === 0)
10
+ continue;
11
+ try {
12
+ out.push(JSON.parse(trimmed));
13
+ }
14
+ catch {
15
+ // ponytail: skip malformed lines (partial write from a crash), but say
16
+ // so — a silent skip reads as "no record found" downstream.
17
+ console.warn(`skipping malformed jsonl line in ${path}: ${trimmed.slice(0, 40)}…`);
18
+ }
19
+ }
20
+ return out;
21
+ }
22
+ //# sourceMappingURL=jsonl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl.js","sourceRoot":"","sources":["../../src/figma/jsonl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,uEAAuE;AACvE,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,MAAM,GAAG,GAAc,EAAE,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACnC,IAAI,CAAC;YACH,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,uEAAuE;YACvE,4DAA4D;YAC5D,OAAO,CAAC,IAAI,CAAC,oCAAoC,IAAI,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { FigmaManifestRecord } from "./types";
2
+ export declare function mediaDir(projectDir: string): string;
3
+ export declare function manifestPath(projectDir: string): string;
4
+ export declare function typeDirPath(projectDir: string, type: FigmaManifestRecord["type"]): string;
5
+ /**
6
+ * Guards figma-OWNED rows only — media-use rows (bgm/sfx/icon, no
7
+ * provenance.source) legitimately fail this and are filtered out of
8
+ * figma's read-view. The shared file is the inventory; each writer
9
+ * reads its own rows. `nextId` is the one cross-writer concern and
10
+ * scans the full file.
11
+ */
12
+ export declare function isFigmaManifestRecord(value: unknown): value is FigmaManifestRecord;
13
+ export declare function readManifest(projectDir: string): FigmaManifestRecord[];
14
+ export declare function appendRecord(projectDir: string, record: FigmaManifestRecord): void;
15
+ export declare function findByFigmaNode(projectDir: string, fileKey: string, nodeId: string): FigmaManifestRecord | null;
16
+ export declare function nextId(projectDir: string, type: FigmaManifestRecord["type"]): string;
17
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/figma/manifest.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAUnD,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,CAAC,MAAM,CAAC,GAAG,MAAM,CAEzF;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAsBlF;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAEtE;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAGlF;AAED,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,mBAAmB,GAAG,IAAI,CAU5B;AAED,wBAAgB,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,CAAC,MAAM,CAAC,GAAG,MAAM,CA6BpF"}
@@ -0,0 +1,96 @@
1
+ import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { readJsonlValues } from "./jsonl.js";
4
+ const MANIFEST_FILE = "manifest.jsonl";
5
+ // Mirrors the media-use `.media/` layout for interop (one shared inventory).
6
+ const TYPE_DIRS = {
7
+ image: "images",
8
+ video: "video",
9
+ };
10
+ export function mediaDir(projectDir) {
11
+ return join(projectDir, ".media");
12
+ }
13
+ export function manifestPath(projectDir) {
14
+ return join(mediaDir(projectDir), MANIFEST_FILE);
15
+ }
16
+ export function typeDirPath(projectDir, type) {
17
+ return join(mediaDir(projectDir), TYPE_DIRS[type]);
18
+ }
19
+ /**
20
+ * Guards figma-OWNED rows only — media-use rows (bgm/sfx/icon, no
21
+ * provenance.source) legitimately fail this and are filtered out of
22
+ * figma's read-view. The shared file is the inventory; each writer
23
+ * reads its own rows. `nextId` is the one cross-writer concern and
24
+ * scans the full file.
25
+ */
26
+ export function isFigmaManifestRecord(value) {
27
+ if (typeof value !== "object" || value === null)
28
+ return false;
29
+ if (!("id" in value) || !("type" in value) || !("path" in value) || !("source" in value))
30
+ return false;
31
+ if (typeof value.id !== "string" ||
32
+ (value.type !== "image" && value.type !== "video") ||
33
+ typeof value.path !== "string")
34
+ return false;
35
+ if (typeof value.source !== "string")
36
+ return false;
37
+ if (!("provenance" in value))
38
+ return false;
39
+ const provenance = value.provenance;
40
+ if (typeof provenance !== "object" || provenance === null)
41
+ return false;
42
+ if (!("source" in provenance) || !("fileKey" in provenance) || !("nodeId" in provenance))
43
+ return false;
44
+ return (provenance.source === "figma" &&
45
+ typeof provenance.fileKey === "string" &&
46
+ typeof provenance.nodeId === "string");
47
+ }
48
+ export function readManifest(projectDir) {
49
+ return readJsonlValues(manifestPath(projectDir)).filter(isFigmaManifestRecord);
50
+ }
51
+ export function appendRecord(projectDir, record) {
52
+ mkdirSync(typeDirPath(projectDir, record.type), { recursive: true });
53
+ appendFileSync(manifestPath(projectDir), JSON.stringify(record) + "\n");
54
+ }
55
+ export function findByFigmaNode(projectDir, fileKey, nodeId) {
56
+ for (const r of readManifest(projectDir)) {
57
+ if (r.provenance.source === "figma" &&
58
+ r.provenance.fileKey === fileKey &&
59
+ r.provenance.nodeId === nodeId)
60
+ return r;
61
+ }
62
+ return null;
63
+ }
64
+ export function nextId(projectDir, type) {
65
+ const re = new RegExp(`^${type}_(\\d+)$`);
66
+ let max = 0;
67
+ // Scan EVERY writer's rows (media-use included), not just figma-owned ones —
68
+ // ids and file paths are shared across the inventory, so a figma id minted
69
+ // from a figma-only view would collide with media-use's image_NNN files.
70
+ const p = manifestPath(projectDir);
71
+ if (!existsSync(p))
72
+ return `${type}_001`;
73
+ for (const line of readFileSync(p, "utf8").split(/\r?\n/)) {
74
+ const trimmed = line.trim();
75
+ if (trimmed.length === 0)
76
+ continue;
77
+ let parsed;
78
+ try {
79
+ parsed = JSON.parse(trimmed);
80
+ }
81
+ catch {
82
+ continue;
83
+ }
84
+ if (typeof parsed !== "object" ||
85
+ parsed === null ||
86
+ !("id" in parsed) ||
87
+ typeof parsed.id !== "string")
88
+ continue;
89
+ const m = parsed.id.match(re);
90
+ const n = m?.[1];
91
+ if (n !== undefined)
92
+ max = Math.max(max, Number.parseInt(n, 10));
93
+ }
94
+ return `${type}_${String(max + 1).padStart(3, "0")}`;
95
+ }
96
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/figma/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { MappedEase, MotionEase } from "./types";
2
+ export declare function mapEase(ease: MotionEase): MappedEase;
3
+ //# sourceMappingURL=motionEase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motionEase.d.ts","sourceRoot":"","sources":["../../src/figma/motionEase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAqCtD,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CASpD"}
@@ -0,0 +1,45 @@
1
+ // Full motion.dev named-ease coverage → nearest GSAP equivalent. Anything
2
+ // outside this table falls back to "none" (linear) — documented in the
3
+ // /figma skill's motion section so the fallback is never a surprise.
4
+ const NAMED_EASE = {
5
+ linear: "none",
6
+ ease: "power1.inOut",
7
+ easein: "power2.in",
8
+ easeout: "power2.out",
9
+ easeinout: "power2.inOut",
10
+ easeinandout: "power2.inOut",
11
+ backin: "back.in",
12
+ backout: "back.out",
13
+ backinout: "back.inOut",
14
+ backinandout: "back.inOut",
15
+ circin: "circ.in",
16
+ circout: "circ.out",
17
+ circinout: "circ.inOut",
18
+ expoin: "expo.in",
19
+ expoout: "expo.out",
20
+ expoinout: "expo.inOut",
21
+ bouncein: "bounce.in",
22
+ bounceout: "bounce.out",
23
+ bounceinout: "bounce.inOut",
24
+ elasticin: "elastic.in",
25
+ elasticout: "elastic.out",
26
+ elasticinout: "elastic.inOut",
27
+ anticipate: "back.in",
28
+ spring: "elastic.out",
29
+ hold: "steps(1)",
30
+ };
31
+ function isBezier4(ease) {
32
+ return ease.length === 4 && ease.every((n) => typeof n === "number" && Number.isFinite(n));
33
+ }
34
+ export function mapEase(ease) {
35
+ if (Array.isArray(ease)) {
36
+ // Runtime-validate the 4-tuple: a malformed payload (3 numbers, NaN)
37
+ // would otherwise emit a broken CustomEase path that fails at load.
38
+ if (isBezier4(ease))
39
+ return { kind: "bezier", bezier: ease };
40
+ return { kind: "named", ease: "none" };
41
+ }
42
+ const key = ease.toLowerCase().replace(/[_\s-]/g, "");
43
+ return { kind: "named", ease: NAMED_EASE[key] ?? "none" };
44
+ }
45
+ //# sourceMappingURL=motionEase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motionEase.js","sourceRoot":"","sources":["../../src/figma/motionEase.ts"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,uEAAuE;AACvE,qEAAqE;AACrE,MAAM,UAAU,GAA2B;IACzC,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,cAAc;IACpB,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,YAAY;IACrB,SAAS,EAAE,cAAc;IACzB,YAAY,EAAE,cAAc;IAC5B,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,UAAU;IACnB,SAAS,EAAE,YAAY;IACvB,YAAY,EAAE,YAAY;IAC1B,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,UAAU;IACnB,SAAS,EAAE,YAAY;IACvB,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,UAAU;IACnB,SAAS,EAAE,YAAY;IACvB,QAAQ,EAAE,WAAW;IACrB,SAAS,EAAE,YAAY;IACvB,WAAW,EAAE,cAAc;IAC3B,SAAS,EAAE,YAAY;IACvB,UAAU,EAAE,aAAa;IACzB,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,SAAS;IACrB,MAAM,EAAE,aAAa;IACrB,IAAI,EAAE,UAAU;CACjB,CAAC;AAEF,SAAS,SAAS,CAAC,IAAe;IAChC,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAgB;IACtC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,qEAAqE;QACrE,oEAAoE;QACpE,IAAI,SAAS,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC7D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACzC,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACtD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { MotionDoc, TimelineSpec } from "./types";
2
+ export declare function motionToGsap(doc: MotionDoc): TimelineSpec;
3
+ //# sourceMappingURL=motionToGsap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motionToGsap.d.ts","sourceRoot":"","sources":["../../src/figma/motionToGsap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,SAAS,EAET,YAAY,EACb,MAAM,SAAS,CAAC;AAgFjB,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS,GAAG,YAAY,CAKzD"}
@@ -0,0 +1,61 @@
1
+ import { mapEase } from "./motionEase.js";
2
+ /**
3
+ * repeat semantics match GSAP and motion.dev: count of EXTRA plays
4
+ * (0 = play once). Infinity clamps to 0 — a single play — because a
5
+ * deterministic render needs a finite timeline; composition-duration-aware
6
+ * loop counts are a later milestone (spec §6 motion notes).
7
+ */
8
+ function clampRepeat(repeat) {
9
+ return repeat !== undefined && Number.isFinite(repeat) && repeat > 0 ? Math.floor(repeat) : 0;
10
+ }
11
+ function deriveId(selector) {
12
+ const base = selector.replace(/^[#.]/, "").replace(/[^A-Za-z0-9_-]/g, "-");
13
+ return `figma-${base.length > 0 ? base : "timeline"}`;
14
+ }
15
+ /** Resolves one segment's ease, registering a CustomEase in `customEases` for bezier arrays. */
16
+ function resolveStepEase(rawEase, customEases, counter) {
17
+ const mapped = mapEase(rawEase);
18
+ if (mapped.kind === "bezier") {
19
+ const name = `hfCe${counter.value}`;
20
+ counter.value += 1;
21
+ customEases.push({ name, bezier: mapped.bezier });
22
+ return name;
23
+ }
24
+ return mapped.ease;
25
+ }
26
+ function buildSteps(track, customEases, counter) {
27
+ const steps = [];
28
+ for (let i = 1; i < track.values.length; i += 1) {
29
+ const tPrev = track.times[i - 1];
30
+ const tCur = track.times[i];
31
+ const value = track.values[i];
32
+ if (tPrev === undefined || tCur === undefined || value === undefined)
33
+ continue;
34
+ const rawEase = track.ease[i - 1] ?? "linear";
35
+ const ease = resolveStepEase(rawEase, customEases, counter);
36
+ steps.push({ value, duration: (tCur - tPrev) * track.duration, ease });
37
+ }
38
+ return steps;
39
+ }
40
+ function buildTween(track, selector, customEases, counter) {
41
+ if (track.values.length < 2 || track.times.length !== track.values.length) {
42
+ throw new Error(`motionToGsap: invalid track "${track.property}" (values/times mismatch)`);
43
+ }
44
+ const initial = track.values[0];
45
+ if (initial === undefined)
46
+ throw new Error(`motionToGsap: empty track "${track.property}"`);
47
+ return {
48
+ selector,
49
+ property: track.property,
50
+ initial,
51
+ steps: buildSteps(track, customEases, counter),
52
+ repeat: clampRepeat(track.repeat),
53
+ };
54
+ }
55
+ export function motionToGsap(doc) {
56
+ const customEases = [];
57
+ const counter = { value: 0 };
58
+ const tweens = doc.tracks.map((track) => buildTween(track, doc.selector, customEases, counter));
59
+ return { timelineId: deriveId(doc.selector), tweens, customEases };
60
+ }
61
+ //# sourceMappingURL=motionToGsap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motionToGsap.js","sourceRoot":"","sources":["../../src/figma/motionToGsap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAUvC;;;;;GAKG;AACH,SAAS,WAAW,CAAC,MAA0B;IAC7C,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChG,CAAC;AAED,SAAS,QAAQ,CAAC,QAAgB;IAChC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IAC3E,OAAO,SAAS,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;AACxD,CAAC;AAOD,gGAAgG;AAChG,SAAS,eAAe,CACtB,OAAkD,EAClD,WAA4B,EAC5B,OAA0B;IAE1B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC;QACpC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;QACnB,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,SAAS,UAAU,CACjB,KAAkB,EAClB,WAA4B,EAC5B,OAA0B;IAE1B,MAAM,KAAK,GAAuB,EAAE,CAAC;IAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAE/E,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,QAAQ,CAAC;QAC9C,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CACjB,KAAkB,EAClB,QAAgB,EAChB,WAA4B,EAC5B,OAA0B;IAE1B,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,gCAAgC,KAAK,CAAC,QAAQ,2BAA2B,CAAC,CAAC;IAC7F,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC;IAE5F,OAAO;QACL,QAAQ;QACR,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO;QACP,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC;QAC9C,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC;KAClC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAc;IACzC,MAAM,WAAW,GAAoB,EAAE,CAAC;IACxC,MAAM,OAAO,GAAsB,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAChD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;IAChG,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;AACrE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { FigmaNodeDocument } from "./client";
2
+ /** Typed children of a node document (unknown-shaped entries skipped). */
3
+ export declare function childDocuments(node: FigmaNodeDocument): FigmaNodeDocument[];
4
+ //# sourceMappingURL=nodeDocument.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeDocument.d.ts","sourceRoot":"","sources":["../../src/figma/nodeDocument.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAmBlD,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,IAAI,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,CAQ3E"}
@@ -0,0 +1,26 @@
1
+ function isRecord(value) {
2
+ return typeof value === "object" && value !== null;
3
+ }
4
+ /** Narrow an unknown child entry to a node document, or null. */
5
+ function asNodeDocument(value) {
6
+ if (isRecord(value) &&
7
+ typeof value.id === "string" &&
8
+ typeof value.name === "string" &&
9
+ typeof value.type === "string") {
10
+ return { ...value, id: value.id, name: value.name, type: value.type };
11
+ }
12
+ return null;
13
+ }
14
+ /** Typed children of a node document (unknown-shaped entries skipped). */
15
+ export function childDocuments(node) {
16
+ if (!Array.isArray(node.children))
17
+ return [];
18
+ const out = [];
19
+ for (const child of node.children) {
20
+ const doc = asNodeDocument(child);
21
+ if (doc)
22
+ out.push(doc);
23
+ }
24
+ return out;
25
+ }
26
+ //# sourceMappingURL=nodeDocument.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeDocument.js","sourceRoot":"","sources":["../../src/figma/nodeDocument.ts"],"names":[],"mappings":"AAEA,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,iEAAiE;AACjE,SAAS,cAAc,CAAC,KAAc;IACpC,IACE,QAAQ,CAAC,KAAK,CAAC;QACf,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ;QAC5B,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC9B,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAC9B,CAAC;QACD,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IACxE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,cAAc,CAAC,IAAuB;IACpD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IAC7C,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,GAAG;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Phase 3 mapper: figma node tree → editable HTML with inline styles
3
+ * (design spec §7, hybrid fidelity routing).
4
+ *
5
+ * - Geometry is exact for free: absolute positioning at figma bounds inside
6
+ * a fixed-size root — no responsive reflow, no drift.
7
+ * - CSS where CSS is faithful: solid/linear-gradient fills, corner radius,
8
+ * opacity, drop shadow, blur, text styles.
9
+ * - Everything CSS can't match faithfully (vectors, boolean ops, exotic
10
+ * paint) routes to the rasterize list — the caller exports those nodes as
11
+ * images (Phase 1) and fills in the placeholder src.
12
+ * - Bindings (§7.1): resolved sites emit var(--slug, literal) so a brand
13
+ * refresh propagates; unresolved sites bake the literal and carry a
14
+ * data-figma-unresolved flag. Never a dangling var().
15
+ * - visible:false nodes and fills are skipped — figma's own renderer
16
+ * semantics, not ours.
17
+ */
18
+ import type { FigmaNodeDocument } from "./client";
19
+ import type { ResolveBindingsResult } from "./resolveBindings";
20
+ export interface RasterizeRequest {
21
+ nodeId: string;
22
+ name: string;
23
+ slug: string;
24
+ }
25
+ export interface NodeToHtmlResult {
26
+ html: string;
27
+ rasterize: RasterizeRequest[];
28
+ }
29
+ export declare function slugify(name: string): string;
30
+ export declare function nodeToHtml(root: FigmaNodeDocument, bindings: ResolveBindingsResult): NodeToHtmlResult;
31
+ //# sourceMappingURL=nodeToHtml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeToHtml.d.ts","sourceRoot":"","sources":["../../src/figma/nodeToHtml.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAGlD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAmCD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5C;AAgND,wBAAgB,UAAU,CACxB,IAAI,EAAE,iBAAiB,EACvB,QAAQ,EAAE,qBAAqB,GAC9B,gBAAgB,CAKlB"}