const t = require('@babel/types')
|
|
const {
|
IDENTIFIER_STYLE,
|
INTERNAL_GET_STYLE,
|
VIRTUAL_HOST_STYLE
|
} = require('../../../constants')
|
|
const {
|
getCode,
|
hyphenate,
|
isRootElement
|
} = 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
|
const mergeVirtualHostAttributes = state.options.mergeVirtualHostAttributes
|
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)} 语法`)
|
}
|
if (mergeVirtualHostAttributes && isRootElement(path.parentPath)) {
|
styleValuePath.replaceWith(t.binaryExpression('+', styleValuePath.node, t.identifier(VIRTUAL_HOST_STYLE)))
|
}
|
} else if (staticStylePath) {
|
if (mergeVirtualHostAttributes && isRootElement(path.parentPath)) {
|
const styleNode = processStaticStyle([t.identifier(VIRTUAL_HOST_STYLE)], staticStylePath, state)
|
const property = t.objectProperty(t.identifier('style'), styleNode)
|
path.node.properties.push(property)
|
return []
|
}
|
staticStylePath.get('value').replaceWith(getStaticStyleStringLiteral(staticStylePath, state))
|
} else {
|
if (mergeVirtualHostAttributes && isRootElement(path.parentPath)) {
|
const property = t.objectProperty(t.identifier('style'), t.identifier(VIRTUAL_HOST_STYLE))
|
path.node.properties.push(property)
|
}
|
}
|
return []
|
}
|