I’ve a CSS string like
#xyz{
color:#ee2ee2;
}
.abc{
background-color:#FFFFFF;
border-color:1px solid #eee;
}
.def #xyz{
border-color:1px solid #ddd;
}
I need to replace the #xyz
(or any other ID selector) with .xyz
without changing the color: #ee2ee2
(or any other color selector).
Basic java-script code would do
I’ve tried some regex but it fails a few cases
cssText.replace(/#([a-zA-Z])/gm, '.$1');
My suggestion here is to use a library that might parse the object into rules, as suggested by @Jakub.
This answer uses the following regular expression, /#(?!:[w]+)(?=([wd[],*=>.s]*[{,[]+))/g
, which should effectively match #
as it proceeds not-captured group (representing the Id itself) which in-turn proceeds the positive lookahead group (as series of word (a-zA-Z0-9_
) and special characters, including whitespace & newline, that proceeds {
, ,
, [
).
var outputElm = document.getElementById("output");
var importedCode = `div#xyz, #xyz, div#xyz[id='xyz'],
.def>#xyz, .def>div#xyz, .def>#xyz,
.def>div#xyz[id=*]
{
color:#ee2ee2;
}
@media (min-width: 30em) and (orientation: landscape)
{
.abc{
background-color :#FFFFFF;
border-color:1px solid #eee ;
}
.def>#xyz, .def #xyz, .def>#xyz{border-color:1px solid #ddd;}
.def>#xyz>div, .def #xyz div, .def>#xyz>div.abc {border-color:1px solid #ddd;}
}`;
var replaceIdRegex = /#(?!:[w]+)(?=([wd[],*=>.s]*[{,[]+))/g;
outputElm.innerText = importedCode.replace(replaceIdRegex, ".");
<p id="output">
</p>
I’ve done a fairly good amount of testing on this, but I can’t say it isn’t brittle or can account for every scenario.
You can test this implementation on regex101 playground as well.
By matching the spaces at the beginning of the line, you can use the regex ^s+#(w+)
.
Example in Java 13:
var regex = "^\s+#(\w+)";
var string = """
#xyz{
color:#ee2ee2;
}
.abc{
background-color:#FFFFFF;
border-color:1px solid #eee;
}
.def #xyz{
border-color:1px solid #ddd;
}
""";
var matcher = Pattern.compile(regex, Pattern.MULTILINE).matcher(string);
var newString = matcher.replaceAll(".$1");
This is not a good job for regex. You will get much more reliable results by using a proper CSS parser. For example:
const css = require('css');
const ast = css.parse(myInputString);
ast.stylesheet.rules.forEach(rule => {
if (rule.type === 'rule') {
rule.selectors = rule.selectors.map(selector => selector.replace('#', '.'))
}
});
return css.stringify(ast);
(Note: I haven’t fully tested this code. But the principle is solid.
This will replace #
with .
only when there is a {
somewhere after in the same line.
cssText = `
#xyz
{
color:#ee2ee2;
}
.abc{
background-color:#FFFFFF;
border-color:1px solid #eee;
}
.def #xyz{
border-color:1px solid #ddd;
}
body{background-color:#fff000;}.ig26{padding:20px;}.icts{width:200px;height:200px;padding:10px;}
`;
console.log(cssText.replace(/#([a-zA-Z])(?=[^}]*{)/g, '.$1'));