Reputation: 12209
Let's say I have the following CSS. I need a regular expression that grabs entire declaration blocks (selector, opening bracket, contents, closing bracket) that do not have the folowing colors in them: #f518e2
and #22f1e6
.foo{
color: #f518e2;
box-spacing: border-box;
}
#bar{
color: #e4e4e4;
box-spacing: border-box;
}
biz.baz{
background: #22f1e6;
font-size: 30px;
}
So in this case, I would want to grab:
#bar{
color: #e4e4e4;
box-spacing: border-box;
}
Assumptions:
#bar{ color: #e4e4e4;
box-spacing: border-box; }biz.baz
{
background: #22f1e6;
font-size: 30px; }
I've tried something like this: /\w*[#.]?\w+\s*{[^\{\}]+}/g
which selects entire declaration blocks, but when it comes to weeding out the ones with #f518e2
and #22f1e6
it's a little beyond what I know about regex.
Upvotes: 1
Views: 122
Reputation: 163277
One option could be to match all lines where {
is at the start of the line, and }
at the end of the line and match all lines in between that do not have either #f518e2
or #22f1e6
using a negative lookahead.
Note that this pattern works for the given examples, but does not take any nesting or data structure into account.
^.*{(?:\r?\n(?!.*#(?:f518e2|22f1e6)\b).*)*\r?\n}
The pattern matches:
^
Start of string.*{
Match the whole line and {
at the end(?:
Non capture group
\r?\n
Match a newline(?!.*#(?:f518e2|22f1e6)\b).*
Assert that the line does not contain the colors and match the whole line)*
Close the non capture group and repeat 0+ times\r?\n
Match a newline}
Match {
Upvotes: 1
Reputation: 10627
You probably want to use JavaScript to do such a task. I've including an example for your studies:
//<[CDATA[
/* js/external.js */
function hexNum(x){
switch(x.toUpperCase()){
case 'A':
return 10;
case 'B':
return 11;
case 'C':
return 12;
case 'D':
return 13;
case 'E':
return 14;
case 'F':
return 15;
default:
return +x;
}
}
function hexToRGBArray(hex){
let s, r = [];
if(hex.match(/^#?[\dA-F]{6}$/i)){
s = hex.replace(/^#/, '').split('');
for(let i=0,q=1; i<6; i+=2,q+=2){
r.push(hexNum(s[i])*16+hexNum(s[q]));
}
}
else if(hex.match(/^#?[\dA-F]{3}/i)){
s = hex.replace(/^#/, '').split('');
for(let i=0,h; i<3; i++){
h = hexNum(s[i]); r.push(h*16+h);
}
}
else{
throw new Error('invalid hexadecimal');
}
return r;
}
addEventListener('load', ()=>{
// stack overflow is including nodes you won't see in real world
const all = document.body.querySelectorAll('*');
const avoid1 = hexToRGBArray('#f518e2').join(), avoid2 = hexToRGBArray('#22f1e6').join();
let s;
for(let n of all){ // n being node
s = getComputedStyle(n).color.replace(/^.+\(|\).*$/g, '').split(/\s*,\s*/).join();
if(s !== avoid1 && s !== avoid2){
console.log(n.textContent);
// n is node
}
}
}); // end load
//]]>
/* css/external.css */
div{
color:#ab7722;
}
#test1{
color:#f518e2;
}
#test4{
color:#22f1e6;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' />
<title>Title Here</title>
<link type='text/css' rel='stylesheet' href='css/external.css' />
<script src='js/external.js'></script>
</head>
<body>
<div id='test1'>nope</div>
<div id='test2'>got this one</div>
<div id='test3'>and this one</div>
<div id='test4'>not this one</div>
</body>
</html>
Note that in the real world document.body
would only access that which is in the body
. Stack Overflow must have something else in mind. They should fix it.
Upvotes: 1