Skip to content

Commit 3194791

Browse files
Breadcrumb migrator (#8071)
### WHY are these changes introduced? In v11 we are moving away from arrays in breadcrumbs props in Page components and using single objects instead in order to make the interface easier to understand. This migrator takes the inside object of the array and keeps it in the same prop. This will make the v11 migration easier for consumers. I might change it to using the last item in the array in case some people are still using multiple items in the array. Web is not but that doesn't mean others aren't. Also I think I'm going to write a codepath to remove the prop altogether if there is an empty array? I could leave the comment though and let people resolve themselves. ### How to 🎩 ``` npx @shopify/polaris-migrator@0.0.0-snapshot-release-20230223014528 v11-react-update-page-breadcrumbs './**/*.{ts,tsx}' ``` then run eslint and prettier: ``` npx eslint --fix . npx prettier --write . ``` After applying a migration, it might be helpful to commit the changes that do not need a manual check from those that do. You can do this a few different ways, but we suggest staging all your changes, then unstaging those that include the manual check comment: ```sh # Stash files with "polaris-migrator:" comments git stash push $(grep -r -l "polaris-migrator:" $(git ls-files -m)) # Stage all files without "polaris-migrator:" comments git add . # Bring back the change with "polaris-migrator:" comments git stash pop # (optional) if there a files that have both "polaris-migrator:" comments # _and_ complete fixes, add the complete fixes now git add -p # Commit all the complete fixes: git commit # Now you're left with changes that have "polaris-migrator:" comments only ``` ### 🎩 checklist - [ ] Tested on [mobile](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting.md#cross-browser-testing) - [ ] Tested on [multiple browsers](https://help.shopify.com/en/manual/shopify-admin/supported-browsers) - [ ] Tested for [accessibility](https://github.com/Shopify/polaris/blob/main/documentation/Accessibility%20testing.md) - [ ] Updated the component's `README.md` with documentation changes - [ ] [Tophatted documentation](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting%20documentation.md) changes in the style guide --------- Co-authored-by: Sam Rose <sam.rose@shopify.com>
1 parent 324c64f commit 3194791

File tree

5 files changed

+185
-0
lines changed

5 files changed

+185
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@shopify/polaris-migrator': minor
3+
---
4+
5+
Added a migration for updating the Page component `breadcrumbs` prop to use an object instead of an array
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React from 'react';
2+
import {Page} from '@shopify/polaris';
3+
4+
export function App({
5+
breadcrumbProps = [{url: '/testing', content: 'Breadcrumb'}],
6+
}) {
7+
const breadcrumbs = [{url: '/testing', content: 'Breadcrumb'}];
8+
const getBreadcrumbs = () => [{url: '/testing', content: 'Breadcrumb'}];
9+
return (
10+
<>
11+
<Page breadcrumbs={[{url: '/testing', content: 'Breadcrumb'}]}>
12+
hello
13+
</Page>
14+
<Page
15+
breadcrumbs={[
16+
{url: '/testing', content: 'Breadcrumb'},
17+
{url: '/testing2', content: 'Breadcrumb2'},
18+
]}
19+
>
20+
hello
21+
</Page>
22+
<Page breadcrumbs={[]}>testing</Page>
23+
<Page breadcrumbs={breadcrumbs}>testing</Page>
24+
<Page breadcrumbs={breadcrumbProps}>testing</Page>
25+
<Page breadcrumbs={getBreadcrumbs()}>testing</Page>
26+
</>
27+
);
28+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react';
2+
import {Page} from '@shopify/polaris';
3+
4+
export function App({
5+
breadcrumbProps = [{url: '/testing', content: 'Breadcrumb'}],
6+
}) {
7+
const breadcrumbs = [{url: '/testing', content: 'Breadcrumb'}];
8+
const getBreadcrumbs = () => [{url: '/testing', content: 'Breadcrumb'}];
9+
return (
10+
<>
11+
<Page backAction={{url: '/testing', content: 'Breadcrumb'}}>hello</Page>
12+
<Page backAction={{url: '/testing2', content: 'Breadcrumb2'}}>hello</Page>
13+
<Page>testing</Page>
14+
<Page
15+
backAction={
16+
/* polaris-migrator: Unable to migrate the following expression. Please upgrade manually. In this case, you will need to update the breadcrumbs variable to be a single object instead of an array as arrays have been deprecated. */
17+
breadcrumbs
18+
}
19+
>
20+
testing
21+
</Page>
22+
<Page
23+
backAction={
24+
/* polaris-migrator: Unable to migrate the following expression. Please upgrade manually. In this case, you will need to update the breadcrumbs variable to be a single object instead of an array as arrays have been deprecated. */
25+
breadcrumbProps
26+
}
27+
>
28+
testing
29+
</Page>
30+
<Page
31+
backAction={
32+
/* polaris-migrator: Unable to migrate the following expression. Please upgrade manually. In this case, you will need to update the breadcrumbs variable to be a single object instead of an array as arrays have been deprecated. */
33+
getBreadcrumbs()
34+
}
35+
>
36+
testing
37+
</Page>
38+
</>
39+
);
40+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {check} from '../../../utilities/testUtils';
2+
3+
const migration = 'v11-react-update-page-breadcrumbs';
4+
const fixtures = ['v11-react-update-page-breadcrumbs'];
5+
6+
for (const fixture of fixtures) {
7+
check(__dirname, {
8+
fixture,
9+
migration,
10+
});
11+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import type {API, FileInfo} from 'jscodeshift';
2+
3+
import {POLARIS_MIGRATOR_COMMENT} from '../../constants';
4+
import {
5+
insertCommentBefore,
6+
removeJSXAttributes,
7+
replaceJSXAttributes,
8+
} from '../../utilities/jsx';
9+
10+
export default function v11reactUpdatePageBreadcrumbs(
11+
fileInfo: FileInfo,
12+
{jscodeshift: j}: API,
13+
) {
14+
const source = j(fileInfo.source);
15+
16+
source
17+
.findJSXElements('Page')
18+
.find(j.JSXAttribute, {
19+
name: {
20+
type: 'JSXIdentifier',
21+
name: 'breadcrumbs',
22+
},
23+
value: {
24+
type: 'JSXExpressionContainer',
25+
},
26+
})
27+
.find(j.JSXExpressionContainer)
28+
.filter((nodePath) => {
29+
if (nodePath.node.expression.type === 'Identifier') {
30+
replaceJSXAttributes(
31+
j,
32+
j(nodePath).closest(j.JSXElement).paths()[0],
33+
'breadcrumbs',
34+
'backAction',
35+
);
36+
37+
insertCommentBefore(
38+
j,
39+
j(nodePath).find(j.Identifier).paths()[0],
40+
`${POLARIS_MIGRATOR_COMMENT} In this case, you will need to update the breadcrumbs variable to be a single object instead of an array as arrays have been deprecated.`,
41+
);
42+
}
43+
44+
if (nodePath.node.expression.type === 'CallExpression') {
45+
replaceJSXAttributes(
46+
j,
47+
j(nodePath).closest(j.JSXElement).paths()[0],
48+
'breadcrumbs',
49+
'backAction',
50+
);
51+
insertCommentBefore(
52+
j,
53+
j(nodePath).find(j.Identifier).paths()[0],
54+
`${POLARIS_MIGRATOR_COMMENT} In this case, you will need to update the breadcrumbs variable to be a single object instead of an array as arrays have been deprecated.`,
55+
);
56+
return false;
57+
}
58+
59+
if (nodePath.node.expression.type === 'ObjectExpression') {
60+
replaceJSXAttributes(
61+
j,
62+
j(nodePath).closest(j.JSXElement).paths()[0],
63+
'breadcrumbs',
64+
'backAction',
65+
);
66+
}
67+
68+
return true;
69+
})
70+
.find(j.ArrayExpression)
71+
.replaceWith((nodePath) => {
72+
const arrayOfBreadcrumbs = nodePath.node.elements;
73+
74+
if (arrayOfBreadcrumbs.length === 0) {
75+
removeJSXAttributes(
76+
j,
77+
nodePath.parentPath.parentPath.parentPath.parentPath,
78+
'breadcrumbs',
79+
);
80+
return;
81+
}
82+
83+
if (
84+
arrayOfBreadcrumbs[arrayOfBreadcrumbs.length - 1]?.type !==
85+
'ObjectExpression'
86+
)
87+
return;
88+
89+
replaceJSXAttributes(
90+
j,
91+
j(nodePath).closest(j.JSXElement).paths()[0],
92+
'breadcrumbs',
93+
'backAction',
94+
);
95+
return j.template.expression`${
96+
arrayOfBreadcrumbs[arrayOfBreadcrumbs.length - 1]
97+
}`;
98+
});
99+
100+
return source.toSource();
101+
}

0 commit comments

Comments
 (0)