const t = require('@babel/types') const uniI18n = require('@dcloudio/uni-cli-i18n') const { VIRTUAL_HOST_CLASS } = require('../../../constants') const { getCode } = require('../../../util') const { 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 platformName = state.options.platform.name const virtualHost = platformName === 'mp-weixin' || platformName === 'mp-alipay' 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 (virtualHost && 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 [] }