@remotion/studio-server 4.0.494 → 4.0.495

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.
@@ -910,6 +910,23 @@ const getInitialValueForMissingProp = ({ schema, key, newValue, }) => {
910
910
  }
911
911
  return newValue;
912
912
  };
913
+ const shouldRemovePropAfterKeyframeOperation = ({ expression, key, operation, schema, videoConfigValues, }) => {
914
+ if (operation.type !== 'remove' || !schema) {
915
+ return false;
916
+ }
917
+ const existing = getInterpolationExpression(expression, videoConfigValues);
918
+ if (!existing || existing.keyframes.length !== 1) {
919
+ return false;
920
+ }
921
+ const field = findFieldInSchema(schema, key);
922
+ if (!field || field.type === 'hidden' || field.default === undefined) {
923
+ return false;
924
+ }
925
+ const valueAfterRemoval = operation.valueWhenLastKeyframeDeleted === null
926
+ ? existing.keyframes[0].value
927
+ : operation.valueWhenLastKeyframeDeleted;
928
+ return JSON.stringify(valueAfterRemoval) === JSON.stringify(field.default);
929
+ };
913
930
  const getObjectExpression = (attr) => {
914
931
  if (!attr.value || attr.value.type !== 'JSXExpressionContainer') {
915
932
  return null;
@@ -934,7 +951,7 @@ const createMissingPropExpression = (missingPropInitialValue) => {
934
951
  const getSequenceWritableProp = ({ attributes, key, missingPropInitialValue, }) => {
935
952
  const dotIndex = key.indexOf('.');
936
953
  if (dotIndex === -1) {
937
- const { attr: topLevelAttr } = findJsxAttribute(attributes, key);
954
+ const { attrIndex, attr: topLevelAttr } = findJsxAttribute(attributes, key);
938
955
  if (!topLevelAttr) {
939
956
  if (missingPropInitialValue) {
940
957
  return {
@@ -942,6 +959,7 @@ const getSequenceWritableProp = ({ attributes, key, missingPropInitialValue, })
942
959
  setExpression: (nextExpression) => {
943
960
  attributes.push(createJsxExpressionAttribute(key, nextExpression));
944
961
  },
962
+ remove: () => undefined,
945
963
  };
946
964
  }
947
965
  throw new Error(`Cannot update keyframes: "${key}" is not set`);
@@ -955,11 +973,14 @@ const getSequenceWritableProp = ({ attributes, key, missingPropInitialValue, })
955
973
  setExpression: (nextExpression) => {
956
974
  topLevelAttr.value = b.jsxExpressionContainer(nextExpression);
957
975
  },
976
+ remove: () => {
977
+ attributes.splice(attrIndex, 1);
978
+ },
958
979
  };
959
980
  }
960
981
  const parentKey = key.slice(0, dotIndex);
961
982
  const childKey = key.slice(dotIndex + 1);
962
- const { attr: parentAttr } = findJsxAttribute(attributes, parentKey);
983
+ const { attrIndex: parentAttrIndex, attr: parentAttr } = findJsxAttribute(attributes, parentKey);
963
984
  if (!parentAttr) {
964
985
  if (missingPropInitialValue) {
965
986
  return {
@@ -971,6 +992,7 @@ const getSequenceWritableProp = ({ attributes, key, missingPropInitialValue, })
971
992
  expression: nextExpression,
972
993
  }));
973
994
  },
995
+ remove: () => undefined,
974
996
  };
975
997
  }
976
998
  throw new Error(`Cannot update keyframes: "${parentKey}" is not set`);
@@ -979,7 +1001,7 @@ const getSequenceWritableProp = ({ attributes, key, missingPropInitialValue, })
979
1001
  if (!objExpr) {
980
1002
  throw new Error(`Cannot update keyframes: "${parentKey}" is computed`);
981
1003
  }
982
- const { prop } = findObjectProperty(objExpr, childKey);
1004
+ const { propIndex, prop } = findObjectProperty(objExpr, childKey);
983
1005
  if (!prop) {
984
1006
  if (missingPropInitialValue) {
985
1007
  return {
@@ -987,6 +1009,7 @@ const getSequenceWritableProp = ({ attributes, key, missingPropInitialValue, })
987
1009
  setExpression: (nextExpression) => {
988
1010
  objExpr.properties.push(createObjectProperty(childKey, nextExpression));
989
1011
  },
1012
+ remove: () => undefined,
990
1013
  };
991
1014
  }
992
1015
  throw new Error(`Cannot update keyframes: "${key}" is not set`);
@@ -996,10 +1019,16 @@ const getSequenceWritableProp = ({ attributes, key, missingPropInitialValue, })
996
1019
  setExpression: (nextExpression) => {
997
1020
  prop.value = nextExpression;
998
1021
  },
1022
+ remove: () => {
1023
+ objExpr.properties.splice(propIndex, 1);
1024
+ if (objExpr.properties.length === 0) {
1025
+ attributes.splice(parentAttrIndex, 1);
1026
+ }
1027
+ },
999
1028
  };
1000
1029
  };
1001
1030
  const getEffectWritableProp = ({ objExpr, key, missingPropInitialValue, }) => {
1002
- const { prop } = findObjectProperty(objExpr, key);
1031
+ const { propIndex, prop } = findObjectProperty(objExpr, key);
1003
1032
  if (!prop) {
1004
1033
  if (missingPropInitialValue) {
1005
1034
  return {
@@ -1007,6 +1036,7 @@ const getEffectWritableProp = ({ objExpr, key, missingPropInitialValue, }) => {
1007
1036
  setExpression: (nextExpression) => {
1008
1037
  objExpr.properties.push(createObjectProperty(key, nextExpression));
1009
1038
  },
1039
+ remove: () => undefined,
1010
1040
  };
1011
1041
  }
1012
1042
  throw new Error(`Cannot update keyframes: "${key}" is not set`);
@@ -1016,6 +1046,9 @@ const getEffectWritableProp = ({ objExpr, key, missingPropInitialValue, }) => {
1016
1046
  setExpression: (nextExpression) => {
1017
1047
  prop.value = nextExpression;
1018
1048
  },
1049
+ remove: () => {
1050
+ objExpr.properties.splice(propIndex, 1);
1051
+ },
1019
1052
  };
1020
1053
  };
1021
1054
  const getEffectPropsObjectExpression = (call) => {
@@ -1072,7 +1105,18 @@ const updateSequenceKeyframesAst = ({ input, nodePath, updates, schema, videoCon
1072
1105
  videoConfigValues: videoConfigIdentifierValues,
1073
1106
  });
1074
1107
  newValueStrings.push(recast.print(nextExpression).code);
1075
- prop.setExpression(nextExpression);
1108
+ if (shouldRemovePropAfterKeyframeOperation({
1109
+ expression: prop.expression,
1110
+ key: update.key,
1111
+ operation: update.operation,
1112
+ schema: schema !== null && schema !== void 0 ? schema : null,
1113
+ videoConfigValues: videoConfigIdentifierValues,
1114
+ })) {
1115
+ prop.remove();
1116
+ }
1117
+ else {
1118
+ prop.setExpression(nextExpression);
1119
+ }
1076
1120
  if (introduced.calleeName) {
1077
1121
  requiredImports.add(introduced.calleeName);
1078
1122
  }
@@ -1180,7 +1224,18 @@ const updateEffectKeyframesAst = ({ input, sequenceNodePath, effectIndex, update
1180
1224
  videoConfigValues: videoConfigIdentifierValues,
1181
1225
  });
1182
1226
  newValueStrings.push(recast.print(nextExpression).code);
1183
- prop.setExpression(nextExpression);
1227
+ if (shouldRemovePropAfterKeyframeOperation({
1228
+ expression: prop.expression,
1229
+ key: update.key,
1230
+ operation: update.operation,
1231
+ schema: schema !== null && schema !== void 0 ? schema : null,
1232
+ videoConfigValues: videoConfigIdentifierValues,
1233
+ })) {
1234
+ prop.remove();
1235
+ }
1236
+ else {
1237
+ prop.setExpression(nextExpression);
1238
+ }
1184
1239
  if (introduced.calleeName) {
1185
1240
  requiredImports.add(introduced.calleeName);
1186
1241
  }
@@ -0,0 +1,6 @@
1
+ export declare const getFigmaClipboardPasteSupportError: (zstdDecompressSync: unknown) => "Figma paste is only available with Node.js 22.15 or newer" | null;
2
+ export declare const convertFigmaClipboardToSvg: (html: string) => {
3
+ height: number;
4
+ svg: string;
5
+ width: number;
6
+ };
@@ -0,0 +1,312 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.convertFigmaClipboardToSvg = exports.getFigmaClipboardPasteSupportError = void 0;
37
+ const node_buffer_1 = require("node:buffer");
38
+ const zlib = __importStar(require("node:zlib"));
39
+ const kiwi_schema_1 = require("kiwi-schema");
40
+ const figma_to_svg_1 = require("./figma-to-svg");
41
+ const figmaMetaStart = '<!--(figmeta)';
42
+ const figmaMetaEnd = '(/figmeta)-->';
43
+ const figmaDataStart = '<!--(figma)';
44
+ const figmaDataEnd = '(/figma)-->';
45
+ const figKiwiPrelude = 'fig-kiwi';
46
+ const maxClipboardHtmlBytes = 25 * 1024 * 1024;
47
+ const maxMetaBytes = 1024 * 1024;
48
+ const maxArchiveBytes = 16 * 1024 * 1024;
49
+ const maxCompressedSchemaBytes = 5 * 1024 * 1024;
50
+ const maxCompressedMessageBytes = 10 * 1024 * 1024;
51
+ const maxSchemaBytes = 10 * 1024 * 1024;
52
+ const maxMessageBytes = 40 * 1024 * 1024;
53
+ const maxSchemaDefinitions = 2000;
54
+ const maxSchemaFields = 50000;
55
+ const maxNodeChanges = 20000;
56
+ const maxBlobs = 20000;
57
+ const nodeVersionRequirement = 'Figma paste is only available with Node.js 22.15 or newer';
58
+ const nativeZstdDecompressSync = zlib.zstdDecompressSync;
59
+ const fail = (message) => {
60
+ throw new Error(`Cannot import Figma selection: ${message}`);
61
+ };
62
+ const withFriendlyFailure = (operation, fallback) => {
63
+ try {
64
+ return operation();
65
+ }
66
+ catch (error) {
67
+ if (error instanceof Error &&
68
+ error.message.startsWith('Cannot import Figma selection:')) {
69
+ throw error;
70
+ }
71
+ return fail(fallback);
72
+ }
73
+ };
74
+ const getFigmaClipboardPasteSupportError = (zstdDecompressSync) => {
75
+ return typeof zstdDecompressSync === 'function'
76
+ ? null
77
+ : nodeVersionRequirement;
78
+ };
79
+ exports.getFigmaClipboardPasteSupportError = getFigmaClipboardPasteSupportError;
80
+ const extractMarker = ({ end, html, label, start, }) => {
81
+ const startIndex = html.indexOf(start);
82
+ if (startIndex === -1) {
83
+ fail(`clipboard is missing its ${label}`);
84
+ }
85
+ const valueStart = startIndex + start.length;
86
+ const endIndex = html.indexOf(end, valueStart);
87
+ if (endIndex === -1) {
88
+ fail(`clipboard has an incomplete ${label}`);
89
+ }
90
+ return html.slice(valueStart, endIndex);
91
+ };
92
+ const decodeBase64 = ({ label, limit, value, }) => {
93
+ const compact = value.replace(/[\t\n\r ]/g, '');
94
+ if (compact.length === 0 ||
95
+ compact.length % 4 !== 0 ||
96
+ !/^[A-Za-z0-9+/]*={0,2}$/.test(compact)) {
97
+ fail(`${label} is not valid Base64`);
98
+ }
99
+ if (compact.length > Math.ceil(limit / 3) * 4) {
100
+ fail(`${label} is too large`);
101
+ }
102
+ const decoded = node_buffer_1.Buffer.from(compact, 'base64');
103
+ if (decoded.byteLength > limit) {
104
+ fail(`${label} is too large`);
105
+ }
106
+ return new Uint8Array(decoded.buffer, decoded.byteOffset, decoded.byteLength);
107
+ };
108
+ const parseMeta = (base64) => {
109
+ const bytes = decodeBase64({
110
+ label: 'Figma metadata',
111
+ limit: maxMetaBytes,
112
+ value: base64,
113
+ });
114
+ let parsed;
115
+ try {
116
+ parsed = JSON.parse(new TextDecoder().decode(bytes));
117
+ }
118
+ catch (_a) {
119
+ fail('clipboard metadata is invalid');
120
+ }
121
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
122
+ fail('clipboard metadata is invalid');
123
+ }
124
+ const meta = parsed;
125
+ if (meta.dataType !== 'scene') {
126
+ fail('clipboard does not contain a Figma scene');
127
+ }
128
+ const { selectedNodeData } = meta;
129
+ if (typeof selectedNodeData !== 'string') {
130
+ fail('clipboard does not identify its selected node');
131
+ }
132
+ const selectedNodeId = selectedNodeData.split('|')[0];
133
+ if (!/^\d+:\d+$/.test(selectedNodeId)) {
134
+ fail('clipboard has an invalid selected node ID');
135
+ }
136
+ return selectedNodeId;
137
+ };
138
+ const parseArchive = (base64) => {
139
+ const bytes = decodeBase64({
140
+ label: 'Figma scene',
141
+ limit: maxArchiveBytes,
142
+ value: base64,
143
+ });
144
+ if (bytes.length < figKiwiPrelude.length + 4) {
145
+ fail('clipboard scene is truncated');
146
+ }
147
+ const prelude = new TextDecoder().decode(bytes.subarray(0, figKiwiPrelude.length));
148
+ if (prelude !== figKiwiPrelude) {
149
+ fail('clipboard scene has an unknown format');
150
+ }
151
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
152
+ const version = view.getUint32(figKiwiPrelude.length, true);
153
+ if (version === 0) {
154
+ fail('clipboard scene has an invalid archive version');
155
+ }
156
+ let offset = figKiwiPrelude.length + 4;
157
+ const chunks = [];
158
+ while (offset < bytes.length) {
159
+ if (offset + 4 > bytes.length) {
160
+ fail('clipboard scene has a truncated chunk header');
161
+ }
162
+ const size = view.getUint32(offset, true);
163
+ offset += 4;
164
+ if (size === 0 || offset + size > bytes.length) {
165
+ fail('clipboard scene has an invalid chunk');
166
+ }
167
+ chunks.push(bytes.slice(offset, offset + size));
168
+ offset += size;
169
+ }
170
+ if (chunks.length !== 2) {
171
+ fail('clipboard scene uses an unsupported archive layout');
172
+ }
173
+ if (chunks[0].length > maxCompressedSchemaBytes) {
174
+ fail('clipboard schema is too large');
175
+ }
176
+ if (chunks[1].length > maxCompressedMessageBytes) {
177
+ fail('clipboard scene is too large');
178
+ }
179
+ return { message: chunks[1], schema: chunks[0] };
180
+ };
181
+ const inflateSchema = (compressed) => {
182
+ const inflated = zlib.inflateRawSync(compressed, {
183
+ maxOutputLength: maxSchemaBytes,
184
+ });
185
+ return new Uint8Array(inflated.buffer, inflated.byteOffset, inflated.byteLength);
186
+ };
187
+ const readLimitedLittleEndian = ({ bytes, limit, length, offset, }) => {
188
+ let result = 0;
189
+ for (let index = length - 1; index >= 0; index--) {
190
+ const nextByte = bytes[offset + index];
191
+ if (result > Math.floor((limit - nextByte) / 256)) {
192
+ fail('clipboard scene expands beyond the size limit');
193
+ }
194
+ result = result * 256 + nextByte;
195
+ }
196
+ return result;
197
+ };
198
+ const getZstandardContentSize = (compressed) => {
199
+ if (compressed.length < 6 ||
200
+ compressed[0] !== 0x28 ||
201
+ compressed[1] !== 0xb5 ||
202
+ compressed[2] !== 0x2f ||
203
+ compressed[3] !== 0xfd) {
204
+ fail('clipboard scene uses an unsupported compression format');
205
+ }
206
+ const descriptor = compressed[4];
207
+ if ((descriptor & 8) !== 0) {
208
+ fail('clipboard scene has an invalid Zstandard frame');
209
+ }
210
+ const singleSegment = (descriptor >> 5) & 1;
211
+ const dictionaryFlag = descriptor & 3;
212
+ const contentSizeFlag = descriptor >> 6;
213
+ const dictionaryBytes = dictionaryFlag === 3 ? 4 : dictionaryFlag;
214
+ const contentSizeBytes = contentSizeFlag
215
+ ? 1 << contentSizeFlag
216
+ : singleSegment;
217
+ if (contentSizeBytes === 0) {
218
+ fail('clipboard scene does not declare its expanded size');
219
+ }
220
+ const contentSizeOffset = 6 - singleSegment + dictionaryBytes;
221
+ if (contentSizeOffset + contentSizeBytes > compressed.length) {
222
+ fail('clipboard scene has a truncated Zstandard header');
223
+ }
224
+ let contentSize = readLimitedLittleEndian({
225
+ bytes: compressed,
226
+ limit: maxMessageBytes,
227
+ length: contentSizeBytes,
228
+ offset: contentSizeOffset,
229
+ });
230
+ if (contentSizeFlag === 1) {
231
+ contentSize += 256;
232
+ }
233
+ if (contentSize <= 0 || contentSize > maxMessageBytes) {
234
+ fail('clipboard scene expands beyond the size limit');
235
+ }
236
+ return contentSize;
237
+ };
238
+ const decompressMessage = ({ compressed, zstdDecompressSync, }) => {
239
+ const expectedBytes = getZstandardContentSize(compressed);
240
+ const decompressed = zstdDecompressSync(compressed, {
241
+ maxOutputLength: expectedBytes,
242
+ });
243
+ if (decompressed.byteLength !== expectedBytes) {
244
+ fail('clipboard scene did not match its declared size');
245
+ }
246
+ return new Uint8Array(decompressed.buffer, decompressed.byteOffset, decompressed.byteLength);
247
+ };
248
+ const decodeMessage = ({ messageBytes, schemaBytes, }) => {
249
+ var _a, _b;
250
+ var _c, _d;
251
+ const schema = (0, kiwi_schema_1.decodeBinarySchema)(schemaBytes);
252
+ if (schema.package !== null &&
253
+ (typeof schema.package !== 'string' ||
254
+ !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(schema.package))) {
255
+ fail('clipboard schema has an invalid package name');
256
+ }
257
+ if (schema.definitions.length > maxSchemaDefinitions) {
258
+ fail('clipboard schema has too many definitions');
259
+ }
260
+ const fieldCount = schema.definitions.reduce((total, definition) => total + definition.fields.length, 0);
261
+ if (fieldCount > maxSchemaFields) {
262
+ fail('clipboard schema has too many fields');
263
+ }
264
+ const compiled = (0, kiwi_schema_1.compileSchema)(schema);
265
+ const decoded = compiled.decodeMessage(messageBytes);
266
+ if (typeof decoded !== 'object' ||
267
+ decoded === null ||
268
+ Array.isArray(decoded)) {
269
+ fail('clipboard scene decoded to an invalid message');
270
+ }
271
+ const message = decoded;
272
+ if (((_c = (_a = message.nodeChanges) === null || _a === void 0 ? void 0 : _a.length) !== null && _c !== void 0 ? _c : 0) > maxNodeChanges ||
273
+ ((_d = (_b = message.blobs) === null || _b === void 0 ? void 0 : _b.length) !== null && _d !== void 0 ? _d : 0) > maxBlobs) {
274
+ fail('clipboard scene has too many objects');
275
+ }
276
+ return message;
277
+ };
278
+ const convertFigmaClipboardToSvg = (html) => {
279
+ if (typeof html !== 'string' || html.length === 0) {
280
+ fail('clipboard HTML is empty');
281
+ }
282
+ if (node_buffer_1.Buffer.byteLength(html, 'utf8') > maxClipboardHtmlBytes) {
283
+ fail('clipboard HTML is too large');
284
+ }
285
+ const supportError = (0, exports.getFigmaClipboardPasteSupportError)(nativeZstdDecompressSync);
286
+ if (supportError !== null) {
287
+ fail(supportError);
288
+ }
289
+ const zstdDecompressSync = nativeZstdDecompressSync;
290
+ const metaBase64 = extractMarker({
291
+ end: figmaMetaEnd,
292
+ html,
293
+ label: 'figmeta section',
294
+ start: figmaMetaStart,
295
+ });
296
+ const figmaBase64 = extractMarker({
297
+ end: figmaDataEnd,
298
+ html,
299
+ label: 'figma section',
300
+ start: figmaDataStart,
301
+ });
302
+ const selectedNodeId = parseMeta(metaBase64);
303
+ const archive = parseArchive(figmaBase64);
304
+ const schemaBytes = withFriendlyFailure(() => inflateSchema(archive.schema), 'clipboard schema could not be decompressed');
305
+ const messageBytes = withFriendlyFailure(() => decompressMessage({
306
+ compressed: archive.message,
307
+ zstdDecompressSync,
308
+ }), 'clipboard scene could not be decompressed');
309
+ const message = withFriendlyFailure(() => decodeMessage({ messageBytes, schemaBytes }), 'clipboard scene could not be decoded');
310
+ return (0, figma_to_svg_1.renderFigmaMessageToSvg)({ message, selectedNodeId });
311
+ };
312
+ exports.convertFigmaClipboardToSvg = convertFigmaClipboardToSvg;
@@ -0,0 +1,116 @@
1
+ type FigmaVector = {
2
+ x: number;
3
+ y: number;
4
+ };
5
+ type FigmaGuid = {
6
+ sessionID?: number;
7
+ localID?: number;
8
+ };
9
+ type FigmaColor = {
10
+ r?: number;
11
+ g?: number;
12
+ b?: number;
13
+ a?: number;
14
+ };
15
+ type FigmaPaint = {
16
+ type?: string;
17
+ color?: FigmaColor;
18
+ opacity?: number;
19
+ visible?: boolean;
20
+ blendMode?: string;
21
+ };
22
+ type FigmaTransform = {
23
+ m00?: number;
24
+ m01?: number;
25
+ m02?: number;
26
+ m10?: number;
27
+ m11?: number;
28
+ m12?: number;
29
+ };
30
+ type FigmaArcData = {
31
+ startingAngle?: number;
32
+ endingAngle?: number;
33
+ innerRadius?: number;
34
+ };
35
+ export type FigmaNode = {
36
+ guid?: FigmaGuid;
37
+ phase?: string;
38
+ parentIndex?: {
39
+ guid?: FigmaGuid;
40
+ position?: string;
41
+ };
42
+ type?: string;
43
+ name?: string;
44
+ visible?: boolean;
45
+ opacity?: number;
46
+ blendMode?: string;
47
+ size?: FigmaVector;
48
+ transform?: FigmaTransform;
49
+ mask?: boolean;
50
+ maskType?: string;
51
+ maskIsOutline?: boolean;
52
+ fillPaints?: FigmaPaint[];
53
+ backgroundPaints?: FigmaPaint[];
54
+ strokePaints?: FigmaPaint[];
55
+ strokeWeight?: number;
56
+ borderTopWeight?: number;
57
+ borderBottomWeight?: number;
58
+ borderLeftWeight?: number;
59
+ borderRightWeight?: number;
60
+ borderStrokeWeightsIndependent?: boolean;
61
+ strokeAlign?: string;
62
+ strokeCap?: string;
63
+ strokeJoin?: string;
64
+ dashPattern?: number[];
65
+ miterLimit?: number;
66
+ cornerRadius?: number;
67
+ cornerSmoothing?: number;
68
+ rectangleTopLeftCornerRadius?: number;
69
+ rectangleTopRightCornerRadius?: number;
70
+ rectangleBottomLeftCornerRadius?: number;
71
+ rectangleBottomRightCornerRadius?: number;
72
+ rectangleCornerRadiiIndependent?: boolean;
73
+ frameMaskDisabled?: boolean;
74
+ resizeToFit?: boolean;
75
+ effects?: Array<{
76
+ visible?: boolean;
77
+ }>;
78
+ vectorData?: {
79
+ vectorNetworkBlob?: number;
80
+ normalizedSize?: FigmaVector;
81
+ };
82
+ arcData?: FigmaArcData;
83
+ };
84
+ export type FigmaMessage = {
85
+ type?: string;
86
+ nodeChanges?: FigmaNode[];
87
+ blobs?: Array<{
88
+ bytes?: Uint8Array;
89
+ }>;
90
+ };
91
+ type VectorVertex = FigmaVector;
92
+ type VectorSegment = {
93
+ start: number;
94
+ end: number;
95
+ tangentStart: FigmaVector;
96
+ tangentEnd: FigmaVector;
97
+ };
98
+ type VectorRegion = {
99
+ windingRule: 'evenodd' | 'nonzero';
100
+ loops: number[][];
101
+ };
102
+ type VectorNetwork = {
103
+ vertices: VectorVertex[];
104
+ segments: VectorSegment[];
105
+ regions: VectorRegion[];
106
+ };
107
+ export declare const decodeFigmaVectorNetwork: (data: Uint8Array<ArrayBufferLike>) => VectorNetwork;
108
+ export declare const renderFigmaMessageToSvg: ({ message, selectedNodeId, }: {
109
+ message: FigmaMessage;
110
+ selectedNodeId: string;
111
+ }) => {
112
+ height: number;
113
+ svg: string;
114
+ width: number;
115
+ };
116
+ export {};