You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
3.4 KiB
142 lines
3.4 KiB
3 years ago
|
// @flow
|
||
|
import {
|
||
|
transformExpressionWithStyles,
|
||
|
getStyledOptions,
|
||
|
addImport,
|
||
|
createTransformerMacro
|
||
|
} from './utils'
|
||
|
|
||
|
const getReferencedSpecifier = (path, specifierName) => {
|
||
|
const specifiers = path.get('specifiers')
|
||
|
return specifierName === 'default'
|
||
|
? specifiers.find(p => p.isImportDefaultSpecifier())
|
||
|
: specifiers.find(p => p.node.local.name === specifierName)
|
||
|
}
|
||
|
|
||
|
export let styledTransformer = ({
|
||
|
state,
|
||
|
babel,
|
||
|
path,
|
||
|
importSource,
|
||
|
reference,
|
||
|
importSpecifierName,
|
||
|
options: { styledBaseImport, isWeb }
|
||
|
}: {
|
||
|
state: Object,
|
||
|
babel: Object,
|
||
|
path: any,
|
||
|
importSource: string,
|
||
|
importSpecifierName: string,
|
||
|
reference: Object,
|
||
|
options: { styledBaseImport?: [string, string], isWeb: boolean }
|
||
|
}) => {
|
||
|
let t = babel.types
|
||
|
|
||
|
let getStyledIdentifier = () => {
|
||
|
if (
|
||
|
!styledBaseImport ||
|
||
|
(styledBaseImport[0] === importSource &&
|
||
|
styledBaseImport[1] === importSpecifierName)
|
||
|
) {
|
||
|
return t.cloneNode(reference.node)
|
||
|
}
|
||
|
|
||
|
if (path.node) {
|
||
|
const referencedSpecifier = getReferencedSpecifier(
|
||
|
path,
|
||
|
importSpecifierName
|
||
|
)
|
||
|
|
||
|
if (referencedSpecifier) {
|
||
|
referencedSpecifier.remove()
|
||
|
}
|
||
|
|
||
|
if (!path.get('specifiers').length) {
|
||
|
path.remove()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const [baseImportSource, baseSpecifierName] = styledBaseImport
|
||
|
|
||
|
return addImport(state, baseImportSource, baseSpecifierName, 'styled')
|
||
|
}
|
||
|
let createStyledComponentPath = null
|
||
|
if (
|
||
|
t.isMemberExpression(reference.parent) &&
|
||
|
reference.parent.computed === false
|
||
|
) {
|
||
|
if (
|
||
|
// checks if the first character is lowercase
|
||
|
// becasue we don't want to transform the member expression if
|
||
|
// it's in primitives/native
|
||
|
reference.parent.property.name.charCodeAt(0) > 96
|
||
|
) {
|
||
|
reference.parentPath.replaceWith(
|
||
|
t.callExpression(getStyledIdentifier(), [
|
||
|
t.stringLiteral(reference.parent.property.name)
|
||
|
])
|
||
|
)
|
||
|
} else {
|
||
|
reference.replaceWith(getStyledIdentifier())
|
||
|
}
|
||
|
|
||
|
createStyledComponentPath = reference.parentPath
|
||
|
} else if (
|
||
|
reference.parentPath &&
|
||
|
t.isCallExpression(reference.parentPath) &&
|
||
|
reference.parent.callee === reference.node
|
||
|
) {
|
||
|
reference.replaceWith(getStyledIdentifier())
|
||
|
createStyledComponentPath = reference.parentPath
|
||
|
}
|
||
|
|
||
|
if (!createStyledComponentPath) {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
const styledCallLikeWithStylesPath = createStyledComponentPath.parentPath
|
||
|
|
||
|
let node = transformExpressionWithStyles({
|
||
|
path: styledCallLikeWithStylesPath,
|
||
|
state,
|
||
|
babel,
|
||
|
shouldLabel: false
|
||
|
})
|
||
|
|
||
|
if (node && isWeb) {
|
||
|
// we know the argument length will be 1 since that's the only time we will have a node since it will be static
|
||
|
styledCallLikeWithStylesPath.node.arguments[0] = node
|
||
|
}
|
||
|
|
||
|
styledCallLikeWithStylesPath.addComment('leading', '#__PURE__')
|
||
|
|
||
|
if (isWeb) {
|
||
|
createStyledComponentPath.node.arguments[1] = getStyledOptions(
|
||
|
t,
|
||
|
createStyledComponentPath,
|
||
|
state
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export let createStyledMacro = ({
|
||
|
importSource,
|
||
|
originalImportSource = importSource,
|
||
|
baseImportName = 'default',
|
||
|
isWeb
|
||
|
}: {
|
||
|
importSource: string,
|
||
|
originalImportSource?: string,
|
||
|
baseImportName?: string,
|
||
|
isWeb: boolean
|
||
|
}) =>
|
||
|
createTransformerMacro(
|
||
|
{
|
||
|
default: [
|
||
|
styledTransformer,
|
||
|
{ styledBaseImport: [importSource, baseImportName], isWeb }
|
||
|
]
|
||
|
},
|
||
|
{ importSource: originalImportSource }
|
||
|
)
|