@figma/code-connect 1.4.0 → 1.4.2

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.
@@ -1,5 +1,7 @@
1
1
  import { CodeConnectJSON } from '../connect/figma_connect';
2
- export declare function writeTemplateFile(doc: CodeConnectJSON, outputDir: string | undefined, baseDir: string, localSourcePath?: string, filePathsCreated?: Set<string>, removeProps?: boolean): {
2
+ /** Migrates a doc's template (Swift helpers, server helpers, V2, id, imports, nestable) and returns the formatted string. */
3
+ export declare function prepareMigratedTemplate(doc: CodeConnectJSON, removeProps?: boolean, useTypeScript?: boolean): string;
4
+ export declare function writeTemplateFile(doc: CodeConnectJSON, outputDir: string | undefined, baseDir: string, localSourcePath?: string, filePathsCreated?: Set<string>, removeProps?: boolean, useTypeScript?: boolean): {
3
5
  outputPath: string;
4
6
  skipped: boolean;
5
7
  };
@@ -37,5 +39,10 @@ type CodeConnectObjectsForFigmaUrl = {
37
39
  * codeConnectObject plus a list of any variants
38
40
  */
39
41
  export declare const groupCodeConnectObjectsByFigmaUrl: (codeConnectObjects: CodeConnectJSON[]) => Record<string, CodeConnectObjectsForFigmaUrl>;
42
+ /** One parserless file per component: branch per variant, each with its own props and template object; export default template. */
43
+ export declare function writeVariantTemplateFile(group: CodeConnectObjectsForFigmaUrl, figmaUrl: string, outputDir: string | undefined, baseDir: string, localSourcePath?: string, filePathsCreated?: Set<string>, useTypeScript?: boolean): {
44
+ outputPath: string;
45
+ skipped: boolean;
46
+ };
40
47
  export {};
41
48
  //# 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,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"}
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;AAuI1D,6HAA6H;AAC7H,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,eAAe,EACpB,WAAW,CAAC,EAAE,OAAO,EACrB,aAAa,CAAC,EAAE,OAAO,GACtB,MAAM,CAeR;AAqCD,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,EACrB,aAAa,UAAO,GACnB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAyB1C;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;AAED,mIAAmI;AACnI,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,6BAA6B,EACpC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,EACxB,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC9B,aAAa,UAAO,GACnB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CA2F1C"}
@@ -37,6 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.groupCodeConnectObjectsByFigmaUrl = exports.migrateV1TemplateToV2 = void 0;
40
+ exports.prepareMigratedTemplate = prepareMigratedTemplate;
40
41
  exports.writeTemplateFile = writeTemplateFile;
41
42
  exports.migrateTemplateToUseServerSideHelpers = migrateTemplateToUseServerSideHelpers;
42
43
  exports.addId = addId;
@@ -44,17 +45,39 @@ exports.addImports = addImports;
44
45
  exports.addNestableToMetadata = addNestableToMetadata;
45
46
  exports.removePropsDefinition = removePropsDefinition;
46
47
  exports.removePropsDefinitionAndMetadata = removePropsDefinitionAndMetadata;
48
+ exports.writeVariantTemplateFile = writeVariantTemplateFile;
47
49
  const fs_1 = __importDefault(require("fs"));
48
50
  const path_1 = __importDefault(require("path"));
49
51
  const prettier = __importStar(require("prettier"));
50
- function writeTemplateFile(doc, outputDir, baseDir, localSourcePath, filePathsCreated, removeProps) {
51
- const suffix = '.figma.js';
52
- // Determine base output filename
53
- let baseOutputPath;
52
+ /** Prettier configuration used for all generated template files */
53
+ const PRETTIER_OPTIONS = {
54
+ parser: 'typescript',
55
+ semi: false,
56
+ trailingComma: 'all',
57
+ pluginSearchDirs: false,
58
+ };
59
+ /** Formats template code with consistent prettier configuration */
60
+ function formatTemplate(code) {
61
+ return prettier.format(code, PRETTIER_OPTIONS);
62
+ }
63
+ /**
64
+ * Common wrapper that handles path determination and file writing for both
65
+ * simple templates and variant templates.
66
+ */
67
+ function writeTemplateFileCommon(componentName, fileContent, outputDir, baseDir, localSourcePath, filePathsCreated, useTypeScript = true) {
68
+ const suffix = useTypeScript ? '.figma.ts' : '.figma.js';
69
+ const baseOutputPath = determineOutputPath(componentName, suffix, outputDir, baseDir, localSourcePath);
70
+ return writeFileWithDuplicateHandling(baseOutputPath, fileContent, suffix, filePathsCreated);
71
+ }
72
+ /**
73
+ * Determines the base output path for a template file.
74
+ * Shared logic between writeTemplateFile and writeVariantTemplateFile.
75
+ */
76
+ function determineOutputPath(componentName, suffix, outputDir, baseDir, localSourcePath) {
54
77
  if (outputDir) {
55
78
  // Use specified output directory
56
- const filename = `${doc.component || 'template'}${suffix}`;
57
- baseOutputPath = path_1.default.join(outputDir, filename);
79
+ const filename = `${componentName}${suffix}`;
80
+ return path_1.default.join(outputDir, filename);
58
81
  }
59
82
  else if (localSourcePath) {
60
83
  // Use same directory as local source file
@@ -73,13 +96,19 @@ function writeTemplateFile(doc, outputDir, baseDir, localSourcePath, filePathsCr
73
96
  sourceBasename = path_1.default.basename(localSourcePath, path_1.default.extname(localSourcePath));
74
97
  }
75
98
  const filename = `${sourceBasename}${suffix}`;
76
- baseOutputPath = path_1.default.join(sourceDir, filename);
99
+ return path_1.default.join(sourceDir, filename);
77
100
  }
78
101
  else {
79
102
  // No source info, use current directory
80
- const filename = `${doc.component || 'template'}${suffix}`;
81
- baseOutputPath = path_1.default.join(baseDir, filename);
103
+ const filename = `${componentName}${suffix}`;
104
+ return path_1.default.join(baseDir, filename);
82
105
  }
106
+ }
107
+ /**
108
+ * Handles file existence checking, duplicate name resolution, and writing.
109
+ * Shared logic between writeTemplateFile and writeVariantTemplateFile.
110
+ */
111
+ function writeFileWithDuplicateHandling(baseOutputPath, fileContent, suffix, filePathsCreated) {
83
112
  // Check if file already exists on disk (pre-existing file, not created in this run)
84
113
  const existsOnDisk = fs_1.default.existsSync(baseOutputPath);
85
114
  const createdInThisRun = filePathsCreated && filePathsCreated.has(baseOutputPath);
@@ -103,34 +132,72 @@ function writeTemplateFile(doc, outputDir, baseDir, localSourcePath, filePathsCr
103
132
  counter++;
104
133
  } while ((filePathsCreated && filePathsCreated.has(outputPath)) || fs_1.default.existsSync(outputPath));
105
134
  }
135
+ // Ensure output directory exists
136
+ const outputDirPath = path_1.default.dirname(outputPath);
137
+ if (!fs_1.default.existsSync(outputDirPath)) {
138
+ fs_1.default.mkdirSync(outputDirPath, { recursive: true });
139
+ }
140
+ // Write the file
141
+ fs_1.default.writeFileSync(outputPath, fileContent, 'utf-8');
142
+ // Track the created file path
143
+ if (filePathsCreated) {
144
+ filePathsCreated.add(outputPath);
145
+ }
146
+ return { outputPath, skipped: false };
147
+ }
148
+ /** Migrates a doc's template (Swift helpers, server helpers, V2, id, imports, nestable) and returns the formatted string. */
149
+ function prepareMigratedTemplate(doc, removeProps, useTypeScript) {
106
150
  let template = doc.template;
107
151
  template = removeSwiftHelpers(template);
108
- // Helpers have not been injected - replace reference with server-side versions
109
152
  template = migrateTemplateToUseServerSideHelpers(template);
110
- // Remove __props definition and from metadata (if flag is set)
111
153
  if (removeProps) {
112
154
  template = removePropsDefinitionAndMetadata(template);
113
155
  }
114
- // V1 -> V2 codemods
115
156
  template = (0, exports.migrateV1TemplateToV2)(template);
116
- // Add required id to template (set to TODO if no usable name)
117
157
  template = addId(template, doc.component || 'TODO');
118
- // Add imports if present
119
158
  template = addImports(template, doc.templateData?.imports);
120
- // Add nestable to metadata (default to false)
121
159
  template = addNestableToMetadata(template, !!doc.templateData?.nestable);
122
- // Format for ease of use
123
- template = prettier.format(template, {
124
- parser: 'typescript',
125
- semi: false,
126
- trailingComma: 'all',
127
- // pluginSearchDirs: false is needed as otherwise prettier picks up other
128
- // prettier plugins in our monorepo and fails with race condition errors
129
- pluginSearchDirs: false,
130
- });
131
- // Create the template file content
160
+ if (useTypeScript) {
161
+ template = convertSyntaxToTypeScript(template);
162
+ }
163
+ return formatTemplate(template);
164
+ }
165
+ function removeSwiftHelpers(template) {
166
+ return template.replace(`function __fcc_renderSwiftChildren(children, prefix) {
167
+ if (children === undefined) {
168
+ return children
169
+ }
170
+ return children.flatMap((child, index) => {
171
+ if (child.type === 'CODE') {
172
+ let code = child.code.split('\\n').map((line) => {
173
+ return line.trim() !== '' ? \`\${prefix}\${line}\` : line;
174
+ }).join('\\n')
175
+ if (index !== children.length - 1) {
176
+ code = code + '\\n'
177
+ }
178
+ return {
179
+ ...child,
180
+ code: code,
181
+ }
182
+ } else {
183
+ let elements = []
184
+ const shouldAddNewline = index > 0 && children[index - 1].type === 'CODE' && !children[index - 1].code.endsWith('\\n')
185
+ elements.push({ type: 'CODE', code: \`\${shouldAddNewline ? '\\n' : ''}\${prefix}\` })
186
+ elements.push(child)
187
+ if (index !== children.length - 1) {
188
+ elements.push({ type: 'CODE', code: '\\n' })
189
+ }
190
+ return elements
191
+ }
192
+ })
193
+ }
194
+ `, '');
195
+ }
196
+ function writeTemplateFile(doc, outputDir, baseDir, localSourcePath, filePathsCreated, removeProps, useTypeScript = true) {
197
+ const componentName = doc.component || 'template';
198
+ const template = prepareMigratedTemplate(doc, removeProps, useTypeScript);
132
199
  // Build comment header lines
133
- const commentLines = [`// url=${doc.figmaNode}`]; // URL is required
200
+ const commentLines = [`// url=${doc.figmaNode}`];
134
201
  if (doc.source) {
135
202
  commentLines.push(`// source=${doc.source}`);
136
203
  }
@@ -139,18 +206,7 @@ function writeTemplateFile(doc, outputDir, baseDir, localSourcePath, filePathsCr
139
206
  }
140
207
  commentLines.push(``);
141
208
  const fileContent = commentLines.join('\n') + '\n' + template;
142
- // Ensure output directory exists
143
- const outputDirPath = path_1.default.dirname(outputPath);
144
- if (!fs_1.default.existsSync(outputDirPath)) {
145
- fs_1.default.mkdirSync(outputDirPath, { recursive: true });
146
- }
147
- // Write the file
148
- fs_1.default.writeFileSync(outputPath, fileContent, 'utf-8');
149
- // Track the created file path
150
- if (filePathsCreated) {
151
- filePathsCreated.add(outputPath);
152
- }
153
- return { outputPath, skipped: false };
209
+ return writeTemplateFileCommon(componentName, fileContent, outputDir, baseDir, localSourcePath, filePathsCreated, useTypeScript);
154
210
  }
155
211
  // Renames must match helpers in code_connect_js_api.raw_source.ts
156
212
  function migrateTemplateToUseServerSideHelpers(template) {
@@ -305,35 +361,72 @@ const groupCodeConnectObjectsByFigmaUrl = (codeConnectObjects) => {
305
361
  }, {});
306
362
  };
307
363
  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' })
364
+ /** One parserless file per component: branch per variant, each with its own props and template object; export default template. */
365
+ function writeVariantTemplateFile(group, figmaUrl, outputDir, baseDir, localSourcePath, filePathsCreated, useTypeScript = true) {
366
+ const variantDocs = group.variants.map((v) => ({ doc: v, variant: v.variant }));
367
+ const defaultDoc = group.main ? { doc: group.main, variant: null } : null;
368
+ const componentName = (group.main ?? group.variants[0])?.component || 'template';
369
+ // Migrate templates and extract their full code (no deduplication)
370
+ const allDocs = [...variantDocs, ...(defaultDoc ? [defaultDoc] : [])];
371
+ const migratedTemplates = allDocs.map(({ doc }) => prepareMigratedTemplate(doc, useTypeScript));
372
+ const exportDefaultPrefix = 'export default ';
373
+ // For each template, replace 'export default' with 'template =' and remove figma require
374
+ const branches = migratedTemplates.map((t) => {
375
+ if (!t.includes(exportDefaultPrefix)) {
376
+ throw new Error(`Variant merge: no "export default" in template for ${figmaUrl}`);
377
+ }
378
+ // Replace 'export default' with 'template ='
379
+ let branchCode = t.replace(exportDefaultPrefix, 'template = ');
380
+ // Remove only the top-level figma require, keep everything else
381
+ const lines = branchCode.split('\n');
382
+ const filteredLines = lines.filter((line) => !line.trim().startsWith('const figma = require'));
383
+ return filteredLines.join('\n').trim();
384
+ });
385
+ // Build the variant switch structure using conditions for all variant properties
386
+ const ifParts = [];
387
+ for (let i = 0; i < variantDocs.length; i++) {
388
+ const { variant } = variantDocs[i];
389
+ const branchCode = branches[i];
390
+ if (variant && Object.keys(variant).length > 0) {
391
+ // Build condition from all properties in the variant
392
+ const condition = Object.entries(variant)
393
+ .map(([key, val]) => `figma.selectedInstance.getPropertyValue('${key}') === ${typeof val === 'string' ? `'${val}'` : val}`)
394
+ .join(' && ');
395
+ ifParts.push(`${ifParts.length ? '} else ' : ''}if (${condition}) {\n${branchCode}`);
332
396
  }
333
- return elements
334
397
  }
335
- })
398
+ // Add default/fallback branch (use the last doc: main if present, otherwise first variant)
399
+ const defaultBranchCode = branches[branches.length - 1];
400
+ ifParts.push(`} else {\n${defaultBranchCode}\n}`);
401
+ const variantComment = group.main != null
402
+ ? `// Branch per variant combination.`
403
+ : `// Branch per variant; no default, else first.`;
404
+ const templateBody = [
405
+ "const figma = require('figma')",
406
+ '',
407
+ variantComment,
408
+ '',
409
+ 'let template',
410
+ ifParts.join('\n'),
411
+ '',
412
+ 'export default template',
413
+ ].join('\n');
414
+ const formatted = formatTemplate(templateBody);
415
+ // Build comment header with url, source, and component
416
+ // Use the representative doc (main or first variant) for source/component values
417
+ const representativeDoc = group.main ?? group.variants[0];
418
+ const commentLines = [`// url=${figmaUrl}`];
419
+ if (representativeDoc?.source) {
420
+ commentLines.push(`// source=${representativeDoc.source}`);
421
+ }
422
+ if (representativeDoc?.component) {
423
+ commentLines.push(`// component=${representativeDoc.component}`);
424
+ }
425
+ commentLines.push(``);
426
+ const fileContent = commentLines.join('\n') + '\n' + formatted;
427
+ return writeTemplateFileCommon(componentName, fileContent, outputDir, baseDir, localSourcePath, filePathsCreated, useTypeScript);
336
428
  }
337
- `, '');
429
+ function convertSyntaxToTypeScript(template) {
430
+ return template.replace(/const __props = {}/, 'const __props: Record<string, unknown> = {}');
338
431
  }
339
432
  //# 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 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
+ {"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\n/** Prettier configuration used for all generated template files */\nconst PRETTIER_OPTIONS = {\n parser: 'typescript' as const,\n semi: false,\n trailingComma: 'all' as const,\n pluginSearchDirs: false as const,\n}\n\n/** Formats template code with consistent prettier configuration */\nfunction formatTemplate(code: string): string {\n return prettier.format(code, PRETTIER_OPTIONS)\n}\n\n/**\n * Common wrapper that handles path determination and file writing for both\n * simple templates and variant templates.\n */\nfunction writeTemplateFileCommon(\n componentName: string,\n fileContent: string,\n outputDir: string | undefined,\n baseDir: string,\n localSourcePath: string | undefined,\n filePathsCreated: Set<string> | undefined,\n useTypeScript = true,\n): { outputPath: string; skipped: boolean } {\n const suffix = useTypeScript ? '.figma.ts' : '.figma.js'\n const baseOutputPath = determineOutputPath(\n componentName,\n suffix,\n outputDir,\n baseDir,\n localSourcePath,\n )\n return writeFileWithDuplicateHandling(baseOutputPath, fileContent, suffix, filePathsCreated)\n}\n\n/**\n * Determines the base output path for a template file.\n * Shared logic between writeTemplateFile and writeVariantTemplateFile.\n */\nfunction determineOutputPath(\n componentName: string,\n suffix: string,\n outputDir: string | undefined,\n baseDir: string,\n localSourcePath: string | undefined,\n): string {\n if (outputDir) {\n // Use specified output directory\n const filename = `${componentName}${suffix}`\n return 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 return path.join(sourceDir, filename)\n } else {\n // No source info, use current directory\n const filename = `${componentName}${suffix}`\n return path.join(baseDir, filename)\n }\n}\n\n/**\n * Handles file existence checking, duplicate name resolution, and writing.\n * Shared logic between writeTemplateFile and writeVariantTemplateFile.\n */\nfunction writeFileWithDuplicateHandling(\n baseOutputPath: string,\n fileContent: string,\n suffix: string,\n filePathsCreated: Set<string> | undefined,\n): { outputPath: string; skipped: boolean } {\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 // 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/** Migrates a doc's template (Swift helpers, server helpers, V2, id, imports, nestable) and returns the formatted string. */\nexport function prepareMigratedTemplate(\n doc: CodeConnectJSON,\n removeProps?: boolean,\n useTypeScript?: boolean,\n): string {\n let template = doc.template\n template = removeSwiftHelpers(template)\n template = migrateTemplateToUseServerSideHelpers(template)\n if (removeProps) {\n template = removePropsDefinitionAndMetadata(template)\n }\n template = migrateV1TemplateToV2(template)\n template = addId(template, doc.component || 'TODO')\n template = addImports(template, doc.templateData?.imports)\n template = addNestableToMetadata(template, !!doc.templateData?.nestable)\n if (useTypeScript) {\n template = convertSyntaxToTypeScript(template)\n }\n return formatTemplate(template)\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\nexport function writeTemplateFile(\n doc: CodeConnectJSON,\n outputDir: string | undefined,\n baseDir: string,\n localSourcePath?: string,\n filePathsCreated?: Set<string>,\n removeProps?: boolean,\n useTypeScript = true,\n): { outputPath: string; skipped: boolean } {\n const componentName = doc.component || 'template'\n const template = prepareMigratedTemplate(doc, removeProps, useTypeScript)\n\n // Build comment header lines\n const commentLines: string[] = [`// url=${doc.figmaNode}`]\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 return writeTemplateFileCommon(\n componentName,\n fileContent,\n outputDir,\n baseDir,\n localSourcePath,\n filePathsCreated,\n useTypeScript,\n )\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\n/** One parserless file per component: branch per variant, each with its own props and template object; export default template. */\nexport function writeVariantTemplateFile(\n group: CodeConnectObjectsForFigmaUrl,\n figmaUrl: string,\n outputDir: string | undefined,\n baseDir: string,\n localSourcePath?: string,\n filePathsCreated?: Set<string>,\n useTypeScript = true,\n): { outputPath: string; skipped: boolean } {\n const variantDocs = group.variants.map((v) => ({ doc: v, variant: v.variant }))\n const defaultDoc = group.main ? { doc: group.main, variant: null } : null\n const componentName = (group.main ?? group.variants[0])?.component || 'template'\n\n // Migrate templates and extract their full code (no deduplication)\n const allDocs = [...variantDocs, ...(defaultDoc ? [defaultDoc] : [])]\n const migratedTemplates = allDocs.map(({ doc }) => prepareMigratedTemplate(doc, useTypeScript))\n const exportDefaultPrefix = 'export default '\n\n // For each template, replace 'export default' with 'template =' and remove figma require\n const branches = migratedTemplates.map((t) => {\n if (!t.includes(exportDefaultPrefix)) {\n throw new Error(`Variant merge: no \"export default\" in template for ${figmaUrl}`)\n }\n\n // Replace 'export default' with 'template ='\n let branchCode = t.replace(exportDefaultPrefix, 'template = ')\n\n // Remove only the top-level figma require, keep everything else\n const lines = branchCode.split('\\n')\n const filteredLines = lines.filter((line) => !line.trim().startsWith('const figma = require'))\n\n return filteredLines.join('\\n').trim()\n })\n\n // Build the variant switch structure using conditions for all variant properties\n const ifParts: string[] = []\n for (let i = 0; i < variantDocs.length; i++) {\n const { variant } = variantDocs[i]\n const branchCode = branches[i]\n\n if (variant && Object.keys(variant).length > 0) {\n // Build condition from all properties in the variant\n const condition = Object.entries(variant)\n .map(\n ([key, val]) =>\n `figma.selectedInstance.getPropertyValue('${key}') === ${typeof val === 'string' ? `'${val}'` : val}`,\n )\n .join(' && ')\n\n ifParts.push(`${ifParts.length ? '} else ' : ''}if (${condition}) {\\n${branchCode}`)\n }\n }\n\n // Add default/fallback branch (use the last doc: main if present, otherwise first variant)\n const defaultBranchCode = branches[branches.length - 1]\n\n ifParts.push(`} else {\\n${defaultBranchCode}\\n}`)\n\n const variantComment =\n group.main != null\n ? `// Branch per variant combination.`\n : `// Branch per variant; no default, else first.`\n\n const templateBody = [\n \"const figma = require('figma')\",\n '',\n variantComment,\n '',\n 'let template',\n ifParts.join('\\n'),\n '',\n 'export default template',\n ].join('\\n')\n\n const formatted = formatTemplate(templateBody)\n\n // Build comment header with url, source, and component\n // Use the representative doc (main or first variant) for source/component values\n const representativeDoc = group.main ?? group.variants[0]\n const commentLines: string[] = [`// url=${figmaUrl}`]\n if (representativeDoc?.source) {\n commentLines.push(`// source=${representativeDoc.source}`)\n }\n if (representativeDoc?.component) {\n commentLines.push(`// component=${representativeDoc.component}`)\n }\n commentLines.push(``)\n\n const fileContent = commentLines.join('\\n') + '\\n' + formatted\n\n return writeTemplateFileCommon(\n componentName,\n fileContent,\n outputDir,\n baseDir,\n localSourcePath,\n filePathsCreated,\n useTypeScript,\n )\n}\n\nfunction convertSyntaxToTypeScript(template: string): string {\n return template.replace(/const __props = {}/, 'const __props: Record<string, unknown> = {}')\n}\n"]}
@@ -51,6 +51,11 @@ export type BaseCodeConnectConfig = {
51
51
  * Custom Figma API URL to use instead of https://api.figma.com/v1
52
52
  */
53
53
  apiUrl?: string;
54
+ /**
55
+ * The default branch name for your repository. Code Connect uses this when generating source code
56
+ * links in Figma. If not specified, Code Connect will attempt to determine this automatically.
57
+ */
58
+ defaultBranch?: string;
54
59
  };
55
60
  export type CodeConnectExecutableParserConfig = BaseCodeConnectConfig & {
56
61
  parser: CodeConnectExecutableParser;
@@ -106,16 +111,16 @@ export declare function getGitRemoteURL(repoPath: string): string;
106
111
  */
107
112
  export declare function getGitRepoAbsolutePath(filePath: string): string;
108
113
  /**
109
- * Find the default branch name (master or main) for the git repository
114
+ * Find the default branch name for the git repository
110
115
  */
111
- export declare function getGitRepoDefaultBranchName(repoPath: string): "master" | "main";
116
+ export declare function getGitRepoDefaultBranchName(repoPath: string, configDefaultBranch?: string): string;
112
117
  /**
113
118
  * Finds the URL of a remote file
114
119
  * @param filePath absolute file path on disk
115
120
  * @param repoURL remote URL, can be a GitHub, GitLab, Bitbucket, etc. URL.
116
121
  * @returns
117
122
  */
118
- export declare function getRemoteFileUrl(filePath: string, repoURL?: string): string;
123
+ export declare function getRemoteFileUrl(filePath: string, repoURL?: string, defaultBranch?: string): string;
119
124
  export declare function getStorybookUrl(filePath: string, storybookUrl: string): string;
120
125
  export type ProjectInfo<ConfigT = CodeConnectConfig> = {
121
126
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/connect/project.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,YAAY,CAAA;AAO3B,OAAO,EAAoB,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAKpF,eAAO,MAAM,+BAA+B;;;;;;;CAQ3C,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAG/E,CAAA;AAGD,MAAM,MAAM,2BAA2B,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,eAAe,CAAA;AAK1F,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,2BAA2B,CAAA;AAE9E,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjD;;OAEG;IACH,MAAM,EAAE,iBAAiB,CAAA;IAEzB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;;OAGG;IACH,QAAQ,CAAC,EAAE,uBAAuB,CAAA;IAElC;;OAEG;IACH,4BAA4B,CAAC,EAAE,MAAM,CAAA;IAErC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,iCAAiC,GAAG,qBAAqB,GAAG;IACtE,MAAM,EAAE,2BAA2B,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,uCAAuC,GAAG,qBAAqB,GAAG;IAC5E,MAAM,EAAE,QAAQ,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,qBAAqB,GAAG;IAC3D,MAAM,EAAE,OAAO,CAAA;IACf;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAChC;;OAEG;IACH,SAAS,CAAC,EAAE;QACV;;WAEG;QACH,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;CACF,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,qBAAqB,GAAG,EAAE,CAAA;AAE9D,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAA;AAE/E,MAAM,MAAM,iBAAiB,GACzB,sBAAsB,GACtB,iCAAiC,GACjC,uCAAuC,GACvC,qBAAqB,GACrB,qBAAqB,CAAA;AAEzB,UAAU,WAAW;IACnB,WAAW,CAAC,EAAE,iBAAiB,CAAA;CAChC;AAED,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,MAAM,EACX,WAAW,UAAO,GACjB,WAAW,GAAG,SAAS,CAgBzB;AAgFD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAuCzE;AAsID,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,UAW/C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,UAkBtD;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,qBA6B3D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,UAmDlE;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,UAoBrE;AAED,MAAM,MAAM,WAAW,CAAC,OAAO,GAAG,iBAAiB,IAAI;IACrD;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;OAEG;IACH,KAAK,EAAE,MAAM,EAAE,CAAA;IACf;;OAEG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC,sBAAsB,CAAC,GAAG;IACnE;;OAEG;IACH,SAAS,EAAE,EAAE,CAAC,OAAO,CAAA;CACtB,CAAA;AAOD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,UAE/C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,UAErC;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;;;GAyC3E;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM;;;GAoCpD;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,WAAW,CAAC,CAoDtB;AAoBD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAO1F;AAED,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,CAAC,sBAAsB,CAAC,GAC/C,gBAAgB,CAOlB;AAED,wBAAgB,YAAY,CAAC,WAAW,EAAE,WAAW,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,OAAO,CAcpF;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI,CAoD7F;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,sBAAsB,GAC7B,MAAM,GAAG,IAAI,CAoBf"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/connect/project.ts"],"names":[],"mappings":"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"}
@@ -280,12 +280,26 @@ function getGitRepoAbsolutePath(filePath) {
280
280
  }
281
281
  }
282
282
  /**
283
- * Find the default branch name (master or main) for the git repository
283
+ * Find the default branch name for the git repository
284
284
  */
285
- function getGitRepoDefaultBranchName(repoPath) {
285
+ function getGitRepoDefaultBranchName(repoPath, configDefaultBranch) {
286
286
  const DEFAULT_BRANCH_NAME = 'master';
287
+ if (configDefaultBranch) {
288
+ return configDefaultBranch;
289
+ }
287
290
  try {
288
- // Get all git branches
291
+ const symbolicRefResult = (0, child_process_1.spawnSync)('git', ['symbolic-ref', 'refs/remotes/origin/HEAD'], {
292
+ cwd: repoPath,
293
+ });
294
+ if (symbolicRefResult.status === 0 && symbolicRefResult.stdout) {
295
+ const ref = symbolicRefResult.stdout.toString().trim();
296
+ // Output format: "refs/remotes/origin/<branch>" – take the last segment
297
+ const branch = ref.split('/').pop();
298
+ if (branch) {
299
+ return branch;
300
+ }
301
+ }
302
+ // Fall back to scanning remote branches for known default branch names
289
303
  const gitBranchResult = (0, child_process_1.spawnSync)('git', ['branch', '-r'], {
290
304
  cwd: repoPath,
291
305
  });
@@ -316,7 +330,7 @@ function getGitRepoDefaultBranchName(repoPath) {
316
330
  * @param repoURL remote URL, can be a GitHub, GitLab, Bitbucket, etc. URL.
317
331
  * @returns
318
332
  */
319
- function getRemoteFileUrl(filePath, repoURL) {
333
+ function getRemoteFileUrl(filePath, repoURL, defaultBranch) {
320
334
  if (!repoURL) {
321
335
  return '';
322
336
  }
@@ -333,20 +347,20 @@ function getRemoteFileUrl(filePath, repoURL) {
333
347
  const repoAbsPath = getGitRepoAbsolutePath(filePath)
334
348
  // Windows uses \ as the path separator, so replace with /
335
349
  .replaceAll(path_1.default.sep, '/');
336
- const defaultBranch = getGitRepoDefaultBranchName(repoAbsPath);
350
+ const resolvedDefaultBranch = getGitRepoDefaultBranchName(repoAbsPath, defaultBranch);
337
351
  const index = filePath.indexOf(repoAbsPath);
338
352
  if (index === -1) {
339
353
  return '';
340
354
  }
341
355
  const relativeFilePath = filePath.substring(index + repoAbsPath.length);
342
356
  if (url.includes('github.com')) {
343
- return `${url}/blob/${defaultBranch}${relativeFilePath}`;
357
+ return `${url}/blob/${resolvedDefaultBranch}${relativeFilePath}`;
344
358
  }
345
359
  else if (url.includes('gitlab.com')) {
346
- return `${url}/-/blob/${defaultBranch}${relativeFilePath}`;
360
+ return `${url}/-/blob/${resolvedDefaultBranch}${relativeFilePath}`;
347
361
  }
348
362
  else if (url.includes('bitbucket.org')) {
349
- return `${url}/src/${defaultBranch}${relativeFilePath}`;
363
+ return `${url}/src/${resolvedDefaultBranch}${relativeFilePath}`;
350
364
  }
351
365
  else if (url.includes('dev.azure.com')) {
352
366
  // `git config --get remote.origin.url` for azure repos will return different strings depending on if it was
@@ -354,17 +368,17 @@ function getRemoteFileUrl(filePath, repoURL) {
354
368
  if (repoURL.startsWith('git@')) {
355
369
  // ssh: "git@ssh.dev.azure.com:v3/org/repo/repo"
356
370
  const [org, project1, project2] = repoURL.split('/').slice(-3);
357
- return `https://dev.azure.com/${org}/${project1}/_git/${project2}?path=${relativeFilePath}&branch=${defaultBranch}`;
371
+ return `https://dev.azure.com/${org}/${project1}/_git/${project2}?path=${relativeFilePath}&branch=${resolvedDefaultBranch}`;
358
372
  }
359
373
  else {
360
374
  // https: "https://org@dev.azure.com/org/repo/_git/repo"
361
375
  const [_, url] = repoURL.split('@');
362
- return `https://${url}?path=${relativeFilePath}&branch=${defaultBranch}`;
376
+ return `https://${url}?path=${relativeFilePath}&branch=${resolvedDefaultBranch}`;
363
377
  }
364
378
  }
365
379
  else {
366
380
  logging_1.logger.debug('Unknown remote URL - assuming GitHub Enterprise', url);
367
- return `${url}/blob/${defaultBranch}${relativeFilePath}`;
381
+ return `${url}/blob/${resolvedDefaultBranch}${relativeFilePath}`;
368
382
  }
369
383
  }
370
384
  function getStorybookUrl(filePath, storybookUrl) {