@ornikar/kitt-universal 27.5.1-canary.4d3ec9b2bbb3371c254ae88141f81bb445a59f73.0 → 27.6.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/CHANGELOG.md +6 -5
- package/dist/definitions/TabBar/TabBar.d.ts +6 -4
- package/dist/definitions/TabBar/TabBar.d.ts.map +1 -1
- package/dist/definitions/TabBar/TabBarItem.d.ts +11 -1
- package/dist/definitions/TabBar/TabBarItem.d.ts.map +1 -1
- package/dist/definitions/native-base/KittNativeBaseProvider.d.ts +180 -12
- package/dist/definitions/native-base/KittNativeBaseProvider.d.ts.map +1 -1
- package/dist/definitions/themes/default.d.ts +1 -12
- package/dist/definitions/themes/default.d.ts.map +1 -1
- package/dist/definitions/themes/late-ocean/icon.d.ts +0 -20
- package/dist/definitions/themes/late-ocean/icon.d.ts.map +1 -1
- package/dist/definitions/themes/late-ocean/tabBar.d.ts +34 -0
- package/dist/definitions/themes/late-ocean/tabBar.d.ts.map +1 -0
- package/dist/definitions/typography/Typography.d.ts.map +1 -1
- package/dist/definitions/typography/TypographyIcon.d.ts.map +1 -1
- package/dist/definitions/typography/utils/getTypographyFamily.d.ts +2 -1
- package/dist/definitions/typography/utils/getTypographyFamily.d.ts.map +1 -1
- package/dist/index-metro.es.android.js +565 -250
- package/dist/index-metro.es.android.js.map +1 -1
- package/dist/index-metro.es.ios.js +565 -250
- package/dist/index-metro.es.ios.js.map +1 -1
- package/dist/index-node-22.17.cjs.js +456 -140
- package/dist/index-node-22.17.cjs.js.map +1 -1
- package/dist/index-node-22.17.cjs.web.js +457 -141
- package/dist/index-node-22.17.cjs.web.js.map +1 -1
- package/dist/index-node-22.17.es.mjs +456 -140
- package/dist/index-node-22.17.es.mjs.map +1 -1
- package/dist/index-node-22.17.es.web.mjs +457 -141
- package/dist/index-node-22.17.es.web.mjs.map +1 -1
- package/dist/index.es.js +567 -242
- package/dist/index.es.js.map +1 -1
- package/dist/index.es.web.js +566 -241
- package/dist/index.es.web.js.map +1 -1
- package/dist/linaria-themes-metro.es.android.js +179 -36
- package/dist/linaria-themes-metro.es.android.js.map +1 -1
- package/dist/linaria-themes-metro.es.ios.js +179 -36
- package/dist/linaria-themes-metro.es.ios.js.map +1 -1
- package/dist/linaria-themes-node-22.17.cjs.js +179 -36
- package/dist/linaria-themes-node-22.17.cjs.js.map +1 -1
- package/dist/linaria-themes-node-22.17.cjs.web.js +179 -36
- package/dist/linaria-themes-node-22.17.cjs.web.js.map +1 -1
- package/dist/linaria-themes-node-22.17.es.mjs +179 -36
- package/dist/linaria-themes-node-22.17.es.mjs.map +1 -1
- package/dist/linaria-themes-node-22.17.es.web.mjs +179 -36
- package/dist/linaria-themes-node-22.17.es.web.mjs.map +1 -1
- package/dist/linaria-themes.es.js +179 -36
- package/dist/linaria-themes.es.js.map +1 -1
- package/dist/linaria-themes.es.web.js +179 -36
- package/dist/linaria-themes.es.web.js.map +1 -1
- package/dist/tsbuildinfo +1 -1
- package/package.json +2 -2
- package/scripts/codemods/card-modal.js +155 -0
- package/scripts/codemods/fullscreen-modal.js +155 -0
- package/scripts/codemods/navigation-modal.js +155 -0
- package/scripts/{run-transformers.js → run-codemods.js} +12 -12
- package/scripts/transformers/card-modal.js +0 -136
- package/scripts/transformers/fullscreen-modal.js +0 -138
- package/scripts/transformers/navigation-modal.js +0 -138
- /package/scripts/{transformers → codemods}/__testfixtures__/card-modal/basic.input.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/card-modal/basic.output.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/card-modal/withExpressions.input.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/card-modal/withExpressions.output.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/card-modal/wrongOrder.input.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/card-modal/wrongOrder.output.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/fullscreen-modal/basic.input.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/fullscreen-modal/basic.output.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/fullscreen-modal/withExpressions.input.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/fullscreen-modal/withExpressions.output.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/fullscreen-modal/wrongOrder.input.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/fullscreen-modal/wrongOrder.output.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/navigation-modal/basic.input.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/navigation-modal/basic.output.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/navigation-modal/withExpressions.input.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/navigation-modal/withExpressions.output.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/navigation-modal/wrongOrder.input.js +0 -0
- /package/scripts/{transformers → codemods}/__testfixtures__/navigation-modal/wrongOrder.output.js +0 -0
- /package/scripts/{transformers → codemods}/__tests__/card-modal.test.js +0 -0
- /package/scripts/{transformers → codemods}/__tests__/fullscreen-modal.test.js +0 -0
- /package/scripts/{transformers → codemods}/__tests__/navigation-modal.test.js +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ornikar/kitt-universal",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.6.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"directory": "@ornikar/kitt-universal",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"./babel-plugin-csf-to-jest": "./babel-plugin-csf-to-jest.js"
|
|
73
73
|
},
|
|
74
74
|
"bin": {
|
|
75
|
-
"run-
|
|
75
|
+
"run-codemods": "./scripts/run-codemods.js"
|
|
76
76
|
},
|
|
77
77
|
"engines": {
|
|
78
78
|
"node": ">=22.17.0"
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Transforms CardModal components from prop-based structure to children-based structure.
|
|
5
|
+
* Converts header, body, and footer props into direct children, maintaining proper order.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Use local jscodeshift instance directly
|
|
9
|
+
const jscodeshift = require('jscodeshift');
|
|
10
|
+
const prettier = require('prettier');
|
|
11
|
+
|
|
12
|
+
module.exports = async function transformer(fileInfo, api) {
|
|
13
|
+
// Use the jscodeshift API to parse the file
|
|
14
|
+
const j = api.jscodeshift || jscodeshift;
|
|
15
|
+
|
|
16
|
+
// Parse the source code of the file
|
|
17
|
+
const root = j(fileInfo.source);
|
|
18
|
+
|
|
19
|
+
// ----------- Start of codemod logic
|
|
20
|
+
|
|
21
|
+
let hasChanges = false;
|
|
22
|
+
|
|
23
|
+
// Find all CardModal JSX elements
|
|
24
|
+
root
|
|
25
|
+
.find(j.JSXElement, {
|
|
26
|
+
openingElement: {
|
|
27
|
+
name: {
|
|
28
|
+
name: 'CardModal',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
.forEach((path) => {
|
|
33
|
+
const element = path.value;
|
|
34
|
+
const openingElement = element.openingElement;
|
|
35
|
+
|
|
36
|
+
// Check if this CardModal has header, body, or footer props
|
|
37
|
+
const headerProp = openingElement.attributes.find(
|
|
38
|
+
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'header',
|
|
39
|
+
);
|
|
40
|
+
const bodyProp = openingElement.attributes.find(
|
|
41
|
+
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'body',
|
|
42
|
+
);
|
|
43
|
+
const footerProp = openingElement.attributes.find(
|
|
44
|
+
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'footer',
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// Only transform if at least one of these props exists
|
|
48
|
+
if (!headerProp && !bodyProp && !footerProp) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
hasChanges = true;
|
|
53
|
+
|
|
54
|
+
// Extract the prop values and create children
|
|
55
|
+
const children = [];
|
|
56
|
+
|
|
57
|
+
// Helper function to extract content from prop value
|
|
58
|
+
const extractPropContent = (prop) => {
|
|
59
|
+
if (!prop || !prop.value) return [];
|
|
60
|
+
|
|
61
|
+
if (prop.value.type === 'JSXExpressionContainer') {
|
|
62
|
+
const expression = prop.value.expression;
|
|
63
|
+
|
|
64
|
+
// Check if the expression is a CardModal.Body - if so, extract its children
|
|
65
|
+
if (
|
|
66
|
+
expression.type === 'JSXElement' &&
|
|
67
|
+
expression.openingElement.name.type === 'JSXMemberExpression' &&
|
|
68
|
+
expression.openingElement.name.object.name === 'CardModal' &&
|
|
69
|
+
expression.openingElement.name.property.name === 'Body'
|
|
70
|
+
) {
|
|
71
|
+
// Return the CardModal.Body element itself, not its children
|
|
72
|
+
return [expression];
|
|
73
|
+
} else if (expression.type === 'JSXElement') {
|
|
74
|
+
// For other JSX elements (header, footer), return the element directly (not wrapped)
|
|
75
|
+
return [expression];
|
|
76
|
+
} else {
|
|
77
|
+
// For other expressions (including conditionals), return as JSX expression
|
|
78
|
+
return [j.jsxExpressionContainer(expression)];
|
|
79
|
+
}
|
|
80
|
+
} else if (prop.value.type === 'JSXElement') {
|
|
81
|
+
// Direct JSX element
|
|
82
|
+
if (
|
|
83
|
+
prop.value.openingElement.name.type === 'JSXMemberExpression' &&
|
|
84
|
+
prop.value.openingElement.name.object.name === 'CardModal' &&
|
|
85
|
+
prop.value.openingElement.name.property.name === 'Body'
|
|
86
|
+
) {
|
|
87
|
+
// Direct CardModal.Body element - return the element itself
|
|
88
|
+
return [prop.value];
|
|
89
|
+
} else {
|
|
90
|
+
// For other direct JSX elements (like CardModal.Header, CardModal.Footer), return as-is
|
|
91
|
+
return [prop.value];
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
// For other types, return as-is
|
|
95
|
+
return [prop.value];
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Add header first
|
|
100
|
+
if (headerProp) {
|
|
101
|
+
const headerContent = extractPropContent(headerProp);
|
|
102
|
+
children.push(...headerContent);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Add body second
|
|
106
|
+
if (bodyProp) {
|
|
107
|
+
const bodyContent = extractPropContent(bodyProp);
|
|
108
|
+
children.push(...bodyContent);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Add footer last
|
|
112
|
+
if (footerProp) {
|
|
113
|
+
const footerContent = extractPropContent(footerProp);
|
|
114
|
+
children.push(...footerContent);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Remove the header, body, and footer props from attributes
|
|
118
|
+
openingElement.attributes = openingElement.attributes.filter((attr) => {
|
|
119
|
+
return !(
|
|
120
|
+
attr.type === 'JSXAttribute' &&
|
|
121
|
+
(attr.name.name === 'header' || attr.name.name === 'body' || attr.name.name === 'footer')
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Update the element to be self-closing if no children, or add children
|
|
126
|
+
if (children.length === 0) {
|
|
127
|
+
openingElement.selfClosing = true;
|
|
128
|
+
element.closingElement = null;
|
|
129
|
+
element.children = [];
|
|
130
|
+
} else {
|
|
131
|
+
openingElement.selfClosing = false;
|
|
132
|
+
if (!element.closingElement) {
|
|
133
|
+
element.closingElement = j.jsxClosingElement(j.jsxIdentifier('CardModal'));
|
|
134
|
+
}
|
|
135
|
+
element.children = children;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Only return modified code if changes were made
|
|
140
|
+
if (!hasChanges) {
|
|
141
|
+
return fileInfo.source;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ----------- End of codemod logic
|
|
145
|
+
|
|
146
|
+
// Return the modified source code after transformation
|
|
147
|
+
const output = root.toSource({ quote: 'single' });
|
|
148
|
+
|
|
149
|
+
const prettierConfig = await prettier.resolveConfig(fileInfo.path);
|
|
150
|
+
|
|
151
|
+
return prettier.format(output, {
|
|
152
|
+
...prettierConfig,
|
|
153
|
+
filepath: fileInfo.path,
|
|
154
|
+
});
|
|
155
|
+
};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Transforms FullscreenModal components from prop-based structure to children-based structure.
|
|
5
|
+
* Converts header, body, and footer props into direct children, maintaining proper order.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Use local jscodeshift instance directly
|
|
9
|
+
const jscodeshift = require('jscodeshift');
|
|
10
|
+
const prettier = require('prettier');
|
|
11
|
+
|
|
12
|
+
module.exports = async function transformer(fileInfo, api) {
|
|
13
|
+
// Use the jscodeshift API to parse the file
|
|
14
|
+
const j = api.jscodeshift || jscodeshift;
|
|
15
|
+
|
|
16
|
+
// Parse the source code of the file
|
|
17
|
+
const root = j(fileInfo.source);
|
|
18
|
+
|
|
19
|
+
// ----------- Start of codemod logic
|
|
20
|
+
|
|
21
|
+
let hasChanges = false;
|
|
22
|
+
|
|
23
|
+
// Find all FullscreenModal JSX elements
|
|
24
|
+
root
|
|
25
|
+
.find(j.JSXElement, {
|
|
26
|
+
openingElement: {
|
|
27
|
+
name: {
|
|
28
|
+
name: 'FullscreenModal',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
.forEach((path) => {
|
|
33
|
+
const element = path.value;
|
|
34
|
+
const openingElement = element.openingElement;
|
|
35
|
+
|
|
36
|
+
// Check if this FullscreenModal has header, body, or footer props
|
|
37
|
+
const headerProp = openingElement.attributes.find(
|
|
38
|
+
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'header',
|
|
39
|
+
);
|
|
40
|
+
const bodyProp = openingElement.attributes.find(
|
|
41
|
+
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'body',
|
|
42
|
+
);
|
|
43
|
+
const footerProp = openingElement.attributes.find(
|
|
44
|
+
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'footer',
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// Only transform if at least one of these props exists
|
|
48
|
+
if (!headerProp && !bodyProp && !footerProp) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
hasChanges = true;
|
|
53
|
+
|
|
54
|
+
// Extract the prop values and create children
|
|
55
|
+
const children = [];
|
|
56
|
+
|
|
57
|
+
// Helper function to extract content from prop value
|
|
58
|
+
const extractPropContent = (prop) => {
|
|
59
|
+
if (!prop || !prop.value) return [];
|
|
60
|
+
|
|
61
|
+
if (prop.value.type === 'JSXExpressionContainer') {
|
|
62
|
+
const expression = prop.value.expression;
|
|
63
|
+
|
|
64
|
+
// Check if the expression is a FullscreenModal.Body - if so, keep the element
|
|
65
|
+
if (
|
|
66
|
+
expression.type === 'JSXElement' &&
|
|
67
|
+
expression.openingElement.name.type === 'JSXMemberExpression' &&
|
|
68
|
+
expression.openingElement.name.object.name === 'FullscreenModal' &&
|
|
69
|
+
expression.openingElement.name.property.name === 'Body'
|
|
70
|
+
) {
|
|
71
|
+
// Return the FullscreenModal.Body element itself
|
|
72
|
+
return [expression];
|
|
73
|
+
} else if (expression.type === 'JSXElement') {
|
|
74
|
+
// For other JSX elements (header, footer), return the element directly (not wrapped)
|
|
75
|
+
return [expression];
|
|
76
|
+
} else {
|
|
77
|
+
// For other expressions (including conditionals), return as JSX expression
|
|
78
|
+
return [j.jsxExpressionContainer(expression)];
|
|
79
|
+
}
|
|
80
|
+
} else if (prop.value.type === 'JSXElement') {
|
|
81
|
+
// Direct JSX element
|
|
82
|
+
if (
|
|
83
|
+
prop.value.openingElement.name.type === 'JSXMemberExpression' &&
|
|
84
|
+
prop.value.openingElement.name.object.name === 'FullscreenModal' &&
|
|
85
|
+
prop.value.openingElement.name.property.name === 'Body'
|
|
86
|
+
) {
|
|
87
|
+
// Direct FullscreenModal.Body element - return the element itself
|
|
88
|
+
return [prop.value];
|
|
89
|
+
} else {
|
|
90
|
+
// For other direct JSX elements (like FullscreenModal.Header, FullscreenModal.Footer), return as-is
|
|
91
|
+
return [prop.value];
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
// For other types, return as-is
|
|
95
|
+
return [prop.value];
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Add header first
|
|
100
|
+
if (headerProp) {
|
|
101
|
+
const headerContent = extractPropContent(headerProp);
|
|
102
|
+
children.push(...headerContent);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Add body second
|
|
106
|
+
if (bodyProp) {
|
|
107
|
+
const bodyContent = extractPropContent(bodyProp);
|
|
108
|
+
children.push(...bodyContent);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Add footer last
|
|
112
|
+
if (footerProp) {
|
|
113
|
+
const footerContent = extractPropContent(footerProp);
|
|
114
|
+
children.push(...footerContent);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Remove the header, body, and footer props from attributes
|
|
118
|
+
openingElement.attributes = openingElement.attributes.filter((attr) => {
|
|
119
|
+
return !(
|
|
120
|
+
attr.type === 'JSXAttribute' &&
|
|
121
|
+
(attr.name.name === 'header' || attr.name.name === 'body' || attr.name.name === 'footer')
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Update the element to be self-closing if no children, or add children
|
|
126
|
+
if (children.length === 0) {
|
|
127
|
+
openingElement.selfClosing = true;
|
|
128
|
+
element.closingElement = null;
|
|
129
|
+
element.children = [];
|
|
130
|
+
} else {
|
|
131
|
+
openingElement.selfClosing = false;
|
|
132
|
+
if (!element.closingElement) {
|
|
133
|
+
element.closingElement = j.jsxClosingElement(j.jsxIdentifier('FullscreenModal'));
|
|
134
|
+
}
|
|
135
|
+
element.children = children;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Only return modified code if changes were made
|
|
140
|
+
if (!hasChanges) {
|
|
141
|
+
return fileInfo.source;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ----------- End of codemod logic
|
|
145
|
+
|
|
146
|
+
// Return the modified source code after transformation
|
|
147
|
+
const output = root.toSource({ quote: 'single' });
|
|
148
|
+
|
|
149
|
+
const prettierConfig = await prettier.resolveConfig(fileInfo.path);
|
|
150
|
+
|
|
151
|
+
return prettier.format(output, {
|
|
152
|
+
...prettierConfig,
|
|
153
|
+
filepath: fileInfo.path,
|
|
154
|
+
});
|
|
155
|
+
};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Transforms NavigationModal components from prop-based structure to children-based structure.
|
|
5
|
+
* Converts header, body, and footer props into direct children, maintaining proper order.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Use local jscodeshift instance directly
|
|
9
|
+
const jscodeshift = require('jscodeshift');
|
|
10
|
+
const prettier = require('prettier');
|
|
11
|
+
|
|
12
|
+
module.exports = async function transformer(fileInfo, api) {
|
|
13
|
+
// Use the jscodeshift API to parse the file
|
|
14
|
+
const j = api.jscodeshift || jscodeshift;
|
|
15
|
+
|
|
16
|
+
// Parse the source code of the file
|
|
17
|
+
const root = j(fileInfo.source);
|
|
18
|
+
|
|
19
|
+
// ----------- Start of codemod logic
|
|
20
|
+
|
|
21
|
+
let hasChanges = false;
|
|
22
|
+
|
|
23
|
+
// Find all NavigationModal JSX elements
|
|
24
|
+
root
|
|
25
|
+
.find(j.JSXElement, {
|
|
26
|
+
openingElement: {
|
|
27
|
+
name: {
|
|
28
|
+
name: 'NavigationModal',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
.forEach((path) => {
|
|
33
|
+
const element = path.value;
|
|
34
|
+
const openingElement = element.openingElement;
|
|
35
|
+
|
|
36
|
+
// Check if this NavigationModal has header, body, or footer props
|
|
37
|
+
const headerProp = openingElement.attributes.find(
|
|
38
|
+
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'header',
|
|
39
|
+
);
|
|
40
|
+
const bodyProp = openingElement.attributes.find(
|
|
41
|
+
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'body',
|
|
42
|
+
);
|
|
43
|
+
const footerProp = openingElement.attributes.find(
|
|
44
|
+
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'footer',
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// Only transform if at least one of these props exists
|
|
48
|
+
if (!headerProp && !bodyProp && !footerProp) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
hasChanges = true;
|
|
53
|
+
|
|
54
|
+
// Extract the prop values and create children
|
|
55
|
+
const children = [];
|
|
56
|
+
|
|
57
|
+
// Helper function to extract content from prop value
|
|
58
|
+
const extractPropContent = (prop) => {
|
|
59
|
+
if (!prop || !prop.value) return [];
|
|
60
|
+
|
|
61
|
+
if (prop.value.type === 'JSXExpressionContainer') {
|
|
62
|
+
const expression = prop.value.expression;
|
|
63
|
+
|
|
64
|
+
// Check if the expression is a NavigationModal.Body - if so, keep the element
|
|
65
|
+
if (
|
|
66
|
+
expression.type === 'JSXElement' &&
|
|
67
|
+
expression.openingElement.name.type === 'JSXMemberExpression' &&
|
|
68
|
+
expression.openingElement.name.object.name === 'NavigationModal' &&
|
|
69
|
+
expression.openingElement.name.property.name === 'Body'
|
|
70
|
+
) {
|
|
71
|
+
// Return the NavigationModal.Body element itself
|
|
72
|
+
return [expression];
|
|
73
|
+
} else if (expression.type === 'JSXElement') {
|
|
74
|
+
// For other JSX elements (header, footer), return the element directly (not wrapped)
|
|
75
|
+
return [expression];
|
|
76
|
+
} else {
|
|
77
|
+
// For other expressions (including conditionals), return as JSX expression
|
|
78
|
+
return [j.jsxExpressionContainer(expression)];
|
|
79
|
+
}
|
|
80
|
+
} else if (prop.value.type === 'JSXElement') {
|
|
81
|
+
// Direct JSX element
|
|
82
|
+
if (
|
|
83
|
+
prop.value.openingElement.name.type === 'JSXMemberExpression' &&
|
|
84
|
+
prop.value.openingElement.name.object.name === 'NavigationModal' &&
|
|
85
|
+
prop.value.openingElement.name.property.name === 'Body'
|
|
86
|
+
) {
|
|
87
|
+
// Direct NavigationModal.Body element - return the element itself
|
|
88
|
+
return [prop.value];
|
|
89
|
+
} else {
|
|
90
|
+
// For other direct JSX elements (like NavigationModal.Header, NavigationModal.Footer), return as-is
|
|
91
|
+
return [prop.value];
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
// For other types, return as-is
|
|
95
|
+
return [prop.value];
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Add header first
|
|
100
|
+
if (headerProp) {
|
|
101
|
+
const headerContent = extractPropContent(headerProp);
|
|
102
|
+
children.push(...headerContent);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Add body second
|
|
106
|
+
if (bodyProp) {
|
|
107
|
+
const bodyContent = extractPropContent(bodyProp);
|
|
108
|
+
children.push(...bodyContent);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Add footer last
|
|
112
|
+
if (footerProp) {
|
|
113
|
+
const footerContent = extractPropContent(footerProp);
|
|
114
|
+
children.push(...footerContent);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Remove the header, body, and footer props from attributes
|
|
118
|
+
openingElement.attributes = openingElement.attributes.filter((attr) => {
|
|
119
|
+
return !(
|
|
120
|
+
attr.type === 'JSXAttribute' &&
|
|
121
|
+
(attr.name.name === 'header' || attr.name.name === 'body' || attr.name.name === 'footer')
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Update the element to be self-closing if no children, or add children
|
|
126
|
+
if (children.length === 0) {
|
|
127
|
+
openingElement.selfClosing = true;
|
|
128
|
+
element.closingElement = null;
|
|
129
|
+
element.children = [];
|
|
130
|
+
} else {
|
|
131
|
+
openingElement.selfClosing = false;
|
|
132
|
+
if (!element.closingElement) {
|
|
133
|
+
element.closingElement = j.jsxClosingElement(j.jsxIdentifier('NavigationModal'));
|
|
134
|
+
}
|
|
135
|
+
element.children = children;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Only return modified code if changes were made
|
|
140
|
+
if (!hasChanges) {
|
|
141
|
+
return fileInfo.source;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ----------- End of codemod logic
|
|
145
|
+
|
|
146
|
+
// Return the modified source code after transformation
|
|
147
|
+
const output = root.toSource({ quote: 'single' });
|
|
148
|
+
|
|
149
|
+
const prettierConfig = await prettier.resolveConfig(fileInfo.path);
|
|
150
|
+
|
|
151
|
+
return prettier.format(output, {
|
|
152
|
+
...prettierConfig,
|
|
153
|
+
filepath: fileInfo.path,
|
|
154
|
+
});
|
|
155
|
+
};
|
|
@@ -16,12 +16,12 @@ const [targetPath] = args;
|
|
|
16
16
|
// Check for --dry argument to enable dry run mode
|
|
17
17
|
const isDryRun = args.includes('--dry');
|
|
18
18
|
|
|
19
|
-
// Check for --only argument to run a specific
|
|
19
|
+
// Check for --only argument to run a specific codemod
|
|
20
20
|
const onlyArg = args.find((arg) => arg.startsWith('--only='));
|
|
21
|
-
const
|
|
21
|
+
const codemodName = onlyArg ? onlyArg.split('=')[1] : null;
|
|
22
22
|
|
|
23
23
|
if (!targetPath) {
|
|
24
|
-
console.error('❌ Usage: node scripts/run-
|
|
24
|
+
console.error('❌ Usage: node scripts/run-codemods.js <targetPath> [--dry] [--only=<codemodName>]');
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -30,17 +30,17 @@ if (!fs.existsSync(targetPath)) {
|
|
|
30
30
|
process.exit(1);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const transformsDir = path.join(__dirname, '
|
|
33
|
+
const transformsDir = path.join(__dirname, 'codemods');
|
|
34
34
|
const transformFiles = fs
|
|
35
35
|
.readdirSync(transformsDir)
|
|
36
|
-
.filter((file) => file.endsWith('.js') && (!
|
|
36
|
+
.filter((file) => file.endsWith('.js') && (!codemodName || file === `${codemodName}.js`));
|
|
37
37
|
|
|
38
38
|
if (transformFiles.length === 0) {
|
|
39
|
-
console.log('✅ No
|
|
39
|
+
console.log('✅ No codemods to apply.');
|
|
40
40
|
process.exit(0);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
console.log(`🛠 Found ${transformFiles.length}
|
|
43
|
+
console.log(`🛠 Found ${transformFiles.length} codemod(s) to apply to: ${targetPath}`);
|
|
44
44
|
|
|
45
45
|
// Utility to recursively collect all .ts/.tsx files
|
|
46
46
|
function getAllFiles(dir) {
|
|
@@ -60,17 +60,17 @@ function getAllFiles(dir) {
|
|
|
60
60
|
const filesToTransform = fs.statSync(targetPath).isDirectory() ? getAllFiles(targetPath) : [targetPath];
|
|
61
61
|
const updatedFiles = new Set();
|
|
62
62
|
|
|
63
|
-
// Execute each
|
|
63
|
+
// Execute each codemod
|
|
64
64
|
for (const transformFile of transformFiles) {
|
|
65
65
|
const transformPath = path.join(transformsDir, transformFile);
|
|
66
|
-
const
|
|
67
|
-
console.log(`➡️ Running
|
|
66
|
+
const codemod = require(transformPath);
|
|
67
|
+
console.log(`➡️ Running codemod: ${transformFile}`);
|
|
68
68
|
|
|
69
69
|
for (const filePath of filesToTransform) {
|
|
70
70
|
const source = fs.readFileSync(filePath, 'utf8');
|
|
71
71
|
|
|
72
72
|
try {
|
|
73
|
-
|
|
73
|
+
codemod(
|
|
74
74
|
{ path: filePath, source },
|
|
75
75
|
{ jscodeshift: jscodeshift.withParser('tsx') },
|
|
76
76
|
{ printOptions: { quote: 'single', trailingComma: true } },
|
|
@@ -107,5 +107,5 @@ if (isDryRun) {
|
|
|
107
107
|
console.log(`🚧 Dry run complete. ${updatedFiles.size} file(s) would be modified.`);
|
|
108
108
|
console.log('Run without --dry to apply changes.');
|
|
109
109
|
} else {
|
|
110
|
-
console.log(`🏁 All
|
|
110
|
+
console.log(`🏁 All codemods done. ${updatedFiles.size} file(s) modified.`);
|
|
111
111
|
}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// Transform CardModal components from prop-based API to children-based API
|
|
4
|
-
// Converts header, body, and footer props to direct children elements
|
|
5
|
-
|
|
6
|
-
// Use local jscodeshift instance directly
|
|
7
|
-
const jscodeshift = require('jscodeshift');
|
|
8
|
-
const prettier = require('prettier');
|
|
9
|
-
|
|
10
|
-
module.exports = async function transformer(fileInfo, api) {
|
|
11
|
-
// Use the jscodeshift API to parse the file
|
|
12
|
-
const j = api.jscodeshift || jscodeshift;
|
|
13
|
-
|
|
14
|
-
// Parse the source code of the file
|
|
15
|
-
const root = j(fileInfo.source);
|
|
16
|
-
|
|
17
|
-
let hasChanges = false;
|
|
18
|
-
|
|
19
|
-
// ----------- Start of transformer logic
|
|
20
|
-
|
|
21
|
-
// Find all JSX elements with the name CardModal
|
|
22
|
-
root
|
|
23
|
-
.find(j.JSXElement, {
|
|
24
|
-
openingElement: {
|
|
25
|
-
name: {
|
|
26
|
-
name: 'CardModal',
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
})
|
|
30
|
-
.forEach((path) => {
|
|
31
|
-
const element = path.value;
|
|
32
|
-
const openingElement = element.openingElement;
|
|
33
|
-
|
|
34
|
-
// Check if this CardModal has header, body, or footer props
|
|
35
|
-
const headerProp = openingElement.attributes.find(
|
|
36
|
-
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'header',
|
|
37
|
-
);
|
|
38
|
-
const bodyProp = openingElement.attributes.find(
|
|
39
|
-
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'body',
|
|
40
|
-
);
|
|
41
|
-
const footerProp = openingElement.attributes.find(
|
|
42
|
-
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'footer',
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
// Only transform if we have at least one of these props
|
|
46
|
-
if (!headerProp && !bodyProp && !footerProp) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
hasChanges = true;
|
|
51
|
-
|
|
52
|
-
// Create new children array in the correct order: header, body, footer
|
|
53
|
-
const newChildren = [];
|
|
54
|
-
|
|
55
|
-
// Add header child if it exists
|
|
56
|
-
if (headerProp && headerProp.value) {
|
|
57
|
-
if (headerProp.value.type === 'JSXExpressionContainer') {
|
|
58
|
-
const expression = headerProp.value.expression;
|
|
59
|
-
if (expression.type === 'JSXElement') {
|
|
60
|
-
// If it's a direct JSX element, add it as a direct child
|
|
61
|
-
newChildren.push(expression);
|
|
62
|
-
} else {
|
|
63
|
-
// If it's a conditional or other expression, keep it wrapped
|
|
64
|
-
newChildren.push(j.jsxExpressionContainer(expression));
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
// If it's a direct JSX element, add it directly
|
|
68
|
-
newChildren.push(headerProp.value);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Add body child if it exists
|
|
73
|
-
if (bodyProp && bodyProp.value) {
|
|
74
|
-
if (bodyProp.value.type === 'JSXExpressionContainer') {
|
|
75
|
-
const expression = bodyProp.value.expression;
|
|
76
|
-
if (expression.type === 'JSXElement') {
|
|
77
|
-
// If it's a direct JSX element, add it as a direct child
|
|
78
|
-
newChildren.push(expression);
|
|
79
|
-
} else {
|
|
80
|
-
// If it's a conditional or other expression, keep it wrapped
|
|
81
|
-
newChildren.push(j.jsxExpressionContainer(expression));
|
|
82
|
-
}
|
|
83
|
-
} else {
|
|
84
|
-
// If it's a direct JSX element, add it directly
|
|
85
|
-
newChildren.push(bodyProp.value);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Add footer child if it exists
|
|
90
|
-
if (footerProp && footerProp.value) {
|
|
91
|
-
if (footerProp.value.type === 'JSXExpressionContainer') {
|
|
92
|
-
const expression = footerProp.value.expression;
|
|
93
|
-
if (expression.type === 'JSXElement') {
|
|
94
|
-
// If it's a direct JSX element, add it as a direct child
|
|
95
|
-
newChildren.push(expression);
|
|
96
|
-
} else {
|
|
97
|
-
// If it's a conditional or other expression, keep it wrapped
|
|
98
|
-
newChildren.push(j.jsxExpressionContainer(expression));
|
|
99
|
-
}
|
|
100
|
-
} else {
|
|
101
|
-
// If it's a direct JSX element, add it directly
|
|
102
|
-
newChildren.push(footerProp.value);
|
|
103
|
-
}
|
|
104
|
-
} // Remove the header, body, and footer attributes
|
|
105
|
-
openingElement.attributes = openingElement.attributes.filter((attr) => {
|
|
106
|
-
if (attr.type !== 'JSXAttribute') return true;
|
|
107
|
-
const name = attr.name.name;
|
|
108
|
-
return name !== 'header' && name !== 'body' && name !== 'footer';
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Update the element's children
|
|
112
|
-
element.children = newChildren;
|
|
113
|
-
|
|
114
|
-
// If the element was self-closing, make it a regular element
|
|
115
|
-
if (openingElement.selfClosing) {
|
|
116
|
-
openingElement.selfClosing = false;
|
|
117
|
-
element.closingElement = j.jsxClosingElement(j.jsxIdentifier('CardModal'));
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// ----------- End of transformer logic
|
|
122
|
-
|
|
123
|
-
// Return the modified source code after transformation
|
|
124
|
-
if (!hasChanges) {
|
|
125
|
-
return fileInfo.source;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const output = root.toSource({ quote: 'single' });
|
|
129
|
-
|
|
130
|
-
const prettierConfig = await prettier.resolveConfig(fileInfo.path);
|
|
131
|
-
|
|
132
|
-
return prettier.format(output, {
|
|
133
|
-
...prettierConfig,
|
|
134
|
-
filepath: fileInfo.path,
|
|
135
|
-
});
|
|
136
|
-
};
|