@ornikar/kitt-universal 27.5.0 → 27.5.1-canary.eac3fc19869888632e3a59913cf9f700a72b0dad.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.
Files changed (27) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +1 -1
  3. package/scripts/transformers/__testfixtures__/card-modal/basic.input.js +19 -0
  4. package/scripts/transformers/__testfixtures__/card-modal/basic.output.js +15 -0
  5. package/scripts/transformers/__testfixtures__/card-modal/withExpressions.input.js +23 -0
  6. package/scripts/transformers/__testfixtures__/card-modal/withExpressions.output.js +19 -0
  7. package/scripts/transformers/__testfixtures__/card-modal/wrongOrder.input.js +19 -0
  8. package/scripts/transformers/__testfixtures__/card-modal/wrongOrder.output.js +15 -0
  9. package/scripts/transformers/__testfixtures__/fullscreen-modal/basic.input.js +19 -0
  10. package/scripts/transformers/__testfixtures__/fullscreen-modal/basic.output.js +15 -0
  11. package/scripts/transformers/__testfixtures__/fullscreen-modal/withExpressions.input.js +23 -0
  12. package/scripts/transformers/__testfixtures__/fullscreen-modal/withExpressions.output.js +19 -0
  13. package/scripts/transformers/__testfixtures__/fullscreen-modal/wrongOrder.input.js +19 -0
  14. package/scripts/transformers/__testfixtures__/fullscreen-modal/wrongOrder.output.js +15 -0
  15. package/scripts/transformers/__testfixtures__/navigation-modal/basic.input.js +19 -0
  16. package/scripts/transformers/__testfixtures__/navigation-modal/basic.output.js +15 -0
  17. package/scripts/transformers/__testfixtures__/navigation-modal/withExpressions.input.js +23 -0
  18. package/scripts/transformers/__testfixtures__/navigation-modal/withExpressions.output.js +19 -0
  19. package/scripts/transformers/__testfixtures__/navigation-modal/wrongOrder.input.js +19 -0
  20. package/scripts/transformers/__testfixtures__/navigation-modal/wrongOrder.output.js +15 -0
  21. package/scripts/transformers/__tests__/card-modal.test.js +10 -0
  22. package/scripts/transformers/__tests__/fullscreen-modal.test.js +10 -0
  23. package/scripts/transformers/__tests__/navigation-modal.test.js +10 -0
  24. package/scripts/transformers/card-modal.js +101 -0
  25. package/scripts/transformers/fullscreen-modal.js +101 -0
  26. package/scripts/transformers/navigation-modal.js +101 -0
  27. package/scripts/transformers/modals.js +0 -102
package/CHANGELOG.md CHANGED
@@ -3,6 +3,21 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [27.5.1-canary.eac3fc19869888632e3a59913cf9f700a72b0dad.0](https://github.com/ornikar/kitt/compare/@ornikar/kitt-universal@27.5.0...@ornikar/kitt-universal@27.5.1-canary.eac3fc19869888632e3a59913cf9f700a72b0dad.0) (2025-09-08)
7
+
8
+
9
+ ### Features
10
+
11
+ * codemod testing ([912aae9](https://github.com/ornikar/kitt/commit/912aae998fe103930e036c66d6303a0deab3beea))
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * tests fixtures revamp ([cb0161a](https://github.com/ornikar/kitt/commit/cb0161a91981fe2e814cd671cde2eb4ef6933b8c))
17
+ * ts lint ([eac3fc1](https://github.com/ornikar/kitt/commit/eac3fc19869888632e3a59913cf9f700a72b0dad))
18
+
19
+
20
+
6
21
  ## [27.5.0](https://github.com/ornikar/kitt/compare/@ornikar/kitt-universal@27.4.0...@ornikar/kitt-universal@27.5.0) (2025-09-03)
7
22
 
8
23
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ornikar/kitt-universal",
3
- "version": "27.5.0",
3
+ "version": "27.5.1-canary.eac3fc19869888632e3a59913cf9f700a72b0dad.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "directory": "@ornikar/kitt-universal",
@@ -0,0 +1,19 @@
1
+ function Test() {
2
+ return (
3
+ <CardModal
4
+ header={<CardModal.Header title="With Header and Body" />}
5
+ body={
6
+ <CardModal.Body>
7
+ <LoremIpsum />
8
+ </CardModal.Body>
9
+ }
10
+ footer={
11
+ <CardModal.Footer shouldHandleBottomNotch={false}>
12
+ <Button stretch type="primary">
13
+ With Body and Footer
14
+ </Button>
15
+ </CardModal.Footer>
16
+ }
17
+ />
18
+ );
19
+ }
@@ -0,0 +1,15 @@
1
+ function Test() {
2
+ return (
3
+ <CardModal>
4
+ <CardModal.Header title="With Header and Body" />
5
+ <CardModal.Body>
6
+ <LoremIpsum />
7
+ </CardModal.Body>
8
+ <CardModal.Footer shouldHandleBottomNotch={false}>
9
+ <Button stretch type="primary">
10
+ With Body and Footer
11
+ </Button>
12
+ </CardModal.Footer>
13
+ </CardModal>
14
+ );
15
+ }
@@ -0,0 +1,23 @@
1
+ function Test() {
2
+ return (
3
+ <CardModal
4
+ header={shouldDisplayHeader ? <CardModal.Header title="With Header and Body" /> : null}
5
+ body={
6
+ shouldDisplayBody ? (
7
+ <View>
8
+ <LoremIpsum />
9
+ </View>
10
+ ) : null
11
+ }
12
+ footer={
13
+ shouldDisplayFooter ? (
14
+ <CardModal.Footer shouldHandleBottomNotch={false}>
15
+ <Button stretch type="primary">
16
+ With Body and Footer
17
+ </Button>
18
+ </CardModal.Footer>
19
+ ) : null
20
+ }
21
+ />
22
+ );
23
+ }
@@ -0,0 +1,19 @@
1
+ function Test() {
2
+ return (
3
+ <CardModal>
4
+ {shouldDisplayHeader ? <CardModal.Header title="With Header and Body" /> : null}
5
+ {shouldDisplayBody ? (
6
+ <View>
7
+ <LoremIpsum />
8
+ </View>
9
+ ) : null}
10
+ {shouldDisplayFooter ? (
11
+ <CardModal.Footer shouldHandleBottomNotch={false}>
12
+ <Button stretch type="primary">
13
+ With Body and Footer
14
+ </Button>
15
+ </CardModal.Footer>
16
+ ) : null}
17
+ </CardModal>
18
+ );
19
+ }
@@ -0,0 +1,19 @@
1
+ function Test() {
2
+ return (
3
+ <CardModal
4
+ footer={
5
+ <CardModal.Footer shouldHandleBottomNotch={false}>
6
+ <Button stretch type="primary">
7
+ With Body and Footer
8
+ </Button>
9
+ </CardModal.Footer>
10
+ }
11
+ header={<CardModal.Header title="With Header and Body" />}
12
+ body={
13
+ <CardModal.Body>
14
+ <LoremIpsum />
15
+ </CardModal.Body>
16
+ }
17
+ />
18
+ );
19
+ }
@@ -0,0 +1,15 @@
1
+ function Test() {
2
+ return (
3
+ <CardModal>
4
+ <CardModal.Header title="With Header and Body" />
5
+ <CardModal.Body>
6
+ <LoremIpsum />
7
+ </CardModal.Body>
8
+ <CardModal.Footer shouldHandleBottomNotch={false}>
9
+ <Button stretch type="primary">
10
+ With Body and Footer
11
+ </Button>
12
+ </CardModal.Footer>
13
+ </CardModal>
14
+ );
15
+ }
@@ -0,0 +1,19 @@
1
+ function Test() {
2
+ return (
3
+ <FullscreenModal
4
+ header={<FullscreenModal.Header title="With Header and Body" />}
5
+ body={
6
+ <FullscreenModal.Body>
7
+ <LoremIpsum />
8
+ </FullscreenModal.Body>
9
+ }
10
+ footer={
11
+ <FullscreenModal.Footer shouldHandleBottomNotch={false}>
12
+ <Button stretch type="primary">
13
+ With Body and Footer
14
+ </Button>
15
+ </FullscreenModal.Footer>
16
+ }
17
+ />
18
+ );
19
+ }
@@ -0,0 +1,15 @@
1
+ function Test() {
2
+ return (
3
+ <FullscreenModal>
4
+ <FullscreenModal.Header title="With Header and Body" />
5
+ <FullscreenModal.Body>
6
+ <LoremIpsum />
7
+ </FullscreenModal.Body>
8
+ <FullscreenModal.Footer shouldHandleBottomNotch={false}>
9
+ <Button stretch type="primary">
10
+ With Body and Footer
11
+ </Button>
12
+ </FullscreenModal.Footer>
13
+ </FullscreenModal>
14
+ );
15
+ }
@@ -0,0 +1,23 @@
1
+ function Test() {
2
+ return (
3
+ <FullscreenModal
4
+ header={shouldDisplayHeader ? <FullscreenModal.Header title="With Header and Body" /> : null}
5
+ body={
6
+ shouldDisplayBody ? (
7
+ <View>
8
+ <LoremIpsum />
9
+ </View>
10
+ ) : null
11
+ }
12
+ footer={
13
+ shouldDisplayFooter ? (
14
+ <FullscreenModal.Footer shouldHandleBottomNotch={false}>
15
+ <Button stretch type="primary">
16
+ With Body and Footer
17
+ </Button>
18
+ </FullscreenModal.Footer>
19
+ ) : null
20
+ }
21
+ />
22
+ );
23
+ }
@@ -0,0 +1,19 @@
1
+ function Test() {
2
+ return (
3
+ <FullscreenModal>
4
+ {shouldDisplayHeader ? <FullscreenModal.Header title="With Header and Body" /> : null}
5
+ {shouldDisplayBody ? (
6
+ <View>
7
+ <LoremIpsum />
8
+ </View>
9
+ ) : null}
10
+ {shouldDisplayFooter ? (
11
+ <FullscreenModal.Footer shouldHandleBottomNotch={false}>
12
+ <Button stretch type="primary">
13
+ With Body and Footer
14
+ </Button>
15
+ </FullscreenModal.Footer>
16
+ ) : null}
17
+ </FullscreenModal>
18
+ );
19
+ }
@@ -0,0 +1,19 @@
1
+ function Test() {
2
+ return (
3
+ <FullscreenModal
4
+ footer={
5
+ <FullscreenModal.Footer shouldHandleBottomNotch={false}>
6
+ <Button stretch type="primary">
7
+ With Body and Footer
8
+ </Button>
9
+ </FullscreenModal.Footer>
10
+ }
11
+ header={<FullscreenModal.Header title="With Header and Body" />}
12
+ body={
13
+ <FullscreenModal.Body>
14
+ <LoremIpsum />
15
+ </FullscreenModal.Body>
16
+ }
17
+ />
18
+ );
19
+ }
@@ -0,0 +1,15 @@
1
+ function Test() {
2
+ return (
3
+ <FullscreenModal>
4
+ <FullscreenModal.Header title="With Header and Body" />
5
+ <FullscreenModal.Body>
6
+ <LoremIpsum />
7
+ </FullscreenModal.Body>
8
+ <FullscreenModal.Footer shouldHandleBottomNotch={false}>
9
+ <Button stretch type="primary">
10
+ With Body and Footer
11
+ </Button>
12
+ </FullscreenModal.Footer>
13
+ </FullscreenModal>
14
+ );
15
+ }
@@ -0,0 +1,19 @@
1
+ function Test() {
2
+ return (
3
+ <NavigationModal
4
+ header={<NavigationModal.Header title="With Header and Body" />}
5
+ body={
6
+ <NavigationModal.Body>
7
+ <LoremIpsum />
8
+ </NavigationModal.Body>
9
+ }
10
+ footer={
11
+ <NavigationModal.Footer shouldHandleBottomNotch={false}>
12
+ <Button stretch type="primary">
13
+ With Body and Footer
14
+ </Button>
15
+ </NavigationModal.Footer>
16
+ }
17
+ />
18
+ );
19
+ }
@@ -0,0 +1,15 @@
1
+ function Test() {
2
+ return (
3
+ <NavigationModal>
4
+ <NavigationModal.Header title="With Header and Body" />
5
+ <NavigationModal.Body>
6
+ <LoremIpsum />
7
+ </NavigationModal.Body>
8
+ <NavigationModal.Footer shouldHandleBottomNotch={false}>
9
+ <Button stretch type="primary">
10
+ With Body and Footer
11
+ </Button>
12
+ </NavigationModal.Footer>
13
+ </NavigationModal>
14
+ );
15
+ }
@@ -0,0 +1,23 @@
1
+ function Test() {
2
+ return (
3
+ <NavigationModal
4
+ header={shouldDisplayHeader ? <NavigationModal.Header title="With Header and Body" /> : null}
5
+ body={
6
+ shouldDisplayBody ? (
7
+ <View>
8
+ <LoremIpsum />
9
+ </View>
10
+ ) : null
11
+ }
12
+ footer={
13
+ shouldDisplayFooter ? (
14
+ <NavigationModal.Footer shouldHandleBottomNotch={false}>
15
+ <Button stretch type="primary">
16
+ With Body and Footer
17
+ </Button>
18
+ </NavigationModal.Footer>
19
+ ) : null
20
+ }
21
+ />
22
+ );
23
+ }
@@ -0,0 +1,19 @@
1
+ function Test() {
2
+ return (
3
+ <NavigationModal>
4
+ {shouldDisplayHeader ? <NavigationModal.Header title="With Header and Body" /> : null}
5
+ {shouldDisplayBody ? (
6
+ <View>
7
+ <LoremIpsum />
8
+ </View>
9
+ ) : null}
10
+ {shouldDisplayFooter ? (
11
+ <NavigationModal.Footer shouldHandleBottomNotch={false}>
12
+ <Button stretch type="primary">
13
+ With Body and Footer
14
+ </Button>
15
+ </NavigationModal.Footer>
16
+ ) : null}
17
+ </NavigationModal>
18
+ );
19
+ }
@@ -0,0 +1,19 @@
1
+ function Test() {
2
+ return (
3
+ <NavigationModal
4
+ footer={
5
+ <NavigationModal.Footer shouldHandleBottomNotch={false}>
6
+ <Button stretch type="primary">
7
+ With Body and Footer
8
+ </Button>
9
+ </NavigationModal.Footer>
10
+ }
11
+ header={<NavigationModal.Header title="With Header and Body" />}
12
+ body={
13
+ <NavigationModal.Body>
14
+ <LoremIpsum />
15
+ </NavigationModal.Body>
16
+ }
17
+ />
18
+ );
19
+ }
@@ -0,0 +1,15 @@
1
+ function Test() {
2
+ return (
3
+ <NavigationModal>
4
+ <NavigationModal.Header title="With Header and Body" />
5
+ <NavigationModal.Body>
6
+ <LoremIpsum />
7
+ </NavigationModal.Body>
8
+ <NavigationModal.Footer shouldHandleBottomNotch={false}>
9
+ <Button stretch type="primary">
10
+ With Body and Footer
11
+ </Button>
12
+ </NavigationModal.Footer>
13
+ </NavigationModal>
14
+ );
15
+ }
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ jest.autoMockOff();
4
+ const { defineTest } = require('jscodeshift/dist/testUtils');
5
+
6
+ const tests = ['basic', 'withExpressions', 'wrongOrder'];
7
+
8
+ describe('CardModal', () => {
9
+ tests.forEach((test) => defineTest(__dirname, 'card-modal', null, `card-modal/${test}`));
10
+ });
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ jest.autoMockOff();
4
+ const { defineTest } = require('jscodeshift/dist/testUtils');
5
+
6
+ const tests = ['basic', 'withExpressions', 'wrongOrder'];
7
+
8
+ describe('FullscreenModal', () => {
9
+ tests.forEach((test) => defineTest(__dirname, 'fullscreen-modal', null, `fullscreen-modal/${test}`));
10
+ });
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ jest.autoMockOff();
4
+ const { defineTest } = require('jscodeshift/dist/testUtils');
5
+
6
+ const tests = ['basic', 'withExpressions', 'wrongOrder'];
7
+
8
+ describe('NavigationModal', () => {
9
+ tests.forEach((test) => defineTest(__dirname, 'navigation-modal', null, `navigation-modal/${test}`));
10
+ });
@@ -0,0 +1,101 @@
1
+ 'use strict';
2
+
3
+ // Transform CardModal from props-based API to children-based API
4
+ // Converts header, body, footer props to nested children in the correct order
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
+ // ----------- Start of transformer logic
18
+
19
+ // Find all CardModal JSX elements
20
+ root
21
+ .find(j.JSXElement, {
22
+ openingElement: {
23
+ name: {
24
+ name: 'CardModal',
25
+ },
26
+ },
27
+ })
28
+ .forEach((path) => {
29
+ const element = path.value;
30
+ const { openingElement } = element;
31
+
32
+ // Extract header, body, and footer props
33
+ const getAttributeByName = (attributes, name) => {
34
+ return attributes.find((attr) => attr.type === 'JSXAttribute' && attr.name.name === name);
35
+ };
36
+
37
+ const headerProp = getAttributeByName(openingElement.attributes, 'header');
38
+ const bodyProp = getAttributeByName(openingElement.attributes, 'body');
39
+ const footerProp = getAttributeByName(openingElement.attributes, 'footer');
40
+
41
+ // If we found any of these props, transform the element
42
+ if (headerProp || bodyProp || footerProp) {
43
+ // Remove the header, body, and footer attributes
44
+ openingElement.attributes = openingElement.attributes.filter((attr) => {
45
+ if (attr.type !== 'JSXAttribute') return true;
46
+ return !['header', 'body', 'footer'].includes(attr.name.name);
47
+ });
48
+
49
+ // Create children array in the correct order: header, body, footer
50
+ const children = [];
51
+
52
+ // Helper function to extract child from prop value
53
+ const extractChild = (propValue) => {
54
+ if (propValue.type === 'JSXExpressionContainer') {
55
+ // Check if the expression is a simple JSX element (not a conditional/complex expression)
56
+ if (propValue.expression.type === 'JSXElement') {
57
+ // For simple JSX elements, use them directly as children
58
+ return propValue.expression;
59
+ }
60
+ // For complex expressions (conditionals, etc.), keep as expression container
61
+ return propValue;
62
+ }
63
+ return propValue;
64
+ };
65
+
66
+ // Add header if it exists
67
+ if (headerProp && headerProp.value) {
68
+ children.push(extractChild(headerProp.value));
69
+ }
70
+
71
+ // Add body if it exists
72
+ if (bodyProp && bodyProp.value) {
73
+ children.push(extractChild(bodyProp.value));
74
+ }
75
+
76
+ // Add footer if it exists
77
+ if (footerProp && footerProp.value) {
78
+ children.push(extractChild(footerProp.value));
79
+ }
80
+
81
+ // Update the element to have children instead of being self-closing
82
+ if (children.length > 0) {
83
+ element.children = children;
84
+ element.closingElement = j.jsxClosingElement(j.jsxIdentifier('CardModal'));
85
+ openingElement.selfClosing = false;
86
+ }
87
+ }
88
+ });
89
+
90
+ // ----------- End of transformer logic
91
+
92
+ // Return the modified source code after transformation
93
+ const output = root.toSource({ quote: 'single' });
94
+
95
+ const prettierConfig = await prettier.resolveConfig(fileInfo.path);
96
+
97
+ return prettier.format(output, {
98
+ ...prettierConfig,
99
+ filepath: fileInfo.path,
100
+ });
101
+ };
@@ -0,0 +1,101 @@
1
+ 'use strict';
2
+
3
+ // Transform FullscreenModal from props-based API to children-based API
4
+ // Converts header, body, footer props to nested children in the correct order
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
+ // ----------- Start of transformer logic
18
+
19
+ // Find all FullscreenModal JSX elements
20
+ root
21
+ .find(j.JSXElement, {
22
+ openingElement: {
23
+ name: {
24
+ name: 'FullscreenModal',
25
+ },
26
+ },
27
+ })
28
+ .forEach((path) => {
29
+ const element = path.value;
30
+ const { openingElement } = element;
31
+
32
+ // Extract header, body, and footer props
33
+ const getAttributeByName = (attributes, name) => {
34
+ return attributes.find((attr) => attr.type === 'JSXAttribute' && attr.name.name === name);
35
+ };
36
+
37
+ const headerProp = getAttributeByName(openingElement.attributes, 'header');
38
+ const bodyProp = getAttributeByName(openingElement.attributes, 'body');
39
+ const footerProp = getAttributeByName(openingElement.attributes, 'footer');
40
+
41
+ // If we found any of these props, transform the element
42
+ if (headerProp || bodyProp || footerProp) {
43
+ // Remove the header, body, and footer attributes
44
+ openingElement.attributes = openingElement.attributes.filter((attr) => {
45
+ if (attr.type !== 'JSXAttribute') return true;
46
+ return !['header', 'body', 'footer'].includes(attr.name.name);
47
+ });
48
+
49
+ // Create children array in the correct order: header, body, footer
50
+ const children = [];
51
+
52
+ // Helper function to extract child from prop value
53
+ const extractChild = (propValue) => {
54
+ if (propValue.type === 'JSXExpressionContainer') {
55
+ // Check if the expression is a simple JSX element (not a conditional/complex expression)
56
+ if (propValue.expression.type === 'JSXElement') {
57
+ // For simple JSX elements, use them directly as children
58
+ return propValue.expression;
59
+ }
60
+ // For complex expressions (conditionals, etc.), keep as expression container
61
+ return propValue;
62
+ }
63
+ return propValue;
64
+ };
65
+
66
+ // Add header if it exists
67
+ if (headerProp && headerProp.value) {
68
+ children.push(extractChild(headerProp.value));
69
+ }
70
+
71
+ // Add body if it exists
72
+ if (bodyProp && bodyProp.value) {
73
+ children.push(extractChild(bodyProp.value));
74
+ }
75
+
76
+ // Add footer if it exists
77
+ if (footerProp && footerProp.value) {
78
+ children.push(extractChild(footerProp.value));
79
+ }
80
+
81
+ // Update the element to have children instead of being self-closing
82
+ if (children.length > 0) {
83
+ element.children = children;
84
+ element.closingElement = j.jsxClosingElement(j.jsxIdentifier('FullscreenModal'));
85
+ openingElement.selfClosing = false;
86
+ }
87
+ }
88
+ });
89
+
90
+ // ----------- End of transformer logic
91
+
92
+ // Return the modified source code after transformation
93
+ const output = root.toSource({ quote: 'single' });
94
+
95
+ const prettierConfig = await prettier.resolveConfig(fileInfo.path);
96
+
97
+ return prettier.format(output, {
98
+ ...prettierConfig,
99
+ filepath: fileInfo.path,
100
+ });
101
+ };
@@ -0,0 +1,101 @@
1
+ 'use strict';
2
+
3
+ // Transform NavigationModal from props-based API to children-based API
4
+ // Converts header, body, footer props to nested children in the correct order
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
+ // ----------- Start of transformer logic
18
+
19
+ // Find all NavigationModal JSX elements
20
+ root
21
+ .find(j.JSXElement, {
22
+ openingElement: {
23
+ name: {
24
+ name: 'NavigationModal',
25
+ },
26
+ },
27
+ })
28
+ .forEach((path) => {
29
+ const element = path.value;
30
+ const { openingElement } = element;
31
+
32
+ // Extract header, body, and footer props
33
+ const getAttributeByName = (attributes, name) => {
34
+ return attributes.find((attr) => attr.type === 'JSXAttribute' && attr.name.name === name);
35
+ };
36
+
37
+ const headerProp = getAttributeByName(openingElement.attributes, 'header');
38
+ const bodyProp = getAttributeByName(openingElement.attributes, 'body');
39
+ const footerProp = getAttributeByName(openingElement.attributes, 'footer');
40
+
41
+ // If we found any of these props, transform the element
42
+ if (headerProp || bodyProp || footerProp) {
43
+ // Remove the header, body, and footer attributes
44
+ openingElement.attributes = openingElement.attributes.filter((attr) => {
45
+ if (attr.type !== 'JSXAttribute') return true;
46
+ return !['header', 'body', 'footer'].includes(attr.name.name);
47
+ });
48
+
49
+ // Create children array in the correct order: header, body, footer
50
+ const children = [];
51
+
52
+ // Helper function to extract child from prop value
53
+ const extractChild = (propValue) => {
54
+ if (propValue.type === 'JSXExpressionContainer') {
55
+ // Check if the expression is a simple JSX element (not a conditional/complex expression)
56
+ if (propValue.expression.type === 'JSXElement') {
57
+ // For simple JSX elements, use them directly as children
58
+ return propValue.expression;
59
+ }
60
+ // For complex expressions (conditionals, etc.), keep as expression container
61
+ return propValue;
62
+ }
63
+ return propValue;
64
+ };
65
+
66
+ // Add header if it exists
67
+ if (headerProp && headerProp.value) {
68
+ children.push(extractChild(headerProp.value));
69
+ }
70
+
71
+ // Add body if it exists
72
+ if (bodyProp && bodyProp.value) {
73
+ children.push(extractChild(bodyProp.value));
74
+ }
75
+
76
+ // Add footer if it exists
77
+ if (footerProp && footerProp.value) {
78
+ children.push(extractChild(footerProp.value));
79
+ }
80
+
81
+ // Update the element to have children instead of being self-closing
82
+ if (children.length > 0) {
83
+ element.children = children;
84
+ element.closingElement = j.jsxClosingElement(j.jsxIdentifier('NavigationModal'));
85
+ openingElement.selfClosing = false;
86
+ }
87
+ }
88
+ });
89
+
90
+ // ----------- End of transformer logic
91
+
92
+ // Return the modified source code after transformation
93
+ const output = root.toSource({ quote: 'single' });
94
+
95
+ const prettierConfig = await prettier.resolveConfig(fileInfo.path);
96
+
97
+ return prettier.format(output, {
98
+ ...prettierConfig,
99
+ filepath: fileInfo.path,
100
+ });
101
+ };
@@ -1,102 +0,0 @@
1
- 'use strict';
2
-
3
- /* eslint-disable prefer-destructuring */
4
- /* eslint-disable unicorn/no-array-method-this-argument */
5
-
6
- // Use local jscodeshift instance directly
7
- const jscodeshift = require('jscodeshift');
8
-
9
- // List of modal component names we want to transform
10
- const MODAL_COMPONENTS = ['FullscreenModal', 'CardModal', 'NavigationModal'];
11
-
12
- module.exports = 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
- // Iterate over each modal component found in the source code
20
- MODAL_COMPONENTS.forEach((componentName) => {
21
- // Find instances of the modal component
22
- root
23
- .find(j.JSXElement, {
24
- openingElement: {
25
- name: { type: 'JSXIdentifier', name: componentName },
26
- },
27
- })
28
- .forEach((path) => {
29
- // Get the node (the JSXElement) from the path
30
- const node = path.node;
31
-
32
- // Check if the modal component already has children or if it is self-closing
33
- const hasChildren = Array.isArray(node.children) && node.children.length > 0;
34
- if (!node.openingElement.selfClosing && hasChildren) {
35
- // If it already has children, do nothing and skip transformation
36
- return;
37
- }
38
-
39
- // Extract the attributes from the JSX element (like `header`, `body`, `footer`)
40
- const attributes = node.openingElement.attributes;
41
-
42
- // Initialize a map to hold potential new children: header, body, footer
43
- const newChildrenMap = {
44
- header: null,
45
- body: null,
46
- footer: null,
47
- };
48
-
49
- // An array to keep attributes that are not `header`, `body`, or `footer`
50
- const keptAttributes = [];
51
-
52
- // Loop over the attributes to check if any match `header`, `body`, or `footer`
53
- attributes.forEach((attr) => {
54
- if (
55
- attr.type === 'JSXAttribute' &&
56
- attr.name &&
57
- Object.prototype.hasOwnProperty.call(newChildrenMap, attr.name.name)
58
- ) {
59
- const key = attr.name.name;
60
- const value = attr.value;
61
-
62
- // Check if the value of the attribute is an expression (like a ternary)
63
- if (value?.type === 'JSXExpressionContainer') {
64
- const expression = value.expression;
65
-
66
- // If it's a JSXElement or JSXFragment, keep it as it is
67
- if (j.JSXElement.check(expression) || j.JSXFragment.check(expression)) {
68
- newChildrenMap[key] = expression;
69
- } else {
70
- // Otherwise, wrap it in an expression container to handle non-JSX expressions
71
- newChildrenMap[key] = j.jsxExpressionContainer(expression);
72
- }
73
- }
74
- } else {
75
- // Keep any other attributes (that are not header/body/footer)
76
- keptAttributes.push(attr);
77
- }
78
- });
79
-
80
- // If no new children were found (no `header`, `body`, or `footer`), do nothing
81
- if (Object.values(newChildrenMap).every((v) => v === null)) {
82
- return;
83
- }
84
-
85
- // If the modal component was self-closing, convert it to a regular JSX element with children
86
- if (node.openingElement.selfClosing) {
87
- node.openingElement.selfClosing = false;
88
- node.closingElement = j.jsxClosingElement(j.jsxIdentifier(node.openingElement.name.name));
89
- }
90
-
91
- // Retain all the other attributes and set the new ones
92
- node.openingElement.attributes = keptAttributes;
93
-
94
- // Force the order of children: header → body → footer
95
- const orderedChildren = Object.values(newChildrenMap).filter(Boolean);
96
- node.children = orderedChildren;
97
- });
98
- });
99
-
100
- // Return the modified source code after transformation
101
- return root.toSource({ quote: 'single' });
102
- };