css variable 解析
给一个开源项目做的css variable支持,外部逻辑都没啥复杂的,主要难点在于解析variable值.
CSS value合理类型
.two {
color: var(—my-var, red); /* Red if —my-var is not defined */
}
.three {
background-color: var(--my-var, var(--my-background, pink)); /* pink if --my-var and --my-background are not defined */
}
.three {
background-color: var(--my-var, --my-background, pink); /* Invalid: "--my-background, pink" */
}
处理思路
首先对字符串进行解析,分割出最外层var(),记录一个css值内包含多少个成立的变量. 直接拿取var(
位置,然后步进查询)
中间遇到(
做括号层级的增加,匹配到第一个符合条件的)
结束,然后递归处理剩下的字符串
然后再逐个对var()值进行解析,根据css var的规则其实可以很简单的发现,文件的替换关系值采用从左到右的规则,具体的var()层级关系不关键,所以只要抽离 成对的var(
和 )
然后再以 ,
字符做分割就好.
要注意的是可能会存在rgba(1,1,1)
这样的css值,所以在进行逗号拆分时要排除掉括号内的逗号,正则:/,(?![^(]*\))/
最后在实际使用时顺序匹配关键字数组就可以了,以--
开头的是css变量.反之为变量值.
拿到css var 具体值后用getComputedStyle(element).getPropertyValue("--my-var")
拿取目标dom上需要替换的css变量值就好
源码:
let res = []
var splitCssValue = function(CssValue,startIndex){
var cssStr = CssValue.slice(startIndex)
let bracketsIndex = 0
if (cssStr.indexOf('var(') >= 0 ){
var start = cssStr.indexOf('var(');
for(var I=start+4; I<cssStr.length; I++){
//get effective var() form selector
if(cssStr[i] == '('){
bracketsIndex++
}
if(cssStr[i] == ')'){
if(bracketsIndex == 0){
//This is a effective var()
var end = i+1
let valueString = cssStr.slice(start,end)
let ValueIndex = 0
let resSrt = ‘’
//exclude ‘var(‘ and ‘)’ form cssValueString
for(let ch = 0; ch < valueString.length; ch++){
if(valueString[ch]==‘v’ && valueString.slice(ch,ch+4) == ‘var(‘){
ValueIndex++
ch+=3;
continue;
}
if(valueString[ch] == ')' && ValueIndex>0){
ValueIndex--
continue;
}
resSrt+=valueString[ch]
}
var re = /,(?![^(]*\))/
res.push({
start: start+startIndex,
end: end+startIndex,
varString: valueString,
varValue:resSrt.split(re)
})
return splitCssValue(CssValue,startIndex+end)
}else{
bracketsIndex--
}
}
}
//brackets number discord law
return false
}
return true;
}
function doTurn(){
const varReg = /var\(.*?\)/gi
if (cssValue && varReg.test(cssValue)) {
const originalValue = cssValue.replace(/^\s+|\s+$/g, '')
let res = ''
this.cssVariableList = []
console.log('originalValue', originalValue)
if (this.analysisCssVariables(originalValue, 0)) {
console.log('cssVariableList', this.cssVariableList)
this.cssVariableList.map(CssVariable => {
if (CssVariable.valueName.length > 0) {
for (let I = 0; I < CssVariable.valueName.length; I++) {
const name = CssVariable.valueName[I].replace(/^\s+|\s+$/g, ‘’)
if (name.slice(0, 2) == ‘—‘) {
const css = getComputedStyle(node).getPropertyValue(name)
console.log('css,name', css, name)
if (css) {
res = originalValue.replace(
originalValue.substring(CssVariable.startIndex, CssVariable.endIndex),
css
)
return
}
} else {
if (name) {
res = originalValue.replace(
originalValue.substring(CssVariable.startIndex, CssVariable.endIndex),
name
)
return
}
}
}
}
})
console.log('last Res', res)
return res
} else {
return cssValue
}
}
}
最后更新于