@figma/code-connect 1.0.5 → 1.1.0
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 +2 -595
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/client/figma_client.d.ts +1 -1
- package/dist/client/figma_client.js +9 -7
- package/dist/client/figma_client.js.map +1 -1
- package/dist/commands/connect.d.ts +4 -2
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +97 -49
- package/dist/commands/connect.js.map +1 -1
- package/dist/connect/api.d.ts +143 -0
- package/dist/connect/api.d.ts.map +1 -0
- package/dist/connect/api.js +3 -0
- package/dist/connect/api.js.map +1 -0
- package/dist/connect/create.d.ts.map +1 -1
- package/dist/connect/create.js +4 -0
- package/dist/connect/create.js.map +1 -1
- package/dist/connect/create_common.d.ts +7 -0
- package/dist/connect/create_common.d.ts.map +1 -0
- package/dist/connect/create_common.js +19 -0
- package/dist/connect/create_common.js.map +1 -0
- package/dist/connect/external_types.d.ts +8 -0
- package/dist/connect/external_types.d.ts.map +1 -0
- package/dist/connect/external_types.js +31 -0
- package/dist/connect/external_types.js.map +1 -0
- package/dist/connect/figma_connect.d.ts +26 -0
- package/dist/connect/figma_connect.d.ts.map +1 -0
- package/dist/connect/figma_connect.js +3 -0
- package/dist/connect/figma_connect.js.map +1 -0
- package/dist/connect/figma_rest_api.d.ts +7 -0
- package/dist/connect/figma_rest_api.d.ts.map +1 -1
- package/dist/connect/figma_rest_api.js.map +1 -1
- package/dist/connect/index_common.d.ts +3 -0
- package/dist/connect/index_common.d.ts.map +1 -0
- package/dist/connect/index_common.js +23 -0
- package/dist/connect/index_common.js.map +1 -0
- package/dist/connect/intrinsics.d.ts +94 -0
- package/dist/connect/intrinsics.d.ts.map +1 -0
- package/dist/connect/intrinsics.js +401 -0
- package/dist/connect/intrinsics.js.map +1 -0
- package/dist/connect/parser_common.d.ts +144 -0
- package/dist/connect/parser_common.d.ts.map +1 -0
- package/dist/connect/parser_common.js +297 -0
- package/dist/connect/parser_common.js.map +1 -0
- package/dist/connect/parser_executable_types.d.ts +20 -23
- package/dist/connect/parser_executable_types.d.ts.map +1 -1
- package/dist/connect/parser_executable_types.js.map +1 -1
- package/dist/connect/parser_executables.js +1 -1
- package/dist/connect/parser_executables.js.map +1 -1
- package/dist/connect/project.d.ts +20 -5
- package/dist/connect/project.d.ts.map +1 -1
- package/dist/connect/project.js +79 -16
- package/dist/connect/project.js.map +1 -1
- package/dist/connect/upload.d.ts +1 -1
- package/dist/connect/upload.d.ts.map +1 -1
- package/dist/connect/validation.d.ts +1 -1
- package/dist/connect/validation.d.ts.map +1 -1
- package/dist/connect/wizard/helpers.d.ts +1 -0
- package/dist/connect/wizard/helpers.d.ts.map +1 -1
- package/dist/connect/wizard/helpers.js +27 -15
- package/dist/connect/wizard/helpers.js.map +1 -1
- package/dist/connect/wizard/prop_mapping.d.ts +12 -7
- package/dist/connect/wizard/prop_mapping.d.ts.map +1 -1
- package/dist/connect/wizard/prop_mapping.js +88 -89
- package/dist/connect/wizard/prop_mapping.js.map +1 -1
- package/dist/connect/wizard/run_wizard.d.ts.map +1 -1
- package/dist/connect/wizard/run_wizard.js +8 -3
- package/dist/connect/wizard/run_wizard.js.map +1 -1
- package/dist/connect/wizard/signature_extraction.d.ts +7 -0
- package/dist/connect/wizard/signature_extraction.d.ts.map +1 -0
- package/dist/connect/wizard/signature_extraction.js +46 -0
- package/dist/connect/wizard/signature_extraction.js.map +1 -0
- package/dist/html/__test__/parser/examples/NoConfigObject.figma.d.ts +2 -0
- package/dist/html/__test__/parser/examples/NoConfigObject.figma.d.ts.map +1 -0
- package/dist/html/__test__/parser/examples/NoConfigObject.figma.js +9 -0
- package/dist/html/__test__/parser/examples/NoConfigObject.figma.js.map +1 -0
- package/dist/html/__test__/parser/examples/NoExample.figma.d.ts +2 -0
- package/dist/html/__test__/parser/examples/NoExample.figma.d.ts.map +1 -0
- package/dist/html/__test__/parser/examples/NoExample.figma.js +9 -0
- package/dist/html/__test__/parser/examples/NoExample.figma.js.map +1 -0
- package/dist/html/__test__/parser/examples/RegularFunctionExampleWithExtraCode.figma.d.ts +2 -0
- package/dist/html/__test__/parser/examples/RegularFunctionExampleWithExtraCode.figma.d.ts.map +1 -0
- package/dist/html/__test__/parser/examples/RegularFunctionExampleWithExtraCode.figma.js +33 -0
- package/dist/html/__test__/parser/examples/RegularFunctionExampleWithExtraCode.figma.js.map +1 -0
- package/dist/html/__test__/parser/examples/WrongSignatureJsx.figma.d.ts +2 -0
- package/dist/html/__test__/parser/examples/WrongSignatureJsx.figma.d.ts.map +1 -0
- package/dist/html/__test__/parser/examples/WrongSignatureJsx.figma.js +15 -0
- package/dist/html/__test__/parser/examples/WrongSignatureJsx.figma.js.map +1 -0
- package/dist/html/__test__/parser/examples/WrongSignatureNoHtmlTag.figma.d.ts +2 -0
- package/dist/html/__test__/parser/examples/WrongSignatureNoHtmlTag.figma.d.ts.map +1 -0
- package/dist/html/__test__/parser/examples/WrongSignatureNoHtmlTag.figma.js +15 -0
- package/dist/html/__test__/parser/examples/WrongSignatureNoHtmlTag.figma.js.map +1 -0
- package/dist/html/__test__/parser/parser.test.d.ts +2 -0
- package/dist/html/__test__/parser/parser.test.d.ts.map +1 -0
- package/dist/html/__test__/parser/parser.test.js +50 -0
- package/dist/html/__test__/parser/parser.test.js.map +1 -0
- package/dist/html/create.d.ts +4 -0
- package/dist/html/create.d.ts.map +1 -0
- package/dist/html/create.js +81 -0
- package/dist/html/create.js.map +1 -0
- package/dist/html/external.d.ts +8 -0
- package/dist/html/external.d.ts.map +1 -0
- package/dist/html/external.js +25 -0
- package/dist/html/external.js.map +1 -0
- package/dist/html/index_html.d.ts +77 -0
- package/dist/html/index_html.d.ts.map +1 -0
- package/dist/html/index_html.js +42 -0
- package/dist/html/index_html.js.map +1 -0
- package/dist/html/parser.d.ts +19 -0
- package/dist/html/parser.d.ts.map +1 -0
- package/dist/html/parser.js +487 -0
- package/dist/html/parser.js.map +1 -0
- package/dist/html/parser_template_helpers.d.ts +2 -0
- package/dist/html/parser_template_helpers.d.ts.map +1 -0
- package/dist/html/parser_template_helpers.js +68 -0
- package/dist/html/parser_template_helpers.js.map +1 -0
- package/dist/html/template_literal.d.ts +5 -0
- package/dist/html/template_literal.d.ts.map +1 -0
- package/dist/html/template_literal.js +8 -0
- package/dist/html/template_literal.js.map +1 -0
- package/dist/parser_scripts/get_swift_parser_dir.d.ts +1 -1
- package/dist/parser_scripts/get_swift_parser_dir.d.ts.map +1 -1
- package/dist/parser_scripts/get_swift_parser_dir.js +38 -10
- package/dist/parser_scripts/get_swift_parser_dir.js.map +1 -1
- package/dist/react/create.d.ts +5 -0
- package/dist/react/create.d.ts.map +1 -1
- package/dist/react/create.js +144 -42
- package/dist/react/create.js.map +1 -1
- package/dist/react/external.d.ts +9 -0
- package/dist/react/external.d.ts.map +1 -0
- package/dist/react/external.js +45 -0
- package/dist/react/external.js.map +1 -0
- package/dist/react/index_react.d.ts +94 -0
- package/dist/react/index_react.d.ts.map +1 -0
- package/dist/react/index_react.js +39 -0
- package/dist/react/index_react.js.map +1 -0
- package/dist/react/parser.d.ts +6 -38
- package/dist/react/parser.d.ts.map +1 -1
- package/dist/react/parser.js +141 -298
- package/dist/react/parser.js.map +1 -1
- package/dist/react/parser_template_helpers.d.ts +15 -15
- package/dist/react/parser_template_helpers.d.ts.map +1 -1
- package/dist/react/parser_template_helpers.js +51 -35
- package/dist/react/parser_template_helpers.js.map +1 -1
- package/dist/storybook/convert.d.ts +1 -1
- package/dist/storybook/convert.d.ts.map +1 -1
- package/dist/storybook/convert.js +6 -4
- package/dist/storybook/convert.js.map +1 -1
- package/dist/storybook/external.d.ts +1 -1
- package/dist/storybook/external.d.ts.map +1 -1
- package/dist/typescript/compiler.d.ts +2 -2
- package/dist/typescript/compiler.d.ts.map +1 -1
- package/dist/typescript/compiler.js +51 -24
- package/dist/typescript/compiler.js.map +1 -1
- package/package.json +28 -8
package/dist/react/parser.js
CHANGED
|
@@ -3,42 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.parseReactDoc = exports.getDefaultTemplate = exports.parseRenderFunction = exports.parseComponentMetadata = exports.extractComponentTypeSignature = exports.findAndResolveImports = void 0;
|
|
7
7
|
const typescript_1 = __importDefault(require("typescript"));
|
|
8
8
|
const project_1 = require("../connect/project");
|
|
9
9
|
const logging_1 = require("../common/logging");
|
|
10
10
|
const compiler_1 = require("../typescript/compiler");
|
|
11
|
-
const intrinsics_1 = require("../
|
|
11
|
+
const intrinsics_1 = require("../connect/intrinsics");
|
|
12
12
|
const parser_template_helpers_1 = require("./parser_template_helpers");
|
|
13
|
-
|
|
14
|
-
constructor(message, context) {
|
|
15
|
-
super(message);
|
|
16
|
-
this.name = 'ParserError';
|
|
17
|
-
this.sourceFileName = context?.sourceFile.fileName || '';
|
|
18
|
-
this.sourceFilePosition =
|
|
19
|
-
context && context.node
|
|
20
|
-
? getPositionInSourceFile(context.node, context.sourceFile) || null
|
|
21
|
-
: null;
|
|
22
|
-
}
|
|
23
|
-
toString() {
|
|
24
|
-
let msg = `${(0, logging_1.highlight)((0, logging_1.error)(this.name))}: ${this.message}\n`;
|
|
25
|
-
if (this.sourceFileName && this.sourceFilePosition) {
|
|
26
|
-
msg += ` -> ${(0, logging_1.reset)(this.sourceFileName)}:${this.sourceFilePosition.line}:${this.sourceFilePosition.character}\n`;
|
|
27
|
-
}
|
|
28
|
-
return msg;
|
|
29
|
-
}
|
|
30
|
-
toDebugString() {
|
|
31
|
-
return this.toString() + `\n ${this.stack}`;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
exports.ParserError = ParserError;
|
|
35
|
-
class InternalError extends ParserError {
|
|
36
|
-
constructor(message) {
|
|
37
|
-
super(message);
|
|
38
|
-
this.name = 'InternalError';
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
exports.InternalError = InternalError;
|
|
13
|
+
const parser_common_1 = require("../connect/parser_common");
|
|
42
14
|
/**
|
|
43
15
|
* Traverses the AST and returns the first JSX element it finds
|
|
44
16
|
* @param node AST node
|
|
@@ -60,20 +32,6 @@ function findBlock(node) {
|
|
|
60
32
|
return typescript_1.default.forEachChild(node, findBlock);
|
|
61
33
|
}
|
|
62
34
|
}
|
|
63
|
-
function findDescendants(node, cb) {
|
|
64
|
-
const matches = [];
|
|
65
|
-
function visit(node) {
|
|
66
|
-
if (cb(node)) {
|
|
67
|
-
matches.push(node);
|
|
68
|
-
}
|
|
69
|
-
typescript_1.default.forEachChild(node, visit);
|
|
70
|
-
}
|
|
71
|
-
visit(node);
|
|
72
|
-
return matches;
|
|
73
|
-
}
|
|
74
|
-
function getPositionInSourceFile(node, sourceFile) {
|
|
75
|
-
return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
|
|
76
|
-
}
|
|
77
35
|
/**
|
|
78
36
|
* Walks up the AST from an assignment to find the import declaration
|
|
79
37
|
*/
|
|
@@ -97,6 +55,33 @@ function getImportsOfModule(sourceFile) {
|
|
|
97
55
|
visit(sourceFile);
|
|
98
56
|
return imports;
|
|
99
57
|
}
|
|
58
|
+
function resolveModuleSpecifier(program, sourceFile, importSpecifier) {
|
|
59
|
+
const compilerHost = typescript_1.default.createCompilerHost(program.getCompilerOptions());
|
|
60
|
+
const moduleResolutionHost = {
|
|
61
|
+
fileExists: compilerHost.fileExists,
|
|
62
|
+
readFile: compilerHost.readFile,
|
|
63
|
+
directoryExists: compilerHost.directoryExists,
|
|
64
|
+
getCurrentDirectory: compilerHost.getCurrentDirectory,
|
|
65
|
+
getDirectories: compilerHost.getDirectories,
|
|
66
|
+
};
|
|
67
|
+
const resolvedModule = typescript_1.default.resolveModuleName(importSpecifier, sourceFile.fileName, program.getCompilerOptions(), moduleResolutionHost);
|
|
68
|
+
return resolvedModule.resolvedModule?.resolvedFileName;
|
|
69
|
+
}
|
|
70
|
+
// Traverse the source file and resolve imports
|
|
71
|
+
function findAndResolveImports(program, sourceFile) {
|
|
72
|
+
const importSpecifierToFilePath = {};
|
|
73
|
+
typescript_1.default.forEachChild(sourceFile, (node) => {
|
|
74
|
+
if (typescript_1.default.isImportDeclaration(node)) {
|
|
75
|
+
const importSpecifier = node.moduleSpecifier.text;
|
|
76
|
+
const resolvedFileName = resolveModuleSpecifier(program, sourceFile, importSpecifier);
|
|
77
|
+
if (resolvedFileName) {
|
|
78
|
+
importSpecifierToFilePath[importSpecifier] = resolvedFileName;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
return importSpecifierToFilePath;
|
|
83
|
+
}
|
|
84
|
+
exports.findAndResolveImports = findAndResolveImports;
|
|
100
85
|
/**
|
|
101
86
|
* Finds all import statements in a file that matches the given identifiers
|
|
102
87
|
*
|
|
@@ -104,13 +89,15 @@ function getImportsOfModule(sourceFile) {
|
|
|
104
89
|
* @param identifiers List of identifiers to find imports for
|
|
105
90
|
* @returns
|
|
106
91
|
*/
|
|
107
|
-
function
|
|
92
|
+
function getSourceFilesOfImportedIdentifiers(parserContext, _identifiers) {
|
|
93
|
+
const { sourceFile, resolvedImports } = parserContext;
|
|
108
94
|
const importDeclarations = getImportsOfModule(sourceFile);
|
|
109
95
|
const imports = [];
|
|
110
96
|
const identifiers = _identifiers.map((identifier) => identifier.split('.')[0]);
|
|
111
97
|
for (const declaration of importDeclarations) {
|
|
112
98
|
let statement = declaration.getText();
|
|
113
|
-
|
|
99
|
+
// remove the quotation marks around the module specifier
|
|
100
|
+
const moduleSpecifier = declaration.moduleSpecifier.getText().slice(1, -1);
|
|
114
101
|
if (declaration.importClause) {
|
|
115
102
|
// Default imports
|
|
116
103
|
if (declaration.importClause.name) {
|
|
@@ -118,7 +105,7 @@ function getImportsForIdentifiers({ sourceFile }, _identifiers) {
|
|
|
118
105
|
if (identifiers.includes(identifier)) {
|
|
119
106
|
imports.push({
|
|
120
107
|
statement,
|
|
121
|
-
file:
|
|
108
|
+
file: resolvedImports[moduleSpecifier],
|
|
122
109
|
});
|
|
123
110
|
}
|
|
124
111
|
}
|
|
@@ -133,7 +120,7 @@ function getImportsForIdentifiers({ sourceFile }, _identifiers) {
|
|
|
133
120
|
if (elements.length > 0) {
|
|
134
121
|
imports.push({
|
|
135
122
|
statement: statement.replace(/{.*}/s, `{ ${elements.join(', ')} }`),
|
|
136
|
-
file:
|
|
123
|
+
file: resolvedImports[moduleSpecifier],
|
|
137
124
|
});
|
|
138
125
|
}
|
|
139
126
|
}
|
|
@@ -143,7 +130,7 @@ function getImportsForIdentifiers({ sourceFile }, _identifiers) {
|
|
|
143
130
|
if (identifiers.includes(identifier)) {
|
|
144
131
|
imports.push({
|
|
145
132
|
statement,
|
|
146
|
-
file:
|
|
133
|
+
file: resolvedImports[moduleSpecifier],
|
|
147
134
|
});
|
|
148
135
|
}
|
|
149
136
|
}
|
|
@@ -193,6 +180,25 @@ function getDeclarationFromSymbol(symbol) {
|
|
|
193
180
|
}
|
|
194
181
|
return symbol.declarations[0];
|
|
195
182
|
}
|
|
183
|
+
function resolveIdentifierSymbol(identifier, checker) {
|
|
184
|
+
const componentSymbol = checker.getSymbolAtLocation(identifier);
|
|
185
|
+
if (!componentSymbol) {
|
|
186
|
+
throw new Error(`Symbol not found at location ${identifier.getText()}`);
|
|
187
|
+
}
|
|
188
|
+
const componentDeclaration = getDeclarationFromSymbol(componentSymbol);
|
|
189
|
+
if (typescript_1.default.isImportSpecifier(componentDeclaration) || typescript_1.default.isImportClause(componentDeclaration)) {
|
|
190
|
+
let importDeclaration = findParentImportDeclaration(componentDeclaration);
|
|
191
|
+
if (!importDeclaration) {
|
|
192
|
+
throw new Error('No import statement found for component');
|
|
193
|
+
}
|
|
194
|
+
// The component should be imported from another file, we need to follow the
|
|
195
|
+
// aliased symbol to get the correct function definition
|
|
196
|
+
if (componentSymbol.flags & typescript_1.default.SymbolFlags.Alias) {
|
|
197
|
+
return checker.getAliasedSymbol(componentSymbol);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return componentSymbol;
|
|
201
|
+
}
|
|
196
202
|
/**
|
|
197
203
|
* This handles a number of cases for finding the function expression of an exported symbol:
|
|
198
204
|
* - A function that is exported directly (function declaration)
|
|
@@ -219,17 +225,24 @@ function findFunctionExpression(declaration, checker, sourceFile) {
|
|
|
219
225
|
// Example: export const MemoButton = memo(Button)
|
|
220
226
|
// Example: export const ButtonWithRef = forwardRef(Button)
|
|
221
227
|
if (typescript_1.default.isVariableDeclaration(declaration)) {
|
|
222
|
-
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
228
|
+
let componentSymbol = undefined;
|
|
229
|
+
// Example: export const SomeAlias = Button
|
|
230
|
+
if (declaration.initializer && typescript_1.default.isIdentifier(declaration.initializer)) {
|
|
231
|
+
componentSymbol = resolveIdentifierSymbol(declaration.initializer, checker);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
const callExpression = findCallExpression(declaration);
|
|
235
|
+
const component = callExpression.arguments[0];
|
|
236
|
+
// follow the symbol to its declaration, then try to find the function expression again
|
|
237
|
+
componentSymbol = checker.getSymbolAtLocation(component);
|
|
238
|
+
}
|
|
226
239
|
if (!componentSymbol) {
|
|
227
240
|
throw new Error('No symbol found at location');
|
|
228
241
|
}
|
|
229
242
|
const componentDeclaration = getDeclarationFromSymbol(componentSymbol);
|
|
230
243
|
return findFunctionExpression(componentDeclaration, checker, sourceFile);
|
|
231
244
|
}
|
|
232
|
-
throw new ParserError('Failed to find function expression for component', {
|
|
245
|
+
throw new parser_common_1.ParserError('Failed to find function expression for component', {
|
|
233
246
|
sourceFile,
|
|
234
247
|
node: declaration,
|
|
235
248
|
});
|
|
@@ -250,10 +263,25 @@ function findFunctionExpression(declaration, checker, sourceFile) {
|
|
|
250
263
|
function extractComponentTypeSignature(symbol, checker, sourceFile) {
|
|
251
264
|
const declaration = getDeclarationFromSymbol(symbol);
|
|
252
265
|
const ReactInterfaceNames = ['HTMLAttributes', 'Attributes', 'AriaAttributes', 'DOMAttributes'];
|
|
253
|
-
|
|
254
|
-
|
|
266
|
+
let propsType = null;
|
|
267
|
+
/**
|
|
268
|
+
* Special case for forwardRef as type is passed as generic arg
|
|
269
|
+
*/
|
|
270
|
+
if (typescript_1.default.isVariableDeclaration(declaration)) {
|
|
271
|
+
const callExpression = findCallExpression(declaration);
|
|
272
|
+
if ((callExpression?.expression.getText() === 'forwardRef' ||
|
|
273
|
+
callExpression?.expression.getText() === 'React.forwardRef') &&
|
|
274
|
+
callExpression.typeArguments &&
|
|
275
|
+
callExpression.typeArguments.length === 2) {
|
|
276
|
+
propsType = checker.getTypeAtLocation(callExpression.typeArguments[1]);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (!propsType) {
|
|
280
|
+
const functionExpression = findFunctionExpression(declaration, checker, sourceFile);
|
|
281
|
+
propsType = checker.getTypeAtLocation(functionExpression.parameters[0]);
|
|
282
|
+
}
|
|
255
283
|
if (!propsType) {
|
|
256
|
-
throw new InternalError(`Failed to extract props from component declaration: ${declaration.getText()}`);
|
|
284
|
+
throw new parser_common_1.InternalError(`Failed to extract props from component declaration: ${declaration.getText()}`);
|
|
257
285
|
}
|
|
258
286
|
const propsMap = {};
|
|
259
287
|
const props = propsType.getProperties();
|
|
@@ -297,7 +325,8 @@ exports.extractComponentTypeSignature = extractComponentTypeSignature;
|
|
|
297
325
|
* @param node The node being parsed. Used for error logging.
|
|
298
326
|
* @returns Metadata object
|
|
299
327
|
*/
|
|
300
|
-
async function parseComponentMetadata(node,
|
|
328
|
+
async function parseComponentMetadata(node, parserContext, silent) {
|
|
329
|
+
const { checker, sourceFile } = parserContext;
|
|
301
330
|
let componentSymbol = checker.getSymbolAtLocation(node);
|
|
302
331
|
let componentSourceFile = sourceFile;
|
|
303
332
|
let component = '';
|
|
@@ -306,7 +335,7 @@ async function parseComponentMetadata(node, { checker, sourceFile, absPath }, si
|
|
|
306
335
|
if (typescript_1.default.isPropertyAccessExpression(node)) {
|
|
307
336
|
componentSymbol = checker.getSymbolAtLocation(node.expression);
|
|
308
337
|
if (!componentSymbol) {
|
|
309
|
-
throw new ParserError(`Could not find symbol for component ${node.expression.getText()}`, {
|
|
338
|
+
throw new parser_common_1.ParserError(`Could not find symbol for component ${node.expression.getText()}`, {
|
|
310
339
|
sourceFile,
|
|
311
340
|
node,
|
|
312
341
|
});
|
|
@@ -319,7 +348,7 @@ async function parseComponentMetadata(node, { checker, sourceFile, absPath }, si
|
|
|
319
348
|
typescript_1.default.isImportClause(componentSymbol.declarations[0]))) {
|
|
320
349
|
let importDeclaration = findParentImportDeclaration(componentSymbol.declarations[0]);
|
|
321
350
|
if (!importDeclaration) {
|
|
322
|
-
throw new ParserError('No import statement found for component, make sure the component is imported', {
|
|
351
|
+
throw new parser_common_1.ParserError('No import statement found for component, make sure the component is imported', {
|
|
323
352
|
sourceFile,
|
|
324
353
|
node,
|
|
325
354
|
});
|
|
@@ -363,17 +392,17 @@ async function parseComponentMetadata(node, { checker, sourceFile, absPath }, si
|
|
|
363
392
|
}
|
|
364
393
|
const source = componentSourceFile.fileName;
|
|
365
394
|
if (!source) {
|
|
366
|
-
throw new InternalError(`Could not find source file for component ${component} - is this file included in the directory passed to \`figma connect <dir>\`?`);
|
|
395
|
+
throw new parser_common_1.InternalError(`Could not find source file for component ${component} - is this file included in the directory passed to \`figma connect <dir>\`?`);
|
|
367
396
|
}
|
|
368
397
|
if (!componentDeclaration) {
|
|
369
|
-
throw new ParserError(`Could not find declaration for component ${component}`, {
|
|
398
|
+
throw new parser_common_1.ParserError(`Could not find declaration for component ${component}`, {
|
|
370
399
|
sourceFile,
|
|
371
400
|
node,
|
|
372
401
|
});
|
|
373
402
|
}
|
|
374
|
-
const line = getPositionInSourceFile(componentDeclaration, componentSourceFile).line;
|
|
403
|
+
const line = (0, parser_common_1.getPositionInSourceFile)(componentDeclaration, componentSourceFile).line;
|
|
375
404
|
if (line === undefined) {
|
|
376
|
-
throw new InternalError(`Could not determine line number for component ${componentDeclaration.getStart(sourceFile)}`);
|
|
405
|
+
throw new parser_common_1.InternalError(`Could not determine line number for component ${componentDeclaration.getStart(sourceFile)}`);
|
|
377
406
|
}
|
|
378
407
|
return {
|
|
379
408
|
source,
|
|
@@ -382,104 +411,6 @@ async function parseComponentMetadata(node, { checker, sourceFile, absPath }, si
|
|
|
382
411
|
};
|
|
383
412
|
}
|
|
384
413
|
exports.parseComponentMetadata = parseComponentMetadata;
|
|
385
|
-
/**
|
|
386
|
-
* Checks if an AST node is a `figma.connect()` call
|
|
387
|
-
*
|
|
388
|
-
* @param node AST node
|
|
389
|
-
* @param sourceFile Source file
|
|
390
|
-
* @returns True if the node is a `figma.connect()` call
|
|
391
|
-
*/
|
|
392
|
-
function isFigmaConnectCall(node, sourceFile) {
|
|
393
|
-
return (typescript_1.default.isCallExpression(node) && node.expression.getText(sourceFile).includes(intrinsics_1.FIGMA_CONNECT_CALL));
|
|
394
|
-
}
|
|
395
|
-
/**
|
|
396
|
-
* Checks if a file contains Code Connect by looking for the `figma.connect()` function call
|
|
397
|
-
*
|
|
398
|
-
* @param program
|
|
399
|
-
* @param file
|
|
400
|
-
* @returns
|
|
401
|
-
*/
|
|
402
|
-
function isFigmaConnectFile(program, file) {
|
|
403
|
-
// We don't support Code Connect in JSX and this throws an error if we let it proceed
|
|
404
|
-
if (!file.endsWith('.tsx')) {
|
|
405
|
-
return false;
|
|
406
|
-
}
|
|
407
|
-
const sourceFile = program.getSourceFile(file);
|
|
408
|
-
if (!sourceFile) {
|
|
409
|
-
throw new InternalError(`Could not find source file for ${file}`);
|
|
410
|
-
}
|
|
411
|
-
return (findDescendants(sourceFile, (node) => {
|
|
412
|
-
if (isFigmaConnectCall(node, sourceFile)) {
|
|
413
|
-
return true;
|
|
414
|
-
}
|
|
415
|
-
return false;
|
|
416
|
-
}).length > 0);
|
|
417
|
-
}
|
|
418
|
-
exports.isFigmaConnectFile = isFigmaConnectFile;
|
|
419
|
-
/**
|
|
420
|
-
* Parses the `links` field of a `figma.connect()` call
|
|
421
|
-
*
|
|
422
|
-
* @param linksArray an ArrayLiteralExpression
|
|
423
|
-
* @param parserContext Parser context
|
|
424
|
-
* @returns An array of link objects
|
|
425
|
-
*/
|
|
426
|
-
function parseLinks(linksArray, parserContext) {
|
|
427
|
-
const { sourceFile } = parserContext;
|
|
428
|
-
const links = [];
|
|
429
|
-
for (const element of linksArray.elements) {
|
|
430
|
-
(0, compiler_1.assertIsObjectLiteralExpression)(element, sourceFile, `'links' must be an array literal with objects of the format { name: string, url: string }`);
|
|
431
|
-
const name = (0, compiler_1.parsePropertyOfType)({
|
|
432
|
-
objectLiteralNode: element,
|
|
433
|
-
propertyName: 'name',
|
|
434
|
-
predicate: typescript_1.default.isStringLiteral,
|
|
435
|
-
parserContext,
|
|
436
|
-
required: true,
|
|
437
|
-
errorMessage: "The 'name' property must be a string literal",
|
|
438
|
-
});
|
|
439
|
-
const url = (0, compiler_1.parsePropertyOfType)({
|
|
440
|
-
objectLiteralNode: element,
|
|
441
|
-
propertyName: 'url',
|
|
442
|
-
predicate: typescript_1.default.isStringLiteral,
|
|
443
|
-
parserContext,
|
|
444
|
-
required: true,
|
|
445
|
-
errorMessage: "The 'url' property must be a string literal",
|
|
446
|
-
});
|
|
447
|
-
if (name && url) {
|
|
448
|
-
links.push({ name: (0, compiler_1.stripQuotes)(name), url: (0, compiler_1.stripQuotes)(url) });
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
return links;
|
|
452
|
-
}
|
|
453
|
-
function parseVariant(variantMap, sourceFile, checker) {
|
|
454
|
-
return (0, compiler_1.convertObjectLiteralToJs)(variantMap, sourceFile, checker, (valueNode) => {
|
|
455
|
-
if (!typescript_1.default.isObjectLiteralElement(valueNode) &&
|
|
456
|
-
!typescript_1.default.isStringLiteral(valueNode) &&
|
|
457
|
-
!typescript_1.default.isNumericLiteral(valueNode) &&
|
|
458
|
-
valueNode.kind !== typescript_1.default.SyntaxKind.TrueKeyword &&
|
|
459
|
-
valueNode.kind !== typescript_1.default.SyntaxKind.FalseKeyword) {
|
|
460
|
-
throw new ParserError(`Invalid value for variant, got: ${valueNode.getText()}`, {
|
|
461
|
-
node: valueNode,
|
|
462
|
-
sourceFile,
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
});
|
|
466
|
-
}
|
|
467
|
-
/**
|
|
468
|
-
* Parses the `imports` field of a `figma.connect()` call
|
|
469
|
-
*
|
|
470
|
-
* @param importsArray an ArrayLiteralExpression
|
|
471
|
-
* @param parserContext Parser context
|
|
472
|
-
* @returns An array of link objects
|
|
473
|
-
*/
|
|
474
|
-
function parseImports(importsArray, parserContext) {
|
|
475
|
-
const { sourceFile } = parserContext;
|
|
476
|
-
const imports = [];
|
|
477
|
-
for (const element of importsArray.elements) {
|
|
478
|
-
(0, compiler_1.assertIsStringLiteral)(element, sourceFile, `'imports' must be an array literal with strings`);
|
|
479
|
-
imports.push((0, compiler_1.stripQuotes)(element));
|
|
480
|
-
}
|
|
481
|
-
return imports;
|
|
482
|
-
}
|
|
483
414
|
/**
|
|
484
415
|
* Parses the render function passed to `figma.connect()`, extracting the code and
|
|
485
416
|
* any import statements matching the JSX elements used in the function body
|
|
@@ -494,42 +425,23 @@ function parseRenderFunction(exp, parserContext, propMappings) {
|
|
|
494
425
|
const { sourceFile } = parserContext;
|
|
495
426
|
let exampleCode;
|
|
496
427
|
if (exp.parameters.length > 1) {
|
|
497
|
-
throw new ParserError(`Expected a single props parameter for the render function, got ${exp.parameters.length} parameters`, { sourceFile, node: exp });
|
|
428
|
+
throw new parser_common_1.ParserError(`Expected a single props parameter for the render function, got ${exp.parameters.length} parameters`, { sourceFile, node: exp });
|
|
498
429
|
}
|
|
499
430
|
const propsParameter = exp.parameters[0];
|
|
500
431
|
// Keep track of any props which are referenced in the example so that we can
|
|
501
432
|
// insert the appropriate `figma.properties` call in the JS template
|
|
502
433
|
const referencedProps = new Set();
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
if (name.includes('.')) {
|
|
509
|
-
propReferenceName = name.split('.')[0];
|
|
510
|
-
}
|
|
511
|
-
const mappedProp = propMappings && propMappings[propReferenceName];
|
|
512
|
-
if (!mappedProp) {
|
|
513
|
-
throw new ParserError(`Could not find prop mapping for ${propReferenceName} in the props object`, {
|
|
514
|
-
sourceFile,
|
|
515
|
-
node,
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
|
-
referencedProps.add(propReferenceName);
|
|
519
|
-
const callExpression = typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier('__PROP__'), undefined, [typescript_1.default.factory.createStringLiteral(name)]);
|
|
520
|
-
if (wrapInJsxExpression) {
|
|
521
|
-
return typescript_1.default.factory.createJsxExpression(undefined, callExpression);
|
|
522
|
-
}
|
|
523
|
-
else {
|
|
524
|
-
return callExpression;
|
|
525
|
-
}
|
|
526
|
-
}
|
|
434
|
+
const createPropPlaceholder = (0, parser_common_1.makeCreatePropPlaceholder)({
|
|
435
|
+
propMappings,
|
|
436
|
+
referencedProps,
|
|
437
|
+
sourceFile,
|
|
438
|
+
});
|
|
527
439
|
// Find all property access expressions in the function body and replace them
|
|
528
440
|
// with a function call like `__PROP__("propName")`, so that we can easily
|
|
529
441
|
// find them in the next step to convert them into
|
|
530
442
|
// `${_fcc_renderReactProp(...)` in the template string.
|
|
531
443
|
//
|
|
532
|
-
// Doing it this way means we can
|
|
444
|
+
// Doing it this way means we can normalize the different ways in which props
|
|
533
445
|
// can be accessed using the compiler API, which is much easier than using a
|
|
534
446
|
// regex, then in the next step we can use a simple regex to convert that into
|
|
535
447
|
// the template string.
|
|
@@ -537,33 +449,14 @@ function parseRenderFunction(exp, parserContext, propMappings) {
|
|
|
537
449
|
exp = typescript_1.default.transform(exp, [
|
|
538
450
|
(context) => (rootNode) => {
|
|
539
451
|
function visit(node) {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
}
|
|
549
|
-
const name = node.name.getText();
|
|
550
|
-
return createPropPlaceholder({ name, node });
|
|
551
|
-
}
|
|
552
|
-
// `props[""]` notation
|
|
553
|
-
if (typescript_1.default.isIdentifier(propsParameter.name) &&
|
|
554
|
-
typescript_1.default.isElementAccessExpression(node) &&
|
|
555
|
-
node.expression.getText().startsWith(propsParameter.name.getText()) &&
|
|
556
|
-
typescript_1.default.isStringLiteral(node.argumentExpression)) {
|
|
557
|
-
const name = (0, compiler_1.stripQuotes)(node.argumentExpression);
|
|
558
|
-
return createPropPlaceholder({ name, node });
|
|
559
|
-
}
|
|
560
|
-
// object destructuring references
|
|
561
|
-
if (typescript_1.default.isObjectBindingPattern(propsParameter.name) &&
|
|
562
|
-
typescript_1.default.isJsxExpression(node) &&
|
|
563
|
-
node.expression &&
|
|
564
|
-
propsParameter.name.elements.find((el) => node.expression?.getText().startsWith(el.name.getText()))) {
|
|
565
|
-
const name = node.expression.getText();
|
|
566
|
-
return createPropPlaceholder({ name, node, wrapInJsxExpression: true });
|
|
452
|
+
const visitResult = (0, parser_common_1.visitPropReferencingNode)({
|
|
453
|
+
propsParameter,
|
|
454
|
+
node,
|
|
455
|
+
createPropPlaceholder,
|
|
456
|
+
useJsx: true,
|
|
457
|
+
});
|
|
458
|
+
if (visitResult) {
|
|
459
|
+
return visitResult;
|
|
567
460
|
}
|
|
568
461
|
// object assignment using destructured reference, e.g `prop={{ key: value }}`
|
|
569
462
|
// (`{{ key: props.value }}` syntax will be captured by the `props.` notation branch above)
|
|
@@ -641,7 +534,7 @@ function parseRenderFunction(exp, parserContext, propMappings) {
|
|
|
641
534
|
exampleCode = printer.printNode(typescript_1.default.EmitHint.Unspecified, functionExpression, sourceFile);
|
|
642
535
|
}
|
|
643
536
|
else {
|
|
644
|
-
throw new ParserError(`Expected a single JSX element or a block statement in the render function, got ${exp.getText()}`, { sourceFile, node: exp });
|
|
537
|
+
throw new parser_common_1.ParserError(`Expected a single JSX element or a block statement in the render function, got ${exp.getText()}`, { sourceFile, node: exp });
|
|
645
538
|
}
|
|
646
539
|
let templateCode = '';
|
|
647
540
|
// Replace React prop placeholders we inserted above (like
|
|
@@ -660,9 +553,10 @@ function parseRenderFunction(exp, parserContext, propMappings) {
|
|
|
660
553
|
exampleCode = exampleCode.replace(/\{__PROP__\("([A-Za-z_\.]+)"\)\}/g, (_match, figmaPropName) => {
|
|
661
554
|
return `\${_fcc_renderReactChildren(${figmaPropName})}`;
|
|
662
555
|
});
|
|
663
|
-
// Replace object values like `{ prop: __PROP__("propName") }`
|
|
664
|
-
// `{ prop: ${propName} }`. These
|
|
665
|
-
|
|
556
|
+
// Replace object values like `{ prop: __PROP__("propName") }` or `{
|
|
557
|
+
// 'aria-prop': __PROP__("propName") }` with `{ prop: ${propName} }`. These
|
|
558
|
+
// never need special treatment based on their type.
|
|
559
|
+
exampleCode = exampleCode.replace(/([^\s]+):\s+__PROP__\("([A-Za-z_\.]+)"\)/g, (_match, objectKey, figmaPropName) => {
|
|
666
560
|
return `${objectKey}: \${_fcc_renderPropValue(${figmaPropName})}`;
|
|
667
561
|
});
|
|
668
562
|
// Generate the template code
|
|
@@ -670,41 +564,22 @@ function parseRenderFunction(exp, parserContext, propMappings) {
|
|
|
670
564
|
templateCode = (0, parser_template_helpers_1.getParsedTemplateHelpersString)() + '\n\n';
|
|
671
565
|
// Require the template API
|
|
672
566
|
templateCode += `const figma = require('figma')\n\n`;
|
|
673
|
-
let nestedLayerCount = 0;
|
|
674
567
|
// Then we output `const propName = figma.properties.<kind>('propName')` calls
|
|
675
568
|
// for each referenced prop, so these are accessible to the template code.
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
}
|
|
685
|
-
if (propMapping.kind === intrinsics_1.IntrinsicKind.NestedProps) {
|
|
686
|
-
// the actual layer name in figma could have a bunch of special characters in it,
|
|
687
|
-
// and if we try to normalize it to a valid JS identifier, it could conflict with
|
|
688
|
-
// other variables in the template code. So we generate a unique variable name
|
|
689
|
-
// for each nested layer reference instead.
|
|
690
|
-
const nestedLayerRef = `nestedLayer${nestedLayerCount++}`;
|
|
691
|
-
templateCode += `const ${nestedLayerRef} = figma.currentLayer.__find__("${propMapping.args.layer}")\n`;
|
|
692
|
-
templateCode += `const ${prop} = {
|
|
693
|
-
${Object.entries(propMapping.args.props).map(([key, intrinsic]) => `${key}: ${(0, intrinsics_1.intrinsicToString)(intrinsic, nestedLayerRef)}\n`)}
|
|
694
|
-
}\n`;
|
|
695
|
-
}
|
|
696
|
-
else {
|
|
697
|
-
templateCode += `const ${prop} = ${(0, intrinsics_1.intrinsicToString)(propMapping)}\n`;
|
|
698
|
-
}
|
|
699
|
-
});
|
|
700
|
-
templateCode += '\n';
|
|
701
|
-
}
|
|
569
|
+
templateCode += (0, parser_common_1.getReferencedPropsForTemplate)({
|
|
570
|
+
propMappings,
|
|
571
|
+
referencedProps,
|
|
572
|
+
exp,
|
|
573
|
+
sourceFile,
|
|
574
|
+
});
|
|
575
|
+
// Escape backticks from the example code, as otherwise those would terminate the `figma.tsx` template literal
|
|
576
|
+
exampleCode = exampleCode.replace(/`/g, '\\`');
|
|
702
577
|
// Finally, output the example code
|
|
703
578
|
templateCode += `export default figma.tsx\`${exampleCode}\`\n`;
|
|
704
579
|
// Find all JSX elements in the function body and extract their import
|
|
705
580
|
// statements
|
|
706
|
-
const jsxTags = findDescendants(exp, (element) => typescript_1.default.isJsxElement(element) || typescript_1.default.isJsxSelfClosingElement(element))
|
|
707
|
-
const imports =
|
|
581
|
+
const jsxTags = (0, parser_common_1.findDescendants)(exp, (element) => typescript_1.default.isJsxElement(element) || typescript_1.default.isJsxSelfClosingElement(element));
|
|
582
|
+
const imports = getSourceFilesOfImportedIdentifiers(parserContext, jsxTags.map(compiler_1.getTagName));
|
|
708
583
|
return {
|
|
709
584
|
code: templateCode,
|
|
710
585
|
imports,
|
|
@@ -730,7 +605,7 @@ function followIdentifierToStringLiteralDeclaration(node, parserContext, errMess
|
|
|
730
605
|
// If we followed the identifier to its declaration and it's not a string literal,
|
|
731
606
|
// throw an error
|
|
732
607
|
if (!result || !typescript_1.default.isStringLiteral(result)) {
|
|
733
|
-
throw new ParserError(errMessage, {
|
|
608
|
+
throw new parser_common_1.ParserError(errMessage, {
|
|
734
609
|
node: result,
|
|
735
610
|
sourceFile: parserContext.sourceFile,
|
|
736
611
|
});
|
|
@@ -854,17 +729,16 @@ function getDefaultTemplate(componentMetadata) {
|
|
|
854
729
|
return `const figma = require("figma")\n\nexport default figma.tsx\`${example}\``;
|
|
855
730
|
}
|
|
856
731
|
exports.getDefaultTemplate = getDefaultTemplate;
|
|
857
|
-
async function
|
|
732
|
+
async function parseReactDoc(node, parserContext, { repoUrl, silent }) {
|
|
858
733
|
const { checker, sourceFile, config } = parserContext;
|
|
859
734
|
// Parse the arguments to the `Figma.connect()` call
|
|
860
735
|
const { componentArg, figmaNodeUrlArg, configObjArg } = parseFigmaConnectArgs(node, parserContext);
|
|
861
|
-
// The ones with ! are definitely defined because their parser fn has required: true,
|
|
862
|
-
// but I couldn't work out how to model that in TypeScript
|
|
863
736
|
const { propsArg, exampleArg, variantArg, linksArg, importsArg } = parseConfigObjectArg(configObjArg, parserContext);
|
|
864
|
-
let figmaNode = (0, compiler_1.
|
|
737
|
+
let figmaNode = (0, compiler_1.stripQuotesFromNode)(figmaNodeUrlArg);
|
|
865
738
|
// TODO This logic is duplicated in connect.ts transformDocFromParser due to some type issues
|
|
866
739
|
if (config.documentUrlSubstitutions) {
|
|
867
740
|
Object.entries(config.documentUrlSubstitutions).forEach(([from, to]) => {
|
|
741
|
+
// @ts-expect-error
|
|
868
742
|
figmaNode = figmaNode.replace(from, to);
|
|
869
743
|
});
|
|
870
744
|
}
|
|
@@ -873,11 +747,11 @@ async function parseDoc(node, parserContext, { repoUrl, silent }) {
|
|
|
873
747
|
: undefined;
|
|
874
748
|
const props = propsArg ? (0, intrinsics_1.parsePropsObject)(propsArg, parserContext) : undefined;
|
|
875
749
|
const render = exampleArg ? parseRenderFunction(exampleArg, parserContext, props) : undefined;
|
|
876
|
-
const variant = variantArg ? parseVariant(variantArg, sourceFile, checker) : undefined;
|
|
877
|
-
const links = linksArg ? parseLinks(linksArg, parserContext) : undefined;
|
|
878
|
-
let
|
|
750
|
+
const variant = variantArg ? (0, parser_common_1.parseVariant)(variantArg, sourceFile, checker) : undefined;
|
|
751
|
+
const links = linksArg ? (0, parser_common_1.parseLinks)(linksArg, parserContext) : undefined;
|
|
752
|
+
let mappedImports;
|
|
879
753
|
if (importsArg) {
|
|
880
|
-
|
|
754
|
+
mappedImports = (0, parser_common_1.parseImports)(importsArg, parserContext);
|
|
881
755
|
}
|
|
882
756
|
else {
|
|
883
757
|
// If no template function was provided, construct one and add the import
|
|
@@ -885,7 +759,7 @@ async function parseDoc(node, parserContext, { repoUrl, silent }) {
|
|
|
885
759
|
let imports = render?.imports
|
|
886
760
|
? render.imports
|
|
887
761
|
: metadata !== undefined
|
|
888
|
-
?
|
|
762
|
+
? getSourceFilesOfImportedIdentifiers(parserContext, [metadata.component])
|
|
889
763
|
: [];
|
|
890
764
|
if (imports.length === 0 && metadata?.component) {
|
|
891
765
|
// If no imports were found, it might mean that the component is not imported, or
|
|
@@ -899,18 +773,18 @@ async function parseDoc(node, parserContext, { repoUrl, silent }) {
|
|
|
899
773
|
},
|
|
900
774
|
];
|
|
901
775
|
}
|
|
902
|
-
|
|
776
|
+
mappedImports =
|
|
903
777
|
imports.map((imp) => {
|
|
904
778
|
if (config) {
|
|
905
|
-
const
|
|
906
|
-
if (
|
|
907
|
-
return imp.statement.replace(/['"]([\.\/a-zA-Z0-
|
|
779
|
+
const mappedPath = (0, project_1.mapImportPath)(imp.file, config);
|
|
780
|
+
if (mappedPath) {
|
|
781
|
+
return imp.statement.replace(/['"]([\.\/a-zA-Z0-9_-]*)['"]/, `'${mappedPath}'`);
|
|
908
782
|
}
|
|
909
783
|
}
|
|
910
784
|
return imp.statement;
|
|
911
785
|
}) ?? [];
|
|
912
786
|
}
|
|
913
|
-
if (
|
|
787
|
+
if (mappedImports.length === 0 && metadata?.component) {
|
|
914
788
|
logging_1.logger.warn(`The import statement for ${metadata.component} could not be automatically resolved, make sure the component is imported (if not colocating) and that the path mappings are correct in your figma.config.json`);
|
|
915
789
|
}
|
|
916
790
|
let template;
|
|
@@ -921,7 +795,7 @@ async function parseDoc(node, parserContext, { repoUrl, silent }) {
|
|
|
921
795
|
template = getDefaultTemplate(metadata);
|
|
922
796
|
}
|
|
923
797
|
else {
|
|
924
|
-
throw new ParserError(`${intrinsics_1.FIGMA_CONNECT_CALL}() requires either a component argument or an example function`, { sourceFile, node });
|
|
798
|
+
throw new parser_common_1.ParserError(`${intrinsics_1.FIGMA_CONNECT_CALL}() requires either a component argument or an example function`, { sourceFile, node });
|
|
925
799
|
}
|
|
926
800
|
return {
|
|
927
801
|
figmaNode,
|
|
@@ -936,7 +810,7 @@ async function parseDoc(node, parserContext, { repoUrl, silent }) {
|
|
|
936
810
|
// TODO: `props` here is currently only used for validation purposes,
|
|
937
811
|
// we should eventually remove it from the JSON payload
|
|
938
812
|
props,
|
|
939
|
-
imports:
|
|
813
|
+
imports: mappedImports,
|
|
940
814
|
// If there's no render function, the default example is always nestable
|
|
941
815
|
nestable: render ? render.nestable : true,
|
|
942
816
|
},
|
|
@@ -946,36 +820,5 @@ async function parseDoc(node, parserContext, { repoUrl, silent }) {
|
|
|
946
820
|
},
|
|
947
821
|
};
|
|
948
822
|
}
|
|
949
|
-
|
|
950
|
-
const sourceFile = program.getSourceFile(file);
|
|
951
|
-
if (!sourceFile) {
|
|
952
|
-
throw new InternalError(`Could not find source file for ${file}`);
|
|
953
|
-
}
|
|
954
|
-
const parserContext = {
|
|
955
|
-
checker: program.getTypeChecker(),
|
|
956
|
-
sourceFile,
|
|
957
|
-
config,
|
|
958
|
-
absPath,
|
|
959
|
-
};
|
|
960
|
-
const codeConnectObjects = [];
|
|
961
|
-
const nodes = [parserContext.sourceFile];
|
|
962
|
-
while (nodes.length > 0) {
|
|
963
|
-
const node = nodes.shift();
|
|
964
|
-
if (isFigmaConnectCall(node, parserContext.sourceFile)) {
|
|
965
|
-
const doc = await parseDoc(node, parserContext, parseOptions);
|
|
966
|
-
if (doc) {
|
|
967
|
-
codeConnectObjects.push(doc);
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
nodes.push(...node.getChildren(parserContext.sourceFile));
|
|
971
|
-
}
|
|
972
|
-
if (codeConnectObjects.length === 0) {
|
|
973
|
-
throw new ParserError(`Didn't find any calls to figma.connect()`, {
|
|
974
|
-
sourceFile: parserContext.sourceFile,
|
|
975
|
-
node: parserContext.sourceFile,
|
|
976
|
-
});
|
|
977
|
-
}
|
|
978
|
-
return codeConnectObjects;
|
|
979
|
-
}
|
|
980
|
-
exports.parse = parse;
|
|
823
|
+
exports.parseReactDoc = parseReactDoc;
|
|
981
824
|
//# sourceMappingURL=parser.js.map
|