|
1 | 1 | import { addNamed } from '@babel/helper-module-imports'; |
2 | 2 | import { declare } from '@babel/helper-plugin-utils'; |
3 | | -import { sxObjectExtractor } from './sxObjectExtractor'; |
| 3 | +import { NodePath } from '@babel/core'; |
| 4 | +import * as Types from '@babel/types'; |
| 5 | +import { sxPropConvertor } from './sxPropConverter'; |
4 | 6 |
|
5 | | -export const babelPlugin = declare((api) => { |
6 | | - api.assertVersion(7); |
7 | | - const { types: t } = api; |
8 | | - return { |
9 | | - name: '@pigmentcss/zero-babel-plugin', |
10 | | - visitor: { |
11 | | - JSXAttribute(path) { |
12 | | - const namePath = path.get('name'); |
13 | | - const openingElement = path.findParent((p) => p.isJSXOpeningElement()); |
14 | | - if ( |
15 | | - !openingElement || |
16 | | - !openingElement.isJSXOpeningElement() || |
17 | | - !namePath.isJSXIdentifier() || |
18 | | - namePath.node.name !== 'sx' |
19 | | - ) { |
20 | | - return; |
21 | | - } |
22 | | - const tagName = openingElement.get('name'); |
23 | | - if (!tagName.isJSXIdentifier()) { |
24 | | - return; |
25 | | - } |
26 | | - const valuePath = path.get('value'); |
27 | | - if (!valuePath.isJSXExpressionContainer()) { |
28 | | - return; |
29 | | - } |
30 | | - const expressionPath = valuePath.get('expression'); |
31 | | - if (!expressionPath.isExpression()) { |
32 | | - return; |
33 | | - } |
34 | | - if (!expressionPath.isObjectExpression() && !expressionPath.isArrowFunctionExpression()) { |
35 | | - return; |
36 | | - } |
37 | | - sxObjectExtractor(expressionPath); |
38 | | - const sxIdentifier = addNamed(namePath, 'sx', process.env.PACKAGE_NAME as string); |
39 | | - expressionPath.replaceWith( |
40 | | - t.callExpression(sxIdentifier, [expressionPath.node, t.identifier(tagName.node.name)]), |
41 | | - ); |
42 | | - }, |
43 | | - ObjectProperty(path) { |
44 | | - // @TODO - Maybe add support for React.createElement calls as well. |
45 | | - // Right now, it only checks for jsx(),jsxs(),jsxDEV() and jsxsDEV() calls. |
46 | | - const keyPath = path.get('key'); |
47 | | - if (!keyPath.isIdentifier() || keyPath.node.name !== 'sx') { |
48 | | - return; |
49 | | - } |
50 | | - const valuePath = path.get('value'); |
51 | | - if (!valuePath.isObjectExpression() && !valuePath.isArrowFunctionExpression()) { |
52 | | - return; |
53 | | - } |
54 | | - const parentJsxCall = path.findParent((p) => p.isCallExpression()); |
55 | | - if (!parentJsxCall || !parentJsxCall.isCallExpression()) { |
56 | | - return; |
57 | | - } |
58 | | - const callee = parentJsxCall.get('callee'); |
59 | | - if (!callee.isIdentifier() || !callee.node.name.includes('jsx')) { |
60 | | - return; |
61 | | - } |
62 | | - const jsxElement = parentJsxCall.get('arguments')[0]; |
63 | | - sxObjectExtractor(valuePath); |
64 | | - const sxIdentifier = addNamed(keyPath, 'sx', process.env.PACKAGE_NAME as string); |
65 | | - valuePath.replaceWith(t.callExpression(sxIdentifier, [valuePath.node, jsxElement.node])); |
66 | | - }, |
67 | | - }, |
| 7 | +function replaceNodePath( |
| 8 | + expressionPath: NodePath<Types.Expression>, |
| 9 | + namePath: NodePath<Types.JSXIdentifier | Types.Identifier>, |
| 10 | + importName: string, |
| 11 | + t: typeof Types, |
| 12 | + tagName: NodePath<Types.JSXIdentifier | Types.Identifier>, |
| 13 | +) { |
| 14 | + const sxIdentifier = addNamed(namePath, importName, process.env.PACKAGE_NAME as string); |
| 15 | + |
| 16 | + const wrapWithSxCall = (expPath: NodePath<Types.Expression>) => { |
| 17 | + expPath.replaceWith( |
| 18 | + t.callExpression(sxIdentifier, [expPath.node, t.identifier(tagName.node.name)]), |
| 19 | + ); |
68 | 20 | }; |
69 | | -}); |
| 21 | + |
| 22 | + sxPropConvertor(expressionPath, wrapWithSxCall); |
| 23 | + // wrapWithSxCall(expressionPath); |
| 24 | +} |
| 25 | + |
| 26 | +export const babelPlugin = declare<{ propName?: string; importName?: string }>( |
| 27 | + (api, { propName = 'sx', importName = 'sx' }) => { |
| 28 | + api.assertVersion(7); |
| 29 | + const { types: t } = api; |
| 30 | + return { |
| 31 | + name: '@pigmentcss/zero-babel-plugin', |
| 32 | + visitor: { |
| 33 | + JSXAttribute(path) { |
| 34 | + const namePath = path.get('name'); |
| 35 | + const openingElement = path.findParent((p) => p.isJSXOpeningElement()); |
| 36 | + if ( |
| 37 | + !openingElement || |
| 38 | + !openingElement.isJSXOpeningElement() || |
| 39 | + !namePath.isJSXIdentifier() || |
| 40 | + namePath.node.name !== propName |
| 41 | + ) { |
| 42 | + return; |
| 43 | + } |
| 44 | + const tagName = openingElement.get('name'); |
| 45 | + if (!tagName.isJSXIdentifier()) { |
| 46 | + return; |
| 47 | + } |
| 48 | + const valuePath = path.get('value'); |
| 49 | + if (!valuePath.isJSXExpressionContainer()) { |
| 50 | + return; |
| 51 | + } |
| 52 | + const expressionPath = valuePath.get('expression'); |
| 53 | + if (!expressionPath.isExpression()) { |
| 54 | + return; |
| 55 | + } |
| 56 | + replaceNodePath(expressionPath, namePath, importName, t, tagName); |
| 57 | + }, |
| 58 | + ObjectProperty(path) { |
| 59 | + // @TODO - Maybe add support for React.createElement calls as well. |
| 60 | + // Right now, it only checks for jsx(),jsxs(),jsxDEV() and jsxsDEV() calls. |
| 61 | + const keyPath = path.get('key'); |
| 62 | + if (!keyPath.isIdentifier() || keyPath.node.name !== propName) { |
| 63 | + return; |
| 64 | + } |
| 65 | + const valuePath = path.get('value'); |
| 66 | + if (!valuePath.isObjectExpression() && !valuePath.isArrowFunctionExpression()) { |
| 67 | + return; |
| 68 | + } |
| 69 | + const parentJsxCall = path.findParent((p) => p.isCallExpression()); |
| 70 | + if (!parentJsxCall || !parentJsxCall.isCallExpression()) { |
| 71 | + return; |
| 72 | + } |
| 73 | + const callee = parentJsxCall.get('callee'); |
| 74 | + if (!callee.isIdentifier() || !callee.node.name.includes('jsx')) { |
| 75 | + return; |
| 76 | + } |
| 77 | + const jsxElement = parentJsxCall.get('arguments')[0] as NodePath<Types.Identifier>; |
| 78 | + replaceNodePath(valuePath, keyPath, importName, t, jsxElement); |
| 79 | + }, |
| 80 | + }, |
| 81 | + }; |
| 82 | + }, |
| 83 | +); |
0 commit comments