Skip to content

Commit d2a69e9

Browse files
author
figma-bot
committed
Code Connect v1.3.4
1 parent e6a9db9 commit d2a69e9

File tree

6 files changed

+70
-30
lines changed

6 files changed

+70
-30
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
# Code Connect v1.3.4 (TBD)
1+
# Code Connect v1.3.4 (26th June 2025)
2+
3+
### Fixed
4+
5+
# React
6+
7+
- Support getProps inside nestedProps
28

39
# Code Connect v1.3.3 (22nd May 2025)
410

cli/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@figma/code-connect",
3-
"version": "1.3.3",
3+
"version": "1.3.4",
44
"description": "A tool for connecting your design system components in code with your design system in Figma",
55
"keywords": [],
66
"author": "Figma",
@@ -38,7 +38,7 @@
3838
"dev": "tsx src/cli.ts",
3939
"build": "rm -rf dist && npm run typecheck && tsc",
4040
"build:web": "pnpm build",
41-
"build:webpack": "cross-env NODE_OPTIONS=\"--max-old-space-size=4096\" webpack --mode production",
41+
"build:webpack": "cross-env NODE_OPTIONS=\"--max-old-space-size=8196\" webpack --mode production",
4242
"test": "npm run test:no-coverage -- --coverage",
4343
"test:no-coverage": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --no-deprecation --max-old-space-size=10240\" npx jest --logHeapUsage --workerIdleMemoryLimit=1.5G",
4444
"test:fast": "npm run test -- --testPathIgnorePatterns=template_rendering.test.ts --testPathIgnorePatterns=e2e_parse_command_swift.test.ts --testPathIgnorePatterns=e2e_wizard_swift.test.ts",
@@ -66,7 +66,7 @@
6666
"@babel/parser": "7.26.10",
6767
"@babel/types": "7.26.10",
6868

69-
"@storybook/csf-tools": "^8.4.7",
69+
"@storybook/csf-tools": "8.5.1",
7070
"@types/cross-spawn": "^6.0.6",
7171
"@types/jest": "^29.5.13",
7272
"@types/jsdom": "^21.1.7",
@@ -83,7 +83,7 @@
8383
"ts-jest": "^29.2.5",
8484
"ts-loader": "^9.5.1",
8585
"tsx": "^4.11.0",
86-
"webpack": "^5.91.0",
86+
"webpack": "^5.99.6",
8787
"webpack-cli": "^5.1.4"
8888
},
8989
"dependencies": {
@@ -108,7 +108,7 @@
108108
"ts-morph": "^23.0.0",
109109
"typescript": "5.5.4",
110110
"undici": "^5.29.0",
111-
"zod": "3.23.8",
112-
"zod-validation-error": "3.4.0"
111+
"zod": "3.25.58",
112+
"zod-validation-error": "^3.2.0"
113113
}
114114
}

cli/src/common/tsconfig.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import fs from 'fs'
2+
import findUp from 'find-up'
3+
import path from 'path'
4+
5+
export function findTsConfigPath(dir: string): string | undefined {
6+
let tsConfigPath: string | undefined = undefined
7+
8+
findUp.sync(
9+
(currentDir) => {
10+
const pathToTry = path.join(currentDir, 'tsconfig.json')
11+
12+
if (fs.existsSync(pathToTry)) {
13+
tsConfigPath = pathToTry
14+
return findUp.stop
15+
}
16+
},
17+
{ cwd: dir },
18+
)
19+
20+
return tsConfigPath
21+
}

cli/src/connect/parser_common.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,17 @@ export function visitPropReferencingNode({
173173
) {
174174
// nested notation e.g `props.nested.prop`
175175
if (ts.isPropertyAccessExpression(node.expression)) {
176-
const name = `${node.expression.name.getText()}.${node.name.getText()}`
176+
let current: ts.Node = node
177+
const parts: string[] = []
178+
179+
// Build the property name by traversing up the chain
180+
while (ts.isPropertyAccessExpression(current)) {
181+
parts.unshift(current.name.getText())
182+
current = current.expression
183+
}
184+
185+
// Join the parts together to form the full property name
186+
const name = parts.join('.')
177187
return createPropPlaceholder({ name, node })
178188
}
179189
const name = node.name.getText()

cli/src/connect/wizard/signature_extraction.ts

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import path from 'path'
2-
import fs from 'fs'
3-
import findUp from 'find-up'
42
import { Project, ScriptTarget, SourceFile, Symbol, ts } from 'ts-morph'
3+
import { findTsConfigPath } from '../../common/tsconfig'
54

65
const DEFAULT_COMPONENT = 'DefaultComponent'
76
const REACT_INTERFACE_NAMES = ['HTMLAttributes', 'Attributes', 'AriaAttributes', 'DOMAttributes']
@@ -161,21 +160,3 @@ function getPropString(tsMorphProject: Project, prop: Symbol, sourceFile: Source
161160
? `?${propTypeString.replace(/undefined \| /g, '')}`
162161
: propTypeString
163162
}
164-
165-
function findTsConfigPath(dir: string): string | undefined {
166-
let tsConfigPath: string | undefined = undefined
167-
168-
findUp.sync(
169-
(currentDir) => {
170-
const pathToTry = path.join(currentDir, 'tsconfig.json')
171-
172-
if (fs.existsSync(pathToTry)) {
173-
tsConfigPath = pathToTry
174-
return findUp.stop
175-
}
176-
},
177-
{ cwd: dir },
178-
)
179-
180-
return tsConfigPath
181-
}

cli/src/html/parser_template_helpers.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66

77
declare const figma: { html: (template: TemplateStringsArray, ...args: any[]) => string }
88

9+
export type FCCValue =
10+
| string
11+
| number
12+
| boolean
13+
| undefined
14+
| ReturnType<typeof _fcc_identifier | typeof _fcc_object | typeof _fcc_templateString>
15+
916
export function _fcc_templateString($value: string) {
1017
return {
1118
$value,
@@ -21,6 +28,13 @@ export function _fcc_object($value: Record<string, any>) {
2128
} as const
2229
}
2330

31+
export function _fcc_identifier($value: string) {
32+
return {
33+
$value,
34+
$type: 'identifier',
35+
} as const
36+
}
37+
2438
/**
2539
* Render a value to HTML, following sensible rules according to the type.
2640
*
@@ -54,7 +68,7 @@ function _fcc_renderHtmlValue(value: any): string {
5468
* @param name The name of the attribute
5569
* @param value The value of the attribute
5670
*/
57-
function _fcc_renderHtmlAttribute(name: string, value: any) {
71+
function _fcc_renderHtmlAttribute(name: string, value: FCCValue) {
5872
// figma.boolean returns undefined instead of false in some cases
5973
if (typeof value === 'undefined') {
6074
return ''
@@ -66,14 +80,22 @@ function _fcc_renderHtmlAttribute(name: string, value: any) {
6680
}
6781
} else if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint') {
6882
return `${name}="${value.toString().replaceAll('\n', '\\n').replaceAll('"', '\\"')}"`
83+
} else if (value.$type === 'identifier') {
84+
return `${name}="${value.$value}"`
6985
} else {
7086
// TODO make this show a proper error in the UI
7187
return `${name}="Code Connect Error: Unsupported type '${typeof value}' for attribute"`
7288
}
7389
}
7490

7591
export function getParsedTemplateHelpersString() {
76-
return [_fcc_templateString, _fcc_object, _fcc_renderHtmlValue, _fcc_renderHtmlAttribute]
92+
return [
93+
_fcc_templateString,
94+
_fcc_object,
95+
_fcc_renderHtmlValue,
96+
_fcc_renderHtmlAttribute,
97+
_fcc_identifier,
98+
]
7799
.map((fn) => fn.toString())
78100
.join('\n')
79101
}

0 commit comments

Comments
 (0)