@figma/code-connect 1.4.1 → 1.4.3
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/README.md +4 -4
- package/dist/commands/connect.d.ts +6 -4
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +80 -107
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/filter_project_info.d.ts +7 -0
- package/dist/commands/filter_project_info.d.ts.map +1 -0
- package/dist/commands/filter_project_info.js +32 -0
- package/dist/commands/filter_project_info.js.map +1 -0
- 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/intrinsics.d.ts +3 -3
- package/dist/connect/intrinsics.d.ts.map +1 -1
- package/dist/connect/intrinsics.js +21 -10
- package/dist/connect/intrinsics.js.map +1 -1
- package/dist/connect/migration_helpers.d.ts +15 -1
- package/dist/connect/migration_helpers.d.ts.map +1 -1
- package/dist/connect/migration_helpers.js +187 -73
- package/dist/connect/migration_helpers.js.map +1 -1
- package/dist/connect/parser_common.d.ts +3 -2
- package/dist/connect/parser_common.d.ts.map +1 -1
- package/dist/connect/parser_common.js +2 -2
- package/dist/connect/parser_common.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 +2 -2
- package/dist/html/parser.d.ts.map +1 -1
- package/dist/html/parser.js +9 -9
- package/dist/html/parser.js.map +1 -1
- package/dist/react/parser.d.ts +3 -3
- package/dist/react/parser.d.ts.map +1 -1
- package/dist/react/parser.js +14 -12
- package/dist/react/parser.js.map +1 -1
- package/dist/storybook/convert.d.ts +7 -1
- package/dist/storybook/convert.d.ts.map +1 -1
- package/dist/storybook/convert.js +12 -5
- package/dist/storybook/convert.js.map +1 -1
- package/figma-types.d.ts +214 -0
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Code Connect is a tool for connecting your design system components in code with your design system in Figma. When using Code Connect, Figma's Dev Mode will display true-to-production code snippets from your design system instead of autogenerated code examples. In addition to connecting component definitions, Code Connect also supports mapping properties from code to Figma enabling dynamic and correct examples. This can be useful for when you have an existing design system and are looking to drive consistent and correct adoption of that design system across design and engineering.
|
|
4
4
|
|
|
5
|
-
Code Connect is easy to set up, easy to maintain, type-safe, and extensible.
|
|
5
|
+
Code Connect is easy to set up, easy to maintain, type-safe, and extensible. The easiest way to get started is using **template files** — a framework-agnostic way to represent any code snippet, giving you full control over how components appear in Dev Mode. Code Connect also includes framework-specific integrations for React (and React Native), Storybook, HTML (e.g. Web Components, Angular and Vue), SwiftUI and Jetpack Compose.
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
@@ -13,11 +13,11 @@ Code Connect is easy to set up, easy to maintain, type-safe, and extensible. Out
|
|
|
13
13
|
|
|
14
14
|
Use Figma’s Code Connect to make your design system easily accessible to your developers and create a shared source of truth for both the design and code elements.
|
|
15
15
|
|
|
16
|
-
Our Getting Started guide will walk you through
|
|
16
|
+
Our Getting Started guide will walk you through setting up Code Connect and publishing your first components using template files. **[Code Connect Documentation →](https://developers.figma.com/docs/code-connect/)**
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
For framework-specific prop mapping and variant support, see the integration guides for:
|
|
19
19
|
|
|
20
20
|
- **[React (and React Native) →](https://www.figma.com/code-connect-docs/react)**
|
|
21
21
|
- **[HTML (e.g. Web Components, Angular and Vue) →](https://www.figma.com/code-connect-docs/html)**
|
|
22
22
|
- **[SwiftUI →](https://www.figma.com/code-connect-docs/swiftui)**
|
|
23
|
-
- **[Jetpack Compose →](https://www.figma.com/code-connect-docs/compose)
|
|
23
|
+
- **[Jetpack Compose →](https://www.figma.com/code-connect-docs/compose)**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as commander from 'commander';
|
|
2
|
-
import {
|
|
2
|
+
import { ProjectInfo } from '../connect/project';
|
|
3
3
|
import { CodeConnectJSON } from '../connect/figma_connect';
|
|
4
4
|
export type BaseCommand = commander.Command & {
|
|
5
5
|
token: string;
|
|
@@ -9,17 +9,19 @@ export type BaseCommand = commander.Command & {
|
|
|
9
9
|
config: string;
|
|
10
10
|
dryRun: boolean;
|
|
11
11
|
dir: string;
|
|
12
|
+
file: string;
|
|
12
13
|
jsonFile: string;
|
|
13
14
|
skipUpdateCheck: boolean;
|
|
14
15
|
exitOnUnreadableFiles: boolean;
|
|
15
16
|
apiUrl?: string;
|
|
16
|
-
|
|
17
|
+
includeProps?: boolean;
|
|
17
18
|
};
|
|
18
19
|
export declare function addConnectCommandToProgram(program: commander.Command): void;
|
|
19
20
|
export declare function getAccessToken(cmd: BaseCommand): string;
|
|
21
|
+
export declare function getAccessTokenOrExit(cmd: BaseCommand): string;
|
|
20
22
|
export declare function getDir(cmd: BaseCommand): string;
|
|
21
|
-
export declare function
|
|
23
|
+
export declare function setupHandler(cmd: BaseCommand): void;
|
|
22
24
|
export declare function getCodeConnectObjects(cmd: BaseCommand & {
|
|
23
25
|
label?: string;
|
|
24
|
-
}, projectInfo: ProjectInfo, silent?: boolean,
|
|
26
|
+
}, projectInfo: ProjectInfo, silent?: boolean, isForMigration?: boolean): Promise<CodeConnectJSON[]>;
|
|
25
27
|
//# sourceMappingURL=connect.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,WAAW,CAAA;AAKtC,OAAO,
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,WAAW,CAAA;AAKtC,OAAO,EAKL,WAAW,EAKZ,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAgC1D,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,GAAG;IAC5C,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,OAAO,CAAA;IACxB,qBAAqB,EAAE,OAAO,CAAA;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,CAAA;AA2BD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,QA4EpE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,UAE9C;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,WAAW,UAUpD;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,WAAW,UAEtC;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,QAI5C;AAkCD,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,WAAW,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EACrC,WAAW,EAAE,WAAW,EACxB,MAAM,UAAQ,EACd,cAAc,UAAQ,GACrB,OAAO,CAAC,eAAe,EAAE,CAAC,CA6H5B"}
|
package/dist/commands/connect.js
CHANGED
|
@@ -5,8 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.addConnectCommandToProgram = addConnectCommandToProgram;
|
|
7
7
|
exports.getAccessToken = getAccessToken;
|
|
8
|
+
exports.getAccessTokenOrExit = getAccessTokenOrExit;
|
|
8
9
|
exports.getDir = getDir;
|
|
9
|
-
exports.
|
|
10
|
+
exports.setupHandler = setupHandler;
|
|
10
11
|
exports.getCodeConnectObjects = getCodeConnectObjects;
|
|
11
12
|
const fs_1 = __importDefault(require("fs"));
|
|
12
13
|
const upload_1 = require("../connect/upload");
|
|
@@ -23,11 +24,13 @@ const parser_executable_types_1 = require("../connect/parser_executable_types");
|
|
|
23
24
|
const path_1 = __importDefault(require("path"));
|
|
24
25
|
const updates_1 = require("../common/updates");
|
|
25
26
|
const helpers_1 = require("../connect/helpers");
|
|
27
|
+
const filter_project_info_1 = require("./filter_project_info");
|
|
26
28
|
const parser_1 = require("../html/parser");
|
|
27
29
|
const parser_common_1 = require("../connect/parser_common");
|
|
28
30
|
const parser_2 = require("../react/parser");
|
|
29
31
|
const label_language_mapping_1 = require("../connect/label_language_mapping");
|
|
30
32
|
const migration_helpers_1 = require("../connect/migration_helpers");
|
|
33
|
+
const raw_templates_1 = require("../connect/raw_templates");
|
|
31
34
|
const run_wizard_2 = require("../connect/wizard/run_wizard");
|
|
32
35
|
const project_2 = require("../connect/project");
|
|
33
36
|
function addBaseCommand(command, name, description) {
|
|
@@ -36,6 +39,7 @@ function addBaseCommand(command, name, description) {
|
|
|
36
39
|
.description(description)
|
|
37
40
|
.usage('[options]')
|
|
38
41
|
.option('-r --dir <dir>', 'directory to parse')
|
|
42
|
+
.option('-f --file <file>', 'path to a single Code Connect file to process')
|
|
39
43
|
.option('-t --token <token>', 'figma access token')
|
|
40
44
|
.option('-v --verbose', 'enable verbose logging for debugging')
|
|
41
45
|
.option('-o --outFile <file>', 'specify a file to output generated Code Connect')
|
|
@@ -57,6 +61,7 @@ function addConnectCommandToProgram(program) {
|
|
|
57
61
|
.option('--skip-validation', 'skip validation of Code Connect docs')
|
|
58
62
|
.option('-l --label <label>', 'label to apply to the published files')
|
|
59
63
|
.option('-b --batch-size <batch_size>', 'optional batch size (in number of documents) to use when uploading. Use this if you hit "request too large" errors. See README for more information.')
|
|
64
|
+
.option('--include-template-files', '(Deprecated) No longer needed - template files are included by default. Will be removed in a future version.')
|
|
60
65
|
.action((0, updates_1.withUpdateCheck)(handlePublish));
|
|
61
66
|
addBaseCommand(connectCommand, 'unpublish', 'Run to find any files that have figma connections and unpublish them from Figma. ' +
|
|
62
67
|
'By default this looks for a config file named "figma.config.json", and uses the `include` and `exclude` fields to determine which files to parse. ' +
|
|
@@ -66,15 +71,15 @@ function addConnectCommandToProgram(program) {
|
|
|
66
71
|
.action((0, updates_1.withUpdateCheck)(handleUnpublish));
|
|
67
72
|
addBaseCommand(connectCommand, 'parse', 'Run Code Connect locally to find any files that have figma connections, then converts them to JSON and outputs to stdout.')
|
|
68
73
|
.option('-l --label <label>', 'label to apply to the parsed files')
|
|
74
|
+
.option('--include-template-files', '(Deprecated) No longer needed - template files are included by default. Will be removed in a future version.')
|
|
69
75
|
.action((0, updates_1.withUpdateCheck)(handleParse));
|
|
70
76
|
addBaseCommand(connectCommand, 'create', 'Generate a Code Connect file with boilerplate in the current directory for a Figma node URL')
|
|
71
77
|
.argument('<figma-node-url>', 'Figma node URL to create the Code Connect file from')
|
|
72
78
|
.action((0, updates_1.withUpdateCheck)(handleCreate));
|
|
73
79
|
addBaseCommand(connectCommand, 'migrate', 'Parse Code Connect files and migrate their templates into .figma.js files that can be published directly without parsing.')
|
|
74
80
|
.argument('[pattern]', 'glob pattern to match files (optional, uses config if not provided)')
|
|
75
|
-
.option('-
|
|
76
|
-
.option('--
|
|
77
|
-
.option('--remove-props', 'remove __props metadata blocks from migrated templates')
|
|
81
|
+
.option('--include-props', 'preserve __props metadata blocks in migrated templates (removed by default). Use if your templates use the React .getProps() or .render() modifiers, or read executeTemplate().metadata.__props from the migrated components')
|
|
82
|
+
.option('--javascript', 'output migrated templates as JavaScript (.figma.js) instead of TypeScript (.figma.ts)')
|
|
78
83
|
.action((0, updates_1.withUpdateCheck)(handleMigrate));
|
|
79
84
|
}
|
|
80
85
|
function getAccessToken(cmd) {
|
|
@@ -105,15 +110,13 @@ function transformDocFromParser(doc, remoteUrl, config) {
|
|
|
105
110
|
}
|
|
106
111
|
}
|
|
107
112
|
catch (e) {
|
|
108
|
-
source = (0, project_1.getRemoteFileUrl)(source, remoteUrl);
|
|
113
|
+
source = (0, project_1.getRemoteFileUrl)(source, remoteUrl, config.defaultBranch);
|
|
109
114
|
}
|
|
110
115
|
}
|
|
111
116
|
// TODO This logic is duplicated in parser.ts parseDoc due to some type issues
|
|
112
117
|
let figmaNode = doc.figmaNode;
|
|
113
118
|
if (config.documentUrlSubstitutions) {
|
|
114
|
-
|
|
115
|
-
figmaNode = figmaNode.replace(from, to);
|
|
116
|
-
});
|
|
119
|
+
figmaNode = (0, helpers_1.applyDocumentUrlSubstitutions)(figmaNode, config.documentUrlSubstitutions);
|
|
117
120
|
}
|
|
118
121
|
return {
|
|
119
122
|
...doc,
|
|
@@ -121,67 +124,7 @@ function transformDocFromParser(doc, remoteUrl, config) {
|
|
|
121
124
|
figmaNode,
|
|
122
125
|
};
|
|
123
126
|
}
|
|
124
|
-
function
|
|
125
|
-
const fileContent = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
126
|
-
const lines = fileContent.split('\n');
|
|
127
|
-
const fields = {};
|
|
128
|
-
let templateStartIndex = 0;
|
|
129
|
-
// Parse consecutive comment lines at the start of the file
|
|
130
|
-
for (let i = 0; i < lines.length; i++) {
|
|
131
|
-
const line = lines[i].trim();
|
|
132
|
-
// Match pattern: // fieldName=value
|
|
133
|
-
const match = line.match(/^\/\/\s*(\w+)=(.+)$/);
|
|
134
|
-
if (match) {
|
|
135
|
-
const [, fieldName, fieldValue] = match;
|
|
136
|
-
const normalizedFieldName = fieldName.toLowerCase();
|
|
137
|
-
if (normalizedFieldName === 'url' ||
|
|
138
|
-
normalizedFieldName === 'component' ||
|
|
139
|
-
normalizedFieldName === 'source') {
|
|
140
|
-
fields[normalizedFieldName] = fieldValue.trim();
|
|
141
|
-
}
|
|
142
|
-
templateStartIndex = i + 1;
|
|
143
|
-
}
|
|
144
|
-
else if (line === '' || line.startsWith('//')) {
|
|
145
|
-
// Allow blank lines or other comments, but don't increment template start
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
// First non-comment line found
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
if (!fields.url) {
|
|
154
|
-
throw new Error(`Missing required url field in ${filePath}. Please add a // url=... comment to the top of the file.`);
|
|
155
|
-
}
|
|
156
|
-
let figmaNodeUrl = fields.url;
|
|
157
|
-
const template = lines.slice(templateStartIndex).join('\n');
|
|
158
|
-
// Apply documentUrlSubstitutions if provided
|
|
159
|
-
if (config?.documentUrlSubstitutions) {
|
|
160
|
-
Object.entries(config.documentUrlSubstitutions).forEach(([from, to]) => {
|
|
161
|
-
figmaNodeUrl = figmaNodeUrl.replace(from, to);
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
// Determine effective label from parameter, config, or default
|
|
165
|
-
const effectiveLabel = label || config?.label || label_language_mapping_1.CodeConnectLabel.Code;
|
|
166
|
-
const language = config?.language || (0, label_language_mapping_1.getInferredLanguageForRaw)(effectiveLabel);
|
|
167
|
-
return {
|
|
168
|
-
figmaNode: figmaNodeUrl,
|
|
169
|
-
component: fields.component,
|
|
170
|
-
template,
|
|
171
|
-
// nestable by default unless user specifies in template
|
|
172
|
-
// (templateData.nestable AND template.metadata.nestable need to
|
|
173
|
-
// be true for instance to be nested)
|
|
174
|
-
templateData: { nestable: true, isParserless: true },
|
|
175
|
-
language,
|
|
176
|
-
label: effectiveLabel,
|
|
177
|
-
source: fields.source || '',
|
|
178
|
-
sourceLocation: { line: -1 },
|
|
179
|
-
metadata: {
|
|
180
|
-
cliVersion: require('../../package.json').version,
|
|
181
|
-
},
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
async function getCodeConnectObjects(cmd, projectInfo, silent = false, skipTemplateHelpers = false) {
|
|
127
|
+
async function getCodeConnectObjects(cmd, projectInfo, silent = false, isForMigration = false) {
|
|
185
128
|
if (cmd.jsonFile) {
|
|
186
129
|
try {
|
|
187
130
|
const docsFromJson = JSON.parse(fs_1.default.readFileSync(cmd.jsonFile, 'utf8'));
|
|
@@ -197,7 +140,7 @@ async function getCodeConnectObjects(cmd, projectInfo, silent = false, skipTempl
|
|
|
197
140
|
}
|
|
198
141
|
let codeConnectObjects = [];
|
|
199
142
|
if (projectInfo.config.parser === 'react') {
|
|
200
|
-
codeConnectObjects = await getReactCodeConnectObjects(projectInfo, cmd, silent,
|
|
143
|
+
codeConnectObjects = await getReactCodeConnectObjects(projectInfo, cmd, silent, isForMigration);
|
|
201
144
|
}
|
|
202
145
|
else if (projectInfo.config.parser === 'html') {
|
|
203
146
|
codeConnectObjects = await getCodeConnectObjectsFromParseFn({
|
|
@@ -206,14 +149,14 @@ async function getCodeConnectObjects(cmd, projectInfo, silent = false, skipTempl
|
|
|
206
149
|
projectInfo,
|
|
207
150
|
cmd,
|
|
208
151
|
silent,
|
|
209
|
-
|
|
152
|
+
isForMigration,
|
|
210
153
|
});
|
|
211
154
|
}
|
|
212
155
|
else {
|
|
213
156
|
const payload = {
|
|
214
157
|
mode: 'PARSE',
|
|
215
158
|
paths: projectInfo.files,
|
|
216
|
-
config: { ...projectInfo.config, skipTemplateHelpers },
|
|
159
|
+
config: { ...projectInfo.config, skipTemplateHelpers: isForMigration },
|
|
217
160
|
verbose: cmd.verbose,
|
|
218
161
|
};
|
|
219
162
|
try {
|
|
@@ -244,12 +187,26 @@ async function getCodeConnectObjects(cmd, projectInfo, silent = false, skipTempl
|
|
|
244
187
|
}
|
|
245
188
|
}
|
|
246
189
|
}
|
|
247
|
-
const rawTemplateFiles = projectInfo.files.filter((f) =>
|
|
190
|
+
const rawTemplateFiles = projectInfo.files.filter((f) => {
|
|
191
|
+
// Suffix may be used by HTML / custom parsers
|
|
192
|
+
const isPotentialRawTemplate = f.endsWith('.figma.js') ||
|
|
193
|
+
f.endsWith('.figma.template.js') ||
|
|
194
|
+
f.endsWith('.figma.ts') ||
|
|
195
|
+
f.endsWith('.figma.template.ts');
|
|
196
|
+
if (!isPotentialRawTemplate)
|
|
197
|
+
return false;
|
|
198
|
+
try {
|
|
199
|
+
return (0, raw_templates_1.isRawTemplate)(fs_1.default.readFileSync(f, 'utf-8'));
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
});
|
|
248
205
|
if (rawTemplateFiles.length > 0) {
|
|
249
206
|
// Resolve the label before parsing so language inference works correctly
|
|
250
207
|
const resolvedLabel = cmd.label || projectInfo.config.label;
|
|
251
208
|
const rawTemplateDocs = rawTemplateFiles.map((file) => {
|
|
252
|
-
const doc = parseRawFile(file, resolvedLabel, projectInfo.config, projectInfo.absPath);
|
|
209
|
+
const doc = (0, raw_templates_1.parseRawFile)(file, resolvedLabel, projectInfo.config, projectInfo.absPath);
|
|
253
210
|
// Store the Code Connect file path for migration purposes
|
|
254
211
|
doc._codeConnectFilePath = file;
|
|
255
212
|
if (!silent || cmd.verbose) {
|
|
@@ -289,8 +246,8 @@ projectInfo,
|
|
|
289
246
|
cmd,
|
|
290
247
|
/** Silences console output */
|
|
291
248
|
silent = false,
|
|
292
|
-
/**
|
|
293
|
-
|
|
249
|
+
/** Whether this parse is for the migrate command */
|
|
250
|
+
isForMigration = false, }) {
|
|
294
251
|
const codeConnectObjects = [];
|
|
295
252
|
const tsProgram = (0, project_1.getTsProgram)(projectInfo);
|
|
296
253
|
const { files, remoteUrl, config, absPath } = projectInfo;
|
|
@@ -307,7 +264,7 @@ skipTemplateHelpers = false, }) {
|
|
|
307
264
|
repoUrl: remoteUrl,
|
|
308
265
|
debug: cmd.verbose,
|
|
309
266
|
silent,
|
|
310
|
-
|
|
267
|
+
isForMigration,
|
|
311
268
|
},
|
|
312
269
|
});
|
|
313
270
|
codeConnectObjects.push(...docs);
|
|
@@ -343,7 +300,7 @@ skipTemplateHelpers = false, }) {
|
|
|
343
300
|
}
|
|
344
301
|
return codeConnectObjects;
|
|
345
302
|
}
|
|
346
|
-
async function getReactCodeConnectObjects(projectInfo, cmd, silent = false,
|
|
303
|
+
async function getReactCodeConnectObjects(projectInfo, cmd, silent = false, isForMigration = false) {
|
|
347
304
|
const codeConnectObjects = await getCodeConnectObjectsFromParseFn({
|
|
348
305
|
parseFn: parser_2.parseReactDoc,
|
|
349
306
|
resolveImportsFn: parser_2.findAndResolveImports,
|
|
@@ -351,18 +308,24 @@ async function getReactCodeConnectObjects(projectInfo, cmd, silent = false, skip
|
|
|
351
308
|
projectInfo,
|
|
352
309
|
cmd,
|
|
353
310
|
silent,
|
|
354
|
-
|
|
311
|
+
isForMigration,
|
|
355
312
|
});
|
|
356
313
|
const storybookCodeConnectObjects = await (0, convert_1.convertStorybookFiles)({
|
|
357
314
|
projectInfo: (0, project_1.getReactProjectInfo)(projectInfo),
|
|
315
|
+
isForMigration,
|
|
358
316
|
});
|
|
359
317
|
const allCodeConnectObjects = codeConnectObjects.concat(storybookCodeConnectObjects);
|
|
360
318
|
return allCodeConnectObjects;
|
|
361
319
|
}
|
|
362
320
|
async function handlePublish(cmd) {
|
|
363
321
|
setupHandler(cmd);
|
|
322
|
+
// Show deprecation warning if the flag is used
|
|
323
|
+
if (cmd.includeTemplateFiles !== undefined) {
|
|
324
|
+
logging_1.logger.warn('[Deprecated] The --include-template-files flag is no longer needed because template files are now included by default. ' +
|
|
325
|
+
"Please don't use this flag - it will be removed in a future version.");
|
|
326
|
+
}
|
|
364
327
|
let dir = getDir(cmd);
|
|
365
|
-
const projectInfo = await (0, project_1.getProjectInfo)(dir, cmd.config);
|
|
328
|
+
const projectInfo = (0, filter_project_info_1.filterProjectInfoByFile)(await (0, project_1.getProjectInfo)(dir, cmd.config), cmd.file);
|
|
366
329
|
const codeConnectObjects = await getCodeConnectObjects(cmd, projectInfo);
|
|
367
330
|
if (codeConnectObjects.length === 0) {
|
|
368
331
|
logging_1.logger.warn(`No Code Connect files found in ${dir} - Make sure you have configured \`include\` and \`exclude\` in your figma.config.json file correctly, or that you are running in a directory that contains Code Connect files.`);
|
|
@@ -416,7 +379,7 @@ async function handleUnpublish(cmd) {
|
|
|
416
379
|
logging_1.logger.info(`Files that would be unpublished:`);
|
|
417
380
|
}
|
|
418
381
|
let nodesToDeleteRelevantInfo;
|
|
419
|
-
const projectInfo = await (0, project_1.getProjectInfo)(dir, cmd.config);
|
|
382
|
+
const projectInfo = (0, filter_project_info_1.filterProjectInfoByFile)(await (0, project_1.getProjectInfo)(dir, cmd.config), cmd.file);
|
|
420
383
|
if (cmd.node) {
|
|
421
384
|
if (!cmd.label) {
|
|
422
385
|
(0, logging_1.exitWithError)('Label is required when specifying a node');
|
|
@@ -446,8 +409,13 @@ async function handleUnpublish(cmd) {
|
|
|
446
409
|
}
|
|
447
410
|
async function handleParse(cmd) {
|
|
448
411
|
setupHandler(cmd);
|
|
412
|
+
// Show deprecation warning if the flag is used
|
|
413
|
+
if (cmd.includeTemplateFiles !== undefined) {
|
|
414
|
+
logging_1.logger.warn('[Deprecated] The --include-template-files flag is no longer needed because template files are now included by default. ' +
|
|
415
|
+
"Please don't use this flag - it will be removed in a future version.");
|
|
416
|
+
}
|
|
449
417
|
const dir = cmd.dir ?? process.cwd();
|
|
450
|
-
const projectInfo = await (0, project_1.getProjectInfo)(dir, cmd.config);
|
|
418
|
+
const projectInfo = (0, filter_project_info_1.filterProjectInfoByFile)(await (0, project_1.getProjectInfo)(dir, cmd.config), cmd.file);
|
|
451
419
|
const codeConnectObjects = await getCodeConnectObjects(cmd, projectInfo);
|
|
452
420
|
if (cmd.dryRun) {
|
|
453
421
|
logging_1.logger.info(`Dry run complete`);
|
|
@@ -522,59 +490,67 @@ async function handleMigrate(pattern, cmd) {
|
|
|
522
490
|
// Parse the files to get Code Connect objects
|
|
523
491
|
const allCodeConnectObjects = await getCodeConnectObjects(cmd, projectInfo, false, true);
|
|
524
492
|
const codeConnectObjectsByFigmaUrl = (0, migration_helpers_1.groupCodeConnectObjectsByFigmaUrl)(allCodeConnectObjects);
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
const codeConnectObjects = Object.values(codeConnectObjectsByFigmaUrl).flatMap((obj) => obj.main ? [obj.main] : []);
|
|
528
|
-
if (codeConnectObjects.length === 0) {
|
|
493
|
+
const groupCount = Object.keys(codeConnectObjectsByFigmaUrl).length;
|
|
494
|
+
if (groupCount === 0) {
|
|
529
495
|
(0, logging_1.exitWithError)('No Code Connect objects found to migrate');
|
|
530
496
|
}
|
|
531
|
-
logging_1.logger.info(`Found ${
|
|
497
|
+
logging_1.logger.info(`Found ${groupCount} component(s) to migrate`);
|
|
532
498
|
let migratedCount = 0;
|
|
533
499
|
let skippedCount = 0;
|
|
534
500
|
const errors = [];
|
|
535
|
-
// Track file paths created during this migration run
|
|
536
501
|
const filePathsCreated = new Set();
|
|
537
|
-
// Get git root path for converting remote URLs to local paths
|
|
538
502
|
const gitRootPath = (0, project_2.getGitRepoAbsolutePath)(dir);
|
|
539
|
-
|
|
540
|
-
for (const
|
|
503
|
+
const useTypeScript = !cmd.javascript;
|
|
504
|
+
for (const [figmaUrl, group] of Object.entries(codeConnectObjectsByFigmaUrl)) {
|
|
541
505
|
try {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
506
|
+
const hasVariants = group.variants.length > 0;
|
|
507
|
+
const representativeDoc = group.main ?? group.variants[0];
|
|
508
|
+
if (!representativeDoc?.template) {
|
|
509
|
+
logging_1.logger.warn(`Skipping ${figmaUrl}: no template found`);
|
|
545
510
|
skippedCount++;
|
|
546
511
|
continue;
|
|
547
512
|
}
|
|
548
513
|
// Determine local source path for output location
|
|
549
514
|
let localSourcePath;
|
|
550
|
-
if (
|
|
515
|
+
if (representativeDoc._codeConnectFilePath) {
|
|
551
516
|
// Use the Code Connect file path directly (preferred)
|
|
552
|
-
localSourcePath =
|
|
517
|
+
localSourcePath = representativeDoc._codeConnectFilePath;
|
|
553
518
|
}
|
|
554
|
-
else if (
|
|
519
|
+
else if (representativeDoc?.source && gitRootPath) {
|
|
555
520
|
// Fallback: Convert remote file URL to local path
|
|
556
521
|
const relativePath = (0, run_wizard_2.convertRemoteFileUrlToRelativePath)({
|
|
557
|
-
remoteFileUrl:
|
|
522
|
+
remoteFileUrl: representativeDoc.source,
|
|
558
523
|
gitRootPath,
|
|
559
524
|
dir,
|
|
560
525
|
});
|
|
561
526
|
if (relativePath) {
|
|
562
|
-
// Convert relative path to absolute path for writeTemplateFile
|
|
563
527
|
localSourcePath = path_1.default.resolve(dir, relativePath);
|
|
564
528
|
}
|
|
565
529
|
}
|
|
566
|
-
const { outputPath, skipped } =
|
|
530
|
+
const { outputPath, skipped } = hasVariants
|
|
531
|
+
? (0, migration_helpers_1.writeVariantTemplateFile)(group, figmaUrl, cmd.outDir, dir, {
|
|
532
|
+
localSourcePath,
|
|
533
|
+
filePathsCreated,
|
|
534
|
+
useTypeScript,
|
|
535
|
+
includeProps: cmd.includeProps,
|
|
536
|
+
})
|
|
537
|
+
: (0, migration_helpers_1.writeTemplateFile)(representativeDoc, cmd.outDir, dir, {
|
|
538
|
+
localSourcePath,
|
|
539
|
+
filePathsCreated,
|
|
540
|
+
includeProps: cmd.includeProps,
|
|
541
|
+
useTypeScript,
|
|
542
|
+
});
|
|
567
543
|
if (skipped) {
|
|
568
544
|
logging_1.logger.warn(`Skipping ${outputPath}: file already exists`);
|
|
569
545
|
skippedCount++;
|
|
570
546
|
}
|
|
571
547
|
else {
|
|
572
|
-
logging_1.logger.info(`${(0, logging_1.success)('✓')} Migrated to ${(0, logging_1.highlight)(outputPath)}`);
|
|
548
|
+
logging_1.logger.info(`${(0, logging_1.success)('✓')} Migrated${hasVariants ? ' (with variants)' : ''} to ${(0, logging_1.highlight)(outputPath)}`);
|
|
573
549
|
migratedCount++;
|
|
574
550
|
}
|
|
575
551
|
}
|
|
576
552
|
catch (error) {
|
|
577
|
-
const errorMsg = `Failed to migrate ${
|
|
553
|
+
const errorMsg = `Failed to migrate ${figmaUrl}: ${error}`;
|
|
578
554
|
logging_1.logger.error(errorMsg);
|
|
579
555
|
errors.push(errorMsg);
|
|
580
556
|
}
|
|
@@ -586,10 +562,10 @@ async function handleMigrate(pattern, cmd) {
|
|
|
586
562
|
logging_1.logger.warn(`Config file already exists at ${(0, logging_1.highlight)(configFilePath)}`);
|
|
587
563
|
}
|
|
588
564
|
else {
|
|
589
|
-
const { language: docLanguage, label } =
|
|
565
|
+
const { language: docLanguage, label } = allCodeConnectObjects[0];
|
|
590
566
|
const language = (0, label_language_mapping_1.getInferredLanguageForRaw)(label, docLanguage);
|
|
591
567
|
const config = {
|
|
592
|
-
include: ['**/*.figma.js'],
|
|
568
|
+
include: [useTypeScript ? '**/*.figma.ts' : '**/*.figma.js'],
|
|
593
569
|
language,
|
|
594
570
|
label,
|
|
595
571
|
...(documentUrlSubstitutions && Object.keys(documentUrlSubstitutions).length > 0
|
|
@@ -604,9 +580,6 @@ async function handleMigrate(pattern, cmd) {
|
|
|
604
580
|
// Summary
|
|
605
581
|
console.log('');
|
|
606
582
|
logging_1.logger.info(`Migration complete: ${(0, logging_1.success)(`${migratedCount} migrated`)}, ${skippedCount} skipped`);
|
|
607
|
-
if (totalVariants > 0) {
|
|
608
|
-
logging_1.logger.error(`${(0, logging_1.error)(`${totalVariants} variant restriction(s)`)} found, but not supported by the migration script yet`);
|
|
609
|
-
}
|
|
610
583
|
if (errors.length > 0) {
|
|
611
584
|
console.log('');
|
|
612
585
|
logging_1.logger.error(`Encountered ${errors.length} error(s):`);
|