@hyperframes/core 0.7.28 → 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 (73) hide show
  1. package/dist/figma/assetSnippet.d.ts +3 -0
  2. package/dist/figma/assetSnippet.d.ts.map +1 -0
  3. package/dist/figma/assetSnippet.js +18 -0
  4. package/dist/figma/assetSnippet.js.map +1 -0
  5. package/dist/figma/bindings.d.ts +38 -0
  6. package/dist/figma/bindings.d.ts.map +1 -0
  7. package/dist/figma/bindings.js +84 -0
  8. package/dist/figma/bindings.js.map +1 -0
  9. package/dist/figma/client.d.ts +67 -0
  10. package/dist/figma/client.d.ts.map +1 -0
  11. package/dist/figma/client.js +134 -0
  12. package/dist/figma/client.js.map +1 -0
  13. package/dist/figma/color.d.ts +3 -0
  14. package/dist/figma/color.d.ts.map +1 -0
  15. package/dist/figma/color.js +23 -0
  16. package/dist/figma/color.js.map +1 -0
  17. package/dist/figma/emitTimelineScript.d.ts +3 -0
  18. package/dist/figma/emitTimelineScript.d.ts.map +1 -0
  19. package/dist/figma/emitTimelineScript.js +42 -0
  20. package/dist/figma/emitTimelineScript.js.map +1 -0
  21. package/dist/figma/freeze.d.ts +16 -0
  22. package/dist/figma/freeze.d.ts.map +1 -0
  23. package/dist/figma/freeze.js +67 -0
  24. package/dist/figma/freeze.js.map +1 -0
  25. package/dist/figma/index.d.ts +21 -0
  26. package/dist/figma/index.d.ts.map +1 -0
  27. package/dist/figma/index.js +15 -0
  28. package/dist/figma/index.js.map +1 -0
  29. package/dist/figma/jsonl.d.ts +3 -0
  30. package/dist/figma/jsonl.d.ts.map +1 -0
  31. package/dist/figma/jsonl.js +22 -0
  32. package/dist/figma/jsonl.js.map +1 -0
  33. package/dist/figma/manifest.d.ts +17 -0
  34. package/dist/figma/manifest.d.ts.map +1 -0
  35. package/dist/figma/manifest.js +96 -0
  36. package/dist/figma/manifest.js.map +1 -0
  37. package/dist/figma/motionEase.d.ts +3 -0
  38. package/dist/figma/motionEase.d.ts.map +1 -0
  39. package/dist/figma/motionEase.js +45 -0
  40. package/dist/figma/motionEase.js.map +1 -0
  41. package/dist/figma/motionToGsap.d.ts +3 -0
  42. package/dist/figma/motionToGsap.d.ts.map +1 -0
  43. package/dist/figma/motionToGsap.js +61 -0
  44. package/dist/figma/motionToGsap.js.map +1 -0
  45. package/dist/figma/nodeDocument.d.ts +4 -0
  46. package/dist/figma/nodeDocument.d.ts.map +1 -0
  47. package/dist/figma/nodeDocument.js +26 -0
  48. package/dist/figma/nodeDocument.js.map +1 -0
  49. package/dist/figma/nodeToHtml.d.ts +31 -0
  50. package/dist/figma/nodeToHtml.d.ts.map +1 -0
  51. package/dist/figma/nodeToHtml.js +244 -0
  52. package/dist/figma/nodeToHtml.js.map +1 -0
  53. package/dist/figma/parseFigmaRef.d.ts +3 -0
  54. package/dist/figma/parseFigmaRef.d.ts.map +1 -0
  55. package/dist/figma/parseFigmaRef.js +31 -0
  56. package/dist/figma/parseFigmaRef.js.map +1 -0
  57. package/dist/figma/resolveBindings.d.ts +31 -0
  58. package/dist/figma/resolveBindings.d.ts.map +1 -0
  59. package/dist/figma/resolveBindings.js +77 -0
  60. package/dist/figma/resolveBindings.js.map +1 -0
  61. package/dist/figma/sanitizeSvg.d.ts +18 -0
  62. package/dist/figma/sanitizeSvg.d.ts.map +1 -0
  63. package/dist/figma/sanitizeSvg.js +52 -0
  64. package/dist/figma/sanitizeSvg.js.map +1 -0
  65. package/dist/figma/tokensToVariables.d.ts +40 -0
  66. package/dist/figma/tokensToVariables.d.ts.map +1 -0
  67. package/dist/figma/tokensToVariables.js +118 -0
  68. package/dist/figma/tokensToVariables.js.map +1 -0
  69. package/dist/figma/types.d.ts +81 -0
  70. package/dist/figma/types.d.ts.map +1 -0
  71. package/dist/figma/types.js +2 -0
  72. package/dist/figma/types.js.map +1 -0
  73. package/package.json +8 -4
@@ -0,0 +1,3 @@
1
+ import type { FigmaRef } from "./types";
2
+ export declare function parseFigmaRef(input: string): FigmaRef;
3
+ //# sourceMappingURL=parseFigmaRef.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseFigmaRef.d.ts","sourceRoot":"","sources":["../../src/figma/parseFigmaRef.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAQxC,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAuBrD"}
@@ -0,0 +1,31 @@
1
+ const FILE_KEY_RE = /\/(?:design|file|proto)\/([A-Za-z0-9]+)/;
2
+ function normalizeNodeId(raw) {
3
+ return raw.replaceAll("-", ":");
4
+ }
5
+ export function parseFigmaRef(input) {
6
+ const trimmed = input.trim();
7
+ if (trimmed.length === 0)
8
+ throw new Error("parseFigmaRef: empty input");
9
+ if (!trimmed.includes("/")) {
10
+ const colon = trimmed.indexOf(":");
11
+ if (colon === -1)
12
+ return { fileKey: trimmed };
13
+ const fileKey = trimmed.slice(0, colon);
14
+ const node = trimmed.slice(colon + 1);
15
+ if (fileKey.length === 0)
16
+ throw new Error(`parseFigmaRef: invalid ref "${input}"`);
17
+ return node.length > 0 ? { fileKey, nodeId: normalizeNodeId(node) } : { fileKey };
18
+ }
19
+ const keyMatch = trimmed.match(FILE_KEY_RE);
20
+ const fileKey = keyMatch?.[1];
21
+ if (fileKey === undefined)
22
+ throw new Error(`parseFigmaRef: no fileKey in "${input}"`);
23
+ const q = trimmed.indexOf("?");
24
+ if (q !== -1) {
25
+ const raw = new URLSearchParams(trimmed.slice(q + 1)).get("node-id");
26
+ if (raw !== null && raw.length > 0)
27
+ return { fileKey, nodeId: normalizeNodeId(raw) };
28
+ }
29
+ return { fileKey };
30
+ }
31
+ //# sourceMappingURL=parseFigmaRef.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseFigmaRef.js","sourceRoot":"","sources":["../../src/figma/parseFigmaRef.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,GAAG,yCAAyC,CAAC;AAE9D,SAAS,eAAe,CAAC,GAAW;IAClC,OAAO,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAExE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACtC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,KAAK,GAAG,CAAC,CAAC;QACnF,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;IACpF,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,KAAK,GAAG,CAAC,CAAC;IAEtF,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACrE,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;IACvF,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Binding resolution pass (design spec §7.1): scan a node tree's complete
3
+ * binding set — boundVariables and style ids, alias chains honored — and
4
+ * partition against the binding index BEFORE any CSS is emitted.
5
+ *
6
+ * Exact-ID matching only. A missed link bakes a visually-correct literal;
7
+ * a wrong link silently changes color at the next brand refresh. Never
8
+ * match by value or name.
9
+ *
10
+ * NOTE: the consumer-side boundVariables shape is probe-flagged in the spec
11
+ * (§7.1 pre-build probes). Extraction here is tolerant: single alias objects
12
+ * and arrays of alias objects both count; unknown shapes are ignored rather
13
+ * than guessed at.
14
+ */
15
+ import type { FigmaBindingRecord } from "./bindings";
16
+ import type { FigmaNodeDocument } from "./client";
17
+ export interface BindingSite {
18
+ nodeId: string;
19
+ /** boundVariables property ("fills") or style slot prefixed "style:" ("style:text") */
20
+ property: string;
21
+ figmaId: string;
22
+ }
23
+ export interface ResolvedBindingSite extends BindingSite {
24
+ compositionVariableId: string;
25
+ }
26
+ export interface ResolveBindingsResult {
27
+ resolved: ResolvedBindingSite[];
28
+ unresolved: BindingSite[];
29
+ }
30
+ export declare function resolveBindings(node: FigmaNodeDocument, index: FigmaBindingRecord[]): ResolveBindingsResult;
31
+ //# sourceMappingURL=resolveBindings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveBindings.d.ts","sourceRoot":"","sources":["../../src/figma/resolveBindings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAGlD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAoB,SAAQ,WAAW;IACtD,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,UAAU,EAAE,WAAW,EAAE,CAAC;CAC3B;AAgDD,wBAAgB,eAAe,CAC7B,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,kBAAkB,EAAE,GAC1B,qBAAqB,CAYvB"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Binding resolution pass (design spec §7.1): scan a node tree's complete
3
+ * binding set — boundVariables and style ids, alias chains honored — and
4
+ * partition against the binding index BEFORE any CSS is emitted.
5
+ *
6
+ * Exact-ID matching only. A missed link bakes a visually-correct literal;
7
+ * a wrong link silently changes color at the next brand refresh. Never
8
+ * match by value or name.
9
+ *
10
+ * NOTE: the consumer-side boundVariables shape is probe-flagged in the spec
11
+ * (§7.1 pre-build probes). Extraction here is tolerant: single alias objects
12
+ * and arrays of alias objects both count; unknown shapes are ignored rather
13
+ * than guessed at.
14
+ */
15
+ import { childDocuments } from "./nodeDocument.js";
16
+ function isRecord(value) {
17
+ return typeof value === "object" && value !== null;
18
+ }
19
+ function aliasId(value) {
20
+ if (isRecord(value) && value.type === "VARIABLE_ALIAS" && typeof value.id === "string")
21
+ return value.id;
22
+ return null;
23
+ }
24
+ function boundVariableSites(node, out) {
25
+ const bound = node.boundVariables;
26
+ if (!isRecord(bound))
27
+ return;
28
+ for (const [property, value] of Object.entries(bound)) {
29
+ const candidates = Array.isArray(value) ? value : [value];
30
+ for (const item of candidates) {
31
+ const id = aliasId(item);
32
+ if (id)
33
+ out.push({ nodeId: node.id, property, figmaId: id });
34
+ }
35
+ }
36
+ }
37
+ function styleSites(node, out) {
38
+ const styles = node.styles;
39
+ if (!isRecord(styles))
40
+ return;
41
+ for (const [slot, styleId] of Object.entries(styles)) {
42
+ if (typeof styleId === "string" && styleId.length > 0)
43
+ out.push({ nodeId: node.id, property: `style:${slot}`, figmaId: styleId });
44
+ }
45
+ }
46
+ function collectSites(node, out) {
47
+ boundVariableSites(node, out);
48
+ styleSites(node, out);
49
+ for (const child of childDocuments(node))
50
+ collectSites(child, out);
51
+ }
52
+ function findInIndex(index, figmaId) {
53
+ for (const b of index) {
54
+ if (b.figmaId === figmaId)
55
+ return b;
56
+ if (b.aliasChain?.includes(figmaId))
57
+ return b;
58
+ if (b.key !== undefined && b.key === figmaId)
59
+ return b;
60
+ }
61
+ return null;
62
+ }
63
+ export function resolveBindings(node, index) {
64
+ const sites = [];
65
+ collectSites(node, sites);
66
+ const resolved = [];
67
+ const unresolved = [];
68
+ for (const site of sites) {
69
+ const match = findInIndex(index, site.figmaId);
70
+ if (match)
71
+ resolved.push({ ...site, compositionVariableId: match.compositionVariableId });
72
+ else
73
+ unresolved.push(site);
74
+ }
75
+ return { resolved, unresolved };
76
+ }
77
+ //# sourceMappingURL=resolveBindings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveBindings.js","sourceRoot":"","sources":["../../src/figma/resolveBindings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAkBhD,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,SAAS,OAAO,CAAC,KAAc;IAC7B,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ;QACpF,OAAO,KAAK,CAAC,EAAE,CAAC;IAClB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAuB,EAAE,GAAkB;IACrE,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC;IAClC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO;IAC7B,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC1D,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YACzB,IAAI,EAAE;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,IAAuB,EAAE,GAAkB;IAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC3B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO;IAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACrD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YACnD,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,IAAuB,EAAE,GAAkB;IAC/D,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC9B,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACtB,KAAK,MAAM,KAAK,IAAI,cAAc,CAAC,IAAI,CAAC;QAAE,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,WAAW,CAAC,KAA2B,EAAE,OAAe;IAC/D,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO;YAAE,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC;YAAE,OAAO,CAAC,CAAC;QAC9C,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO;YAAE,OAAO,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,IAAuB,EACvB,KAA2B;IAE3B,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAE1B,MAAM,QAAQ,GAA0B,EAAE,CAAC;IAC3C,MAAM,UAAU,GAAkB,EAAE,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/C,IAAI,KAAK;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,qBAAqB,EAAE,KAAK,CAAC,qBAAqB,EAAE,CAAC,CAAC;;YACrF,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;AAClC,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Sanitize a figma-exported SVG before it touches disk (design spec §5).
3
+ *
4
+ * Threat model: figma-SHAPED exports, hardened against the cheap adversarial
5
+ * variants (nesting, unquoted attrs, scheme smuggling). This is a lexical
6
+ * pass, not a general-purpose HTML sanitizer — content from arbitrary
7
+ * untrusted sources should go through a real sanitizer (DOMPurify) instead.
8
+ * Strips:
9
+ * - <script> elements (with content) and <style> blocks (@import exfil)
10
+ * - <foreignObject> subtrees (arbitrary embedded HTML)
11
+ * - on* event-handler attributes (quoted and unquoted)
12
+ * - href/xlink:href values unless local fragment (#id) or data:image/
13
+ *
14
+ * Keeps local fragment refs (#id) and data:image embeds, which figma uses
15
+ * for clip paths and embedded rasters.
16
+ */
17
+ export declare function sanitizeSvg(svg: string): string;
18
+ //# sourceMappingURL=sanitizeSvg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizeSvg.d.ts","sourceRoot":"","sources":["../../src/figma/sanitizeSvg.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAaH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAwB/C"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Sanitize a figma-exported SVG before it touches disk (design spec §5).
3
+ *
4
+ * Threat model: figma-SHAPED exports, hardened against the cheap adversarial
5
+ * variants (nesting, unquoted attrs, scheme smuggling). This is a lexical
6
+ * pass, not a general-purpose HTML sanitizer — content from arbitrary
7
+ * untrusted sources should go through a real sanitizer (DOMPurify) instead.
8
+ * Strips:
9
+ * - <script> elements (with content) and <style> blocks (@import exfil)
10
+ * - <foreignObject> subtrees (arbitrary embedded HTML)
11
+ * - on* event-handler attributes (quoted and unquoted)
12
+ * - href/xlink:href values unless local fragment (#id) or data:image/
13
+ *
14
+ * Keeps local fragment refs (#id) and data:image embeds, which figma uses
15
+ * for clip paths and embedded rasters.
16
+ */
17
+ /** Apply a replacement until the output stops changing (defeats nesting). */
18
+ function replaceStable(input, pattern, replacement) {
19
+ let out = input;
20
+ let prev;
21
+ do {
22
+ prev = out;
23
+ out = out.replace(pattern, replacement);
24
+ } while (out !== prev);
25
+ return out;
26
+ }
27
+ export function sanitizeSvg(svg) {
28
+ let out = svg;
29
+ out = replaceStable(out, /<script\b[\s\S]*?<\/script\b[^>]*>/gi, "");
30
+ out = replaceStable(out, /<script\b[^>]*\/>/gi, "");
31
+ out = replaceStable(out, /<style\b[\s\S]*?<\/style\b[^>]*>/gi, "");
32
+ out = replaceStable(out, /<foreignObject\b[\s\S]*?<\/foreignObject\b[^>]*>/gi, "");
33
+ out = replaceStable(out, /<foreignObject\b[^>]*\/>/gi, "");
34
+ // Nesting leaves inert orphan close tags after the stable pass — drop them.
35
+ out = out.replace(/<\/(?:script|style|foreignObject)\b[^>]*>/gi, "");
36
+ // on* handler attributes: quoted and unquoted forms.
37
+ out = replaceStable(out, /\son[a-z]+\s*=\s*"[^"]*"/gi, "");
38
+ out = replaceStable(out, /\son[a-z]+\s*=\s*'[^']*'/gi, "");
39
+ out = replaceStable(out, /\son[a-z]+\s*=\s*[^\s>'"]+/gi, "");
40
+ // href-like attributes: POSITIVE allowlist — keep only local fragments and
41
+ // data:image embeds; drop everything else (javascript:, https?:, blob:,
42
+ // vbscript:, data:text/html, protocol-relative, …).
43
+ // xmlns declarations are attribute *names*, not href values — untouched.
44
+ out = out.replace(/\s(href|xlink:href)\s*=\s*"([^"]*)"/gi, (m, attr, value) => isAllowedHref(value) ? m : "");
45
+ out = out.replace(/\s(href|xlink:href)\s*=\s*'([^']*)'/gi, (m, attr, value) => isAllowedHref(value) ? m : "");
46
+ return out;
47
+ }
48
+ function isAllowedHref(value) {
49
+ const v = value.trim().toLowerCase();
50
+ return v.startsWith("#") || v.startsWith("data:image/");
51
+ }
52
+ //# sourceMappingURL=sanitizeSvg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizeSvg.js","sourceRoot":"","sources":["../../src/figma/sanitizeSvg.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,6EAA6E;AAC7E,SAAS,aAAa,CAAC,KAAa,EAAE,OAAe,EAAE,WAAmB;IACxE,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,IAAI,IAAI,CAAC;IACT,GAAG,CAAC;QACF,IAAI,GAAG,GAAG,CAAC;QACX,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAC1C,CAAC,QAAQ,GAAG,KAAK,IAAI,EAAE;IACvB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,GAAG,GAAG,GAAG,CAAC;IACd,GAAG,GAAG,aAAa,CAAC,GAAG,EAAE,sCAAsC,EAAE,EAAE,CAAC,CAAC;IACrE,GAAG,GAAG,aAAa,CAAC,GAAG,EAAE,qBAAqB,EAAE,EAAE,CAAC,CAAC;IACpD,GAAG,GAAG,aAAa,CAAC,GAAG,EAAE,oCAAoC,EAAE,EAAE,CAAC,CAAC;IACnE,GAAG,GAAG,aAAa,CAAC,GAAG,EAAE,oDAAoD,EAAE,EAAE,CAAC,CAAC;IACnF,GAAG,GAAG,aAAa,CAAC,GAAG,EAAE,4BAA4B,EAAE,EAAE,CAAC,CAAC;IAC3D,4EAA4E;IAC5E,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,6CAA6C,EAAE,EAAE,CAAC,CAAC;IACrE,qDAAqD;IACrD,GAAG,GAAG,aAAa,CAAC,GAAG,EAAE,4BAA4B,EAAE,EAAE,CAAC,CAAC;IAC3D,GAAG,GAAG,aAAa,CAAC,GAAG,EAAE,4BAA4B,EAAE,EAAE,CAAC,CAAC;IAC3D,GAAG,GAAG,aAAa,CAAC,GAAG,EAAE,8BAA8B,EAAE,EAAE,CAAC,CAAC;IAC7D,2EAA2E;IAC3E,wEAAwE;IACxE,oDAAoD;IACpD,yEAAyE;IACzE,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,uCAAuC,EAAE,CAAC,CAAC,EAAE,IAAY,EAAE,KAAa,EAAE,EAAE,CAC5F,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAC9B,CAAC;IACF,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,uCAAuC,EAAE,CAAC,CAAC,EAAE,IAAY,EAAE,KAAa,EAAE,EAAE,CAC5F,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAC9B,CAAC;IACF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Phase 2 translator: figma variables → composition brand-variable entries,
3
+ * a human-readable sidecar, and binding-index records (design spec §6, §7.1).
4
+ *
5
+ * Pure — REST payload in, artifacts out. Alias chains are walked to the leaf
6
+ * value (cycle-safe) but the binding records the semantic id the designer
7
+ * bound, so a swapped primitive doesn't orphan the link.
8
+ */
9
+ import type { FigmaVariablesResult } from "./client";
10
+ import type { FigmaBindingRecord } from "./bindings";
11
+ /** data-composition-variables entry (runtime getVariables contract). */
12
+ export interface CompositionVariableEntry {
13
+ id: string;
14
+ type: "string" | "number" | "color" | "boolean";
15
+ label: string;
16
+ default: string | number | boolean;
17
+ brandRole?: string;
18
+ }
19
+ export interface FigmaTokenSidecarEntry {
20
+ name: string;
21
+ type: string;
22
+ figmaId: string;
23
+ key?: string;
24
+ value: string | number | boolean | null;
25
+ }
26
+ export interface FigmaTokensSidecar {
27
+ source: TokenSource;
28
+ tokens: FigmaTokenSidecarEntry[];
29
+ }
30
+ export interface TokenSource {
31
+ fileKey: string;
32
+ version: string;
33
+ }
34
+ export interface TokensToVariablesResult {
35
+ entries: CompositionVariableEntry[];
36
+ bindings: FigmaBindingRecord[];
37
+ sidecar: FigmaTokensSidecar;
38
+ }
39
+ export declare function tokensToVariables(vars: FigmaVariablesResult, source: TokenSource): TokensToVariablesResult;
40
+ //# sourceMappingURL=tokensToVariables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokensToVariables.d.ts","sourceRoot":"","sources":["../../src/figma/tokensToVariables.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAwB,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAC3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGrD,wEAAwE;AACxE,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,sBAAsB,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,wBAAwB,EAAE,CAAC;IACpC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AA4ED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,oBAAoB,EAC1B,MAAM,EAAE,WAAW,GAClB,uBAAuB,CAgDzB"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Phase 2 translator: figma variables → composition brand-variable entries,
3
+ * a human-readable sidecar, and binding-index records (design spec §6, §7.1).
4
+ *
5
+ * Pure — REST payload in, artifacts out. Alias chains are walked to the leaf
6
+ * value (cycle-safe) but the binding records the semantic id the designer
7
+ * bound, so a swapped primitive doesn't orphan the link.
8
+ */
9
+ import { figmaColorToCss } from "./color.js";
10
+ const TYPE_MAP = {
11
+ COLOR: "color",
12
+ FLOAT: "number",
13
+ STRING: "string",
14
+ BOOLEAN: "boolean",
15
+ };
16
+ function isRecord(value) {
17
+ return typeof value === "object" && value !== null;
18
+ }
19
+ /**
20
+ * The collection's defaultModeId is the authority for "which mode is the
21
+ * base value" (Light vs Dark). Falls back to first-inserted mode when the
22
+ * collection or its default mode isn't in the payload.
23
+ */
24
+ function baseModeValue(payload, collections) {
25
+ const modes = payload.valuesByMode ?? {};
26
+ const collection = collections[payload.variableCollectionId ?? ""];
27
+ if (isRecord(collection) && typeof collection.defaultModeId === "string") {
28
+ const preferred = modes[collection.defaultModeId];
29
+ if (preferred !== undefined)
30
+ return preferred;
31
+ }
32
+ for (const value of Object.values(modes))
33
+ return value;
34
+ return undefined;
35
+ }
36
+ function collectionName(payload, collections) {
37
+ const collection = collections[payload.variableCollectionId ?? ""];
38
+ return isRecord(collection) && typeof collection.name === "string" ? collection.name : null;
39
+ }
40
+ /** Follow VARIABLE_ALIAS links to a leaf value; null on cycle/missing. */
41
+ function resolveValue(start, vars) {
42
+ const chain = [];
43
+ const seen = new Set();
44
+ let currentId = start;
45
+ while (!seen.has(currentId)) {
46
+ chain.push(currentId);
47
+ seen.add(currentId);
48
+ const payload = vars.variables[currentId];
49
+ if (!payload)
50
+ return null;
51
+ const value = baseModeValue(payload, vars.variableCollections);
52
+ if (isRecord(value) && value.type === "VARIABLE_ALIAS" && typeof value.id === "string") {
53
+ currentId = value.id;
54
+ continue;
55
+ }
56
+ return { value, chain };
57
+ }
58
+ return null; // cycle
59
+ }
60
+ /** Value must match the declared resolvedType — a stringified "8" for a
61
+ * FLOAT would silently break the CompositionVariableEntry contract. */
62
+ function toEntryValue(resolvedType, raw) {
63
+ if (resolvedType === "COLOR")
64
+ return figmaColorToCss(raw);
65
+ if (resolvedType === "FLOAT")
66
+ return typeof raw === "number" ? raw : null;
67
+ if (resolvedType === "BOOLEAN")
68
+ return typeof raw === "boolean" ? raw : null;
69
+ if (resolvedType === "STRING")
70
+ return typeof raw === "string" ? raw : null;
71
+ return null;
72
+ }
73
+ export function tokensToVariables(vars, source) {
74
+ const entries = [];
75
+ const bindings = [];
76
+ const sidecarTokens = [];
77
+ for (const [figmaId, payload] of Object.entries(vars.variables)) {
78
+ const entryType = TYPE_MAP[payload.resolvedType ?? ""];
79
+ const resolved = resolveValue(figmaId, vars);
80
+ const value = resolved ? toEntryValue(payload.resolvedType, resolved.value) : null;
81
+ // Namespace by collection: figma allows the same variable name in
82
+ // different collections (Semantic Blue/500 vs Primitive Blue/500), and a
83
+ // collision here would silently merge two distinct bindings.
84
+ const collection = collectionName(payload, vars.variableCollections);
85
+ const compositionVariableId = collection
86
+ ? `figma:${collection}/${payload.name}`
87
+ : `figma:${payload.name}`;
88
+ // Sidecar keeps EVERY variable — including unresolvable ones (value:
89
+ // null) — for designer visibility into what didn't map; entries/bindings
90
+ // below only get the mappable subset.
91
+ sidecarTokens.push({
92
+ name: payload.name,
93
+ type: entryType ?? payload.resolvedType ?? "unknown",
94
+ figmaId,
95
+ key: payload.key,
96
+ value,
97
+ });
98
+ if (!entryType || value === null || !resolved)
99
+ continue;
100
+ entries.push({
101
+ id: compositionVariableId,
102
+ type: entryType,
103
+ label: payload.name,
104
+ default: value,
105
+ });
106
+ bindings.push({
107
+ kind: "binding",
108
+ figmaId,
109
+ key: payload.key,
110
+ sourceFileKey: source.fileKey,
111
+ aliasChain: resolved.chain.length > 1 ? resolved.chain : undefined,
112
+ compositionVariableId,
113
+ version: source.version,
114
+ });
115
+ }
116
+ return { entries, bindings, sidecar: { source, tokens: sidecarTokens } };
117
+ }
118
+ //# sourceMappingURL=tokensToVariables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokensToVariables.js","sourceRoot":"","sources":["../../src/figma/tokensToVariables.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ export interface FigmaRef {
2
+ fileKey: string;
3
+ nodeId?: string;
4
+ }
5
+ export type FigmaAssetFormat = "png" | "svg" | "jpg" | "pdf";
6
+ export interface FigmaProvenance {
7
+ source: "figma";
8
+ fileKey: string;
9
+ nodeId: string;
10
+ version?: string;
11
+ format?: FigmaAssetFormat;
12
+ scale?: number;
13
+ }
14
+ export interface FigmaManifestRecord {
15
+ id: string;
16
+ type: "image" | "video";
17
+ path: string;
18
+ source: string;
19
+ description?: string;
20
+ width?: number;
21
+ height?: number;
22
+ provenance: FigmaProvenance;
23
+ }
24
+ export interface AssetSnippet {
25
+ path: string;
26
+ html: string;
27
+ }
28
+ /** A motion.dev easing value as returned by get_motion_context: a named ease
29
+ * (e.g. "linear") or a cubic-bezier control-point array [x1,y1,x2,y2]. */
30
+ export type MotionEase = string | [number, number, number, number];
31
+ /** One animated property, normalized from get_motion_context's motion.dev snippet. */
32
+ export interface MotionTrack {
33
+ /** motion.dev property name: "opacity" | "x" | "y" | "scaleX" | "scaleY" | "rotation" | ... */
34
+ property: string;
35
+ values: Array<number | string>;
36
+ /** normalized 0..1, same length as values */
37
+ times: number[];
38
+ /** length values.length - 1; ease[i] governs the segment values[i] -> values[i+1] */
39
+ ease: MotionEase[];
40
+ /** seconds */
41
+ duration: number;
42
+ /** Infinity or a finite count; clamped to finite during translation */
43
+ repeat?: number;
44
+ }
45
+ export interface MotionDoc {
46
+ /** string-literal CSS selector for the target element, e.g. "#hero-title" */
47
+ selector: string;
48
+ tracks: MotionTrack[];
49
+ }
50
+ export type MappedEase = {
51
+ kind: "named";
52
+ ease: string;
53
+ } | {
54
+ kind: "bezier";
55
+ bezier: [number, number, number, number];
56
+ };
57
+ export interface CustomEaseRef {
58
+ name: string;
59
+ bezier: [number, number, number, number];
60
+ }
61
+ export interface GsapKeyframeStep {
62
+ value: number | string;
63
+ /** seconds */
64
+ duration: number;
65
+ /** GSAP ease string or a registered CustomEase name */
66
+ ease: string;
67
+ }
68
+ export interface GsapTween {
69
+ selector: string;
70
+ property: string;
71
+ initial: number | string;
72
+ steps: GsapKeyframeStep[];
73
+ /** finite; 0 = play once */
74
+ repeat: number;
75
+ }
76
+ export interface TimelineSpec {
77
+ timelineId: string;
78
+ tweens: GsapTween[];
79
+ customEases: CustomEaseRef[];
80
+ }
81
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/figma/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,eAAe,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;2EAC2E;AAC3E,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEnE,sFAAsF;AACtF,MAAM,WAAW,WAAW;IAC1B,+FAA+F;IAC/F,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAC/B,6CAA6C;IAC7C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,qFAAqF;IACrF,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,cAAc;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC;AAEjE,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,cAAc;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,WAAW,EAAE,aAAa,EAAE,CAAC;CAC9B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/figma/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/core",
3
- "version": "0.7.28",
3
+ "version": "0.7.29",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -38,6 +38,10 @@
38
38
  "import": "./dist/editing/affordances.js",
39
39
  "types": "./dist/editing/affordances.d.ts"
40
40
  },
41
+ "./figma": {
42
+ "import": "./dist/figma/index.js",
43
+ "types": "./dist/figma/index.d.ts"
44
+ },
41
45
  "./generators": {
42
46
  "import": "./dist/generators/hyperframes.js",
43
47
  "types": "./dist/generators/hyperframes.d.ts"
@@ -154,9 +158,9 @@
154
158
  "bpm-detective": "^2.0.5",
155
159
  "linkedom": "^0.18.12",
156
160
  "postcss": "^8.5.8",
157
- "@hyperframes/lint": "0.7.28",
158
- "@hyperframes/studio-server": "0.7.28",
159
- "@hyperframes/parsers": "0.7.28"
161
+ "@hyperframes/lint": "0.7.29",
162
+ "@hyperframes/studio-server": "0.7.29",
163
+ "@hyperframes/parsers": "0.7.29"
160
164
  },
161
165
  "devDependencies": {
162
166
  "@types/jsdom": "^28.0.0",