Reputation:
As an exercise in learning RegEx in JavaScript, I've been trying to select an attribute's value within a CSS stylesheet. Given the following CSS:
foo {
color: rgb(0, 0, 0) !important;
background-color: rgb(0, 0, 0) !important;
border-left: 1px solid #111;
}
and a function getStyle(css, attribute)
such that getStyle(css, 'background-color')
returns "rgb(0, 0, 0)"
, I've come up with the following code:
function getStyle(css, attribute) {
var pattern = new RegExp(attribute + ':\\s+([^!;]+)');
return pattern.exec(css);
}
This gets pretty close: it matches until it hits a !
or a ;
, whichever comes first. But in the case of getStyle(css, 'color')
, it also returns the whitespace after rgb(0, 0, 0)
and before !important
:
color = "rgb(0, 0, 0) "
background-color = "rgb(0, 0, 0) "
border-left = "1px solid #111"
I've tried things like attribute + ':\\s+([^\\s+!;]+)'
, but that winds up returning only rgb(0,
because of the spaces in the value. I've also been able to get the expected output using different regex and look behinds, but JavaScript doesn't support them.
I've also thought that maybe I could indicate something like match while \\s+!
or \\s+.+;
isn't true: that is, stop matching once it finds whitespace before a specific character, but I'm not sure how to key that in regex.
I could just as easily strip the whitespace in a second step, but I'm wondering: is there a way to get the expected output in one RegEx?
Upvotes: 1
Views: 1878
Reputation: 75222
I would use
'\\s*:\\s*([^\\s+!;]+(?:\\s+[^\\s+!;]+)*)'
If there's some whitespace that's followed by more non-whitespace/bang/semicolon characters, treat it as a continuation of the attribute value.
I also changed the first part, because the whitespace before and after the colon is optional.
You might want to add something like '[\\s;]' +
to the beginning, too. The way you have it, the color
regex will match both the color
and background-color
attributes.
Upvotes: 1
Reputation: 118651
You need what's called a look-ahead. It will match the text you give it, but not include it in the output.
pattern = new RegExp(attribute + ':\\s+.+?(?=\\s*[!;])');
The (?=...)
is a look-ahead, where I'm allowing leading whitespace and either of !;
. I'm using .+?
so that it matches as little as possible before the first matched thing in the look-ahead (otherwise, it'd capture the !important
before the ;
).
Upvotes: 2