解析CSS背景图像

时间:2011-08-07 01:55:11

标签: javascript css regex

如何解析支持多个值的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"
]

3 个答案:

答案 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-imageuri),其结构如下:

<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 &lt;hr&gt;</p>

<div id="result"></div>