|
import type { ExpressionKind } from 'ast-types/gen/kinds'; |
|
import type { API, FileInfo, JSXAttribute, ObjectProperty } from 'jscodeshift'; |
|
|
|
export default function transformer(file: FileInfo, api: API) { |
|
const index_ = api.jscodeshift; |
|
const root = index_(file.source); |
|
|
|
// Step 1: Transform JSX Grid props |
|
root.findJSXElements('Grid').forEach((path) => { |
|
const attributes = path.node.openingElement.attributes ?? []; |
|
const newAttributes: JSXAttribute[] = []; |
|
const sizeProps: ObjectProperty[] = []; |
|
|
|
attributes.forEach((attribute) => { |
|
if (attribute.type === 'JSXAttribute' && attribute.name.name) { |
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string |
|
const name = attribute.name.name.toString(); |
|
|
|
// Remove `item` prop |
|
if (name === 'item') { |
|
return; |
|
} |
|
|
|
// Move responsive props to `sizes` object |
|
if (['xs', 'sm', 'md', 'lg', 'xl'].includes(name)) { |
|
if (attribute.value && attribute.value.type === 'JSXExpressionContainer') { |
|
sizeProps.push( |
|
index_.objectProperty(index_.identifier(name), attribute.value.expression as ExpressionKind), |
|
); |
|
} |
|
} else { |
|
newAttributes.push(attribute); |
|
} |
|
} |
|
}); |
|
|
|
// Add `size={{ xs: ..., sm: ... }}` if any responsive props exist |
|
if (sizeProps.length > 0) { |
|
newAttributes.push( |
|
index_.jsxAttribute( |
|
index_.jsxIdentifier('size'), |
|
index_.jsxExpressionContainer(index_.objectExpression(sizeProps)), |
|
), |
|
); |
|
} |
|
|
|
// Replace old attributes with new ones |
|
path.node.openingElement.attributes = newAttributes; |
|
}); |
|
|
|
// Step 2: Update imports from @mui/material |
|
root.find(index_.ImportDeclaration).forEach((importPath) => { |
|
const importNode = importPath.node; |
|
|
|
if (importNode.source.value === '@mui/material') { |
|
const specifiers = importNode.specifiers ?? []; |
|
let hasGrid = false as boolean; |
|
|
|
specifiers.forEach((specifier, index) => { |
|
if (specifier.type === 'ImportSpecifier' && specifier.imported.name === 'Grid') { |
|
hasGrid = true; |
|
// Replace "Grid" with "Grid2 as Grid" |
|
specifiers[index] = index_.importSpecifier(index_.identifier('Grid2'), index_.identifier('Grid')); |
|
} |
|
}); |
|
|
|
// Replace the specifiers with the updated version |
|
if (hasGrid) { |
|
importNode.specifiers = specifiers; |
|
} |
|
} |
|
}); |
|
|
|
return root.toSource(); |
|
} |