@figma/code-connect 1.4.8 → 1.5.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 +3 -0
- package/dist/commands/connect.d.ts +5 -0
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +94 -26
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/connect_template.d.ts.map +1 -1
- package/dist/commands/connect_template.js +2 -2
- package/dist/commands/connect_template.js.map +1 -1
- package/dist/commands/preview_utils.d.ts +103 -5
- package/dist/commands/preview_utils.d.ts.map +1 -1
- package/dist/commands/preview_utils.js +453 -76
- package/dist/commands/preview_utils.js.map +1 -1
- package/dist/commands/property_list_table.d.ts +11 -0
- package/dist/commands/property_list_table.d.ts.map +1 -0
- package/dist/commands/property_list_table.js +67 -0
- package/dist/commands/property_list_table.js.map +1 -0
- package/dist/common/updates.d.ts +4 -1
- package/dist/common/updates.d.ts.map +1 -1
- package/dist/common/updates.js +26 -5
- package/dist/common/updates.js.map +1 -1
- package/dist/connect/api.d.ts +34 -1
- package/dist/connect/api.d.ts.map +1 -1
- package/dist/connect/api.js.map +1 -1
- package/dist/connect/batch_templates.d.ts +1 -1
- package/dist/connect/batch_templates.d.ts.map +1 -1
- package/dist/connect/batch_templates.js +2 -2
- package/dist/connect/batch_templates.js.map +1 -1
- package/dist/connect/intrinsics.d.ts +1 -0
- package/dist/connect/intrinsics.d.ts.map +1 -1
- package/dist/connect/intrinsics.js +29 -0
- package/dist/connect/intrinsics.js.map +1 -1
- package/dist/connect/migration_batch_helpers.d.ts.map +1 -1
- package/dist/connect/migration_batch_helpers.js +1 -15
- package/dist/connect/migration_batch_helpers.js.map +1 -1
- package/dist/connect/migration_helpers.d.ts +6 -0
- package/dist/connect/migration_helpers.d.ts.map +1 -1
- package/dist/connect/migration_helpers.js +66 -0
- package/dist/connect/migration_helpers.js.map +1 -1
- package/dist/connect/parser_executables.d.ts.map +1 -1
- package/dist/connect/parser_executables.js +25 -13
- package/dist/connect/parser_executables.js.map +1 -1
- package/dist/connect/property_combinations.d.ts +69 -0
- package/dist/connect/property_combinations.d.ts.map +1 -0
- package/dist/connect/property_combinations.js +172 -0
- package/dist/connect/property_combinations.js.map +1 -0
- package/dist/connect/raw_template_bundler.d.ts +13 -0
- package/dist/connect/raw_template_bundler.d.ts.map +1 -0
- package/dist/connect/raw_template_bundler.js +178 -0
- package/dist/connect/raw_template_bundler.js.map +1 -0
- package/dist/connect/raw_templates.d.ts +1 -1
- package/dist/connect/raw_templates.d.ts.map +1 -1
- package/dist/connect/raw_templates.js +85 -24
- package/dist/connect/raw_templates.js.map +1 -1
- package/dist/parser_scripts/get_swift_parser_dir.js +5 -5
- package/dist/parser_scripts/get_swift_parser_dir.js.map +1 -1
- package/dist/react/parser.d.ts.map +1 -1
- package/dist/react/parser.js.map +1 -1
- package/figma-types-no-require.d.ts +231 -0
- package/figma-types.d.ts +19 -8
- package/package.json +8 -4
|
@@ -38,6 +38,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.groupCodeConnectObjectsByFigmaUrl = exports.migrateV1TemplateToV2 = void 0;
|
|
40
40
|
exports.formatTemplate = formatTemplate;
|
|
41
|
+
exports.removeUnusedGeneratedPropDeclarations = removeUnusedGeneratedPropDeclarations;
|
|
41
42
|
exports.getFilenameFromComponentName = getFilenameFromComponentName;
|
|
42
43
|
exports.prepareMigratedTemplateBody = prepareMigratedTemplateBody;
|
|
43
44
|
exports.prepareMigratedTemplate = prepareMigratedTemplate;
|
|
@@ -52,6 +53,7 @@ exports.writeVariantTemplateFile = writeVariantTemplateFile;
|
|
|
52
53
|
const fs_1 = __importDefault(require("fs"));
|
|
53
54
|
const path_1 = __importDefault(require("path"));
|
|
54
55
|
const prettier = __importStar(require("prettier"));
|
|
56
|
+
const ts_morph_1 = require("ts-morph");
|
|
55
57
|
/** Prettier configuration used for all generated template files */
|
|
56
58
|
const PRETTIER_OPTIONS = {
|
|
57
59
|
parser: 'typescript',
|
|
@@ -63,6 +65,69 @@ const PRETTIER_OPTIONS = {
|
|
|
63
65
|
function formatTemplate(code) {
|
|
64
66
|
return prettier.format(code, PRETTIER_OPTIONS);
|
|
65
67
|
}
|
|
68
|
+
let unusedPropCleanupProject;
|
|
69
|
+
let unusedPropCleanupFileId = 0;
|
|
70
|
+
function getUnusedPropCleanupProject() {
|
|
71
|
+
unusedPropCleanupProject ??= new ts_morph_1.Project({
|
|
72
|
+
useInMemoryFileSystem: true,
|
|
73
|
+
skipAddingFilesFromTsConfig: true,
|
|
74
|
+
compilerOptions: {
|
|
75
|
+
module: ts_morph_1.ModuleKind.ESNext,
|
|
76
|
+
target: ts_morph_1.ScriptTarget.ESNext,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
return unusedPropCleanupProject;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Removes unused top-level const declarations generated from parser prop mappings.
|
|
83
|
+
* If the template cannot be safely analyzed, leave it unchanged so cleanup never
|
|
84
|
+
* prevents an otherwise valid migration.
|
|
85
|
+
*/
|
|
86
|
+
function removeUnusedGeneratedPropDeclarations(template, props) {
|
|
87
|
+
const generatedPropNames = new Set(Object.keys(props || {}));
|
|
88
|
+
if (generatedPropNames.size === 0) {
|
|
89
|
+
return template;
|
|
90
|
+
}
|
|
91
|
+
let project;
|
|
92
|
+
let sourceFile;
|
|
93
|
+
try {
|
|
94
|
+
project = getUnusedPropCleanupProject();
|
|
95
|
+
sourceFile = project.createSourceFile(`migration-template-${unusedPropCleanupFileId++}.ts`, template);
|
|
96
|
+
if (project.getProgram().getSyntacticDiagnostics(sourceFile).length > 0) {
|
|
97
|
+
return template;
|
|
98
|
+
}
|
|
99
|
+
// Repeat so a generated declaration referenced only by another unused
|
|
100
|
+
// generated declaration can also be removed.
|
|
101
|
+
while (true) {
|
|
102
|
+
const unusedStatement = sourceFile.getVariableStatements().find((statement) => {
|
|
103
|
+
if (statement.getDeclarationKind() !== ts_morph_1.VariableDeclarationKind.Const) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
const declarations = statement.getDeclarations();
|
|
107
|
+
if (declarations.length !== 1) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
const name = declarations[0].getNameNode();
|
|
111
|
+
return (ts_morph_1.Node.isIdentifier(name) &&
|
|
112
|
+
generatedPropNames.has(name.getText()) &&
|
|
113
|
+
name.findReferencesAsNodes().length === 0);
|
|
114
|
+
});
|
|
115
|
+
if (!unusedStatement) {
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
unusedStatement.remove();
|
|
119
|
+
}
|
|
120
|
+
return sourceFile.getFullText();
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return template;
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
if (project && sourceFile) {
|
|
127
|
+
project.removeSourceFile(sourceFile);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
66
131
|
/**
|
|
67
132
|
* Common wrapper that handles path determination and file writing for both
|
|
68
133
|
* simple templates and variant templates.
|
|
@@ -175,6 +240,7 @@ function prepareMigratedTemplateBody(doc, includeProps = false, useTypeScript) {
|
|
|
175
240
|
if (useTypeScript) {
|
|
176
241
|
template = convertSyntaxToTypeScript(template);
|
|
177
242
|
}
|
|
243
|
+
template = removeUnusedGeneratedPropDeclarations(template, doc.templateData?.props);
|
|
178
244
|
return template;
|
|
179
245
|
}
|
|
180
246
|
/** Migrates a doc's template (Swift helpers, server helpers, V2, id, imports, nestable) and returns the formatted string. */
|
|
@@ -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\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 */\nexport function 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\nexport function getFilenameFromComponentName(componentName: string): string {\n const allowlisted = /[a-zA-Z0-9\\-\\.]/\n return componentName\n .split('')\n .map((ch) => (allowlisted.test(ch) ? ch : '_'))\n .join('')\n .replace(/_+/g, '_')\n .replace(/^_|_$/g, '')\n}\n\n/**\n * Determines the base output path for a template file.\n * Shared logic between writeTemplateFile and writeVariantTemplateFile.\n */\nfunction determineOutputPath(\n rawComponentName: string,\n suffix: string,\n outputDir: string | undefined,\n baseDir: string,\n localSourcePath: string | undefined,\n): string {\n // Extract basename from localSourcePath when available, falling back to componentName\n const componentFilename = getFilenameFromComponentName(rawComponentName)\n let basename = componentFilename\n if (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 basename = sourceBasename\n }\n\n if (outputDir) {\n // Use specified output directory with basename derived from source path\n return path.join(outputDir, `${basename}${suffix}`)\n } else if (localSourcePath) {\n // Use same directory as local source file\n return path.join(path.dirname(localSourcePath), `${basename}${suffix}`)\n } else {\n // No source info, use current directory\n const filename = `${componentFilename}${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) without formatting. */\nexport function prepareMigratedTemplateBody(\n doc: CodeConnectJSON,\n includeProps = false,\n useTypeScript?: boolean,\n): string {\n let template = doc.template\n template = removeSwiftHelpers(template)\n template = migrateTemplateToUseServerSideHelpers(template)\n if (!includeProps) {\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 template\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 includeProps = false,\n useTypeScript?: boolean,\n): string {\n const template = prepareMigratedTemplateBody(doc, includeProps, useTypeScript)\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 type WriteTemplateFileOptions = {\n localSourcePath?: string\n filePathsCreated?: Set<string>\n includeProps?: boolean\n useTypeScript?: boolean\n}\n\nexport function writeTemplateFile(\n doc: CodeConnectJSON,\n outputDir: string | undefined,\n baseDir: string,\n {\n localSourcePath,\n filePathsCreated,\n includeProps = false,\n useTypeScript = true,\n }: WriteTemplateFileOptions = {},\n): { outputPath: string; skipped: boolean } {\n const componentName = doc.component || 'template'\n const template = prepareMigratedTemplate(doc, includeProps, 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 // Don't add id if already present (e.g. when re-migrating a previously-migrated template)\n if (/export default\\s*\\{\\s*id:\\s*['\"]/.test(template)) {\n return template\n }\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').__render__()\n //\n // We intentionally keep `.__render__()` here rather than the friendlier\n // `.textContent`. `findText` returns `TextHandle | ErrorHandle`, and\n // `textContent` only exists on `TextHandle` - so `.findText('X').textContent`\n // (a) fails to typecheck (`textContent` does not exist on `ErrorHandle`), and\n // (b) silently evaluates to `undefined` for a missing layer, swallowing the\n // error. `__render__()` exists on both handles (returning the text string on\n // success and an error section on failure), exactly matching the pre-migration\n // runtime behavior of the React parser's `figma.textContent('X')`.\n //\n // We emit a sentinel so the blanket `__render__()` -> `executeTemplate().example`\n // rewrite below (step 8) doesn't clobber it - `TextHandle` has no\n // `executeTemplate`, so that rewrite would re-break the text case. The sentinel\n // is converted back to `__render__()` at the end of this function.\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*name:\\s*'([^']+)',\\s*type:\\s*\"TEXT\"\\s*\\}\\)\\.__render__\\(\\)/g,\n \".findText('$1').__FCC_TEXT_RENDER__()\",\n )\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*type:\\s*\"TEXT\",\\s*name:\\s*'([^']+)'\\s*\\}\\)\\.__render__\\(\\)/g,\n \".findText('$1').__FCC_TEXT_RENDER__()\",\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 // 12. Restore the TEXT __render__ sentinel emitted in step 6 (kept out of the\n // way of step 8's __render__ -> executeTemplate().example rewrite).\n migrated = migrated.replace(/\\.__FCC_TEXT_RENDER__\\(\\)/g, '.__render__()')\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 {\n localSourcePath,\n filePathsCreated,\n useTypeScript = true,\n includeProps = false,\n }: WriteTemplateFileOptions = {},\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 }) =>\n prepareMigratedTemplate(doc, includeProps, useTypeScript),\n )\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/import, keep everything else\n const lines = branchCode.split('\\n')\n const filteredLines = lines.filter(\n (line) =>\n !line.trim().startsWith('const figma = require') &&\n !line.trim().startsWith('import figma from'),\n )\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 useTypeScript ? `import figma from \"figma\"` : `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\n .replace(/const figma = require\\(['\"]figma['\"]\\)/, `import figma from \"figma\"`)\n .replace(/const __props = {}/, 'const __props: Record<string, unknown> = {}')\n .replace(\n /if \\((\\w+) && \\1\\.type !== \"ERROR\"\\)/g,\n 'if ($1 && ($1 as { type?: string }).type !== \"ERROR\")',\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 { ModuleKind, Node, Project, ScriptTarget, VariableDeclarationKind } from 'ts-morph'\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 */\nexport function formatTemplate(code: string): string {\n return prettier.format(code, PRETTIER_OPTIONS)\n}\n\nlet unusedPropCleanupProject: Project | undefined\nlet unusedPropCleanupFileId = 0\n\nfunction getUnusedPropCleanupProject() {\n unusedPropCleanupProject ??= new Project({\n useInMemoryFileSystem: true,\n skipAddingFilesFromTsConfig: true,\n compilerOptions: {\n module: ModuleKind.ESNext,\n target: ScriptTarget.ESNext,\n },\n })\n return unusedPropCleanupProject\n}\n\n/**\n * Removes unused top-level const declarations generated from parser prop mappings.\n * If the template cannot be safely analyzed, leave it unchanged so cleanup never\n * prevents an otherwise valid migration.\n */\nexport function removeUnusedGeneratedPropDeclarations(\n template: string,\n props: CodeConnectJSON['templateData']['props'],\n): string {\n const generatedPropNames = new Set(Object.keys(props || {}))\n if (generatedPropNames.size === 0) {\n return template\n }\n\n let project: Project | undefined\n let sourceFile\n\n try {\n project = getUnusedPropCleanupProject()\n sourceFile = project.createSourceFile(\n `migration-template-${unusedPropCleanupFileId++}.ts`,\n template,\n )\n\n if (project.getProgram().getSyntacticDiagnostics(sourceFile).length > 0) {\n return template\n }\n\n // Repeat so a generated declaration referenced only by another unused\n // generated declaration can also be removed.\n while (true) {\n const unusedStatement = sourceFile.getVariableStatements().find((statement) => {\n if (statement.getDeclarationKind() !== VariableDeclarationKind.Const) {\n return false\n }\n\n const declarations = statement.getDeclarations()\n if (declarations.length !== 1) {\n return false\n }\n\n const name = declarations[0].getNameNode()\n return (\n Node.isIdentifier(name) &&\n generatedPropNames.has(name.getText()) &&\n name.findReferencesAsNodes().length === 0\n )\n })\n\n if (!unusedStatement) {\n break\n }\n unusedStatement.remove()\n }\n\n return sourceFile.getFullText()\n } catch {\n return template\n } finally {\n if (project && sourceFile) {\n project.removeSourceFile(sourceFile)\n }\n }\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\nexport function getFilenameFromComponentName(componentName: string): string {\n const allowlisted = /[a-zA-Z0-9\\-\\.]/\n return componentName\n .split('')\n .map((ch) => (allowlisted.test(ch) ? ch : '_'))\n .join('')\n .replace(/_+/g, '_')\n .replace(/^_|_$/g, '')\n}\n\n/**\n * Determines the base output path for a template file.\n * Shared logic between writeTemplateFile and writeVariantTemplateFile.\n */\nfunction determineOutputPath(\n rawComponentName: string,\n suffix: string,\n outputDir: string | undefined,\n baseDir: string,\n localSourcePath: string | undefined,\n): string {\n // Extract basename from localSourcePath when available, falling back to componentName\n const componentFilename = getFilenameFromComponentName(rawComponentName)\n let basename = componentFilename\n if (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 basename = sourceBasename\n }\n\n if (outputDir) {\n // Use specified output directory with basename derived from source path\n return path.join(outputDir, `${basename}${suffix}`)\n } else if (localSourcePath) {\n // Use same directory as local source file\n return path.join(path.dirname(localSourcePath), `${basename}${suffix}`)\n } else {\n // No source info, use current directory\n const filename = `${componentFilename}${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) without formatting. */\nexport function prepareMigratedTemplateBody(\n doc: CodeConnectJSON,\n includeProps = false,\n useTypeScript?: boolean,\n): string {\n let template = doc.template\n template = removeSwiftHelpers(template)\n template = migrateTemplateToUseServerSideHelpers(template)\n if (!includeProps) {\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 template = removeUnusedGeneratedPropDeclarations(template, doc.templateData?.props)\n return template\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 includeProps = false,\n useTypeScript?: boolean,\n): string {\n const template = prepareMigratedTemplateBody(doc, includeProps, useTypeScript)\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 type WriteTemplateFileOptions = {\n localSourcePath?: string\n filePathsCreated?: Set<string>\n includeProps?: boolean\n useTypeScript?: boolean\n}\n\nexport function writeTemplateFile(\n doc: CodeConnectJSON,\n outputDir: string | undefined,\n baseDir: string,\n {\n localSourcePath,\n filePathsCreated,\n includeProps = false,\n useTypeScript = true,\n }: WriteTemplateFileOptions = {},\n): { outputPath: string; skipped: boolean } {\n const componentName = doc.component || 'template'\n const template = prepareMigratedTemplate(doc, includeProps, 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 // Don't add id if already present (e.g. when re-migrating a previously-migrated template)\n if (/export default\\s*\\{\\s*id:\\s*['\"]/.test(template)) {\n return template\n }\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').__render__()\n //\n // We intentionally keep `.__render__()` here rather than the friendlier\n // `.textContent`. `findText` returns `TextHandle | ErrorHandle`, and\n // `textContent` only exists on `TextHandle` - so `.findText('X').textContent`\n // (a) fails to typecheck (`textContent` does not exist on `ErrorHandle`), and\n // (b) silently evaluates to `undefined` for a missing layer, swallowing the\n // error. `__render__()` exists on both handles (returning the text string on\n // success and an error section on failure), exactly matching the pre-migration\n // runtime behavior of the React parser's `figma.textContent('X')`.\n //\n // We emit a sentinel so the blanket `__render__()` -> `executeTemplate().example`\n // rewrite below (step 8) doesn't clobber it - `TextHandle` has no\n // `executeTemplate`, so that rewrite would re-break the text case. The sentinel\n // is converted back to `__render__()` at the end of this function.\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*name:\\s*'([^']+)',\\s*type:\\s*\"TEXT\"\\s*\\}\\)\\.__render__\\(\\)/g,\n \".findText('$1').__FCC_TEXT_RENDER__()\",\n )\n migrated = migrated.replace(\n /\\.__findChildWithCriteria__\\(\\{\\s*type:\\s*\"TEXT\",\\s*name:\\s*'([^']+)'\\s*\\}\\)\\.__render__\\(\\)/g,\n \".findText('$1').__FCC_TEXT_RENDER__()\",\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 // 12. Restore the TEXT __render__ sentinel emitted in step 6 (kept out of the\n // way of step 8's __render__ -> executeTemplate().example rewrite).\n migrated = migrated.replace(/\\.__FCC_TEXT_RENDER__\\(\\)/g, '.__render__()')\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 {\n localSourcePath,\n filePathsCreated,\n useTypeScript = true,\n includeProps = false,\n }: WriteTemplateFileOptions = {},\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 }) =>\n prepareMigratedTemplate(doc, includeProps, useTypeScript),\n )\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/import, keep everything else\n const lines = branchCode.split('\\n')\n const filteredLines = lines.filter(\n (line) =>\n !line.trim().startsWith('const figma = require') &&\n !line.trim().startsWith('import figma from'),\n )\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 useTypeScript ? `import figma from \"figma\"` : `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\n .replace(/const figma = require\\(['\"]figma['\"]\\)/, `import figma from \"figma\"`)\n .replace(/const __props = {}/, 'const __props: Record<string, unknown> = {}')\n .replace(\n /if \\((\\w+) && \\1\\.type !== \"ERROR\"\\)/g,\n 'if ($1 && ($1 as { type?: string }).type !== \"ERROR\")',\n )\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser_executables.d.ts","sourceRoot":"","sources":["../../src/connect/parser_executables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAEL,iCAAiC,EAGlC,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EAGrB,MAAM,2BAA2B,CAAA;AA+
|
|
1
|
+
{"version":3,"file":"parser_executables.d.ts","sourceRoot":"","sources":["../../src/connect/parser_executables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAEL,iCAAiC,EAGlC,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EAGrB,MAAM,2BAA2B,CAAA;AA+FlC,wBAAsB,UAAU,CAC9B,MAAM,EAAE,iCAAiC,EACzC,OAAO,EAAE,oBAAoB,EAC7B,GAAG,EAAE,MAAM,mBA0LZ;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC;;EAsBhF"}
|
|
@@ -17,20 +17,28 @@ const temporaryOutputDirectoryPath = 'tmp/parser-output';
|
|
|
17
17
|
const FIRST_PARTY_PARSERS = {
|
|
18
18
|
swift: {
|
|
19
19
|
command: async (cwd, config) => {
|
|
20
|
-
|
|
20
|
+
const packagePath = await (0, get_swift_parser_dir_1.getSwiftParserDir)(cwd, config.xcodeprojPath, config.swiftPackagePath, config.sourcePackagesPath);
|
|
21
|
+
return {
|
|
22
|
+
cmd: 'swift',
|
|
23
|
+
args: ['run', '--package-path', packagePath, 'figma-swift'],
|
|
24
|
+
};
|
|
21
25
|
},
|
|
22
26
|
},
|
|
23
27
|
compose: {
|
|
24
28
|
command: async (cwd, config, mode) => {
|
|
25
29
|
const gradlewPath = await (0, get_gradlew_path_1.getGradleWrapperPath)(cwd, config.gradleWrapperPath);
|
|
26
30
|
const gradleExecutableInvocation = (0, get_gradlew_path_1.getGradleWrapperExecutablePath)(gradlewPath);
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
const verbose = Boolean(config.verbose);
|
|
32
|
+
const task = mode === 'CREATE' ? 'createCodeConnect' : 'parseCodeConnect';
|
|
33
|
+
const args = [
|
|
34
|
+
'-p',
|
|
35
|
+
gradlewPath,
|
|
36
|
+
task,
|
|
37
|
+
`-PfilePath=${temporaryInputFilePath}`,
|
|
38
|
+
...(verbose ? ['--stacktrace'] : []),
|
|
39
|
+
`-PoutputDir=${temporaryOutputDirectoryPath}`,
|
|
40
|
+
];
|
|
41
|
+
return { cmd: gradleExecutableInvocation, args };
|
|
34
42
|
},
|
|
35
43
|
temporaryInputFilePath: temporaryInputFilePath,
|
|
36
44
|
temporaryOutputDirectoryPath: temporaryOutputDirectoryPath,
|
|
@@ -41,11 +49,15 @@ const FIRST_PARTY_PARSERS = {
|
|
|
41
49
|
(0, logging_1.exitWithError)('No `parserCommand` specified in config. A command is required when using the `custom` parser.');
|
|
42
50
|
}
|
|
43
51
|
logging_1.logger.info('Using custom parser command: ' + config.parserCommand);
|
|
44
|
-
|
|
52
|
+
// Keep user quoting intact for free-form custom commands.
|
|
53
|
+
return { cmd: config.parserCommand, args: [], shell: true };
|
|
45
54
|
},
|
|
46
55
|
},
|
|
47
56
|
__unit_test__: {
|
|
48
|
-
command: async () =>
|
|
57
|
+
command: async () => ({
|
|
58
|
+
cmd: 'node',
|
|
59
|
+
args: ['parser/unit_test_parser.js'],
|
|
60
|
+
}),
|
|
49
61
|
},
|
|
50
62
|
};
|
|
51
63
|
function getParser(config) {
|
|
@@ -73,10 +85,10 @@ async function callParser(config, payload, cwd) {
|
|
|
73
85
|
if (parser.temporaryOutputDirectoryPath) {
|
|
74
86
|
fs_1.default.mkdirSync(parser.temporaryOutputDirectoryPath, { recursive: true });
|
|
75
87
|
}
|
|
76
|
-
logging_1.logger.debug(`Running parser: ${command}`);
|
|
77
|
-
const
|
|
78
|
-
const child = (0, cross_spawn_1.spawn)(commandSplit[0], commandSplit.slice(1), {
|
|
88
|
+
logging_1.logger.debug(`Running parser: ${command.cmd} ${command.args.join(' ')}`);
|
|
89
|
+
const child = (0, cross_spawn_1.spawn)(command.cmd, command.args, {
|
|
79
90
|
cwd,
|
|
91
|
+
shell: command.shell,
|
|
80
92
|
});
|
|
81
93
|
let stdout = '';
|
|
82
94
|
let stderr = '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser_executables.js","sourceRoot":"","sources":["../../src/connect/parser_executables.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod'\nimport { exitWithError, logger } from '../common/logging'\nimport {\n CodeConnectCustomExecutableParserConfig,\n CodeConnectExecutableParserConfig,\n CodeConnectExecutableParser,\n CodeConnectParser,\n} from './project'\nimport {\n ParserExecutableMessages,\n ParserRequestPayload,\n ParseResponsePayload,\n CreateResponsePayload,\n} from './parser_executable_types'\nimport { spawn } from 'cross-spawn'\nimport { getSwiftParserDir } from '../parser_scripts/get_swift_parser_dir'\nimport fs from 'fs'\nimport path from 'path'\nimport {\n getGradleWrapperExecutablePath,\n getGradleWrapperPath,\n} from '../parser_scripts/get_gradlew_path'\nimport { getComposeErrorSuggestion } from '../parser_scripts/compose_errors'\n\nconst temporaryInputFilePath = 'tmp/figma-code-connect-parser-io.json.tmp'\nconst temporaryOutputDirectoryPath = 'tmp/parser-output'\n\ntype ParserInfo = {\n command: (\n cwd: string,\n config: CodeConnectExecutableParserConfig | CodeConnectCustomExecutableParserConfig,\n mode: ParserRequestPayload['mode'],\n ) => Promise<string>\n temporaryInputFilePath?: string\n temporaryOutputDirectoryPath?: string\n}\n\nconst FIRST_PARTY_PARSERS: Record<CodeConnectExecutableParser, ParserInfo> = {\n swift: {\n command: async (cwd, config) => {\n return `swift run --package-path ${await getSwiftParserDir(\n cwd,\n (config as any).xcodeprojPath,\n (config as any).swiftPackagePath,\n (config as any).sourcePackagesPath,\n )} figma-swift`\n },\n },\n compose: {\n command: async (cwd, config, mode) => {\n const gradlewPath = await getGradleWrapperPath(cwd, (config as any).gradleWrapperPath)\n const gradleExecutableInvocation = getGradleWrapperExecutablePath(gradlewPath)\n const verboseFlags = (config as any).verbose ? ' --stacktrace' : ''\n if (mode === 'CREATE') {\n return `${gradleExecutableInvocation} -p ${gradlewPath} createCodeConnect -PfilePath=${temporaryInputFilePath}${verboseFlags} -PoutputDir=${temporaryOutputDirectoryPath}`\n } else {\n return `${gradleExecutableInvocation} -p ${gradlewPath} parseCodeConnect -PfilePath=${temporaryInputFilePath}${verboseFlags} -PoutputDir=${temporaryOutputDirectoryPath}`\n }\n },\n temporaryInputFilePath: temporaryInputFilePath,\n temporaryOutputDirectoryPath: temporaryOutputDirectoryPath,\n },\n custom: {\n command: async (cwd, config) => {\n if (!('parserCommand' in config)) {\n exitWithError(\n 'No `parserCommand` specified in config. A command is required when using the `custom` parser.',\n )\n }\n logger.info('Using custom parser command: ' + config.parserCommand)\n return config.parserCommand\n },\n },\n __unit_test__: {\n command: async () => 'node parser/unit_test_parser.js',\n },\n}\n\nfunction getParser(config: CodeConnectExecutableParserConfig): ParserInfo | never {\n const parser = FIRST_PARTY_PARSERS[config.parser]\n\n if (!parser) {\n exitWithError(\n `Invalid parser specified: \"${config.parser}\". Valid parsers are: ${Object.keys(\n FIRST_PARTY_PARSERS,\n ).join(', ')}.`,\n )\n }\n\n return parser\n}\n\nexport async function callParser(\n config: CodeConnectExecutableParserConfig,\n payload: ParserRequestPayload,\n cwd: string,\n) {\n return new Promise<object>(async (resolve, reject) => {\n try {\n const parser = getParser(config)\n const configWithVerbose = {\n ...config,\n verbose: (payload as any).verbose,\n }\n\n const command = await parser.command(cwd, configWithVerbose, payload.mode)\n\n // Create temporary input file if it exists\n if (parser.temporaryInputFilePath) {\n fs.mkdirSync(path.dirname(parser.temporaryInputFilePath), { recursive: true })\n fs.writeFileSync(parser.temporaryInputFilePath, JSON.stringify(payload))\n }\n\n // Create temporary output directory if it exists\n if (parser.temporaryOutputDirectoryPath) {\n fs.mkdirSync(parser.temporaryOutputDirectoryPath, { recursive: true })\n }\n\n logger.debug(`Running parser: ${command}`)\n const commandSplit = command.split(' ')\n\n const child = spawn(commandSplit[0], commandSplit.slice(1), {\n cwd,\n })\n\n let stdout = ''\n let stderr = ''\n\n child.stdout.on('data', (data) => {\n stdout += data.toString()\n })\n\n // This handles any stderr output from the parser.\n //\n // Parsers should not generally write to stderr, and should instead return\n // an array of messages at the end of execution, but there are cases where\n // you might want to log output immediately rather than at the end of the\n // run - e.g. if the parser can take a while to compile first time, you\n // might want to inform the user immediately that it is compiling.\n //\n // To log output, the parser should write a JSON object to stderr with the\n // same structure as the `messages` response object, e.g. `{ \"level\":\n // \"INFO\", \"message\": \"Compiling parser...\" }`.\n //\n // Non-JSON output will be logged as debug messages, as this is likely to\n // be e.g. compiler output which the user doesn't need to see ordinarily.\n child.stderr.on('data', (data) => {\n const message = data.toString()\n const trimmedMessage = message.trim()\n try {\n const parsed = JSON.parse(trimmedMessage)\n handleMessages([parsed])\n } catch (e) {\n stderr += message\n logger.debug(trimmedMessage)\n }\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n const errorSuggestion = determineErrorSuggestionFromStderr(stderr, config.parser)\n if (errorSuggestion) {\n reject(new Error(`Parser exited with code ${code}: ${errorSuggestion}`))\n } else {\n reject(new Error(`Parser exited with code ${code}`))\n }\n } else {\n // List the files in the temporary output directory if it exists and log them\n if (parser.temporaryOutputDirectoryPath) {\n try {\n const outputDir = parser.temporaryOutputDirectoryPath\n if (fs.existsSync(outputDir)) {\n const files = fs.readdirSync(outputDir)\n logger.debug(\n `Files in temporary output directory (${outputDir}): ${files.length > 0 ? files.join(', ') : '[empty]'}`,\n )\n\n // Combine all JSON files in the output directory into a single JSON object.\n // For PARSE responses: Each file has a \"docs\" array and a \"messages\" array.\n // For CREATE responses: Each file has a \"createdFiles\" array and a \"messages\" array.\n // The combined output will have a single array of the appropriate type and a single \"messages\" array.\n\n // Filter for .json files only\n const jsonFiles = files.filter((f) => f.endsWith('.json'))\n let allMessages: z.infer<typeof ParserExecutableMessages> = []\n const uniqueDocsMap = new Map<\n string,\n z.infer<typeof ParseResponsePayload>['docs'][number]\n >()\n let allCreatedFiles: z.infer<typeof CreateResponsePayload>['createdFiles'] = []\n\n for (const file of jsonFiles) {\n const filePath = path.join(outputDir, file)\n try {\n const content = fs.readFileSync(filePath, 'utf8')\n const parsed = JSON.parse(content)\n if (Array.isArray(parsed.docs)) {\n // Deduplicate docs based on figmaNode + template\n // The template contains the actual code example and is unique per component.\n // This allows multiple different code components to map to the same Figma node,\n // while preventing the same component from being duplicated in multi-module projects.\n for (const doc of parsed.docs) {\n const dedupeKey = JSON.stringify({\n figmaNode: doc.figmaNode,\n template: doc.template,\n })\n if (!uniqueDocsMap.has(dedupeKey)) {\n uniqueDocsMap.set(dedupeKey, doc)\n }\n }\n }\n if (Array.isArray(parsed.createdFiles)) {\n allCreatedFiles = allCreatedFiles.concat(parsed.createdFiles)\n }\n if (Array.isArray(parsed.messages)) {\n allMessages = allMessages.concat(parsed.messages)\n }\n } catch (err) {\n logger.warn(`Failed to parse output file ${file}: ${err}`)\n }\n }\n\n const allDocs = Array.from(uniqueDocsMap.values())\n\n // Return the appropriate response based on the mode\n if (payload.mode === 'CREATE') {\n resolve({\n createdFiles: allCreatedFiles,\n messages: allMessages,\n })\n } else {\n resolve({\n docs: allDocs,\n messages: allMessages,\n })\n }\n } else {\n logger.debug(`Temporary output directory (${outputDir}) does not exist.`)\n }\n } catch (err) {\n logger.warn(`Failed to list files in temporary output directory: ${err}`)\n }\n } else {\n // Assume the output is in the stdout\n resolve(JSON.parse(stdout))\n }\n }\n\n if (parser.temporaryInputFilePath) {\n // Retain temp file and directory when verbose mode is enabled\n if (!(payload as any).verbose) {\n fs.unlinkSync(parser.temporaryInputFilePath)\n // Delete parent directory if empty after removing temp file\n const parentDir = path.dirname(parser.temporaryInputFilePath)\n if (fs.readdirSync(parentDir).length === 0) {\n fs.rmdirSync(parentDir)\n }\n }\n }\n })\n\n child.on('error', (e) => {\n reject(e)\n })\n if (!parser.temporaryInputFilePath) {\n child.stdin.write(JSON.stringify(payload))\n child.stdin.end()\n }\n } catch (e) {\n if ((payload as any).verbose) {\n console.trace(e)\n\n // Don't say to enable verbose if the user has already enabled it.\n exitWithError(`Error calling parser: ${e}.`)\n } else {\n exitWithError(\n `Error calling parser: ${e}. Try re-running the command with --verbose for more information.`,\n )\n }\n }\n })\n}\n\nexport function handleMessages(messages: z.infer<typeof ParserExecutableMessages>) {\n let hasErrors = false\n\n messages.forEach((message) => {\n switch (message.level) {\n case 'DEBUG':\n logger.debug(message.message)\n break\n case 'INFO':\n logger.info(message.message)\n break\n case 'WARN':\n logger.warn(message.message)\n break\n case 'ERROR':\n logger.error(message.message)\n hasErrors = true\n break\n }\n })\n\n return { hasErrors }\n}\n\n// This function is used to determine if there is a suggestion for the error based on the output\n// to stderr. Certain parsers return the same error code for different types of errors such as\n// errors from invoking the gradle wrapper for Compose.\n// In the future we should consider exposing a different API for having the parser return a suggestion directly.\nfunction determineErrorSuggestionFromStderr(\n stderr: string,\n parser: CodeConnectParser,\n): string | null {\n if (parser === 'compose') {\n return getComposeErrorSuggestion(stderr)\n }\n return null\n}\n"]}
|
|
1
|
+
{"version":3,"file":"parser_executables.js","sourceRoot":"","sources":["../../src/connect/parser_executables.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod'\nimport { exitWithError, logger } from '../common/logging'\nimport {\n CodeConnectCustomExecutableParserConfig,\n CodeConnectExecutableParserConfig,\n CodeConnectExecutableParser,\n CodeConnectParser,\n} from './project'\nimport {\n ParserExecutableMessages,\n ParserRequestPayload,\n ParseResponsePayload,\n CreateResponsePayload,\n} from './parser_executable_types'\nimport { spawn } from 'cross-spawn'\nimport { getSwiftParserDir } from '../parser_scripts/get_swift_parser_dir'\nimport fs from 'fs'\nimport path from 'path'\nimport {\n getGradleWrapperExecutablePath,\n getGradleWrapperPath,\n} from '../parser_scripts/get_gradlew_path'\nimport { getComposeErrorSuggestion } from '../parser_scripts/compose_errors'\n\nconst temporaryInputFilePath = 'tmp/figma-code-connect-parser-io.json.tmp'\nconst temporaryOutputDirectoryPath = 'tmp/parser-output'\n\n// Parser invocation in argv form; only custom parser uses shell.\ntype ParserCommand = { cmd: string; args: string[]; shell?: boolean }\n\ntype ParserInfo = {\n command: (\n cwd: string,\n config: CodeConnectExecutableParserConfig | CodeConnectCustomExecutableParserConfig,\n mode: ParserRequestPayload['mode'],\n ) => Promise<ParserCommand>\n temporaryInputFilePath?: string\n temporaryOutputDirectoryPath?: string\n}\n\nconst FIRST_PARTY_PARSERS: Record<CodeConnectExecutableParser, ParserInfo> = {\n swift: {\n command: async (cwd, config) => {\n const packagePath = await getSwiftParserDir(\n cwd,\n (config as any).xcodeprojPath,\n (config as any).swiftPackagePath,\n (config as any).sourcePackagesPath,\n )\n return {\n cmd: 'swift',\n args: ['run', '--package-path', packagePath, 'figma-swift'],\n }\n },\n },\n compose: {\n command: async (cwd, config, mode) => {\n const gradlewPath = await getGradleWrapperPath(cwd, (config as any).gradleWrapperPath)\n const gradleExecutableInvocation = getGradleWrapperExecutablePath(gradlewPath)\n const verbose = Boolean((config as any).verbose)\n const task = mode === 'CREATE' ? 'createCodeConnect' : 'parseCodeConnect'\n const args = [\n '-p',\n gradlewPath,\n task,\n `-PfilePath=${temporaryInputFilePath}`,\n ...(verbose ? ['--stacktrace'] : []),\n `-PoutputDir=${temporaryOutputDirectoryPath}`,\n ]\n return { cmd: gradleExecutableInvocation, args }\n },\n temporaryInputFilePath: temporaryInputFilePath,\n temporaryOutputDirectoryPath: temporaryOutputDirectoryPath,\n },\n custom: {\n command: async (cwd, config) => {\n if (!('parserCommand' in config)) {\n exitWithError(\n 'No `parserCommand` specified in config. A command is required when using the `custom` parser.',\n )\n }\n logger.info('Using custom parser command: ' + config.parserCommand)\n // Keep user quoting intact for free-form custom commands.\n return { cmd: config.parserCommand, args: [], shell: true }\n },\n },\n __unit_test__: {\n command: async () => ({\n cmd: 'node',\n args: ['parser/unit_test_parser.js'],\n }),\n },\n}\n\nfunction getParser(config: CodeConnectExecutableParserConfig): ParserInfo | never {\n const parser = FIRST_PARTY_PARSERS[config.parser]\n\n if (!parser) {\n exitWithError(\n `Invalid parser specified: \"${config.parser}\". Valid parsers are: ${Object.keys(\n FIRST_PARTY_PARSERS,\n ).join(', ')}.`,\n )\n }\n\n return parser\n}\n\nexport async function callParser(\n config: CodeConnectExecutableParserConfig,\n payload: ParserRequestPayload,\n cwd: string,\n) {\n return new Promise<object>(async (resolve, reject) => {\n try {\n const parser = getParser(config)\n const configWithVerbose = {\n ...config,\n verbose: (payload as any).verbose,\n }\n\n const command = await parser.command(cwd, configWithVerbose, payload.mode)\n\n // Create temporary input file if it exists\n if (parser.temporaryInputFilePath) {\n fs.mkdirSync(path.dirname(parser.temporaryInputFilePath), { recursive: true })\n fs.writeFileSync(parser.temporaryInputFilePath, JSON.stringify(payload))\n }\n\n // Create temporary output directory if it exists\n if (parser.temporaryOutputDirectoryPath) {\n fs.mkdirSync(parser.temporaryOutputDirectoryPath, { recursive: true })\n }\n\n logger.debug(`Running parser: ${command.cmd} ${command.args.join(' ')}`)\n\n const child = spawn(command.cmd, command.args, {\n cwd,\n shell: command.shell,\n })\n\n let stdout = ''\n let stderr = ''\n\n child.stdout.on('data', (data) => {\n stdout += data.toString()\n })\n\n // This handles any stderr output from the parser.\n //\n // Parsers should not generally write to stderr, and should instead return\n // an array of messages at the end of execution, but there are cases where\n // you might want to log output immediately rather than at the end of the\n // run - e.g. if the parser can take a while to compile first time, you\n // might want to inform the user immediately that it is compiling.\n //\n // To log output, the parser should write a JSON object to stderr with the\n // same structure as the `messages` response object, e.g. `{ \"level\":\n // \"INFO\", \"message\": \"Compiling parser...\" }`.\n //\n // Non-JSON output will be logged as debug messages, as this is likely to\n // be e.g. compiler output which the user doesn't need to see ordinarily.\n child.stderr.on('data', (data) => {\n const message = data.toString()\n const trimmedMessage = message.trim()\n try {\n const parsed = JSON.parse(trimmedMessage)\n handleMessages([parsed])\n } catch (e) {\n stderr += message\n logger.debug(trimmedMessage)\n }\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n const errorSuggestion = determineErrorSuggestionFromStderr(stderr, config.parser)\n if (errorSuggestion) {\n reject(new Error(`Parser exited with code ${code}: ${errorSuggestion}`))\n } else {\n reject(new Error(`Parser exited with code ${code}`))\n }\n } else {\n // List the files in the temporary output directory if it exists and log them\n if (parser.temporaryOutputDirectoryPath) {\n try {\n const outputDir = parser.temporaryOutputDirectoryPath\n if (fs.existsSync(outputDir)) {\n const files = fs.readdirSync(outputDir)\n logger.debug(\n `Files in temporary output directory (${outputDir}): ${files.length > 0 ? files.join(', ') : '[empty]'}`,\n )\n\n // Combine all JSON files in the output directory into a single JSON object.\n // For PARSE responses: Each file has a \"docs\" array and a \"messages\" array.\n // For CREATE responses: Each file has a \"createdFiles\" array and a \"messages\" array.\n // The combined output will have a single array of the appropriate type and a single \"messages\" array.\n\n // Filter for .json files only\n const jsonFiles = files.filter((f) => f.endsWith('.json'))\n let allMessages: z.infer<typeof ParserExecutableMessages> = []\n const uniqueDocsMap = new Map<\n string,\n z.infer<typeof ParseResponsePayload>['docs'][number]\n >()\n let allCreatedFiles: z.infer<typeof CreateResponsePayload>['createdFiles'] = []\n\n for (const file of jsonFiles) {\n const filePath = path.join(outputDir, file)\n try {\n const content = fs.readFileSync(filePath, 'utf8')\n const parsed = JSON.parse(content)\n if (Array.isArray(parsed.docs)) {\n // Deduplicate docs based on figmaNode + template\n // The template contains the actual code example and is unique per component.\n // This allows multiple different code components to map to the same Figma node,\n // while preventing the same component from being duplicated in multi-module projects.\n for (const doc of parsed.docs) {\n const dedupeKey = JSON.stringify({\n figmaNode: doc.figmaNode,\n template: doc.template,\n })\n if (!uniqueDocsMap.has(dedupeKey)) {\n uniqueDocsMap.set(dedupeKey, doc)\n }\n }\n }\n if (Array.isArray(parsed.createdFiles)) {\n allCreatedFiles = allCreatedFiles.concat(parsed.createdFiles)\n }\n if (Array.isArray(parsed.messages)) {\n allMessages = allMessages.concat(parsed.messages)\n }\n } catch (err) {\n logger.warn(`Failed to parse output file ${file}: ${err}`)\n }\n }\n\n const allDocs = Array.from(uniqueDocsMap.values())\n\n // Return the appropriate response based on the mode\n if (payload.mode === 'CREATE') {\n resolve({\n createdFiles: allCreatedFiles,\n messages: allMessages,\n })\n } else {\n resolve({\n docs: allDocs,\n messages: allMessages,\n })\n }\n } else {\n logger.debug(`Temporary output directory (${outputDir}) does not exist.`)\n }\n } catch (err) {\n logger.warn(`Failed to list files in temporary output directory: ${err}`)\n }\n } else {\n // Assume the output is in the stdout\n resolve(JSON.parse(stdout))\n }\n }\n\n if (parser.temporaryInputFilePath) {\n // Retain temp file and directory when verbose mode is enabled\n if (!(payload as any).verbose) {\n fs.unlinkSync(parser.temporaryInputFilePath)\n // Delete parent directory if empty after removing temp file\n const parentDir = path.dirname(parser.temporaryInputFilePath)\n if (fs.readdirSync(parentDir).length === 0) {\n fs.rmdirSync(parentDir)\n }\n }\n }\n })\n\n child.on('error', (e) => {\n reject(e)\n })\n if (!parser.temporaryInputFilePath) {\n child.stdin.write(JSON.stringify(payload))\n child.stdin.end()\n }\n } catch (e) {\n if ((payload as any).verbose) {\n console.trace(e)\n\n // Don't say to enable verbose if the user has already enabled it.\n exitWithError(`Error calling parser: ${e}.`)\n } else {\n exitWithError(\n `Error calling parser: ${e}. Try re-running the command with --verbose for more information.`,\n )\n }\n }\n })\n}\n\nexport function handleMessages(messages: z.infer<typeof ParserExecutableMessages>) {\n let hasErrors = false\n\n messages.forEach((message) => {\n switch (message.level) {\n case 'DEBUG':\n logger.debug(message.message)\n break\n case 'INFO':\n logger.info(message.message)\n break\n case 'WARN':\n logger.warn(message.message)\n break\n case 'ERROR':\n logger.error(message.message)\n hasErrors = true\n break\n }\n })\n\n return { hasErrors }\n}\n\n// This function is used to determine if there is a suggestion for the error based on the output\n// to stderr. Certain parsers return the same error code for different types of errors such as\n// errors from invoking the gradle wrapper for Compose.\n// In the future we should consider exposing a different API for having the parser return a suggestion directly.\nfunction determineErrorSuggestionFromStderr(\n stderr: string,\n parser: CodeConnectParser,\n): string | null {\n if (parser === 'compose') {\n return getComposeErrorSuggestion(stderr)\n }\n return null\n}\n"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { FigmaRestApi } from './figma_rest_api';
|
|
2
|
+
/**
|
|
3
|
+
* A single property value to overlay a node's `.properties`. `name` is normalized
|
|
4
|
+
* (no `#id` suffix) so it matches template references, e.g. `figma.boolean('Has Icon Start')`.
|
|
5
|
+
*/
|
|
6
|
+
export interface PropertyCombinationValue {
|
|
7
|
+
name: string;
|
|
8
|
+
type: FigmaRestApi.ComponentPropertyType;
|
|
9
|
+
value: string | boolean;
|
|
10
|
+
}
|
|
11
|
+
/** One renderable property combination: a label plus the full set of property values to overlay. */
|
|
12
|
+
export interface PropertyCombination {
|
|
13
|
+
label: string;
|
|
14
|
+
properties: PropertyCombinationValue[];
|
|
15
|
+
}
|
|
16
|
+
/** The typed vocabulary of a component's properties, attached to failed previews for repair hints. */
|
|
17
|
+
export interface AvailableProperty {
|
|
18
|
+
name: string;
|
|
19
|
+
type: FigmaRestApi.ComponentPropertyType;
|
|
20
|
+
variantOptions?: string[];
|
|
21
|
+
default?: string | boolean;
|
|
22
|
+
}
|
|
23
|
+
/** The typed, normalized property vocabulary of a component. */
|
|
24
|
+
export declare function toAvailableProperties(defs: Record<string, FigmaRestApi.ComponentPropertyDefinition>): AvailableProperty[];
|
|
25
|
+
export interface EnumeratePropertyCombinationsResult {
|
|
26
|
+
propertyCombinations: PropertyCombination[];
|
|
27
|
+
availableProperties: AvailableProperty[];
|
|
28
|
+
/** Set only when an explicit `maxCombinations` cap truncated the full cartesian. */
|
|
29
|
+
truncated: {
|
|
30
|
+
total: number;
|
|
31
|
+
cap: number;
|
|
32
|
+
} | null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Enumerate a component's renderable property combinations from its
|
|
36
|
+
* `componentPropertyDefinitions`: the cartesian product of VARIANT axes
|
|
37
|
+
* (their `variantOptions`) and BOOLEAN axes ({false, true}).
|
|
38
|
+
* TEXT/INSTANCE_SWAP props are held at `defaultValue` in every combination.
|
|
39
|
+
* Uncapped by default; pass `maxCombinations` to bound it.
|
|
40
|
+
*/
|
|
41
|
+
export declare function enumeratePropertyCombinations(defs: Record<string, FigmaRestApi.ComponentPropertyDefinition>, opts?: {
|
|
42
|
+
maxCombinations?: number;
|
|
43
|
+
}): EnumeratePropertyCombinationsResult;
|
|
44
|
+
export interface BuildPropertyCombinationResult {
|
|
45
|
+
propertyCombination: PropertyCombination;
|
|
46
|
+
availableProperties: AvailableProperty[];
|
|
47
|
+
/** Supplied property names that don't exist on the component. */
|
|
48
|
+
unknown: string[];
|
|
49
|
+
/** Supplied values that aren't valid for their VARIANT property. */
|
|
50
|
+
invalid: Array<{
|
|
51
|
+
name: string;
|
|
52
|
+
value: string;
|
|
53
|
+
options: string[];
|
|
54
|
+
}>;
|
|
55
|
+
/** Supplied names that match multiple types with no `TYPE:` prefix to disambiguate. */
|
|
56
|
+
ambiguous: Array<{
|
|
57
|
+
name: string;
|
|
58
|
+
types: FigmaRestApi.ComponentPropertyType[];
|
|
59
|
+
}>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Build a single property combination from an explicit set of `name=value` pairs
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildPropertyCombinationFromProps(defs: Record<string, FigmaRestApi.ComponentPropertyDefinition>, pairs: Array<{
|
|
65
|
+
name: string;
|
|
66
|
+
value: string;
|
|
67
|
+
type?: FigmaRestApi.ComponentPropertyType;
|
|
68
|
+
}>): BuildPropertyCombinationResult;
|
|
69
|
+
//# sourceMappingURL=property_combinations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"property_combinations.d.ts","sourceRoot":"","sources":["../../src/connect/property_combinations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAW/C;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,YAAY,CAAC,qBAAqB,CAAA;IACxC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;CACxB;AAED,oGAAoG;AACpG,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,wBAAwB,EAAE,CAAA;CACvC;AAED,sGAAsG;AACtG,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,YAAY,CAAC,qBAAqB,CAAA;IACxC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAC3B;AAED,gEAAgE;AAChE,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,2BAA2B,CAAC,GAC7D,iBAAiB,EAAE,CAOrB;AAED,MAAM,WAAW,mCAAmC;IAClD,oBAAoB,EAAE,mBAAmB,EAAE,CAAA;IAC3C,mBAAmB,EAAE,iBAAiB,EAAE,CAAA;IACxC,oFAAoF;IACpF,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CACjD;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,2BAA2B,CAAC,EAC9D,IAAI,GAAE;IAAE,eAAe,CAAC,EAAE,MAAM,CAAA;CAAO,GACtC,mCAAmC,CA0DrC;AAED,MAAM,WAAW,8BAA8B;IAC7C,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,mBAAmB,EAAE,iBAAiB,EAAE,CAAA;IACxC,iEAAiE;IACjE,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,oEAAoE;IACpE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;IAClE,uFAAuF;IACvF,SAAS,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,YAAY,CAAC,qBAAqB,EAAE,CAAA;KAAE,CAAC,CAAA;CAChF;AAED;;GAEG;AACH,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,2BAA2B,CAAC,EAC9D,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,YAAY,CAAC,qBAAqB,CAAA;CAAE,CAAC,GACvF,8BAA8B,CA6GhC"}
|