1

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:

  • There are hundreds of selectors in the file
  • The syntax is always valid CSS, but spacing, new lines, and use of semi-colons is inconsistent. For example:
#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.

2 Answers 2

1

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 {

Regex demo

Sign up to request clarification or add additional context in comments.

Comments

1

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.

4 Comments

This is really cool, thanks for sharing. I actually just want to select and delete all of the declarations blocks without those colors in a code editor so I can paste the optimized code as text into a larger project.
Use your editor. It takes regular expressions, if it's any good.
I know, I'm trying to construct a regular expression that will select every declaration block that doesn't have those hex values.
You could use .+{[^}]+(#f518e2|#22f1e6)[^}]+} in Komodo and replace all with nothing and the rest will be left over.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.