const t = require('@babel/types')
|
const uniI18n = require('@dcloudio/uni-cli-i18n')
|
|
const {
|
VIRTUAL_HOST_CLASS
|
} = require('../../../constants')
|
|
const {
|
getCode,
|
isRootElement
|
} = require('../../../util')
|
|
function processClassArrayExpressionElements (classArrayExpression) {
|
let binaryExpression
|
|
classArrayExpression.elements.forEach(expr => {
|
if (t.isArrayExpression(expr)) {
|
expr = processClassArrayExpressionElements(expr)
|
}
|
if (!binaryExpression) {
|
binaryExpression = t.parenthesizedExpression(expr)
|
} else {
|
binaryExpression = t.parenthesizedExpression(t.binaryExpression(
|
'+',
|
t.binaryExpression(
|
'+',
|
binaryExpression,
|
t.stringLiteral(' ')
|
),
|
expr
|
))
|
}
|
})
|
|
return binaryExpression
|
}
|
|
function processStaticClass (classArrayExpression, staticClassPath, state) {
|
if (staticClassPath) {
|
const staticClassPathArr = staticClassPath.node.value.value.split(' ')
|
for (let len = staticClassPathArr.length, index = len - 1; index >= 0; index--) {
|
classArrayExpression.elements.unshift(t.stringLiteral(staticClassPathArr[index]))
|
}
|
staticClassPath.remove()
|
}
|
|
const transPlatform = ['mp-toutiao', 'mp-alipay', 'mp-lark']
|
if (transPlatform.includes(state.options.platform.name)) {
|
// classArrayExpression => binaryExpression
|
return processClassArrayExpressionElements(classArrayExpression)
|
}
|
return classArrayExpression
|
}
|
|
function processClassObjectExpression (classValuePath) {
|
const elements = []
|
const propertyPaths = classValuePath.get('properties')
|
propertyPaths.forEach(propertyPath => {
|
const key = propertyPath.node.key
|
elements.push(
|
t.conditionalExpression(
|
t.parenthesizedExpression(propertyPath.node.value),
|
t.stringLiteral(key.name || key.value),
|
t.stringLiteral('')
|
)
|
)
|
})
|
return t.arrayExpression(elements)
|
}
|
|
function processClassArrayExpression (classValuePath) {
|
const elementPaths = classValuePath.get('elements')
|
elementPaths.forEach(elementPath => {
|
if (elementPath.isObjectExpression()) {
|
elementPath.replaceWith(processClassObjectExpression(elementPath))
|
}
|
})
|
return classValuePath.node
|
}
|
|
module.exports = function processClass (paths, path, state) {
|
const classPath = paths.class
|
const staticClassPath = paths.staticClass
|
const mergeVirtualHostAttributes = state.options.mergeVirtualHostAttributes
|
let classArrayExpression
|
if (classPath) {
|
const classValuePath = classPath.get('value')
|
if (classValuePath.isObjectExpression()) { // object
|
classArrayExpression = processClassObjectExpression(classValuePath)
|
} else if (classValuePath.isArrayExpression()) { // array
|
classArrayExpression = processClassArrayExpression(classValuePath)
|
} else if (
|
classValuePath.isStringLiteral() || // :class="'a'"
|
classValuePath.isIdentifier() || // TODO 需要优化到下一个条件,:class="classObject"
|
classValuePath.isMemberExpression() || // 需要优化到下一个条件,:class="item.classObject"
|
classValuePath.isConditionalExpression() ||
|
classValuePath.isLogicalExpression() ||
|
classValuePath.isBinaryExpression()
|
) {
|
// 理论上 ConditionalExpression,LogicalExpression 可能存在 classObject,应该__get_class,还是先不考虑这种情况吧
|
// ConditionalExpression :class="index === currentIndex ? activeStyle : itemStyle"
|
// BinaryExpression :class="'m-content-head-'+message.user"
|
classArrayExpression = t.arrayExpression([classValuePath.node])
|
} else if (
|
classValuePath.isIdentifier() ||
|
classValuePath.isMemberExpression()
|
) { // classObject :class="classObject" :class="vm.classObject"
|
// TODO 目前先不考虑 classObject,styleObject
|
|
// const args = [classPath.node.value]
|
// if (staticClassPath) {
|
// args.push(staticClassPath.node.value)
|
// staticClassPath.remove()
|
// }
|
// classValuePath.replaceWith(
|
// getMemberExpr(
|
// classPath,
|
// IDENTIFIER_CLASS,
|
// t.callExpression(t.identifier(INTERNAL_GET_CLASS), args),
|
// state
|
// )
|
// )
|
} else {
|
state.errors.add(':class' + uniI18n.__('templateCompiler.noSupportSyntax', { 0: getCode(classValuePath.node) }))
|
}
|
}
|
if (mergeVirtualHostAttributes && isRootElement(path.parentPath)) {
|
const virtualHostClass = t.identifier(VIRTUAL_HOST_CLASS)
|
if (classArrayExpression) {
|
classArrayExpression.elements.push(virtualHostClass)
|
} else {
|
classArrayExpression = t.arrayExpression([virtualHostClass])
|
const property = t.objectProperty(t.identifier('class'), processStaticClass(classArrayExpression, staticClassPath, state))
|
path.node.properties.push(property)
|
return []
|
}
|
}
|
if (classArrayExpression) {
|
const classValuePath = classPath.get('value')
|
classValuePath.replaceWith(processStaticClass(classArrayExpression, staticClassPath, state))
|
}
|
return []
|
}
|