@figma/code-connect 1.3.13 → 1.4.1

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 (65) hide show
  1. package/dist/commands/connect.d.ts +1 -1
  2. package/dist/commands/connect.d.ts.map +1 -1
  3. package/dist/commands/connect.js +104 -25
  4. package/dist/commands/connect.js.map +1 -1
  5. package/dist/common/error_formatting.d.ts +34 -0
  6. package/dist/common/error_formatting.d.ts.map +1 -0
  7. package/dist/common/error_formatting.js +115 -0
  8. package/dist/common/error_formatting.js.map +1 -0
  9. package/dist/connect/api.d.ts +13 -0
  10. package/dist/connect/api.d.ts.map +1 -1
  11. package/dist/connect/api.js.map +1 -1
  12. package/dist/connect/external_types.d.ts +1 -0
  13. package/dist/connect/external_types.d.ts.map +1 -1
  14. package/dist/connect/external_types.js +4 -0
  15. package/dist/connect/external_types.js.map +1 -1
  16. package/dist/connect/figma_connect.d.ts +3 -1
  17. package/dist/connect/figma_connect.d.ts.map +1 -1
  18. package/dist/connect/figma_connect.js.map +1 -1
  19. package/dist/connect/intrinsics.d.ts +9 -2
  20. package/dist/connect/intrinsics.d.ts.map +1 -1
  21. package/dist/connect/intrinsics.js +19 -0
  22. package/dist/connect/intrinsics.js.map +1 -1
  23. package/dist/connect/label_language_mapping.d.ts +20 -5
  24. package/dist/connect/label_language_mapping.d.ts.map +1 -1
  25. package/dist/connect/label_language_mapping.js +36 -22
  26. package/dist/connect/label_language_mapping.js.map +1 -1
  27. package/dist/connect/migration_helpers.d.ts +22 -2
  28. package/dist/connect/migration_helpers.d.ts.map +1 -1
  29. package/dist/connect/migration_helpers.js +184 -24
  30. package/dist/connect/migration_helpers.js.map +1 -1
  31. package/dist/connect/parser_common.d.ts.map +1 -1
  32. package/dist/connect/parser_common.js +1 -0
  33. package/dist/connect/parser_common.js.map +1 -1
  34. package/dist/connect/parser_executable_types.d.ts +11 -5
  35. package/dist/connect/parser_executable_types.d.ts.map +1 -1
  36. package/dist/connect/parser_executable_types.js +5 -1
  37. package/dist/connect/parser_executable_types.js.map +1 -1
  38. package/dist/connect/project.d.ts +3 -2
  39. package/dist/connect/project.d.ts.map +1 -1
  40. package/dist/connect/project.js +1 -1
  41. package/dist/connect/project.js.map +1 -1
  42. package/dist/connect/upload.d.ts.map +1 -1
  43. package/dist/connect/upload.js +9 -4
  44. package/dist/connect/upload.js.map +1 -1
  45. package/dist/html/external.d.ts +1 -1
  46. package/dist/html/external.d.ts.map +1 -1
  47. package/dist/html/external.js +1 -0
  48. package/dist/html/external.js.map +1 -1
  49. package/dist/html/parser.js +1 -1
  50. package/dist/html/parser.js.map +1 -1
  51. package/dist/react/create.d.ts.map +1 -1
  52. package/dist/react/create.js +3 -0
  53. package/dist/react/create.js.map +1 -1
  54. package/dist/react/external.d.ts +2 -2
  55. package/dist/react/external.d.ts.map +1 -1
  56. package/dist/react/external.js +2 -1
  57. package/dist/react/external.js.map +1 -1
  58. package/dist/react/parser.js +1 -1
  59. package/dist/react/parser.js.map +1 -1
  60. package/dist/react/parser_template_helpers.d.ts.map +1 -1
  61. package/dist/react/parser_template_helpers.js +4 -1
  62. package/dist/react/parser_template_helpers.js.map +1 -1
  63. package/dist/storybook/convert.js +1 -1
  64. package/dist/storybook/convert.js.map +1 -1
  65. package/package.json +4 -2
@@ -1,21 +1,41 @@
1
1
  import { CodeConnectJSON } from '../connect/figma_connect';
2
- export declare function writeTemplateFile(doc: CodeConnectJSON, outputDir: string | undefined, baseDir: string, localSourcePath?: string): {
2
+ export declare function writeTemplateFile(doc: CodeConnectJSON, outputDir: string | undefined, baseDir: string, localSourcePath?: string, filePathsCreated?: Set<string>, removeProps?: boolean): {
3
3
  outputPath: string;
4
4
  skipped: boolean;
5
5
  };
6
6
  export declare function migrateTemplateToUseServerSideHelpers(template: string): string;
7
7
  export declare function addId(template: string, id: string): string;
8
+ export declare function addImports(template: string, imports: string[] | undefined): string;
9
+ export declare function addNestableToMetadata(template: string, nestable: boolean): string;
8
10
  /**
9
11
  * Migrates V1 templates to V2 API.
10
12
  *
11
13
  * This performs safe, incremental transformations. The following patterns
12
14
  * are intentionally NOT migrated as they're still supported in V2:
13
15
  *
14
- * - .__properties__.children() - no direct V2 equivalent, still supported
15
16
  * - __props metadata building pattern - still valid JavaScript
16
17
  * - __renderWithFn__() - complex transformation, still supported
17
18
  *
18
19
  * These may be addressed in future migrations.
19
20
  */
20
21
  export declare const migrateV1TemplateToV2: (template: string) => string;
22
+ /**
23
+ * Removes the __props definition and props assignments. These are only used by icons
24
+ * helpers and significantly bloat templates.
25
+ */
26
+ export declare function removePropsDefinition(template: string): string;
27
+ /**
28
+ * Removes the __props definition/assignments and removes __props from the default export
29
+ */
30
+ export declare function removePropsDefinitionAndMetadata(template: string): string;
31
+ type CodeConnectObjectsForFigmaUrl = {
32
+ main: CodeConnectJSON | null;
33
+ variants: CodeConnectJSON[];
34
+ };
35
+ /**
36
+ * For each figmaUrl in the given codeConnectObjects, return the main (non-variant)
37
+ * codeConnectObject plus a list of any variants
38
+ */
39
+ export declare const groupCodeConnectObjectsByFigmaUrl: (codeConnectObjects: CodeConnectJSON[]) => Record<string, CodeConnectObjectsForFigmaUrl>;
40
+ export {};
21
41
  //# sourceMappingURL=migration_helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration_helpers.d.ts","sourceRoot":"","sources":["../../src/connect/migration_helpers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE1D,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,eAAe,EACpB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,GACvB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CA2D1C;AAGD,wBAAgB,qCAAqC,CAAC,QAAQ,EAAE,MAAM,UAqBrE;AAED,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,GAAI,UAAU,MAAM,KAAG,MAqFxD,CAAA"}
1
+ {"version":3,"file":"migration_helpers.d.ts","sourceRoot":"","sources":["../../src/connect/migration_helpers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE1D,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,eAAe,EACpB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,EACxB,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC9B,WAAW,CAAC,EAAE,OAAO,GACpB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAuH1C;AAGD,wBAAgB,qCAAqC,CAAC,QAAQ,EAAE,MAAM,UAqBrE;AAED,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,CAsBlF;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CAGjF;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAAI,UAAU,MAAM,KAAG,MA8FxD,CAAA;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAI9D;AAED;;GAEG;AACH,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAgBzE;AAED,KAAK,6BAA6B,GAAG;IACnC,IAAI,EAAE,eAAe,GAAG,IAAI,CAAA;IAC5B,QAAQ,EAAE,eAAe,EAAE,CAAA;CAC5B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,iCAAiC,GAAI,oBAAoB,eAAe,EAAE,kDAkBtF,CAAA"}
@@ -36,45 +36,89 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.migrateV1TemplateToV2 = void 0;
39
+ exports.groupCodeConnectObjectsByFigmaUrl = exports.migrateV1TemplateToV2 = void 0;
40
40
  exports.writeTemplateFile = writeTemplateFile;
41
41
  exports.migrateTemplateToUseServerSideHelpers = migrateTemplateToUseServerSideHelpers;
42
42
  exports.addId = addId;
43
+ exports.addImports = addImports;
44
+ exports.addNestableToMetadata = addNestableToMetadata;
45
+ exports.removePropsDefinition = removePropsDefinition;
46
+ exports.removePropsDefinitionAndMetadata = removePropsDefinitionAndMetadata;
43
47
  const fs_1 = __importDefault(require("fs"));
44
48
  const path_1 = __importDefault(require("path"));
45
49
  const prettier = __importStar(require("prettier"));
46
- function writeTemplateFile(doc, outputDir, baseDir, localSourcePath) {
47
- const suffix = '.figma.template.js';
48
- // Determine output filename
49
- let outputPath;
50
+ function writeTemplateFile(doc, outputDir, baseDir, localSourcePath, filePathsCreated, removeProps) {
51
+ const suffix = '.figma.js';
52
+ // Determine base output filename
53
+ let baseOutputPath;
50
54
  if (outputDir) {
51
55
  // Use specified output directory
52
56
  const filename = `${doc.component || 'template'}${suffix}`;
53
- outputPath = path_1.default.join(outputDir, filename);
57
+ baseOutputPath = path_1.default.join(outputDir, filename);
54
58
  }
55
59
  else if (localSourcePath) {
56
60
  // Use same directory as local source file
57
61
  const sourceDir = path_1.default.dirname(localSourcePath);
58
- const sourceBasename = path_1.default.basename(localSourcePath, path_1.default.extname(localSourcePath));
62
+ let sourceBasename = path_1.default.basename(localSourcePath);
63
+ // If this is a Code Connect file, extract the base component name
64
+ // Handles patterns like: Button.figma.tsx, Button.figmadoc.tsx, Button.figma.template.js
65
+ // Should all become: Button.figma.js
66
+ const codeConnectPattern = /\.(figma|figmadoc)(\.[^.]+)+$/;
67
+ if (codeConnectPattern.test(sourceBasename)) {
68
+ // Extract everything before the .figma/.figmadoc pattern
69
+ sourceBasename = sourceBasename.replace(codeConnectPattern, '');
70
+ }
71
+ else {
72
+ // For regular component files, strip extension normally
73
+ sourceBasename = path_1.default.basename(localSourcePath, path_1.default.extname(localSourcePath));
74
+ }
59
75
  const filename = `${sourceBasename}${suffix}`;
60
- outputPath = path_1.default.join(sourceDir, filename);
76
+ baseOutputPath = path_1.default.join(sourceDir, filename);
61
77
  }
62
78
  else {
63
79
  // No source info, use current directory
64
80
  const filename = `${doc.component || 'template'}${suffix}`;
65
- outputPath = path_1.default.join(baseDir, filename);
81
+ baseOutputPath = path_1.default.join(baseDir, filename);
66
82
  }
67
- // Check if file exists and skip (always skip existing files)
68
- if (fs_1.default.existsSync(outputPath)) {
69
- return { outputPath, skipped: true };
83
+ // Check if file already exists on disk (pre-existing file, not created in this run)
84
+ const existsOnDisk = fs_1.default.existsSync(baseOutputPath);
85
+ const createdInThisRun = filePathsCreated && filePathsCreated.has(baseOutputPath);
86
+ if (existsOnDisk && !createdInThisRun) {
87
+ // This file existed before the migration run, skip it
88
+ return { outputPath: baseOutputPath, skipped: true };
89
+ }
90
+ // Handle duplicate names (either created in this run or would conflict with an existing file)
91
+ let outputPath = baseOutputPath;
92
+ if (createdInThisRun || existsOnDisk) {
93
+ // Find a unique name by appending _1, _2, etc. before the suffix
94
+ const dir = path_1.default.dirname(baseOutputPath);
95
+ const basename = path_1.default.basename(baseOutputPath);
96
+ // Remove the suffix to get the base name (works for any suffix like .figma.js or .figma.ts)
97
+ const baseNameWithoutSuffix = basename.endsWith(suffix)
98
+ ? basename.slice(0, -suffix.length)
99
+ : basename;
100
+ let counter = 1;
101
+ do {
102
+ outputPath = path_1.default.join(dir, `${baseNameWithoutSuffix}_${counter}${suffix}`);
103
+ counter++;
104
+ } while ((filePathsCreated && filePathsCreated.has(outputPath)) || fs_1.default.existsSync(outputPath));
70
105
  }
71
106
  let template = doc.template;
107
+ template = removeSwiftHelpers(template);
72
108
  // Helpers have not been injected - replace reference with server-side versions
73
109
  template = migrateTemplateToUseServerSideHelpers(template);
110
+ // Remove __props definition and from metadata (if flag is set)
111
+ if (removeProps) {
112
+ template = removePropsDefinitionAndMetadata(template);
113
+ }
74
114
  // V1 -> V2 codemods
75
115
  template = (0, exports.migrateV1TemplateToV2)(template);
76
116
  // Add required id to template (set to TODO if no usable name)
77
117
  template = addId(template, doc.component || 'TODO');
118
+ // Add imports if present
119
+ template = addImports(template, doc.templateData?.imports);
120
+ // Add nestable to metadata (default to false)
121
+ template = addNestableToMetadata(template, !!doc.templateData?.nestable);
78
122
  // Format for ease of use
79
123
  template = prettier.format(template, {
80
124
  parser: 'typescript',
@@ -85,8 +129,16 @@ function writeTemplateFile(doc, outputDir, baseDir, localSourcePath) {
85
129
  pluginSearchDirs: false,
86
130
  });
87
131
  // Create the template file content
88
- // Format: first line is the URL, rest is the template
89
- const fileContent = `// url=${doc.figmaNode}\n${template}`;
132
+ // Build comment header lines
133
+ const commentLines = [`// url=${doc.figmaNode}`]; // URL is required
134
+ if (doc.source) {
135
+ commentLines.push(`// source=${doc.source}`);
136
+ }
137
+ if (doc.component) {
138
+ commentLines.push(`// component=${doc.component}`);
139
+ }
140
+ commentLines.push(``);
141
+ const fileContent = commentLines.join('\n') + '\n' + template;
90
142
  // Ensure output directory exists
91
143
  const outputDirPath = path_1.default.dirname(outputPath);
92
144
  if (!fs_1.default.existsSync(outputDirPath)) {
@@ -94,6 +146,10 @@ function writeTemplateFile(doc, outputDir, baseDir, localSourcePath) {
94
146
  }
95
147
  // Write the file
96
148
  fs_1.default.writeFileSync(outputPath, fileContent, 'utf-8');
149
+ // Track the created file path
150
+ if (filePathsCreated) {
151
+ filePathsCreated.add(outputPath);
152
+ }
97
153
  return { outputPath, skipped: false };
98
154
  }
99
155
  // Renames must match helpers in code_connect_js_api.raw_source.ts
@@ -120,13 +176,32 @@ function migrateTemplateToUseServerSideHelpers(template) {
120
176
  function addId(template, id) {
121
177
  return template.replace(/export default \{/, `export default { id: '${id}',`);
122
178
  }
179
+ function addImports(template, imports) {
180
+ if (!imports || imports.length === 0) {
181
+ return template;
182
+ }
183
+ // Escape imports for safe insertion into JS
184
+ const importsJson = JSON.stringify(imports);
185
+ // Add imports after the id field if it exists, otherwise at the start
186
+ // Match: export default { id: '...', (with optional whitespace/newlines)
187
+ const withId = template.replace(/(export default\s*\{\s*id:\s*'[^']*',)/, `$1 imports: ${importsJson},`);
188
+ // If id replacement worked, return
189
+ if (withId !== template) {
190
+ return withId;
191
+ }
192
+ // Otherwise, add at the start (after opening brace)
193
+ return template.replace(/export default\s*\{/, `export default { imports: ${importsJson},`);
194
+ }
195
+ function addNestableToMetadata(template, nestable) {
196
+ // Find "metadata: {" and replace with "metadata: { nestable: <value>,"
197
+ return template.replace(/metadata:\s*\{/, `metadata: { nestable: ${nestable},`);
198
+ }
123
199
  /**
124
200
  * Migrates V1 templates to V2 API.
125
201
  *
126
202
  * This performs safe, incremental transformations. The following patterns
127
203
  * are intentionally NOT migrated as they're still supported in V2:
128
204
  *
129
- * - .__properties__.children() - no direct V2 equivalent, still supported
130
205
  * - __props metadata building pattern - still valid JavaScript
131
206
  * - __renderWithFn__() - complex transformation, still supported
132
207
  *
@@ -136,16 +211,23 @@ const migrateV1TemplateToV2 = (template) => {
136
211
  let migrated = template;
137
212
  // 1. Core object rename
138
213
  migrated = migrated.replace(/figma\.currentLayer/g, 'figma.selectedInstance');
139
- // 2. Property accessor methods
214
+ // 2. Normalize template types to figma.code
215
+ migrated = migrated.replace(/figma\.html/g, 'figma.code');
216
+ migrated = migrated.replace(/figma\.tsx/g, 'figma.code');
217
+ migrated = migrated.replace(/figma\.swift/g, 'figma.code');
218
+ migrated = migrated.replace(/figma\.kotlin/g, 'figma.code');
219
+ // 3. Property accessor methods
140
220
  migrated = migrated.replace(/\.__properties__\.string\(/g, '.getString(');
141
221
  migrated = migrated.replace(/\.__properties__\.boolean\(/g, '.getBoolean(');
142
222
  migrated = migrated.replace(/\.__properties__\.enum\(/g, '.getEnum(');
143
223
  migrated = migrated.replace(/\.__properties__\.__instance__\(/g, '.getInstanceSwap(');
144
224
  // .__properties__.instance() auto-renders, so we need to add .executeTemplate().example
145
- migrated = migrated.replace(/\.__properties__\.instance\(([^)]+)\)/g, '.getInstanceSwap($1).executeTemplate().example');
146
- // 3. Other method renames
225
+ migrated = migrated.replace(/\.__properties__\.instance\(([^)]+)\)/g, '.getInstanceSwap($1)?.executeTemplate().example');
226
+ // 4. Alias for __properties__ on selectedInstance
227
+ migrated = migrated.replace(/figma\.selectedInstance\.__properties__\./g, 'figma.properties.');
228
+ // 5. Other method renames
147
229
  migrated = migrated.replace(/\.__getPropertyValue__\(/g, '.getPropertyValue(');
148
- // 4. __findChildWithCriteria__ - migrate based on type parameter
230
+ // 6. __findChildWithCriteria__ - migrate based on type parameter
149
231
  // For TEXT type with __render__(): __findChildWithCriteria__({ name: 'X', type: "TEXT" }).__render__() → findText('X').textContent
150
232
  migrated = migrated.replace(/\.__findChildWithCriteria__\(\{\s*name:\s*'([^']+)',\s*type:\s*"TEXT"\s*\}\)\.__render__\(\)/g, ".findText('$1').textContent");
151
233
  migrated = migrated.replace(/\.__findChildWithCriteria__\(\{\s*type:\s*"TEXT",\s*name:\s*'([^']+)'\s*\}\)\.__render__\(\)/g, ".findText('$1').textContent");
@@ -155,25 +237,103 @@ const migrateV1TemplateToV2 = (template) => {
155
237
  // For TEXT type without __render__(): __findChildWithCriteria__({ type: 'TEXT', name: 'X' }) → findText('X')
156
238
  migrated = migrated.replace(/\.__findChildWithCriteria__\(\{\s*name:\s*'([^']+)',\s*type:\s*['"]TEXT['"]\s*\}\)/g, ".findText('$1')");
157
239
  migrated = migrated.replace(/\.__findChildWithCriteria__\(\{\s*type:\s*['"]TEXT['"],\s*name:\s*'([^']+)'\s*\}\)/g, ".findText('$1')");
158
- // 5. __find__() - migrate to findInstance()
240
+ // 7. __find__() - migrate to findInstance()
159
241
  migrated = migrated.replace(/\.__find__\(("([^"]+)"|'([^']+)')\)/g, (match, quote, doubleQuoted, singleQuoted) => {
160
242
  const name = doubleQuoted || singleQuoted;
161
243
  return `.findInstance("${name}")`;
162
244
  });
163
- // 6. __render__() - migrate to executeTemplate().example (but not if part of __findChildWithCriteria__)
245
+ // 8. __render__() - migrate to executeTemplate().example (but not if part of __findChildWithCriteria__)
164
246
  migrated = migrated.replace(/\.__render__\(\)/g, '.executeTemplate().example');
165
- // 7. __getProps__() - migrate to executeTemplate().metadata.props
247
+ // 9. __getProps__() - migrate to executeTemplate().metadata.props
166
248
  migrated = migrated.replace(/\.__getProps__\(\)/g, '.executeTemplate().metadata.props');
167
- // 8. Export format - simple case
249
+ // 10. Export format - simple case
168
250
  // Match export default figma.code` (or tsx, html, etc) and wrap in { example: ... }
169
251
  migrated = migrated.replace(/export default figma\.(code|tsx|html|swift|kotlin)`/g, 'export default { example: figma.$1`');
170
252
  // Close the template literal for simple exports (look for backtick at end, handling multiline)
171
253
  // Use a more robust approach: find the last backtick that's not followed by more content
172
254
  migrated = migrated.replace(/(export default \{ example: figma\.\w+`[\s\S]*?)`(?=\s*$)/gm, '$1` }');
173
- // 9. Export format - spread operator case
255
+ // 11. Export format - spread operator case
174
256
  // { ...figma.code`...`, metadata: ... } → { example: figma.code`...`, metadata: ... }
175
257
  migrated = migrated.replace(/\{\s*\.\.\.figma\.(code|tsx|html|swift|kotlin)`/g, '{ example: figma.$1`');
176
258
  return migrated;
177
259
  };
178
260
  exports.migrateV1TemplateToV2 = migrateV1TemplateToV2;
261
+ /**
262
+ * Removes the __props definition and props assignments. These are only used by icons
263
+ * helpers and significantly bloat templates.
264
+ */
265
+ function removePropsDefinition(template) {
266
+ // Match from "const __props = {" through everything up until (but not including) "export default {"
267
+ // Uses [\s\S] to match any character including newlines
268
+ return template.replace(/const\s+__props\s*=\s*\{[\s\S]*?(?=export\s+default\s*\{)/g, '\n');
269
+ }
270
+ /**
271
+ * Removes the __props definition/assignments and removes __props from the default export
272
+ */
273
+ function removePropsDefinitionAndMetadata(template) {
274
+ // First remove the __props definition and assignments
275
+ let result = removePropsDefinition(template);
276
+ const exportMatch = result.match(/(export\s+default\s+\{[\s\S]*$)/);
277
+ if (exportMatch) {
278
+ const exportSection = exportMatch[1];
279
+ const cleanedExport = exportSection
280
+ .replace(/metadata:\s*\{\s*__props\s*\}/g, 'metadata: {}') // metadata: { __props }
281
+ .replace(/metadata:\s*\{\s*__props\s*,/g, 'metadata: {') // metadata: { __props, ...
282
+ .replace(/,\s*__props\s*\}/g, ' }') // metadata: { ..., __props }
283
+ .replace(/,\s*__props\s*,/g, ','); // metadata: { ..., __props, ... }
284
+ result = result.substring(0, result.indexOf(exportSection)) + cleanedExport;
285
+ }
286
+ return result;
287
+ }
288
+ /**
289
+ * For each figmaUrl in the given codeConnectObjects, return the main (non-variant)
290
+ * codeConnectObject plus a list of any variants
291
+ */
292
+ const groupCodeConnectObjectsByFigmaUrl = (codeConnectObjects) => {
293
+ return codeConnectObjects.reduce((acc, obj) => {
294
+ const figmaUrl = obj.figmaNode;
295
+ if (!acc[figmaUrl]) {
296
+ acc[figmaUrl] = { main: null, variants: [] };
297
+ }
298
+ if (obj.variant && Object.keys(obj.variant).length > 0) {
299
+ acc[figmaUrl].variants.push(obj);
300
+ }
301
+ else {
302
+ acc[figmaUrl].main = obj;
303
+ }
304
+ return acc;
305
+ }, {});
306
+ };
307
+ exports.groupCodeConnectObjectsByFigmaUrl = groupCodeConnectObjectsByFigmaUrl;
308
+ function removeSwiftHelpers(template) {
309
+ return template.replace(`function __fcc_renderSwiftChildren(children, prefix) {
310
+ if (children === undefined) {
311
+ return children
312
+ }
313
+ return children.flatMap((child, index) => {
314
+ if (child.type === 'CODE') {
315
+ let code = child.code.split('\\n').map((line) => {
316
+ return line.trim() !== '' ? \`\${prefix}\${line}\` : line;
317
+ }).join('\\n')
318
+ if (index !== children.length - 1) {
319
+ code = code + '\\n'
320
+ }
321
+ return {
322
+ ...child,
323
+ code: code,
324
+ }
325
+ } else {
326
+ let elements = []
327
+ const shouldAddNewline = index > 0 && children[index - 1].type === 'CODE' && !children[index - 1].code.endsWith('\\n')
328
+ elements.push({ type: 'CODE', code: \`\${shouldAddNewline ? '\\n' : ''}\${prefix}\` })
329
+ elements.push(child)
330
+ if (index !== children.length - 1) {
331
+ elements.push({ type: 'CODE', code: '\\n' })
332
+ }
333
+ return elements
334
+ }
335
+ })
336
+ }
337
+ `, '');
338
+ }
179
339
  //# sourceMappingURL=migration_helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration_helpers.js","sourceRoot":"","sources":["../../src/connect/migration_helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport * as prettier from 'prettier'\nimport { CodeConnectJSON } from '../connect/figma_connect'\n\nexport function writeTemplateFile(\n doc: CodeConnectJSON,\n outputDir: string | undefined,\n baseDir: string,\n localSourcePath?: string,\n): { outputPath: string; skipped: boolean } {\n const suffix = '.figma.template.js'\n\n // Determine output filename\n let outputPath: string\n\n if (outputDir) {\n // Use specified output directory\n const filename = `${doc.component || 'template'}${suffix}`\n outputPath = path.join(outputDir, filename)\n } else if (localSourcePath) {\n // Use same directory as local source file\n const sourceDir = path.dirname(localSourcePath)\n const sourceBasename = path.basename(localSourcePath, path.extname(localSourcePath))\n const filename = `${sourceBasename}${suffix}`\n outputPath = path.join(sourceDir, filename)\n } else {\n // No source info, use current directory\n const filename = `${doc.component || 'template'}${suffix}`\n outputPath = path.join(baseDir, filename)\n }\n\n // Check if file exists and skip (always skip existing files)\n if (fs.existsSync(outputPath)) {\n return { outputPath, skipped: true }\n }\n\n let template = doc.template\n\n // Helpers have not been injected - replace reference with server-side versions\n template = migrateTemplateToUseServerSideHelpers(template)\n // V1 -> V2 codemods\n template = migrateV1TemplateToV2(template)\n // Add required id to template (set to TODO if no usable name)\n template = addId(template, doc.component || 'TODO')\n // Format for ease of use\n template = prettier.format(template, {\n parser: 'typescript',\n semi: false,\n trailingComma: 'all',\n // pluginSearchDirs: false is needed as otherwise prettier picks up other\n // prettier plugins in our monorepo and fails with race condition errors\n pluginSearchDirs: false,\n })\n\n // Create the template file content\n // Format: first line is the URL, rest is the template\n const fileContent = `// url=${doc.figmaNode}\\n${template}`\n\n // Ensure output directory exists\n const outputDirPath = path.dirname(outputPath)\n if (!fs.existsSync(outputDirPath)) {\n fs.mkdirSync(outputDirPath, { recursive: true })\n }\n\n // Write the file\n fs.writeFileSync(outputPath, fileContent, 'utf-8')\n\n return { outputPath, skipped: false }\n}\n\n// Renames must match helpers in code_connect_js_api.raw_source.ts\nexport function migrateTemplateToUseServerSideHelpers(template: string) {\n return (\n template\n // React helpers\n .replace(/_fcc_renderReactProp/g, 'figma.helpers.react.renderProp')\n .replace(/_fcc_renderReactChildren/g, 'figma.helpers.react.renderChildren')\n .replace(/_fcc_jsxElement/g, 'figma.helpers.react.jsxElement')\n .replace(/_fcc_function/g, 'figma.helpers.react.function')\n .replace(/_fcc_identifier/g, 'figma.helpers.react.identifier')\n .replace(/_fcc_object/g, 'figma.helpers.react.object')\n .replace(/_fcc_templateString/g, 'figma.helpers.react.templateString')\n .replace(/_fcc_renderPropValue/g, 'figma.helpers.react.renderPropValue')\n .replace(/_fcc_stringifyObject/g, 'figma.helpers.react.stringifyObject')\n .replace(/_fcc_reactComponent/g, 'figma.helpers.react.reactComponent')\n .replace(/_fcc_array/g, 'figma.helpers.react.array')\n .replace(/isReactComponentArray/g, 'figma.helpers.react.isReactComponentArray')\n // Swift helpers\n .replace(/__fcc_renderSwiftChildren/g, 'figma.helpers.swift.renderChildren')\n // Kotlin/Compose helpers\n .replace(/__fcc_renderComposeChildren/g, 'figma.helpers.kotlin.renderChildren')\n )\n}\n\nexport function addId(template: string, id: string): string {\n return template.replace(/export default \\{/, `export default { id: '${id}',`)\n}\n\n/**\n * Migrates V1 templates to V2 API.\n *\n * This performs safe, incremental transformations. The following patterns\n * are intentionally NOT migrated as they're still supported in V2:\n *\n * - .__properties__.children() - no direct V2 equivalent, still supported\n * - __props metadata building pattern - still valid JavaScript\n * - __renderWithFn__() - complex transformation, still supported\n *\n * These may be addressed in future migrations.\n */\nexport const migrateV1TemplateToV2 = (template: string): string => {\n let migrated = template\n\n // 1. Core object rename\n migrated = migrated.replace(/figma\\.currentLayer/g, 'figma.selectedInstance')\n\n // 2. Property accessor methods\n migrated = migrated.replace(/\\.__properties__\\.string\\(/g, '.getString(')\n migrated = migrated.replace(/\\.__properties__\\.boolean\\(/g, '.getBoolean(')\n migrated = migrated.replace(/\\.__properties__\\.enum\\(/g, '.getEnum(')\n migrated = migrated.replace(/\\.__properties__\\.__instance__\\(/g, '.getInstanceSwap(')\n // .__properties__.instance() auto-renders, so we need to add .executeTemplate().example\n migrated = migrated.replace(\n /\\.__properties__\\.instance\\(([^)]+)\\)/g,\n '.getInstanceSwap($1).executeTemplate().example',\n )\n\n // 3. Other method renames\n migrated = migrated.replace(/\\.__getPropertyValue__\\(/g, '.getPropertyValue(')\n\n // 4. __findChildWithCriteria__ - migrate based on type parameter\n // For TEXT type with __render__(): __findChildWithCriteria__({ name: 'X', type: \"TEXT\" }).__render__() → findText('X').textContent\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*name:\\s*'([^']+)',\\s*type:\\s*\"TEXT\"\\s*\\}\\)\\.__render__\\(\\)/g,\n \".findText('$1').textContent\",\n )\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*type:\\s*\"TEXT\",\\s*name:\\s*'([^']+)'\\s*\\}\\)\\.__render__\\(\\)/g,\n \".findText('$1').textContent\",\n )\n // For INSTANCE type: __findChildWithCriteria__({ type: 'INSTANCE', name: 'X' }) → findInstance('X')\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*name:\\s*'([^']+)',\\s*type:\\s*['\"]INSTANCE['\"]\\s*\\}\\)/g,\n \".findInstance('$1')\",\n )\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*type:\\s*['\"]INSTANCE['\"],\\s*name:\\s*'([^']+)'\\s*\\}\\)/g,\n \".findInstance('$1')\",\n )\n // For TEXT type without __render__(): __findChildWithCriteria__({ type: 'TEXT', name: 'X' }) → findText('X')\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*name:\\s*'([^']+)',\\s*type:\\s*['\"]TEXT['\"]\\s*\\}\\)/g,\n \".findText('$1')\",\n )\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*type:\\s*['\"]TEXT['\"],\\s*name:\\s*'([^']+)'\\s*\\}\\)/g,\n \".findText('$1')\",\n )\n\n // 5. __find__() - migrate to findInstance()\n migrated = migrated.replace(\n /\\.__find__\\((\"([^\"]+)\"|'([^']+)')\\)/g,\n (match, quote, doubleQuoted, singleQuoted) => {\n const name = doubleQuoted || singleQuoted\n return `.findInstance(\"${name}\")`\n },\n )\n\n // 6. __render__() - migrate to executeTemplate().example (but not if part of __findChildWithCriteria__)\n migrated = migrated.replace(/\\.__render__\\(\\)/g, '.executeTemplate().example')\n\n // 7. __getProps__() - migrate to executeTemplate().metadata.props\n migrated = migrated.replace(/\\.__getProps__\\(\\)/g, '.executeTemplate().metadata.props')\n\n // 8. Export format - simple case\n // Match export default figma.code` (or tsx, html, etc) and wrap in { example: ... }\n migrated = migrated.replace(\n /export default figma\\.(code|tsx|html|swift|kotlin)`/g,\n 'export default { example: figma.$1`',\n )\n // Close the template literal for simple exports (look for backtick at end, handling multiline)\n // Use a more robust approach: find the last backtick that's not followed by more content\n migrated = migrated.replace(\n /(export default \\{ example: figma\\.\\w+`[\\s\\S]*?)`(?=\\s*$)/gm,\n '$1` }',\n )\n\n // 9. Export format - spread operator case\n // { ...figma.code`...`, metadata: ... } → { example: figma.code`...`, metadata: ... }\n migrated = migrated.replace(\n /\\{\\s*\\.\\.\\.figma\\.(code|tsx|html|swift|kotlin)`/g,\n '{ example: figma.$1`',\n )\n\n return migrated\n}\n"]}
1
+ {"version":3,"file":"migration_helpers.js","sourceRoot":"","sources":["../../src/connect/migration_helpers.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport * as prettier from 'prettier'\nimport { CodeConnectJSON } from '../connect/figma_connect'\n\nexport function writeTemplateFile(\n doc: CodeConnectJSON,\n outputDir: string | undefined,\n baseDir: string,\n localSourcePath?: string,\n filePathsCreated?: Set<string>,\n removeProps?: boolean,\n): { outputPath: string; skipped: boolean } {\n const suffix = '.figma.js'\n\n // Determine base output filename\n let baseOutputPath: string\n\n if (outputDir) {\n // Use specified output directory\n const filename = `${doc.component || 'template'}${suffix}`\n baseOutputPath = path.join(outputDir, filename)\n } else if (localSourcePath) {\n // Use same directory as local source file\n const sourceDir = path.dirname(localSourcePath)\n let sourceBasename = path.basename(localSourcePath)\n\n // If this is a Code Connect file, extract the base component name\n // Handles patterns like: Button.figma.tsx, Button.figmadoc.tsx, Button.figma.template.js\n // Should all become: Button.figma.js\n const codeConnectPattern = /\\.(figma|figmadoc)(\\.[^.]+)+$/\n if (codeConnectPattern.test(sourceBasename)) {\n // Extract everything before the .figma/.figmadoc pattern\n sourceBasename = sourceBasename.replace(codeConnectPattern, '')\n } else {\n // For regular component files, strip extension normally\n sourceBasename = path.basename(localSourcePath, path.extname(localSourcePath))\n }\n\n const filename = `${sourceBasename}${suffix}`\n baseOutputPath = path.join(sourceDir, filename)\n } else {\n // No source info, use current directory\n const filename = `${doc.component || 'template'}${suffix}`\n baseOutputPath = path.join(baseDir, filename)\n }\n\n // Check if file already exists on disk (pre-existing file, not created in this run)\n const existsOnDisk = fs.existsSync(baseOutputPath)\n const createdInThisRun = filePathsCreated && filePathsCreated.has(baseOutputPath)\n\n if (existsOnDisk && !createdInThisRun) {\n // This file existed before the migration run, skip it\n return { outputPath: baseOutputPath, skipped: true }\n }\n\n // Handle duplicate names (either created in this run or would conflict with an existing file)\n let outputPath = baseOutputPath\n if (createdInThisRun || existsOnDisk) {\n // Find a unique name by appending _1, _2, etc. before the suffix\n const dir = path.dirname(baseOutputPath)\n const basename = path.basename(baseOutputPath)\n\n // Remove the suffix to get the base name (works for any suffix like .figma.js or .figma.ts)\n const baseNameWithoutSuffix = basename.endsWith(suffix)\n ? basename.slice(0, -suffix.length)\n : basename\n\n let counter = 1\n do {\n outputPath = path.join(dir, `${baseNameWithoutSuffix}_${counter}${suffix}`)\n counter++\n } while ((filePathsCreated && filePathsCreated.has(outputPath)) || fs.existsSync(outputPath))\n }\n\n let template = doc.template\n\n template = removeSwiftHelpers(template)\n // Helpers have not been injected - replace reference with server-side versions\n template = migrateTemplateToUseServerSideHelpers(template)\n // Remove __props definition and from metadata (if flag is set)\n if (removeProps) {\n template = removePropsDefinitionAndMetadata(template)\n }\n // V1 -> V2 codemods\n template = migrateV1TemplateToV2(template)\n // Add required id to template (set to TODO if no usable name)\n template = addId(template, doc.component || 'TODO')\n // Add imports if present\n template = addImports(template, doc.templateData?.imports)\n // Add nestable to metadata (default to false)\n template = addNestableToMetadata(template, !!doc.templateData?.nestable)\n // Format for ease of use\n template = prettier.format(template, {\n parser: 'typescript',\n semi: false,\n trailingComma: 'all',\n // pluginSearchDirs: false is needed as otherwise prettier picks up other\n // prettier plugins in our monorepo and fails with race condition errors\n pluginSearchDirs: false,\n })\n\n // Create the template file content\n\n // Build comment header lines\n const commentLines: string[] = [`// url=${doc.figmaNode}`] // URL is required\n if (doc.source) {\n commentLines.push(`// source=${doc.source}`)\n }\n if (doc.component) {\n commentLines.push(`// component=${doc.component}`)\n }\n commentLines.push(``)\n\n const fileContent = commentLines.join('\\n') + '\\n' + template\n\n // Ensure output directory exists\n const outputDirPath = path.dirname(outputPath)\n if (!fs.existsSync(outputDirPath)) {\n fs.mkdirSync(outputDirPath, { recursive: true })\n }\n\n // Write the file\n fs.writeFileSync(outputPath, fileContent, 'utf-8')\n\n // Track the created file path\n if (filePathsCreated) {\n filePathsCreated.add(outputPath)\n }\n\n return { outputPath, skipped: false }\n}\n\n// Renames must match helpers in code_connect_js_api.raw_source.ts\nexport function migrateTemplateToUseServerSideHelpers(template: string) {\n return (\n template\n // React helpers\n .replace(/_fcc_renderReactProp/g, 'figma.helpers.react.renderProp')\n .replace(/_fcc_renderReactChildren/g, 'figma.helpers.react.renderChildren')\n .replace(/_fcc_jsxElement/g, 'figma.helpers.react.jsxElement')\n .replace(/_fcc_function/g, 'figma.helpers.react.function')\n .replace(/_fcc_identifier/g, 'figma.helpers.react.identifier')\n .replace(/_fcc_object/g, 'figma.helpers.react.object')\n .replace(/_fcc_templateString/g, 'figma.helpers.react.templateString')\n .replace(/_fcc_renderPropValue/g, 'figma.helpers.react.renderPropValue')\n .replace(/_fcc_stringifyObject/g, 'figma.helpers.react.stringifyObject')\n .replace(/_fcc_reactComponent/g, 'figma.helpers.react.reactComponent')\n .replace(/_fcc_array/g, 'figma.helpers.react.array')\n .replace(/isReactComponentArray/g, 'figma.helpers.react.isReactComponentArray')\n // Swift helpers\n .replace(/__fcc_renderSwiftChildren/g, 'figma.helpers.swift.renderChildren')\n // Kotlin/Compose helpers\n .replace(/__fcc_renderComposeChildren/g, 'figma.helpers.kotlin.renderChildren')\n )\n}\n\nexport function addId(template: string, id: string): string {\n return template.replace(/export default \\{/, `export default { id: '${id}',`)\n}\n\nexport function addImports(template: string, imports: string[] | undefined): string {\n if (!imports || imports.length === 0) {\n return template\n }\n\n // Escape imports for safe insertion into JS\n const importsJson = JSON.stringify(imports)\n\n // Add imports after the id field if it exists, otherwise at the start\n // Match: export default { id: '...', (with optional whitespace/newlines)\n const withId = template.replace(\n /(export default\\s*\\{\\s*id:\\s*'[^']*',)/,\n `$1 imports: ${importsJson},`,\n )\n\n // If id replacement worked, return\n if (withId !== template) {\n return withId\n }\n\n // Otherwise, add at the start (after opening brace)\n return template.replace(/export default\\s*\\{/, `export default { imports: ${importsJson},`)\n}\n\nexport function addNestableToMetadata(template: string, nestable: boolean): string {\n // Find \"metadata: {\" and replace with \"metadata: { nestable: <value>,\"\n return template.replace(/metadata:\\s*\\{/, `metadata: { nestable: ${nestable},`)\n}\n\n/**\n * Migrates V1 templates to V2 API.\n *\n * This performs safe, incremental transformations. The following patterns\n * are intentionally NOT migrated as they're still supported in V2:\n *\n * - __props metadata building pattern - still valid JavaScript\n * - __renderWithFn__() - complex transformation, still supported\n *\n * These may be addressed in future migrations.\n */\nexport const migrateV1TemplateToV2 = (template: string): string => {\n let migrated = template\n\n // 1. Core object rename\n migrated = migrated.replace(/figma\\.currentLayer/g, 'figma.selectedInstance')\n\n // 2. Normalize template types to figma.code\n migrated = migrated.replace(/figma\\.html/g, 'figma.code')\n migrated = migrated.replace(/figma\\.tsx/g, 'figma.code')\n migrated = migrated.replace(/figma\\.swift/g, 'figma.code')\n migrated = migrated.replace(/figma\\.kotlin/g, 'figma.code')\n\n // 3. Property accessor methods\n migrated = migrated.replace(/\\.__properties__\\.string\\(/g, '.getString(')\n migrated = migrated.replace(/\\.__properties__\\.boolean\\(/g, '.getBoolean(')\n migrated = migrated.replace(/\\.__properties__\\.enum\\(/g, '.getEnum(')\n migrated = migrated.replace(/\\.__properties__\\.__instance__\\(/g, '.getInstanceSwap(')\n // .__properties__.instance() auto-renders, so we need to add .executeTemplate().example\n migrated = migrated.replace(\n /\\.__properties__\\.instance\\(([^)]+)\\)/g,\n '.getInstanceSwap($1)?.executeTemplate().example',\n )\n\n // 4. Alias for __properties__ on selectedInstance\n migrated = migrated.replace(/figma\\.selectedInstance\\.__properties__\\./g, 'figma.properties.')\n\n // 5. Other method renames\n migrated = migrated.replace(/\\.__getPropertyValue__\\(/g, '.getPropertyValue(')\n\n // 6. __findChildWithCriteria__ - migrate based on type parameter\n // For TEXT type with __render__(): __findChildWithCriteria__({ name: 'X', type: \"TEXT\" }).__render__() → findText('X').textContent\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*name:\\s*'([^']+)',\\s*type:\\s*\"TEXT\"\\s*\\}\\)\\.__render__\\(\\)/g,\n \".findText('$1').textContent\",\n )\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*type:\\s*\"TEXT\",\\s*name:\\s*'([^']+)'\\s*\\}\\)\\.__render__\\(\\)/g,\n \".findText('$1').textContent\",\n )\n // For INSTANCE type: __findChildWithCriteria__({ type: 'INSTANCE', name: 'X' }) → findInstance('X')\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*name:\\s*'([^']+)',\\s*type:\\s*['\"]INSTANCE['\"]\\s*\\}\\)/g,\n \".findInstance('$1')\",\n )\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*type:\\s*['\"]INSTANCE['\"],\\s*name:\\s*'([^']+)'\\s*\\}\\)/g,\n \".findInstance('$1')\",\n )\n // For TEXT type without __render__(): __findChildWithCriteria__({ type: 'TEXT', name: 'X' }) → findText('X')\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*name:\\s*'([^']+)',\\s*type:\\s*['\"]TEXT['\"]\\s*\\}\\)/g,\n \".findText('$1')\",\n )\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*type:\\s*['\"]TEXT['\"],\\s*name:\\s*'([^']+)'\\s*\\}\\)/g,\n \".findText('$1')\",\n )\n\n // 7. __find__() - migrate to findInstance()\n migrated = migrated.replace(\n /\\.__find__\\((\"([^\"]+)\"|'([^']+)')\\)/g,\n (match, quote, doubleQuoted, singleQuoted) => {\n const name = doubleQuoted || singleQuoted\n return `.findInstance(\"${name}\")`\n },\n )\n\n // 8. __render__() - migrate to executeTemplate().example (but not if part of __findChildWithCriteria__)\n migrated = migrated.replace(/\\.__render__\\(\\)/g, '.executeTemplate().example')\n\n // 9. __getProps__() - migrate to executeTemplate().metadata.props\n migrated = migrated.replace(/\\.__getProps__\\(\\)/g, '.executeTemplate().metadata.props')\n\n // 10. Export format - simple case\n // Match export default figma.code` (or tsx, html, etc) and wrap in { example: ... }\n migrated = migrated.replace(\n /export default figma\\.(code|tsx|html|swift|kotlin)`/g,\n 'export default { example: figma.$1`',\n )\n // Close the template literal for simple exports (look for backtick at end, handling multiline)\n // Use a more robust approach: find the last backtick that's not followed by more content\n migrated = migrated.replace(\n /(export default \\{ example: figma\\.\\w+`[\\s\\S]*?)`(?=\\s*$)/gm,\n '$1` }',\n )\n\n // 11. Export format - spread operator case\n // { ...figma.code`...`, metadata: ... } → { example: figma.code`...`, metadata: ... }\n migrated = migrated.replace(\n /\\{\\s*\\.\\.\\.figma\\.(code|tsx|html|swift|kotlin)`/g,\n '{ example: figma.$1`',\n )\n\n return migrated\n}\n\n/**\n * Removes the __props definition and props assignments. These are only used by icons\n * helpers and significantly bloat templates.\n */\nexport function removePropsDefinition(template: string): string {\n // Match from \"const __props = {\" through everything up until (but not including) \"export default {\"\n // Uses [\\s\\S] to match any character including newlines\n return template.replace(/const\\s+__props\\s*=\\s*\\{[\\s\\S]*?(?=export\\s+default\\s*\\{)/g, '\\n')\n}\n\n/**\n * Removes the __props definition/assignments and removes __props from the default export\n */\nexport function removePropsDefinitionAndMetadata(template: string): string {\n // First remove the __props definition and assignments\n let result = removePropsDefinition(template)\n const exportMatch = result.match(/(export\\s+default\\s+\\{[\\s\\S]*$)/)\n if (exportMatch) {\n const exportSection = exportMatch[1]\n const cleanedExport = exportSection\n .replace(/metadata:\\s*\\{\\s*__props\\s*\\}/g, 'metadata: {}') // metadata: { __props }\n .replace(/metadata:\\s*\\{\\s*__props\\s*,/g, 'metadata: {') // metadata: { __props, ...\n .replace(/,\\s*__props\\s*\\}/g, ' }') // metadata: { ..., __props }\n .replace(/,\\s*__props\\s*,/g, ',') // metadata: { ..., __props, ... }\n\n result = result.substring(0, result.indexOf(exportSection)) + cleanedExport\n }\n\n return result\n}\n\ntype CodeConnectObjectsForFigmaUrl = {\n main: CodeConnectJSON | null\n variants: CodeConnectJSON[]\n}\n\n/**\n * For each figmaUrl in the given codeConnectObjects, return the main (non-variant)\n * codeConnectObject plus a list of any variants\n */\nexport const groupCodeConnectObjectsByFigmaUrl = (codeConnectObjects: CodeConnectJSON[]) => {\n return codeConnectObjects.reduce(\n (acc, obj) => {\n const figmaUrl = obj.figmaNode\n if (!acc[figmaUrl]) {\n acc[figmaUrl] = { main: null, variants: [] }\n }\n\n if (obj.variant && Object.keys(obj.variant).length > 0) {\n acc[figmaUrl].variants.push(obj)\n } else {\n acc[figmaUrl].main = obj\n }\n\n return acc\n },\n {} as Record<string, CodeConnectObjectsForFigmaUrl>,\n )\n}\n\nfunction removeSwiftHelpers(template: string): string {\n return template.replace(\n `function __fcc_renderSwiftChildren(children, prefix) {\n if (children === undefined) {\n return children\n }\n return children.flatMap((child, index) => {\n if (child.type === 'CODE') {\n let code = child.code.split('\\\\n').map((line) => {\n return line.trim() !== '' ? \\`\\${prefix}\\${line}\\` : line;\n }).join('\\\\n')\n if (index !== children.length - 1) {\n code = code + '\\\\n'\n }\n return {\n ...child,\n code: code,\n }\n } else {\n let elements = []\n const shouldAddNewline = index > 0 && children[index - 1].type === 'CODE' && !children[index - 1].code.endsWith('\\\\n')\n elements.push({ type: 'CODE', code: \\`\\${shouldAddNewline ? '\\\\n' : ''}\\${prefix}\\` })\n elements.push(child)\n if (index !== children.length - 1) {\n elements.push({ type: 'CODE', code: '\\\\n' })\n }\n return elements\n }\n })\n}\n`,\n '',\n )\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"parser_common.d.ts","sourceRoot":"","sources":["../../src/connect/parser_common.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parser_common.d.ts","sourceRoot":"","sources":["../../src/connect/parser_common.ts"],"names":[],"mappings":"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"}
@@ -308,6 +308,7 @@ async function parseCodeConnect({ program, file, config, absPath, parseFn, resol
308
308
  if (isFigmaConnectCall(node, parserContext.sourceFile)) {
309
309
  const doc = await parseFn(node, parserContext, parseOptions);
310
310
  if (doc) {
311
+ doc._codeConnectFilePath = file;
311
312
  codeConnectObjects.push(doc);
312
313
  }
313
314
  }
@@ -1 +1 @@
1
- {"version":3,"file":"parser_common.js","sourceRoot":"","sources":["../../src/connect/parser_common.ts"],"names":[],"mappings":"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","sourcesContent":["import ts, { JsxExpression } from 'typescript'\nimport { FIGMA_CONNECT_CALL, PropMappings, valueToString } from './intrinsics'\nimport { highlight, reset } from '../common/logging'\nimport { error } from 'console'\nimport {\n assertIsObjectLiteralExpression,\n assertIsStringLiteral,\n convertObjectLiteralToJs,\n parsePropertyOfType,\n stripQuotesFromNode,\n} from '../typescript/compiler'\nimport { BaseCodeConnectConfig } from './project'\nimport { CodeConnectJSON } from './figma_connect'\n\ninterface ParserErrorContext {\n sourceFile: ts.SourceFile\n node: ts.Node | undefined\n}\n\nexport function getPositionInSourceFile(node: ts.Node, sourceFile: ts.SourceFile) {\n return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile))\n}\n\nexport class ParserError extends Error {\n sourceFilePosition: ts.LineAndCharacter | null\n sourceFileName: string\n\n constructor(message: string, context?: ParserErrorContext) {\n super(message)\n this.name = 'ParserError'\n this.sourceFileName = context?.sourceFile.fileName || ''\n this.sourceFilePosition =\n context && context.node\n ? getPositionInSourceFile(context.node, context.sourceFile) || null\n : null\n }\n\n toString() {\n let msg = `${highlight(error(this.name))}: ${this.message}\\n`\n if (this.sourceFileName && this.sourceFilePosition) {\n msg += ` -> ${reset(this.sourceFileName)}:${this.sourceFilePosition.line}:${\n this.sourceFilePosition.character\n }\\n`\n }\n return msg\n }\n\n toDebugString() {\n return this.toString() + `\\n ${this.stack}`\n }\n}\n\nexport class InternalError extends ParserError {\n constructor(message: string) {\n super(message)\n this.name = 'InternalError'\n }\n}\n\nexport interface ParserContext {\n checker: ts.TypeChecker\n sourceFile: ts.SourceFile\n resolvedImports: Record<string, string>\n config: any\n absPath: string\n}\n\n/**\n * Factory to create a function that is used to create `__PROP__(propName)`\n * function nodes, which are used to replace prop references and ultimately\n * replaced.\n *\n * @returns Function to create `__PROP__(propName)` function nodes\n */\nexport function makeCreatePropPlaceholder({\n propMappings,\n referencedProps,\n sourceFile,\n}: {\n /** The prop mappings object */\n propMappings?: PropMappings | undefined\n /** The set of referenced props in the current example */\n referencedProps: Set<string>\n /** The source file */\n sourceFile: ts.SourceFile\n}) {\n return function ({\n name,\n node,\n wrapInJsxExpression = false,\n }: {\n /** The prop name */\n name: string\n /** The props node, used for error reporting */\n node: ts.Node\n /** Whether to wrap the placeholder in a JSX expression node */\n wrapInJsxExpression?: boolean\n }) {\n let propReferenceName = name\n // for nested prop references like `nested.prop`, we only want to look for\n // the prop mapping of `nested`, but include the full `nested.prop` in the\n // __PROP__ call\n if (name.includes('.')) {\n propReferenceName = name.split('.')[0]\n }\n\n // if prop mappings exist, check that the prop reference is in the mappings\n if (propMappings) {\n const mappedProp = propMappings[propReferenceName]\n if (!mappedProp) {\n throw new ParserError(\n `Could not find prop mapping for ${propReferenceName} in the props object`,\n {\n sourceFile,\n node,\n },\n )\n }\n }\n\n referencedProps.add(propReferenceName)\n const callExpression = ts.factory.createCallExpression(\n ts.factory.createIdentifier('__PROP__'),\n undefined,\n [ts.factory.createStringLiteral(name)],\n )\n\n if (wrapInJsxExpression) {\n return ts.factory.createJsxExpression(undefined, callExpression)\n } else {\n return callExpression\n }\n }\n}\n\n/**\n * TS AST visitor function for use with example functions, which replaces\n * references to the `props` argument in various forms in the example code with\n * `__PROP__(propName)` placeholders (created with a createPropPlaceholder\n * function).\n *\n * This is called when transforming the TS AST, and allows us to normalise the\n * different forms of supported prop references into a single representation,\n * which we can then handle consistently (currently we replace the placeholders,\n * using a regex).\n *\n * @returns Placeholder node, or undefined if the node is not a supported prop\n * reference (which results in no transformation)\n */\nexport function visitPropReferencingNode({\n propsParameter,\n node,\n createPropPlaceholder,\n useJsx,\n}: {\n /** The props function parameter node */\n propsParameter: ts.ParameterDeclaration\n /** The node to visit */\n node: ts.Node\n /**\n * The function to create `__PROP__(propName)` function nodes, created by\n * `baseCreatePropPlaceholder`\n * */\n createPropPlaceholder: ReturnType<typeof makeCreatePropPlaceholder>\n /** Whether to support JSX syntax or not */\n useJsx?: boolean\n}): ts.Expression | undefined {\n // `props.` notation\n if (\n ts.isIdentifier(propsParameter.name) &&\n ts.isPropertyAccessExpression(node) &&\n node.expression.getText().startsWith(propsParameter.name.getText())\n ) {\n // nested notation e.g `props.nested.prop`\n if (ts.isPropertyAccessExpression(node.expression)) {\n let current: ts.Node = node\n const parts: string[] = []\n\n // Build the property name by traversing up the chain\n while (ts.isPropertyAccessExpression(current)) {\n parts.unshift(current.name.getText())\n current = current.expression\n }\n\n // Join the parts together to form the full property name\n const name = parts.join('.')\n return createPropPlaceholder({ name, node })\n }\n const name = node.name.getText()\n return createPropPlaceholder({ name, node })\n }\n // `props[\"\"]` notation\n if (\n ts.isIdentifier(propsParameter.name) &&\n ts.isElementAccessExpression(node) &&\n node.expression.getText().startsWith(propsParameter.name.getText()) &&\n ts.isStringLiteral(node.argumentExpression)\n ) {\n const name = stripQuotesFromNode(node.argumentExpression)\n return createPropPlaceholder({ name, node })\n }\n // object destructuring references\n if (ts.isObjectBindingPattern(propsParameter.name)) {\n const isValidNode = useJsx\n ? ts.isJsxExpression(node)\n : ts.isPropertyAccessExpression(node) || ts.isIdentifier(node)\n const target = useJsx ? (node as JsxExpression).expression : node\n\n if (\n isValidNode &&\n target &&\n propsParameter.name.elements.find((el) => target?.getText().startsWith(el.name.getText()))\n ) {\n const name = target.getText()\n return createPropPlaceholder({ name, node, wrapInJsxExpression: useJsx })\n }\n }\n\n return undefined\n}\n\n/**\n * Get template code to create variables referencing the props in the prop\n * mappings. This converts the prop mappings into JS calls like `const propName\n * = figma.properties.string('Prop Name')`, which can then be prepended to the\n * template code.\n *\n * @returns Template code string\n */\nexport function getReferencedPropsForTemplate({\n propMappings = {},\n}: {\n /** The prop mappings object */\n propMappings: PropMappings | undefined\n /** The top level node, used for error reporting */\n exp: ts.Node\n /** The source file */\n sourceFile: ts.SourceFile\n}) {\n let templateCode = ''\n\n if (Object.keys(propMappings).length > 0) {\n for (const prop in propMappings) {\n const propMapping = propMappings[prop]\n templateCode += `const ${prop} = ${valueToString(propMapping)}\\n`\n }\n templateCode += `const __props = {}\\n`\n Object.keys(propMappings).forEach((prop) => {\n // If trying to render prop resulted in an error (e.g. layer was not found\n // because it was invisible), don't include it in the __props object as\n // this will result in a runtime error.\n //\n // TODO Note that this can also happen if there is a typo in the prop name\n // of a nested prop, because we don't validate these at publish time,\n // which would be confusing. Perhaps we should have a way to show a\n // warning but not an error to the user.\n templateCode += `if (${prop} && ${prop}.type !== 'ERROR') {\n __props[\"${prop}\"] = ${prop}\n}\\n`\n })\n templateCode += `\\n`\n }\n\n return templateCode\n}\n\n/**\n * Checks if a file contains Code Connect by looking for the `figma.connect()` function call\n */\nexport function isFigmaConnectFile(\n program: ts.Program,\n file: string,\n extension: string | string[],\n) {\n const allowedExtensions = Array.isArray(extension) ? extension : [extension]\n const fileExtension = file.split('.').pop()\n\n // If the file has no extension, we can't determine if it's a Code Connect file\n if (!fileExtension) {\n return false\n }\n\n // If the file extension is not in the list of supported extensions, it's not a Code Connect file\n if (!allowedExtensions.includes(fileExtension)) {\n return false\n }\n\n const sourceFile = program.getSourceFile(file)\n if (!sourceFile) {\n throw new InternalError(`Could not find source file for ${file}`)\n }\n\n return (\n findDescendants(sourceFile, (node: ts.Node) => {\n if (isFigmaConnectCall(node, sourceFile)) {\n return true\n }\n return false\n }).length > 0\n )\n}\n\n/**\n * Checks if an AST node is a `figma.connect()` call\n *\n * @param node AST node\n * @param sourceFile Source file\n * @returns True if the node is a `figma.connect()` call\n */\nexport function isFigmaConnectCall(\n node: ts.Node,\n sourceFile: ts.SourceFile,\n): node is ts.CallExpression {\n return (\n ts.isCallExpression(node) && node.expression.getText(sourceFile).includes(FIGMA_CONNECT_CALL)\n )\n}\n\nexport function findDescendants(node: ts.Node, cb: (node: ts.Node) => boolean): ts.Node[] {\n const matches: ts.Node[] = []\n function visit(node: ts.Node) {\n if (cb(node)) {\n matches.push(node)\n }\n ts.forEachChild(node, visit)\n }\n visit(node)\n return matches\n}\n\n/**\n * Parses the `links` field of a `figma.connect()` call\n *\n * @param linksArray an ArrayLiteralExpression\n * @param parserContext Parser context\n * @returns An array of link objects\n */\nexport function parseLinks(linksArray: ts.ArrayLiteralExpression, parserContext: ParserContext) {\n const { sourceFile } = parserContext\n const links: { name: string; url: string }[] = []\n for (const element of linksArray.elements) {\n assertIsObjectLiteralExpression(\n element,\n sourceFile,\n `'links' must be an array literal with objects of the format { name: string, url: string }`,\n )\n const name = parsePropertyOfType({\n objectLiteralNode: element,\n propertyName: 'name',\n predicate: ts.isStringLiteral,\n parserContext,\n required: true,\n errorMessage: \"The 'name' property must be a string literal\",\n })\n const url = parsePropertyOfType({\n objectLiteralNode: element,\n propertyName: 'url',\n predicate: ts.isStringLiteral,\n parserContext,\n required: true,\n errorMessage: \"The 'url' property must be a string literal\",\n })\n\n if (name && url) {\n links.push({ name: stripQuotesFromNode(name), url: stripQuotesFromNode(url) })\n }\n }\n\n return links\n}\n\nexport function parseVariant(\n variantMap: ts.ObjectLiteralExpression,\n sourceFile: ts.SourceFile,\n checker: ts.TypeChecker,\n) {\n return convertObjectLiteralToJs(variantMap, sourceFile, checker, (valueNode) => {\n if (\n !ts.isObjectLiteralElement(valueNode) &&\n !ts.isStringLiteral(valueNode) &&\n !ts.isNumericLiteral(valueNode) &&\n valueNode.kind !== ts.SyntaxKind.TrueKeyword &&\n valueNode.kind !== ts.SyntaxKind.FalseKeyword\n ) {\n throw new ParserError(`Invalid value for variant, got: ${valueNode.getText()}`, {\n node: valueNode,\n sourceFile,\n })\n }\n })\n}\n\n/**\n * Parses the `imports` field of a `figma.connect()` call\n *\n * @param importsArray an ArrayLiteralExpression\n * @param parserContext Parser context\n * @returns An array of link objects\n */\nexport function parseImports(\n importsArray: ts.ArrayLiteralExpression,\n parserContext: ParserContext,\n) {\n const { sourceFile } = parserContext\n const imports: string[] = []\n for (const element of importsArray.elements) {\n assertIsStringLiteral(element, sourceFile, `'imports' must be an array literal with strings`)\n imports.push(stripQuotesFromNode(element))\n }\n\n return imports\n}\n\nexport type ParseOptions = {\n repoUrl?: string\n debug?: boolean\n silent?: boolean\n skipTemplateHelpers?: boolean\n}\n\nexport type ParseFn = (\n node: ts.CallExpression,\n parserContext: ParserContext,\n { repoUrl, silent }: ParseOptions,\n) => Promise<CodeConnectJSON>\n\nexport type ResolveImportsFn = (\n program: ts.Program,\n sourceFile: ts.SourceFile,\n) => Record<string, string>\n\nexport async function parseCodeConnect<T extends BaseCodeConnectConfig>({\n program,\n file,\n config,\n absPath,\n parseFn,\n resolveImportsFn,\n parseOptions = {},\n}: {\n program: ts.Program\n file: string\n config: T\n absPath: string\n parseFn: ParseFn\n resolveImportsFn?: ResolveImportsFn\n parseOptions?: ParseOptions\n}): Promise<any[]> {\n const sourceFile = program.getSourceFile(file)\n if (!sourceFile) {\n throw new InternalError(`Could not find source file for ${file}`)\n }\n\n const parserContext = {\n checker: program.getTypeChecker(),\n sourceFile,\n resolvedImports: resolveImportsFn ? resolveImportsFn(program, sourceFile) : {},\n config,\n absPath,\n }\n const codeConnectObjects: CodeConnectJSON[] = []\n\n const nodes: ts.Node[] = [parserContext.sourceFile]\n while (nodes.length > 0) {\n const node = nodes.shift()!\n if (isFigmaConnectCall(node, parserContext.sourceFile)) {\n const doc = await parseFn(node, parserContext, parseOptions)\n if (doc) {\n codeConnectObjects.push(doc)\n }\n }\n nodes.push(...node.getChildren(parserContext.sourceFile))\n }\n\n if (codeConnectObjects.length === 0) {\n throw new ParserError(`Didn't find any calls to figma.connect()`, {\n sourceFile: parserContext.sourceFile,\n node: parserContext.sourceFile,\n })\n }\n\n return codeConnectObjects\n}\n"]}
1
+ {"version":3,"file":"parser_common.js","sourceRoot":"","sources":["../../src/connect/parser_common.ts"],"names":[],"mappings":";;;;;;AAmBA,0DAEC;AAqDD,8DA2DC;AAgBD,4DAsEC;AAUD,sEAmCC;AAKD,gDA+BC;AASD,gDAOC;AAED,0CAUC;AASD,gCAgCC;AAED,oCAmBC;AASD,oCAYC;AAoBD,4CAoDC;AAneD,4DAA8C;AAC9C,6CAA8E;AAC9E,+CAAoD;AACpD,qCAA+B;AAC/B,qDAM+B;AAS/B,SAAgB,uBAAuB,CAAC,IAAa,EAAE,UAAyB;IAC9E,OAAO,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAA;AAC5E,CAAC;AAED,MAAa,WAAY,SAAQ,KAAK;IAIpC,YAAY,OAAe,EAAE,OAA4B;QACvD,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,aAAa,CAAA;QACzB,IAAI,CAAC,cAAc,GAAG,OAAO,EAAE,UAAU,CAAC,QAAQ,IAAI,EAAE,CAAA;QACxD,IAAI,CAAC,kBAAkB;YACrB,OAAO,IAAI,OAAO,CAAC,IAAI;gBACrB,CAAC,CAAC,uBAAuB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,IAAI;gBACnE,CAAC,CAAC,IAAI,CAAA;IACZ,CAAC;IAED,QAAQ;QACN,IAAI,GAAG,GAAG,GAAG,IAAA,mBAAS,EAAC,IAAA,eAAK,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,IAAI,CAAA;QAC7D,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACnD,GAAG,IAAI,OAAO,IAAA,eAAK,EAAC,IAAI,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,kBAAkB,CAAC,IAAI,IACtE,IAAI,CAAC,kBAAkB,CAAC,SAC1B,IAAI,CAAA;QACN,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAA;IAC7C,CAAC;CACF;AA3BD,kCA2BC;AAED,MAAa,aAAc,SAAQ,WAAW;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,eAAe,CAAA;IAC7B,CAAC;CACF;AALD,sCAKC;AAUD;;;;;;GAMG;AACH,SAAgB,yBAAyB,CAAC,EACxC,YAAY,EACZ,eAAe,EACf,UAAU,GAQX;IACC,OAAO,UAAU,EACf,IAAI,EACJ,IAAI,EACJ,mBAAmB,GAAG,KAAK,GAQ5B;QACC,IAAI,iBAAiB,GAAG,IAAI,CAAA;QAC5B,0EAA0E;QAC1E,0EAA0E;QAC1E,gBAAgB;QAChB,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QACxC,CAAC;QAED,2EAA2E;QAC3E,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,UAAU,GAAG,YAAY,CAAC,iBAAiB,CAAC,CAAA;YAClD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,WAAW,CACnB,mCAAmC,iBAAiB,sBAAsB,EAC1E;oBACE,UAAU;oBACV,IAAI;iBACL,CACF,CAAA;YACH,CAAC;QACH,CAAC;QAED,eAAe,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;QACtC,MAAM,cAAc,GAAG,oBAAE,CAAC,OAAO,CAAC,oBAAoB,CACpD,oBAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,EACvC,SAAS,EACT,CAAC,oBAAE,CAAC,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CACvC,CAAA;QAED,IAAI,mBAAmB,EAAE,CAAC;YACxB,OAAO,oBAAE,CAAC,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAA;QAClE,CAAC;aAAM,CAAC;YACN,OAAO,cAAc,CAAA;QACvB,CAAC;IACH,CAAC,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,wBAAwB,CAAC,EACvC,cAAc,EACd,IAAI,EACJ,qBAAqB,EACrB,MAAM,GAaP;IACC,oBAAoB;IACpB,IACE,oBAAE,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC;QACpC,oBAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC;QACnC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EACnE,CAAC;QACD,0CAA0C;QAC1C,IAAI,oBAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACnD,IAAI,OAAO,GAAY,IAAI,CAAA;YAC3B,MAAM,KAAK,GAAa,EAAE,CAAA;YAE1B,qDAAqD;YACrD,OAAO,oBAAE,CAAC,0BAA0B,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9C,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAA;gBACrC,OAAO,GAAG,OAAO,CAAC,UAAU,CAAA;YAC9B,CAAC;YAED,yDAAyD;YACzD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAC5B,OAAO,qBAAqB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAC9C,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAA;QAChC,OAAO,qBAAqB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IAC9C,CAAC;IACD,uBAAuB;IACvB,IACE,oBAAE,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC;QACpC,oBAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACnE,oBAAE,CAAC,eAAe,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAC3C,CAAC;QACD,MAAM,IAAI,GAAG,IAAA,8BAAmB,EAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;QACzD,OAAO,qBAAqB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IAC9C,CAAC;IACD,kCAAkC;IAClC,IAAI,oBAAE,CAAC,sBAAsB,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,MAAM,WAAW,GAAG,MAAM;YACxB,CAAC,CAAC,oBAAE,CAAC,eAAe,CAAC,IAAI,CAAC;YAC1B,CAAC,CAAC,oBAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,oBAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;QAChE,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAE,IAAsB,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAA;QAEjE,IACE,WAAW;YACX,MAAM;YACN,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,EAC1F,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAA;YAC7B,OAAO,qBAAqB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,CAAC,CAAA;QAC3E,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,6BAA6B,CAAC,EAC5C,YAAY,GAAG,EAAE,GAQlB;IACC,IAAI,YAAY,GAAG,EAAE,CAAA;IAErB,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;YACtC,YAAY,IAAI,SAAS,IAAI,MAAM,IAAA,0BAAa,EAAC,WAAW,CAAC,IAAI,CAAA;QACnE,CAAC;QACD,YAAY,IAAI,sBAAsB,CAAA;QACtC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACzC,0EAA0E;YAC1E,uEAAuE;YACvE,uCAAuC;YACvC,EAAE;YACF,0EAA0E;YAC1E,qEAAqE;YACrE,mEAAmE;YACnE,wCAAwC;YACxC,YAAY,IAAI,OAAO,IAAI,OAAO,IAAI;aAC/B,IAAI,QAAQ,IAAI;IACzB,CAAA;QACA,CAAC,CAAC,CAAA;QACF,YAAY,IAAI,IAAI,CAAA;IACtB,CAAC;IAED,OAAO,YAAY,CAAA;AACrB,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAChC,OAAmB,EACnB,IAAY,EACZ,SAA4B;IAE5B,MAAM,iBAAiB,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC5E,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAA;IAE3C,+EAA+E;IAC/E,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,KAAK,CAAA;IACd,CAAC;IAED,iGAAiG;IACjG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/C,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;IAC9C,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,aAAa,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAA;IACnE,CAAC;IAED,OAAO,CACL,eAAe,CAAC,UAAU,EAAE,CAAC,IAAa,EAAE,EAAE;QAC5C,IAAI,kBAAkB,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CACd,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,kBAAkB,CAChC,IAAa,EACb,UAAyB;IAEzB,OAAO,CACL,oBAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,+BAAkB,CAAC,CAC9F,CAAA;AACH,CAAC;AAED,SAAgB,eAAe,CAAC,IAAa,EAAE,EAA8B;IAC3E,MAAM,OAAO,GAAc,EAAE,CAAA;IAC7B,SAAS,KAAK,CAAC,IAAa;QAC1B,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACpB,CAAC;QACD,oBAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC9B,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,CAAA;IACX,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,UAAU,CAAC,UAAqC,EAAE,aAA4B;IAC5F,MAAM,EAAE,UAAU,EAAE,GAAG,aAAa,CAAA;IACpC,MAAM,KAAK,GAAoC,EAAE,CAAA;IACjD,KAAK,MAAM,OAAO,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;QAC1C,IAAA,0CAA+B,EAC7B,OAAO,EACP,UAAU,EACV,2FAA2F,CAC5F,CAAA;QACD,MAAM,IAAI,GAAG,IAAA,8BAAmB,EAAC;YAC/B,iBAAiB,EAAE,OAAO;YAC1B,YAAY,EAAE,MAAM;YACpB,SAAS,EAAE,oBAAE,CAAC,eAAe;YAC7B,aAAa;YACb,QAAQ,EAAE,IAAI;YACd,YAAY,EAAE,8CAA8C;SAC7D,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,IAAA,8BAAmB,EAAC;YAC9B,iBAAiB,EAAE,OAAO;YAC1B,YAAY,EAAE,KAAK;YACnB,SAAS,EAAE,oBAAE,CAAC,eAAe;YAC7B,aAAa;YACb,QAAQ,EAAE,IAAI;YACd,YAAY,EAAE,6CAA6C;SAC5D,CAAC,CAAA;QAEF,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAA,8BAAmB,EAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAA,8BAAmB,EAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAChF,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAgB,YAAY,CAC1B,UAAsC,EACtC,UAAyB,EACzB,OAAuB;IAEvB,OAAO,IAAA,mCAAwB,EAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,EAAE;QAC7E,IACE,CAAC,oBAAE,CAAC,sBAAsB,CAAC,SAAS,CAAC;YACrC,CAAC,oBAAE,CAAC,eAAe,CAAC,SAAS,CAAC;YAC9B,CAAC,oBAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC;YAC/B,SAAS,CAAC,IAAI,KAAK,oBAAE,CAAC,UAAU,CAAC,WAAW;YAC5C,SAAS,CAAC,IAAI,KAAK,oBAAE,CAAC,UAAU,CAAC,YAAY,EAC7C,CAAC;YACD,MAAM,IAAI,WAAW,CAAC,mCAAmC,SAAS,CAAC,OAAO,EAAE,EAAE,EAAE;gBAC9E,IAAI,EAAE,SAAS;gBACf,UAAU;aACX,CAAC,CAAA;QACJ,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,YAAY,CAC1B,YAAuC,EACvC,aAA4B;IAE5B,MAAM,EAAE,UAAU,EAAE,GAAG,aAAa,CAAA;IACpC,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;QAC5C,IAAA,gCAAqB,EAAC,OAAO,EAAE,UAAU,EAAE,iDAAiD,CAAC,CAAA;QAC7F,OAAO,CAAC,IAAI,CAAC,IAAA,8BAAmB,EAAC,OAAO,CAAC,CAAC,CAAA;IAC5C,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAoBM,KAAK,UAAU,gBAAgB,CAAkC,EACtE,OAAO,EACP,IAAI,EACJ,MAAM,EACN,OAAO,EACP,OAAO,EACP,gBAAgB,EAChB,YAAY,GAAG,EAAE,GASlB;IACC,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;IAC9C,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,aAAa,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAA;IACnE,CAAC;IAED,MAAM,aAAa,GAAG;QACpB,OAAO,EAAE,OAAO,CAAC,cAAc,EAAE;QACjC,UAAU;QACV,eAAe,EAAE,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE;QAC9E,MAAM;QACN,OAAO;KACR,CAAA;IACD,MAAM,kBAAkB,GAAsB,EAAE,CAAA;IAEhD,MAAM,KAAK,GAAc,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;IACnD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAG,CAAA;QAC3B,IAAI,kBAAkB,CAAC,IAAI,EAAE,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;YACvD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,aAAa,EAAE,YAAY,CAAC,CAAA;YAC5D,IAAI,GAAG,EAAE,CAAC;gBACR,GAAG,CAAC,oBAAoB,GAAG,IAAI,CAAA;gBAC/B,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAA;IAC3D,CAAC;IAED,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,WAAW,CAAC,0CAA0C,EAAE;YAChE,UAAU,EAAE,aAAa,CAAC,UAAU;YACpC,IAAI,EAAE,aAAa,CAAC,UAAU;SAC/B,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,kBAAkB,CAAA;AAC3B,CAAC","sourcesContent":["import ts, { JsxExpression } from 'typescript'\nimport { FIGMA_CONNECT_CALL, PropMappings, valueToString } from './intrinsics'\nimport { highlight, reset } from '../common/logging'\nimport { error } from 'console'\nimport {\n assertIsObjectLiteralExpression,\n assertIsStringLiteral,\n convertObjectLiteralToJs,\n parsePropertyOfType,\n stripQuotesFromNode,\n} from '../typescript/compiler'\nimport { BaseCodeConnectConfig } from './project'\nimport { CodeConnectJSON } from './figma_connect'\n\ninterface ParserErrorContext {\n sourceFile: ts.SourceFile\n node: ts.Node | undefined\n}\n\nexport function getPositionInSourceFile(node: ts.Node, sourceFile: ts.SourceFile) {\n return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile))\n}\n\nexport class ParserError extends Error {\n sourceFilePosition: ts.LineAndCharacter | null\n sourceFileName: string\n\n constructor(message: string, context?: ParserErrorContext) {\n super(message)\n this.name = 'ParserError'\n this.sourceFileName = context?.sourceFile.fileName || ''\n this.sourceFilePosition =\n context && context.node\n ? getPositionInSourceFile(context.node, context.sourceFile) || null\n : null\n }\n\n toString() {\n let msg = `${highlight(error(this.name))}: ${this.message}\\n`\n if (this.sourceFileName && this.sourceFilePosition) {\n msg += ` -> ${reset(this.sourceFileName)}:${this.sourceFilePosition.line}:${\n this.sourceFilePosition.character\n }\\n`\n }\n return msg\n }\n\n toDebugString() {\n return this.toString() + `\\n ${this.stack}`\n }\n}\n\nexport class InternalError extends ParserError {\n constructor(message: string) {\n super(message)\n this.name = 'InternalError'\n }\n}\n\nexport interface ParserContext {\n checker: ts.TypeChecker\n sourceFile: ts.SourceFile\n resolvedImports: Record<string, string>\n config: any\n absPath: string\n}\n\n/**\n * Factory to create a function that is used to create `__PROP__(propName)`\n * function nodes, which are used to replace prop references and ultimately\n * replaced.\n *\n * @returns Function to create `__PROP__(propName)` function nodes\n */\nexport function makeCreatePropPlaceholder({\n propMappings,\n referencedProps,\n sourceFile,\n}: {\n /** The prop mappings object */\n propMappings?: PropMappings | undefined\n /** The set of referenced props in the current example */\n referencedProps: Set<string>\n /** The source file */\n sourceFile: ts.SourceFile\n}) {\n return function ({\n name,\n node,\n wrapInJsxExpression = false,\n }: {\n /** The prop name */\n name: string\n /** The props node, used for error reporting */\n node: ts.Node\n /** Whether to wrap the placeholder in a JSX expression node */\n wrapInJsxExpression?: boolean\n }) {\n let propReferenceName = name\n // for nested prop references like `nested.prop`, we only want to look for\n // the prop mapping of `nested`, but include the full `nested.prop` in the\n // __PROP__ call\n if (name.includes('.')) {\n propReferenceName = name.split('.')[0]\n }\n\n // if prop mappings exist, check that the prop reference is in the mappings\n if (propMappings) {\n const mappedProp = propMappings[propReferenceName]\n if (!mappedProp) {\n throw new ParserError(\n `Could not find prop mapping for ${propReferenceName} in the props object`,\n {\n sourceFile,\n node,\n },\n )\n }\n }\n\n referencedProps.add(propReferenceName)\n const callExpression = ts.factory.createCallExpression(\n ts.factory.createIdentifier('__PROP__'),\n undefined,\n [ts.factory.createStringLiteral(name)],\n )\n\n if (wrapInJsxExpression) {\n return ts.factory.createJsxExpression(undefined, callExpression)\n } else {\n return callExpression\n }\n }\n}\n\n/**\n * TS AST visitor function for use with example functions, which replaces\n * references to the `props` argument in various forms in the example code with\n * `__PROP__(propName)` placeholders (created with a createPropPlaceholder\n * function).\n *\n * This is called when transforming the TS AST, and allows us to normalise the\n * different forms of supported prop references into a single representation,\n * which we can then handle consistently (currently we replace the placeholders,\n * using a regex).\n *\n * @returns Placeholder node, or undefined if the node is not a supported prop\n * reference (which results in no transformation)\n */\nexport function visitPropReferencingNode({\n propsParameter,\n node,\n createPropPlaceholder,\n useJsx,\n}: {\n /** The props function parameter node */\n propsParameter: ts.ParameterDeclaration\n /** The node to visit */\n node: ts.Node\n /**\n * The function to create `__PROP__(propName)` function nodes, created by\n * `baseCreatePropPlaceholder`\n * */\n createPropPlaceholder: ReturnType<typeof makeCreatePropPlaceholder>\n /** Whether to support JSX syntax or not */\n useJsx?: boolean\n}): ts.Expression | undefined {\n // `props.` notation\n if (\n ts.isIdentifier(propsParameter.name) &&\n ts.isPropertyAccessExpression(node) &&\n node.expression.getText().startsWith(propsParameter.name.getText())\n ) {\n // nested notation e.g `props.nested.prop`\n if (ts.isPropertyAccessExpression(node.expression)) {\n let current: ts.Node = node\n const parts: string[] = []\n\n // Build the property name by traversing up the chain\n while (ts.isPropertyAccessExpression(current)) {\n parts.unshift(current.name.getText())\n current = current.expression\n }\n\n // Join the parts together to form the full property name\n const name = parts.join('.')\n return createPropPlaceholder({ name, node })\n }\n const name = node.name.getText()\n return createPropPlaceholder({ name, node })\n }\n // `props[\"\"]` notation\n if (\n ts.isIdentifier(propsParameter.name) &&\n ts.isElementAccessExpression(node) &&\n node.expression.getText().startsWith(propsParameter.name.getText()) &&\n ts.isStringLiteral(node.argumentExpression)\n ) {\n const name = stripQuotesFromNode(node.argumentExpression)\n return createPropPlaceholder({ name, node })\n }\n // object destructuring references\n if (ts.isObjectBindingPattern(propsParameter.name)) {\n const isValidNode = useJsx\n ? ts.isJsxExpression(node)\n : ts.isPropertyAccessExpression(node) || ts.isIdentifier(node)\n const target = useJsx ? (node as JsxExpression).expression : node\n\n if (\n isValidNode &&\n target &&\n propsParameter.name.elements.find((el) => target?.getText().startsWith(el.name.getText()))\n ) {\n const name = target.getText()\n return createPropPlaceholder({ name, node, wrapInJsxExpression: useJsx })\n }\n }\n\n return undefined\n}\n\n/**\n * Get template code to create variables referencing the props in the prop\n * mappings. This converts the prop mappings into JS calls like `const propName\n * = figma.properties.string('Prop Name')`, which can then be prepended to the\n * template code.\n *\n * @returns Template code string\n */\nexport function getReferencedPropsForTemplate({\n propMappings = {},\n}: {\n /** The prop mappings object */\n propMappings: PropMappings | undefined\n /** The top level node, used for error reporting */\n exp: ts.Node\n /** The source file */\n sourceFile: ts.SourceFile\n}) {\n let templateCode = ''\n\n if (Object.keys(propMappings).length > 0) {\n for (const prop in propMappings) {\n const propMapping = propMappings[prop]\n templateCode += `const ${prop} = ${valueToString(propMapping)}\\n`\n }\n templateCode += `const __props = {}\\n`\n Object.keys(propMappings).forEach((prop) => {\n // If trying to render prop resulted in an error (e.g. layer was not found\n // because it was invisible), don't include it in the __props object as\n // this will result in a runtime error.\n //\n // TODO Note that this can also happen if there is a typo in the prop name\n // of a nested prop, because we don't validate these at publish time,\n // which would be confusing. Perhaps we should have a way to show a\n // warning but not an error to the user.\n templateCode += `if (${prop} && ${prop}.type !== 'ERROR') {\n __props[\"${prop}\"] = ${prop}\n}\\n`\n })\n templateCode += `\\n`\n }\n\n return templateCode\n}\n\n/**\n * Checks if a file contains Code Connect by looking for the `figma.connect()` function call\n */\nexport function isFigmaConnectFile(\n program: ts.Program,\n file: string,\n extension: string | string[],\n) {\n const allowedExtensions = Array.isArray(extension) ? extension : [extension]\n const fileExtension = file.split('.').pop()\n\n // If the file has no extension, we can't determine if it's a Code Connect file\n if (!fileExtension) {\n return false\n }\n\n // If the file extension is not in the list of supported extensions, it's not a Code Connect file\n if (!allowedExtensions.includes(fileExtension)) {\n return false\n }\n\n const sourceFile = program.getSourceFile(file)\n if (!sourceFile) {\n throw new InternalError(`Could not find source file for ${file}`)\n }\n\n return (\n findDescendants(sourceFile, (node: ts.Node) => {\n if (isFigmaConnectCall(node, sourceFile)) {\n return true\n }\n return false\n }).length > 0\n )\n}\n\n/**\n * Checks if an AST node is a `figma.connect()` call\n *\n * @param node AST node\n * @param sourceFile Source file\n * @returns True if the node is a `figma.connect()` call\n */\nexport function isFigmaConnectCall(\n node: ts.Node,\n sourceFile: ts.SourceFile,\n): node is ts.CallExpression {\n return (\n ts.isCallExpression(node) && node.expression.getText(sourceFile).includes(FIGMA_CONNECT_CALL)\n )\n}\n\nexport function findDescendants(node: ts.Node, cb: (node: ts.Node) => boolean): ts.Node[] {\n const matches: ts.Node[] = []\n function visit(node: ts.Node) {\n if (cb(node)) {\n matches.push(node)\n }\n ts.forEachChild(node, visit)\n }\n visit(node)\n return matches\n}\n\n/**\n * Parses the `links` field of a `figma.connect()` call\n *\n * @param linksArray an ArrayLiteralExpression\n * @param parserContext Parser context\n * @returns An array of link objects\n */\nexport function parseLinks(linksArray: ts.ArrayLiteralExpression, parserContext: ParserContext) {\n const { sourceFile } = parserContext\n const links: { name: string; url: string }[] = []\n for (const element of linksArray.elements) {\n assertIsObjectLiteralExpression(\n element,\n sourceFile,\n `'links' must be an array literal with objects of the format { name: string, url: string }`,\n )\n const name = parsePropertyOfType({\n objectLiteralNode: element,\n propertyName: 'name',\n predicate: ts.isStringLiteral,\n parserContext,\n required: true,\n errorMessage: \"The 'name' property must be a string literal\",\n })\n const url = parsePropertyOfType({\n objectLiteralNode: element,\n propertyName: 'url',\n predicate: ts.isStringLiteral,\n parserContext,\n required: true,\n errorMessage: \"The 'url' property must be a string literal\",\n })\n\n if (name && url) {\n links.push({ name: stripQuotesFromNode(name), url: stripQuotesFromNode(url) })\n }\n }\n\n return links\n}\n\nexport function parseVariant(\n variantMap: ts.ObjectLiteralExpression,\n sourceFile: ts.SourceFile,\n checker: ts.TypeChecker,\n) {\n return convertObjectLiteralToJs(variantMap, sourceFile, checker, (valueNode) => {\n if (\n !ts.isObjectLiteralElement(valueNode) &&\n !ts.isStringLiteral(valueNode) &&\n !ts.isNumericLiteral(valueNode) &&\n valueNode.kind !== ts.SyntaxKind.TrueKeyword &&\n valueNode.kind !== ts.SyntaxKind.FalseKeyword\n ) {\n throw new ParserError(`Invalid value for variant, got: ${valueNode.getText()}`, {\n node: valueNode,\n sourceFile,\n })\n }\n })\n}\n\n/**\n * Parses the `imports` field of a `figma.connect()` call\n *\n * @param importsArray an ArrayLiteralExpression\n * @param parserContext Parser context\n * @returns An array of link objects\n */\nexport function parseImports(\n importsArray: ts.ArrayLiteralExpression,\n parserContext: ParserContext,\n) {\n const { sourceFile } = parserContext\n const imports: string[] = []\n for (const element of importsArray.elements) {\n assertIsStringLiteral(element, sourceFile, `'imports' must be an array literal with strings`)\n imports.push(stripQuotesFromNode(element))\n }\n\n return imports\n}\n\nexport type ParseOptions = {\n repoUrl?: string\n debug?: boolean\n silent?: boolean\n skipTemplateHelpers?: boolean\n}\n\nexport type ParseFn = (\n node: ts.CallExpression,\n parserContext: ParserContext,\n { repoUrl, silent }: ParseOptions,\n) => Promise<CodeConnectJSON>\n\nexport type ResolveImportsFn = (\n program: ts.Program,\n sourceFile: ts.SourceFile,\n) => Record<string, string>\n\nexport async function parseCodeConnect<T extends BaseCodeConnectConfig>({\n program,\n file,\n config,\n absPath,\n parseFn,\n resolveImportsFn,\n parseOptions = {},\n}: {\n program: ts.Program\n file: string\n config: T\n absPath: string\n parseFn: ParseFn\n resolveImportsFn?: ResolveImportsFn\n parseOptions?: ParseOptions\n}): Promise<any[]> {\n const sourceFile = program.getSourceFile(file)\n if (!sourceFile) {\n throw new InternalError(`Could not find source file for ${file}`)\n }\n\n const parserContext = {\n checker: program.getTypeChecker(),\n sourceFile,\n resolvedImports: resolveImportsFn ? resolveImportsFn(program, sourceFile) : {},\n config,\n absPath,\n }\n const codeConnectObjects: CodeConnectJSON[] = []\n\n const nodes: ts.Node[] = [parserContext.sourceFile]\n while (nodes.length > 0) {\n const node = nodes.shift()!\n if (isFigmaConnectCall(node, parserContext.sourceFile)) {\n const doc = await parseFn(node, parserContext, parseOptions)\n if (doc) {\n doc._codeConnectFilePath = file\n codeConnectObjects.push(doc)\n }\n }\n nodes.push(...node.getChildren(parserContext.sourceFile))\n }\n\n if (codeConnectObjects.length === 0) {\n throw new ParserError(`Didn't find any calls to figma.connect()`, {\n sourceFile: parserContext.sourceFile,\n node: parserContext.sourceFile,\n })\n }\n\n return codeConnectObjects\n}\n"]}