@hyperframes/core 0.7.28 → 0.7.30
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.
- package/dist/figma/assetSnippet.d.ts +3 -0
- package/dist/figma/assetSnippet.d.ts.map +1 -0
- package/dist/figma/assetSnippet.js +18 -0
- package/dist/figma/assetSnippet.js.map +1 -0
- package/dist/figma/bindings.d.ts +38 -0
- package/dist/figma/bindings.d.ts.map +1 -0
- package/dist/figma/bindings.js +84 -0
- package/dist/figma/bindings.js.map +1 -0
- package/dist/figma/client.d.ts +67 -0
- package/dist/figma/client.d.ts.map +1 -0
- package/dist/figma/client.js +134 -0
- package/dist/figma/client.js.map +1 -0
- package/dist/figma/color.d.ts +3 -0
- package/dist/figma/color.d.ts.map +1 -0
- package/dist/figma/color.js +23 -0
- package/dist/figma/color.js.map +1 -0
- package/dist/figma/emitTimelineScript.d.ts +3 -0
- package/dist/figma/emitTimelineScript.d.ts.map +1 -0
- package/dist/figma/emitTimelineScript.js +42 -0
- package/dist/figma/emitTimelineScript.js.map +1 -0
- package/dist/figma/freeze.d.ts +16 -0
- package/dist/figma/freeze.d.ts.map +1 -0
- package/dist/figma/freeze.js +67 -0
- package/dist/figma/freeze.js.map +1 -0
- package/dist/figma/index.d.ts +21 -0
- package/dist/figma/index.d.ts.map +1 -0
- package/dist/figma/index.js +15 -0
- package/dist/figma/index.js.map +1 -0
- package/dist/figma/jsonl.d.ts +3 -0
- package/dist/figma/jsonl.d.ts.map +1 -0
- package/dist/figma/jsonl.js +22 -0
- package/dist/figma/jsonl.js.map +1 -0
- package/dist/figma/manifest.d.ts +17 -0
- package/dist/figma/manifest.d.ts.map +1 -0
- package/dist/figma/manifest.js +96 -0
- package/dist/figma/manifest.js.map +1 -0
- package/dist/figma/motionEase.d.ts +3 -0
- package/dist/figma/motionEase.d.ts.map +1 -0
- package/dist/figma/motionEase.js +45 -0
- package/dist/figma/motionEase.js.map +1 -0
- package/dist/figma/motionToGsap.d.ts +3 -0
- package/dist/figma/motionToGsap.d.ts.map +1 -0
- package/dist/figma/motionToGsap.js +61 -0
- package/dist/figma/motionToGsap.js.map +1 -0
- package/dist/figma/nodeDocument.d.ts +4 -0
- package/dist/figma/nodeDocument.d.ts.map +1 -0
- package/dist/figma/nodeDocument.js +26 -0
- package/dist/figma/nodeDocument.js.map +1 -0
- package/dist/figma/nodeToHtml.d.ts +31 -0
- package/dist/figma/nodeToHtml.d.ts.map +1 -0
- package/dist/figma/nodeToHtml.js +244 -0
- package/dist/figma/nodeToHtml.js.map +1 -0
- package/dist/figma/parseFigmaRef.d.ts +3 -0
- package/dist/figma/parseFigmaRef.d.ts.map +1 -0
- package/dist/figma/parseFigmaRef.js +31 -0
- package/dist/figma/parseFigmaRef.js.map +1 -0
- package/dist/figma/resolveBindings.d.ts +31 -0
- package/dist/figma/resolveBindings.d.ts.map +1 -0
- package/dist/figma/resolveBindings.js +77 -0
- package/dist/figma/resolveBindings.js.map +1 -0
- package/dist/figma/sanitizeSvg.d.ts +18 -0
- package/dist/figma/sanitizeSvg.d.ts.map +1 -0
- package/dist/figma/sanitizeSvg.js +52 -0
- package/dist/figma/sanitizeSvg.js.map +1 -0
- package/dist/figma/tokensToVariables.d.ts +40 -0
- package/dist/figma/tokensToVariables.d.ts.map +1 -0
- package/dist/figma/tokensToVariables.js +118 -0
- package/dist/figma/tokensToVariables.js.map +1 -0
- package/dist/figma/types.d.ts +81 -0
- package/dist/figma/types.d.ts.map +1 -0
- package/dist/figma/types.js +2 -0
- package/dist/figma/types.js.map +1 -0
- package/dist/generated/runtime-inline.js +1 -1
- package/dist/generated/runtime-inline.js.map +1 -1
- package/dist/hyperframe.runtime.iife.js +24 -24
- package/dist/runtime/analytics.d.ts +19 -0
- package/dist/runtime/analytics.d.ts.map +1 -0
- package/dist/runtime/analytics.js +31 -0
- package/dist/runtime/analytics.js.map +1 -0
- package/dist/runtime/diagnostics.d.ts +2 -0
- package/dist/runtime/diagnostics.d.ts.map +1 -0
- package/dist/runtime/diagnostics.js +53 -0
- package/dist/runtime/diagnostics.js.map +1 -0
- package/dist/runtime/globals.d.ts +12 -0
- package/dist/runtime/globals.d.ts.map +1 -0
- package/dist/runtime/globals.js +4 -0
- package/dist/runtime/globals.js.map +1 -0
- package/dist/runtime/positionEdits.d.ts +47 -0
- package/dist/runtime/positionEdits.d.ts.map +1 -0
- package/dist/runtime/positionEdits.js +166 -0
- package/dist/runtime/positionEdits.js.map +1 -0
- package/package.json +12 -4
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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":"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"}
|
|
@@ -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"}
|
|
@@ -0,0 +1,244 @@
|
|
|
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 { figmaColorToCss } from "./color.js";
|
|
19
|
+
import { childDocuments } from "./nodeDocument.js";
|
|
20
|
+
const RASTERIZE_TYPES = new Set([
|
|
21
|
+
"VECTOR",
|
|
22
|
+
"BOOLEAN_OPERATION",
|
|
23
|
+
"STAR",
|
|
24
|
+
"LINE",
|
|
25
|
+
"POLYGON",
|
|
26
|
+
"REGULAR_POLYGON",
|
|
27
|
+
]);
|
|
28
|
+
function isRecord(value) {
|
|
29
|
+
return typeof value === "object" && value !== null;
|
|
30
|
+
}
|
|
31
|
+
function boxOf(node) {
|
|
32
|
+
const b = node.absoluteBoundingBox;
|
|
33
|
+
if (isRecord(b) &&
|
|
34
|
+
typeof b.x === "number" &&
|
|
35
|
+
typeof b.y === "number" &&
|
|
36
|
+
typeof b.width === "number" &&
|
|
37
|
+
typeof b.height === "number")
|
|
38
|
+
return { x: b.x, y: b.y, width: b.width, height: b.height };
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
export function slugify(name) {
|
|
42
|
+
const slug = name
|
|
43
|
+
.toLowerCase()
|
|
44
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
45
|
+
.replace(/^-+|-+$/g, "");
|
|
46
|
+
return slug.length > 0 ? slug : "node";
|
|
47
|
+
}
|
|
48
|
+
function cssVarName(compositionVariableId) {
|
|
49
|
+
return `--${slugify(compositionVariableId)}`;
|
|
50
|
+
}
|
|
51
|
+
function escapeHtml(text) {
|
|
52
|
+
return text
|
|
53
|
+
.replace(/&/g, "&")
|
|
54
|
+
.replace(/</g, "<")
|
|
55
|
+
.replace(/>/g, ">")
|
|
56
|
+
.replace(/"/g, """);
|
|
57
|
+
}
|
|
58
|
+
function round(n) {
|
|
59
|
+
return Math.round(n * 100) / 100;
|
|
60
|
+
}
|
|
61
|
+
function firstVisibleFill(node) {
|
|
62
|
+
const fills = node.fills;
|
|
63
|
+
if (!Array.isArray(fills))
|
|
64
|
+
return null;
|
|
65
|
+
for (const fill of fills) {
|
|
66
|
+
if (isRecord(fill) && fill.visible !== false)
|
|
67
|
+
return fill;
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
function gradientCss(fill) {
|
|
72
|
+
const stops = fill.gradientStops;
|
|
73
|
+
if (!Array.isArray(stops))
|
|
74
|
+
return null;
|
|
75
|
+
const parts = [];
|
|
76
|
+
for (const stop of stops) {
|
|
77
|
+
if (!isRecord(stop) || typeof stop.position !== "number")
|
|
78
|
+
return null;
|
|
79
|
+
const color = figmaColorToCss(stop.color);
|
|
80
|
+
if (color === null)
|
|
81
|
+
return null;
|
|
82
|
+
parts.push(`${color} ${round(stop.position * 100)}%`);
|
|
83
|
+
}
|
|
84
|
+
if (parts.length === 0)
|
|
85
|
+
return null;
|
|
86
|
+
// ponytail: fixed 180deg; exact angle from gradientHandlePositions when the
|
|
87
|
+
// probe confirms the handle-space math (spec §7.1 probe list).
|
|
88
|
+
return `linear-gradient(180deg, ${parts.join(", ")})`;
|
|
89
|
+
}
|
|
90
|
+
function fillCss(node) {
|
|
91
|
+
const fill = firstVisibleFill(node);
|
|
92
|
+
if (fill === null)
|
|
93
|
+
return null;
|
|
94
|
+
if (fill.type === "SOLID")
|
|
95
|
+
return figmaColorToCss(fill.color);
|
|
96
|
+
if (fill.type === "GRADIENT_LINEAR")
|
|
97
|
+
return gradientCss(fill);
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
function dropShadowCss(effect) {
|
|
101
|
+
if (!isRecord(effect.offset))
|
|
102
|
+
return null;
|
|
103
|
+
const color = figmaColorToCss(effect.color);
|
|
104
|
+
const { x, y } = effect.offset;
|
|
105
|
+
if (color === null || typeof x !== "number" || typeof y !== "number")
|
|
106
|
+
return null;
|
|
107
|
+
const radius = typeof effect.radius === "number" ? effect.radius : 0;
|
|
108
|
+
return `box-shadow: ${round(x)}px ${round(y)}px ${round(radius)}px ${color}`;
|
|
109
|
+
}
|
|
110
|
+
function effectCss(effect) {
|
|
111
|
+
if (!isRecord(effect) || effect.visible === false)
|
|
112
|
+
return null;
|
|
113
|
+
if (effect.type === "DROP_SHADOW")
|
|
114
|
+
return dropShadowCss(effect);
|
|
115
|
+
if (effect.type === "LAYER_BLUR" && typeof effect.radius === "number")
|
|
116
|
+
return `filter: blur(${round(effect.radius)}px)`;
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
function effectsCss(node, styles) {
|
|
120
|
+
const effects = node.effects;
|
|
121
|
+
if (!Array.isArray(effects))
|
|
122
|
+
return;
|
|
123
|
+
for (const effect of effects) {
|
|
124
|
+
const css = effectCss(effect);
|
|
125
|
+
if (css !== null)
|
|
126
|
+
styles.push(css);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function textCss(node, styles) {
|
|
130
|
+
const s = node.style;
|
|
131
|
+
if (!isRecord(s))
|
|
132
|
+
return;
|
|
133
|
+
// fontFamily is the one content-controlled string that reaches CSS — strip
|
|
134
|
+
// quote/escape chars so it can't break out of the font-family value (the
|
|
135
|
+
// whole style attribute is additionally HTML-escaped at emission).
|
|
136
|
+
if (typeof s.fontFamily === "string")
|
|
137
|
+
styles.push(`font-family: '${s.fontFamily.replace(/['"\\;]/g, "")}'`);
|
|
138
|
+
if (typeof s.fontWeight === "number")
|
|
139
|
+
styles.push(`font-weight: ${s.fontWeight}`);
|
|
140
|
+
if (typeof s.fontSize === "number")
|
|
141
|
+
styles.push(`font-size: ${round(s.fontSize)}px`);
|
|
142
|
+
if (typeof s.lineHeightPx === "number")
|
|
143
|
+
styles.push(`line-height: ${round(s.lineHeightPx)}px`);
|
|
144
|
+
if (typeof s.letterSpacing === "number" && s.letterSpacing !== 0)
|
|
145
|
+
styles.push(`letter-spacing: ${round(s.letterSpacing)}px`);
|
|
146
|
+
}
|
|
147
|
+
function uniqueSlug(ctx, name) {
|
|
148
|
+
const base = slugify(name);
|
|
149
|
+
let slug = base;
|
|
150
|
+
let n = 2;
|
|
151
|
+
while (ctx.usedSlugs.has(slug))
|
|
152
|
+
slug = `${base}-${n++}`;
|
|
153
|
+
ctx.usedSlugs.add(slug);
|
|
154
|
+
return slug;
|
|
155
|
+
}
|
|
156
|
+
function backgroundValue(node, ctx) {
|
|
157
|
+
const literal = fillCss(node);
|
|
158
|
+
if (literal === null)
|
|
159
|
+
return null;
|
|
160
|
+
const resolved = ctx.bindings.resolved.find((r) => r.nodeId === node.id && r.property === "fills");
|
|
161
|
+
if (resolved)
|
|
162
|
+
return `var(${cssVarName(resolved.compositionVariableId)}, ${literal})`;
|
|
163
|
+
return literal;
|
|
164
|
+
}
|
|
165
|
+
function unresolvedAttr(node, ctx) {
|
|
166
|
+
const props = ctx.bindings.unresolved.filter((u) => u.nodeId === node.id).map((u) => u.property);
|
|
167
|
+
if (props.length === 0)
|
|
168
|
+
return "";
|
|
169
|
+
return ` data-figma-unresolved="${escapeHtml(props.join(" "))}"`;
|
|
170
|
+
}
|
|
171
|
+
function geometryCss(node, ctx, isRoot) {
|
|
172
|
+
const box = boxOf(node);
|
|
173
|
+
const styles = [];
|
|
174
|
+
if (!box)
|
|
175
|
+
return styles;
|
|
176
|
+
if (isRoot) {
|
|
177
|
+
styles.push("position: relative", `width: ${round(box.width)}px`, `height: ${round(box.height)}px`);
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
styles.push("position: absolute", `left: ${round(box.x - ctx.origin.x)}px`, `top: ${round(box.y - ctx.origin.y)}px`, `width: ${round(box.width)}px`, `height: ${round(box.height)}px`);
|
|
181
|
+
}
|
|
182
|
+
return styles;
|
|
183
|
+
}
|
|
184
|
+
function decorationCss(node, ctx) {
|
|
185
|
+
const styles = [];
|
|
186
|
+
// backgroundValue is the binding-aware path (var(--slug, literal)) — TEXT
|
|
187
|
+
// color goes through it too, so a token-bound text fill keeps its link.
|
|
188
|
+
const bg = backgroundValue(node, ctx);
|
|
189
|
+
if (node.type === "TEXT") {
|
|
190
|
+
if (bg !== null)
|
|
191
|
+
styles.push(`color: ${bg}`);
|
|
192
|
+
textCss(node, styles);
|
|
193
|
+
}
|
|
194
|
+
else if (bg !== null) {
|
|
195
|
+
styles.push(`background: ${bg}`);
|
|
196
|
+
}
|
|
197
|
+
if (node.type === "ELLIPSE") {
|
|
198
|
+
styles.push("border-radius: 50%");
|
|
199
|
+
}
|
|
200
|
+
else if (typeof node.cornerRadius === "number" && node.cornerRadius > 0) {
|
|
201
|
+
styles.push(`border-radius: ${round(node.cornerRadius)}px`);
|
|
202
|
+
}
|
|
203
|
+
if (node.clipsContent === true)
|
|
204
|
+
styles.push("overflow: hidden");
|
|
205
|
+
if (typeof node.opacity === "number" && node.opacity < 1)
|
|
206
|
+
styles.push(`opacity: ${round(node.opacity)}`);
|
|
207
|
+
effectsCss(node, styles);
|
|
208
|
+
return styles;
|
|
209
|
+
}
|
|
210
|
+
// ponytail: depth cap so a runaway auto-generated tree degrades to a skip
|
|
211
|
+
// instead of a RangeError; real figma frames are nowhere near this deep.
|
|
212
|
+
const MAX_DEPTH = 500;
|
|
213
|
+
function renderChildren(node, ctx, depth) {
|
|
214
|
+
const childHtml = [];
|
|
215
|
+
for (const child of childDocuments(node)) {
|
|
216
|
+
const rendered = renderNodeHtml(child, ctx, false, depth + 1);
|
|
217
|
+
if (rendered.length > 0)
|
|
218
|
+
childHtml.push(rendered);
|
|
219
|
+
}
|
|
220
|
+
return childHtml.length > 0 ? `\n${childHtml.join("\n")}\n` : "";
|
|
221
|
+
}
|
|
222
|
+
function renderNodeHtml(node, ctx, isRoot, depth = 0) {
|
|
223
|
+
if (node.visible === false || depth > MAX_DEPTH)
|
|
224
|
+
return "";
|
|
225
|
+
const slug = uniqueSlug(ctx, node.name);
|
|
226
|
+
const style = escapeHtml([...geometryCss(node, ctx, isRoot), ...decorationCss(node, ctx)].join("; "));
|
|
227
|
+
const idAttrs = `id="${slug}" data-figma-id="${escapeHtml(node.id)}"${unresolvedAttr(node, ctx)}`;
|
|
228
|
+
if (RASTERIZE_TYPES.has(node.type)) {
|
|
229
|
+
ctx.rasterize.push({ nodeId: node.id, name: node.name, slug });
|
|
230
|
+
return `<img ${idAttrs} data-figma-rasterize="${escapeHtml(node.id)}" alt="${escapeHtml(node.name)}" style="${style}" />`;
|
|
231
|
+
}
|
|
232
|
+
if (node.type === "TEXT") {
|
|
233
|
+
const text = typeof node.characters === "string" ? escapeHtml(node.characters) : "";
|
|
234
|
+
return `<div ${idAttrs} style="${style}">${text}</div>`;
|
|
235
|
+
}
|
|
236
|
+
return `<div ${idAttrs} style="${style}">${renderChildren(node, ctx, depth)}</div>`;
|
|
237
|
+
}
|
|
238
|
+
export function nodeToHtml(root, bindings) {
|
|
239
|
+
const origin = boxOf(root) ?? { x: 0, y: 0, width: 0, height: 0 };
|
|
240
|
+
const ctx = { origin, bindings, rasterize: [], usedSlugs: new Set() };
|
|
241
|
+
const html = renderNodeHtml(root, ctx, true);
|
|
242
|
+
return { html, rasterize: ctx.rasterize };
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=nodeToHtml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodeToHtml.js","sourceRoot":"","sources":["../../src/figma/nodeToHtml.ts"],"names":[],"mappings":"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"}
|