简体   繁体   中英

Parsing CSS background-image

How do I parse CSS background-image , which supports multiple values, which may be none and functions (eg url() and linear-gradient() ) with multiple comma-separated arguments? I can't seem to do this correctly with regexps. A good test case is as follows:

  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

Which I'd want to convert to the following array:

[
      "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"
]
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"]

Looking at the current W3C Candidate Recommendation for CSS3 (in particular, see background-image and uri ), it is structured as follows:

<background-image> = <bg-image> [ , <bg-image> ]* 
<bg-image> = <image> | none
<image> = <url> | <image-list> | <element-reference> | <image-combination> | <gradient>

... (you can find the rest of syntax for images here )

EDIT:

You will need to parse for matching parenthese or none then, and the former is not possible with regex. This post has a pseudo code for the algorithm: Python parsing bracketed blocks .

I know, the question is pretty old, but if you stumble over it and need another solution, you can use this one:

 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM