刮刮前端
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.
 
 
 
 

143 lines
5.0 KiB

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 []
}