const t = require('@babel/types') const { IDENTIFIER_STYLE, INTERNAL_GET_STYLE } = require('../../../constants') const { getCode, hyphenate } = require('../../../util') const getMemberExpr = require('../member-expr') const REGEX_PX = /(:|\s|\(|\/)[+-]?\d+(\.\d+)?u?px/g const REGEX_UPX = /(:|\s|\(|\/)[+-]?\d+(\.\d+)?upx/g function processStaticStyleUnit (styleStr, state) { if (typeof styleStr === 'string') { let matches = styleStr.match(REGEX_UPX) if (matches && matches.length) { matches.forEach(function (match) { styleStr = styleStr.replace(match, match.substr(0, match.length - 3) + 'rpx') }) } // TODO 不应该再支持 px 转 rpx if (state.options.transformPx) { // 需要转换 px matches = styleStr.match(REGEX_PX) if (matches && matches.length) { matches.forEach(function (match) { styleStr = styleStr.replace(match, match.substr(0, match.length - 2) + 'rpx') }) } } } return styleStr } function getStaticStyleStringLiteral (staticStylePath, state) { const staticStyle = staticStylePath.node.value.properties .map(property => { return `${property.key.value}:${property.value.value}` }) .join(';') const staticStyleStr = processStaticStyleUnit(staticStyle, state).trim() return t.stringLiteral(staticStyleStr + (!staticStyleStr.endsWith(';') ? ';' : '')) } function processStaticStyle (binaryExpressions, staticStylePath, state) { let binaryExpression binaryExpressions.forEach(binaryExpr => { if (!binaryExpression) { if (staticStylePath) { binaryExpression = t.binaryExpression( '+', getStaticStyleStringLiteral(staticStylePath, state), binaryExpr ) staticStylePath.remove() } else { binaryExpression = binaryExpr } } else { binaryExpression = t.binaryExpression( '+', binaryExpression, binaryExpr ) } }) return binaryExpression } function processStyleObjectExpression (styleValuePath) { const binaryExpressions = [] const propertyPaths = styleValuePath.get('properties') propertyPaths.forEach(propertyPath => { const key = propertyPath.node.key binaryExpressions.push( t.binaryExpression( '+', t.binaryExpression( '+', t.stringLiteral(hyphenate(key.name || key.value) + ':'), t.parenthesizedExpression(propertyPath.node.value) ), t.stringLiteral(';') ) ) }) return binaryExpressions } function processStyleArrayExpression (elementPaths) { let binaryExpressions = [] elementPaths.forEach(elementPath => { binaryExpressions = binaryExpressions.concat(processStyleObjectExpression(elementPath)) }) return binaryExpressions } function generateGetStyle (stylePath, styleValuePath, staticStylePath, state) { const args = [stylePath.node.value] if (staticStylePath) { args.push(staticStylePath.node.value) staticStylePath.remove() } styleValuePath.replaceWith( getMemberExpr( stylePath, IDENTIFIER_STYLE, t.callExpression(t.identifier(INTERNAL_GET_STYLE), args), state ) ) } module.exports = function processStyle (paths, path, state) { const stylePath = paths['style'] const staticStylePath = paths['staticStyle'] if (stylePath) { const styleValuePath = stylePath.get('value') if (styleValuePath.isObjectExpression()) { styleValuePath.replaceWith( processStaticStyle( processStyleObjectExpression(styleValuePath), staticStylePath, state ) ) } else if (styleValuePath.isArrayExpression()) { // array const elementPaths = styleValuePath.get('elements') const dynamicStyle = elementPaths.find(elementPath => !elementPath.isObjectExpression()) if (dynamicStyle) { generateGetStyle(stylePath, styleValuePath, staticStylePath, state) } else { styleValuePath.replaceWith( processStaticStyle( processStyleArrayExpression(elementPaths), staticStylePath, state ) ) } } else if ( styleValuePath.isStringLiteral() || // :style="'background:red'" styleValuePath.isIdentifier() || // TODO 需要优化到下一个条件,:style="styleObject" styleValuePath.isMemberExpression() || // TODO 需要优化到下一个条件,:style="item.styleObject" styleValuePath.isConditionalExpression() || styleValuePath.isLogicalExpression() || styleValuePath.isBinaryExpression() ) { // 理论上 ConditionalExpression,LogicalExpression 可能存在 styleObject,应该__get_style,还是先不考虑这种情况吧 // ConditionalExpression :style="index === currentIndex ? activeStyle : itemStyle" // BinaryExpression :style="'m-content-head-'+message.user" styleValuePath.replaceWith( processStaticStyle( [t.parenthesizedExpression(styleValuePath.node)], staticStylePath, state ) ) } else if ( styleValuePath.isIdentifier() || styleValuePath.isMemberExpression() ) { // TODO 目前先不考虑 classObject,styleObject // generateGetStyle(stylePath, styleValuePath, staticStylePath, state) } else { state.errors.add(`:style 不支持 ${getCode(styleValuePath.node)} 语法`) } } else if (staticStylePath) { staticStylePath.get('value').replaceWith(getStaticStyleStringLiteral(staticStylePath, state)) } return [] }