如何解析支持多个值的CSS background-image
,这些值可能是none
并且函数(例如url()
和linear-gradient()
)具有多个以逗号分隔的参数?我似乎无法使用正则表达式正确执行此操作。一个好的测试用例如下:
linear-gradient(top left, red, rgba(255,0,0,0))
, url(a)
, image(url(b.svg), 'b.png' 150dpi, 'b.gif', rgba(0,0,255,0.5))
, none
我想将其转换为以下数组:
[
"linear-gradient(top left, red, rgba(255,0,0,0))"
, "url(a)"
, "image(url(b.svg), 'b.png' 150dpi, 'b.gif', rgba(0,0,255,0.5))"
, "none"
]
答案 0 :(得分:7)
function split (string) {
var token = /((?:[^"']|".*?"|'.*?')*?)([(,)]|$)/g;
return (function recurse () {
for (var array = [];;) {
var result = token.exec(string);
if (result[2] == '(') {
array.push(result[1].trim() + '(' + recurse().join(',') + ')');
result = token.exec(string);
} else array.push(result[1].trim());
if (result[2] != ',') return array
}
})()
}
split("linear-gradient(top left, red, rgba(255,0,0,0)), url(a), image(url" +
"(b.svg), 'b.png' 150dpi, 'b.gif', rgba(0,0,255,0.5)), none").toSource()
["linear-gradient(top left,red,rgba(255,0,0,0))", "url(a)",
"image(url(b.svg),'b.png' 150dpi,'b.gif',rgba(0,0,255,0.5))", "none"]
答案 1 :(得分:4)
查看当前针对CSS3的W3C候选建议书(特别是background-image和uri),其结构如下:
<background-image> = <bg-image> [ , <bg-image> ]*
<bg-image> = <image> | none
<image> = <url> | <image-list> | <element-reference> | <image-combination> | <gradient>
...(您可以找到图像的其余语法here)
编辑:
您需要解析匹配的括号或none
然后,前者不可能使用正则表达式。这篇文章有一个算法的伪代码:Python parsing bracketed blocks。
答案 2 :(得分:1)
我知道,这个问题已经很老了,但是如果您偶然发现它并需要其他解决方案,您可以使用这个:
let mydiv = document.getElementById('mydiv'),
result = document.getElementById('result'),
bgImageArray = getBackgroundImageArray(mydiv);
console.log(bgImageArray);
result.innerHTML = bgImageArray.join('<hr>');
function getBackgroundImageArray(el)
{
// get backgroundImageStyle
let bgimg_style = getComputedStyle(el).backgroundImage,
// count for parenthesis
parenthesis = -1;
// split background by characters...
return bgimg_style.split('').reduce((str_to_split, character) => {
// if opening parenthesis
if(character === '(') {
// if first opening parenthesis set parenthesis count to zero
if(parenthesis === -1) {
parenthesis = 0;
}
// add 1 to parenthesis count
parenthesis++;
}
// for closing parenthesis reduce parenthesis count by 1
else if(character === ')') {
parenthesis--;
}
else {
// if current character is a comma and it is not inside a parenthesis, at a "split" character
if(character === ',') {
if(parenthesis === 0) {
str_to_split += '||';
return str_to_split;
}
}
}
// else keep the character
str_to_split += character;
return str_to_split;
}, '')
// split the resulting string by the split characters including whitespaces before and after to generate an array
.split(/\s*\|\|\s*/);
}
#mydiv {
height: 75px;
background-image:
/* first bg image */
linear-gradient(90deg, rgba(28,221,218,1) 0%, rgba(45,109,210,1) 35%, rgba(0,212,255,1) 100%),
/* second bg image */
-webkit-image-set(url(nothing.jpg) 1x, url(everything.png) 2x),
/* third bg image */
url('there/is/an/image.svg');
}
<div id="mydiv"></div>
<p>See in console for actual result array, below is the array splitted by <hr></p>
<div id="result"></div>