Skip to content

Commit 5987f41

Browse files
gigigimaymaytiya.m
andauthored
fix: handle useMemo, useCallback, forwardRef, list of elements (#10)
* refactor: refactor conditions for more readability * feat: rewrite function component injection * test: update snapshots * chore: update some packages * refactor: swap code order * feat: add more skipping logic; add more cases + update nodemon config * refactor: move processReactFunctionComponent into if * fix: fix return; fix lint; change to absolute import --------- Co-authored-by: maytiya.m <[email protected]>
1 parent 24680ef commit 5987f41

File tree

16 files changed

+221
-215
lines changed

16 files changed

+221
-215
lines changed

CONTRIBUTING.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@ yarn example:install
1111

1212
# Start development
1313
yarn dev
14+
15+
# Start development while updating snapshots
16+
yarn dev -u
1417
```

examples/src/components/functionComponents/__snapshots__/index.test.tsx.snap

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,23 @@ exports[`function components > 04 - with a const element in function scope 1`] =
3939
`;
4040

4141
exports[`function components > 05 - with a useCallback element in function scope 1`] = `
42-
<div>
42+
<div
43+
data-qa="component05"
44+
>
4345
<div
44-
data-qa="component05"
46+
data-qa="b"
4547
>
4648
xxx
4749
</div>
4850
</div>
4951
`;
5052

5153
exports[`function components > 06 - with a useMemo in function scope 1`] = `
52-
<div>
54+
<div
55+
data-qa="component06"
56+
>
5357
<div
54-
data-qa="component06"
58+
data-qa="b"
5559
>
5660
xxx
5761
</div>
@@ -71,14 +75,16 @@ exports[`function components > 07 - with a function component child element 1`]
7175
`;
7276

7377
exports[`function components > 08 - with list of elements in useMemo 1`] = `
74-
<div>
78+
<div
79+
data-qa="component08"
80+
>
7581
<div
76-
data-qa="component08"
82+
data-qa="list"
7783
>
7884
xxx
7985
</div>
8086
<div
81-
data-qa="component08"
87+
data-qa="list"
8288
>
8389
yyy
8490
</div>
@@ -98,21 +104,29 @@ HTMLCollection [
98104

99105
exports[`function components > 10 - fragment with list of elements in a const 1`] = `
100106
HTMLCollection [
101-
<div>
107+
<div
108+
data-qa="list"
109+
>
102110
xxx
103111
</div>,
104-
<div>
112+
<div
113+
data-qa="list"
114+
>
105115
yyy
106116
</div>,
107117
]
108118
`;
109119

110120
exports[`function components > 11 - fragment with list of elements in useMemo 1`] = `
111121
HTMLCollection [
112-
<div>
122+
<div
123+
data-qa="list"
124+
>
113125
xxx
114126
</div>,
115-
<div>
127+
<div
128+
data-qa="list"
129+
>
116130
yyy
117131
</div>,
118132
]
@@ -135,7 +149,9 @@ exports[`function components > 13 - with a function component with spreaded prop
135149
`;
136150

137151
exports[`function components > 14 - wrapped with forwardRef 1`] = `
138-
<div>
152+
<div
153+
data-qa="component14"
154+
>
139155
xxx
140156
</div>
141157
`;
@@ -148,10 +164,14 @@ HTMLCollection [
148164

149165
exports[`function components > 16 - fragment with list of elements from const 1`] = `
150166
HTMLCollection [
151-
<div>
167+
<div
168+
data-qa="list"
169+
>
152170
1
153171
</div>,
154-
<div>
172+
<div
173+
data-qa="list"
174+
>
155175
2
156176
</div>,
157177
]

examples/src/components/styledComponents/__snapshots__/index.test.tsx.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ exports[`styled components > 03 - returning styled component but with useMemo ab
3737
3838
<div
3939
class="c0"
40-
data-qa="styled-a"
40+
data-qa="component03"
4141
>
4242
<div
43-
data-qa="component03"
43+
data-qa="b"
4444
>
4545
xxx
4646
</div>

examples/yarn.lock

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@
377377
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
378378
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
379379

380-
"@jridgewell/sourcemap-codec@^1.4.13", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0":
380+
"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0":
381381
version "1.5.4"
382382
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz#7358043433b2e5da569aa02cbc4c121da3af27d7"
383383
integrity sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==
@@ -395,14 +395,14 @@
395395
resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.19.tgz#fc3b95145a8e7a3bf92754269d8e4f40eea8a244"
396396
integrity sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==
397397

398-
"@rollup/pluginutils@5.0.2":
399-
version "5.0.2"
400-
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.2.tgz#012b8f53c71e4f6f9cb317e311df1404f56e7a33"
401-
integrity sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==
398+
"@rollup/pluginutils@5.2.0":
399+
version "5.2.0"
400+
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.2.0.tgz#eac25ca5b0bdda4ba735ddaca5fbf26bd435f602"
401+
integrity sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==
402402
dependencies:
403403
"@types/estree" "^1.0.0"
404404
estree-walker "^2.0.2"
405-
picomatch "^2.3.1"
405+
picomatch "^4.0.2"
406406

407407
408408
version "4.45.0"
@@ -1154,14 +1154,7 @@ lz-string@^1.5.0:
11541154
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941"
11551155
integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==
11561156

1157-
1158-
version "0.27.0"
1159-
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3"
1160-
integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==
1161-
dependencies:
1162-
"@jridgewell/sourcemap-codec" "^1.4.13"
1163-
1164-
magic-string@^0.30.17:
1157+
[email protected], magic-string@^0.30.17:
11651158
version "0.30.17"
11661159
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453"
11671160
integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==
@@ -1247,11 +1240,6 @@ picocolors@^1.1.1:
12471240
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
12481241
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
12491242

1250-
picomatch@^2.3.1:
1251-
version "2.3.1"
1252-
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
1253-
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
1254-
12551243
picomatch@^4.0.2:
12561244
version "4.0.2"
12571245
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab"
@@ -1327,11 +1315,11 @@ redent@^3.0.0:
13271315
"rollup-plugin-data-qa@file:../dist":
13281316
version "1.0.15"
13291317
dependencies:
1330-
"@rollup/pluginutils" "5.0.2"
1318+
"@rollup/pluginutils" "5.2.0"
13311319
change-case "4.1.2"
13321320
estree-walker "2.0.2"
13331321
lodash "4.17.21"
1334-
magic-string "0.27.0"
1322+
magic-string "0.30.17"
13351323

13361324
rollup@^4.40.0:
13371325
version "4.45.0"

nodemon.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"watch": ["src"],
2+
"watch": ["src", "examples/src"],
33
"ext": "ts,tsx",
44
"ignore": ["src/**/*.spec.ts", "src/**/*.test.ts", "dist/**/*"],
55
"exec": "yarn build && yarn example:sync && yarn example:test --run",
6-
"delay": 200
6+
"delay": 100
77
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@
4343
"postversion": "cp package.json .."
4444
},
4545
"dependencies": {
46-
"@rollup/pluginutils": "5.0.2",
46+
"@rollup/pluginutils": "5.2.0",
4747
"change-case": "4.1.2",
4848
"estree-walker": "2.0.2",
4949
"lodash": "4.17.21",
50-
"magic-string": "0.27.0"
50+
"magic-string": "0.30.17"
5151
},
5252
"devDependencies": {
5353
"@optimize-lodash/rollup-plugin": "4.0.1",

src/core/injectReactFunctionComponent/index.ts

Lines changed: 48 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,69 +6,66 @@ import isObjectAssigning from 'utils/isObjectAssigning'
66
import appendObject from 'utils/magicString/appendObject'
77
import insertToObject from 'utils/magicString/insertToObject'
88
import overwriteWithObject from 'utils/magicString/overwriteWithObject'
9-
import isReactNode from 'utils/magicString/react/isReactNode'
9+
import isReactNode from 'utils/react/isReactNode'
1010

1111
type Params = {
1212
node: Record<string, any>
13-
parent: Record<string, any>
1413
code: MagicString
1514
componentName: string
1615
}
1716

18-
export default function injectReactFunctionComponent({
19-
node,
20-
parent,
21-
code,
22-
componentName,
23-
}: Params) {
24-
if (isReactNode(node) && parent.type !== 'CallExpression') {
25-
const tagProps = node.arguments[1]
17+
export default function injectReactFunctionComponent({ node, code, componentName }: Params) {
18+
if (!isReactNode(node)) return false
2619

27-
if (tagProps?.start || !isEmpty(tagProps.properties)) {
28-
const hasProps = tagProps.value !== null // NOTE: if a component has props, the value will always be undefined
20+
const tagProps = node.arguments[1]
2921

30-
if (hasProps) {
31-
// e.g `<svg>...</svg>`
32-
if (isObjectAssigning(tagProps)) {
33-
const firstArgs = head(tagProps.arguments as Record<string, any>[])
22+
if (!tagProps?.start && isEmpty(tagProps.properties)) return false
3423

35-
firstArgs &&
36-
insertToObject({
37-
code,
38-
node: firstArgs,
39-
attrs: { [DATA_QA]: componentName },
40-
})
41-
} else {
42-
// e.g `<div />`
43-
if (isEmpty(tagProps.properties)) {
44-
insertToObject({
45-
code,
46-
node: tagProps,
47-
attrs: { [DATA_QA]: componentName },
48-
})
49-
} else {
50-
const props = head(tagProps.properties as Record<string, any>[])
24+
// NOTE: if a component has props, the value will always be undefined
25+
const hasProps = tagProps.value !== null
5126

52-
props &&
53-
appendObject({
54-
code,
55-
startPosition: props.start,
56-
attrs: { [DATA_QA]: componentName },
57-
})
58-
}
59-
}
60-
} else {
61-
overwriteWithObject({
62-
code,
63-
startPosition: tagProps.start,
64-
endPosition: tagProps.end,
65-
attrs: { [DATA_QA]: componentName },
66-
})
67-
}
27+
if (!hasProps) {
28+
overwriteWithObject({
29+
code,
30+
startPosition: tagProps.start,
31+
endPosition: tagProps.end,
32+
attrs: { [DATA_QA]: componentName },
33+
})
34+
return true
35+
}
36+
37+
// e.g `<svg>...</svg>`
38+
if (isObjectAssigning(tagProps)) {
39+
const firstArgs = head(tagProps.arguments as Record<string, any>[])
6840

69-
return true
70-
}
41+
if (!firstArgs) return false
42+
43+
insertToObject({
44+
code,
45+
node: firstArgs,
46+
attrs: { [DATA_QA]: componentName },
47+
})
48+
return true
7149
}
7250

73-
return false
51+
// e.g `<div />`
52+
if (isEmpty(tagProps.properties)) {
53+
insertToObject({
54+
code,
55+
node: tagProps,
56+
attrs: { [DATA_QA]: componentName },
57+
})
58+
return true
59+
}
60+
61+
const props = head(tagProps.properties as Record<string, any>[])
62+
63+
if (!props) return false
64+
65+
appendObject({
66+
code,
67+
startPosition: props.start,
68+
attrs: { [DATA_QA]: componentName },
69+
})
70+
return true
7471
}

src/core/injectStyledComponent/index.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ type Params = {
99
code: MagicString
1010
styledComponentName: string
1111
node: Record<string, any>
12-
parent: Record<string, any>
12+
parent: Record<string, any> | null
1313
}
1414

1515
export default function injectStyledComponent({ styledComponentName, node, parent, code }: Params) {
1616
if (
1717
node?.type === 'MemberExpression' &&
1818
node?.object.name === 'styled' &&
19-
parent.property?.name !== 'attrs'
19+
parent?.property?.name !== 'attrs'
2020
) {
2121
chainFunctionWithProps({
2222
code,
@@ -26,7 +26,9 @@ export default function injectStyledComponent({ styledComponentName, node, paren
2626
})
2727

2828
return true
29-
} else if (
29+
}
30+
31+
if (
3032
parent?.callee?.property?.name === 'attrs' &&
3133
node.type === 'ArrowFunctionExpression' &&
3234
!isEmpty(node.body.properties)
@@ -40,7 +42,9 @@ export default function injectStyledComponent({ styledComponentName, node, paren
4042
})
4143

4244
return true
43-
} else if (
45+
}
46+
47+
if (
4448
parent?.callee?.property?.name === 'attrs' &&
4549
node.type === 'ObjectExpression' &&
4650
!isEmpty(node.properties)

0 commit comments

Comments
 (0)