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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.