codemods/deprecateUtilityComponents.js (98 lines of code) (raw):
const prettify = require('./lib/prettify')
module.exports = (file, api) => {
const j = api.jscodeshift
const ast = j(file.source)
deprecateComponents(ast, j, '@primer/components', {
Flex: {
identifier: 'Box',
attributes: {
display: 'flex'
}
},
Grid: {
identifier: 'Box',
attributes: {
display: 'grid'
}
},
Position: {
identifier: 'Box',
attributes: {}
},
Absolute: {
identifier: 'Box',
attributes: {
position: 'absolute'
}
},
Relative: {
identifier: 'Box',
attributes: {
position: 'relative'
}
},
Fixed: {
identifier: 'Box',
attributes: {
position: 'fixed'
}
},
Sticky: {
identifier: 'Box',
attributes: {
position: 'sticky'
}
},
BorderBox: {
identifier: 'Box',
attributes: {
borderWidth: '1px',
borderStyle: 'solid',
borderColor: 'border.default',
borderRadius: 2
}
}
})
return prettify(ast, file)
}
function deprecateComponents(ast, j, importSource, importMap) {
const imports = ast.find(j.ImportDeclaration, {source: {value: importSource}})
const importsByName = {}
imports.forEach(decl => {
j(decl)
.find(j.ImportSpecifier)
.forEach(spec => {
importsByName[spec.node.imported.name] = spec
})
})
for (const [from, to] of Object.entries(importMap)) {
rewriteImport(from, to.identifier, to.attributes)
}
function rewriteImport(from, to, attributes) {
imports.forEach(decl => {
j(decl)
.find(j.ImportSpecifier, {imported: {name: from}})
.forEach(spec => {
if (importsByName[to]) {
// if the destination import already exists and there are members
// in this identifier, then this one is a dupe
j(spec).remove()
} else {
// otherwise, we can safely rename this one to the new identifier
spec.node.imported.name = to
importsByName[to] = spec
}
})
})
ast.find(j.JSXOpeningElement, {name: {name: from}}).forEach(nodePath => {
for (const [attr, value] of Object.entries(attributes || {})) {
const expression = typeof value === 'string' ? j.literal(value) : j.jsxExpressionContainer(j.literal(value))
const attrExists = nodePath.value.attributes.find(a => a?.name?.name === attr)
if (!attrExists) {
nodePath.value.attributes.push(j.jsxAttribute(j.jsxIdentifier(attr), expression))
}
}
})
// replace all of the rewritten identifiers with member expressions
ast
.find(j.Identifier, {name: from})
.filter(id => id.parent.node.type !== 'ImportSpecifier')
.replaceWith(j.jsxIdentifier(to))
}
}