@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.
- package/dist/commands/connect.d.ts +1 -2
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +52 -92
- package/dist/commands/connect.js.map +1 -1
- package/dist/connect/helpers.d.ts +6 -0
- package/dist/connect/helpers.d.ts.map +1 -1
- package/dist/connect/helpers.js +18 -0
- package/dist/connect/helpers.js.map +1 -1
- package/dist/connect/migration_helpers.d.ts +8 -1
- package/dist/connect/migration_helpers.d.ts.map +1 -1
- package/dist/connect/migration_helpers.js +158 -65
- package/dist/connect/migration_helpers.js.map +1 -1
- package/dist/connect/project.d.ts +8 -3
- package/dist/connect/project.d.ts.map +1 -1
- package/dist/connect/project.js +25 -11
- package/dist/connect/project.js.map +1 -1
- package/dist/connect/raw_templates.d.ts +11 -0
- package/dist/connect/raw_templates.d.ts.map +1 -0
- package/dist/connect/raw_templates.js +149 -0
- package/dist/connect/raw_templates.js.map +1 -0
- package/dist/connect/upload.d.ts.map +1 -1
- package/dist/connect/upload.js +27 -6
- package/dist/connect/upload.js.map +1 -1
- package/dist/html/parser.d.ts.map +1 -1
- package/dist/html/parser.js +2 -4
- package/dist/html/parser.js.map +1 -1
- package/dist/react/parser.d.ts.map +1 -1
- package/dist/react/parser.js +5 -5
- package/dist/react/parser.js.map +1 -1
- package/dist/storybook/convert.js +1 -1
- package/dist/storybook/convert.js.map +1 -1
- package/figma-module.d.ts +207 -0
- package/package.json +7 -3
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { CodeConnectJSON } from '../connect/figma_connect';
|
|
2
|
-
|
|
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;
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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 = `${
|
|
57
|
-
|
|
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
|
-
|
|
99
|
+
return path_1.default.join(sourceDir, filename);
|
|
77
100
|
}
|
|
78
101
|
else {
|
|
79
102
|
// No source info, use current directory
|
|
80
|
-
const filename = `${
|
|
81
|
-
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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}`];
|
|
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
|
-
|
|
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
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
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
|
|
114
|
+
* Find the default branch name for the git repository
|
|
110
115
|
*/
|
|
111
|
-
export declare function getGitRepoDefaultBranchName(repoPath: string):
|
|
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;
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/connect/project.ts"],"names":[],"mappings":"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"}
|
package/dist/connect/project.js
CHANGED
|
@@ -280,12 +280,26 @@ function getGitRepoAbsolutePath(filePath) {
|
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
/**
|
|
283
|
-
* Find the default branch name
|
|
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
|
-
|
|
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
|
|
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/${
|
|
357
|
+
return `${url}/blob/${resolvedDefaultBranch}${relativeFilePath}`;
|
|
344
358
|
}
|
|
345
359
|
else if (url.includes('gitlab.com')) {
|
|
346
|
-
return `${url}/-/blob/${
|
|
360
|
+
return `${url}/-/blob/${resolvedDefaultBranch}${relativeFilePath}`;
|
|
347
361
|
}
|
|
348
362
|
else if (url.includes('bitbucket.org')) {
|
|
349
|
-
return `${url}/src/${
|
|
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=${
|
|
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=${
|
|
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/${
|
|
381
|
+
return `${url}/blob/${resolvedDefaultBranch}${relativeFilePath}`;
|
|
368
382
|
}
|
|
369
383
|
}
|
|
370
384
|
function getStorybookUrl(filePath, storybookUrl) {
|