0

I'm working on an app that allows a bit of user-defined CSS. I need to wrap every CSS selector with a parent class, .template-container. Example:

h2 { 
   border: 5px solid yellow;
   background: green;
   border-radius: 100%;
   text-align: center;
}

label, li, p, h1 {
   color: red !important;
}

.class > p {
  color: green;
}

should get changed to:

.template-container h2 { 
   border: 5px solid yellow;
   background: green;
   border-radius: 100%;
   text-align: center;
}

.template-container label, 
.template-container li,
.template-container p,
.template-container h1 {
   color: red !important;
}

.template-container .class > p {
  color: green;
}

Link to my expression example: https://regex101.com/r/uPIdR4/1

So far I've come up with: (.*)(,|{) -- the selectors get added to the first group, the , or { gets added to a second group. Then for the substitution I'm using .template-container $1 $2

The issue is, for the second group, only the label is getting that parent class added, the rest of the elements do not. So it comes out as:

.template-container label, li, p, h1  {
   color: red !important;
}

I've been trying to fix this but I'm not having any luck. Any help would be much appreciated.

5 Answers 5

2

I would suggest this:

(?=\S)([^,{\n\r]+(?=.*\{))

Replace with: .template-container $1

This requires that the opening brace is on the same line.

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

1 Comment

Perfect! Thank you so much.
1

You can wrap the children in :is(). Also, you may need to split up the { in another capture group, so the regex pattern will be /(.*)(,|)({)/gm.

For example:

function addStyle(styleString) {
  const style = document.createElement('style');
  style.textContent = styleString;
  document.head.append(style);
}

var cssString = `h2 { 
   border: 5px solid yellow;
   background: green;
   border-radius: 100%;
   text-align: center;
}

label, li, p, h1 {
   color: red !important;
}

.class > p {
  color: green;
}`;

var regex = /(.*)(,|)({)/gm;
var result = cssString.replace(regex, ".template-container :is($1 $2) $3");

function apply(){
  addStyle(result); 
  console.log(result);
}
<div class="template-container">
  <h2>Heading 2</h2>
  <p>Lorem Ipsum</p>
  <label>Dolor sit amet</label>
  <div class="class"><p>Class P</p></div>
</div>

<p>Lorem Ipsum</p>

<button onclick="apply()">Click Me to see the Magic</button>

1 Comment

This is awesome, thank you! Only issue on my side is that, unfortunately, I have to support IE11.
1

You can use this pattern: ([^,\n]+)(?={|,)

See Regex Demo

Regex101 code:

const regex = /([^,\n]+)(?={|,)/g;
const str = `h2 { 
border: 5px solid yellow;
background: green;
border-radius: 100%;
text-align: center;
}

label, li, p, h1 {
color: red !important;
}

.class > p {

}`;
const subst = `.template-container $1\n`;
const result = str.replace(regex, subst);

console.log(result);

Comments

0

You could try with just one argument on substitution

([\w]*(,)|[\w]*( {)|\.[\w]*.*)

Substitution: .template-container $1

Regex101 link: https://regex101.com/r/pFpRer/1

Comments

0

You can try this:

(\w*)(,|\s{)

regex example:

enter image description here

1 Comment

Thanks. Only issue is the third selector in my example... the .template-container gets added to the p element rather than before the first class: screenshot

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.