How do I match individual CSS attributes using RegEx - css

I'm trying to expand a minified CSS file (don't ask) to make it human readable.
I've managed to get most of the expanding done but I'm stuck at a very weird case that I can't figure out.
I have CSS that looks like this:
.innerRight {
border:0;color:#000;width:auto;padding-top:0;margin:0;
}
a {
color:#000;text-decoration:underline;font-size:12px;
}
p,small,ul,li {
color:#000;font-size:12px;padding:0;
}
I've tried (.+):(.+); as the search and \t\1: \2;\n as the replace. The find RegEx is valid, the only problem is that it matches the entire line of attributes. I've tried the non-greedy character, but I must not be putting it in the right place.
What the above find RegEx matches is:
0: border:0;color:#000;width:auto;padding-top:0;margin:0;
1: color:#000;text-decoration:underline;font-size:12px;
2: color:#000;font-size:12px;padding:0;
While those are technically correct matches, I need it to match border:0;, color:#000;, etc separately for my replace to work.

Try this - use non-greedy matching. This works for me
(.+?):(.+?);

Forget the colon. Just replace all semicolons with ";\n".
In Javascript, for example, you could write:
text = text.replace(/;/gm,";\n");
I would further refine that to address leading-space issues, etc., but this will put every style rule on its own line.

Related

regex to find pattern not inside another pattern

I'm trying to write a regex to find all ID selectors in a CSS file. Basically, that means any word that starts with a #, so okay
#\w+
Except ... color specifiers can also start with a #. So what I really want is all words that start with a # that are NOT between { and }. I can't figure out how to say this.
I'm doing this in Notepad++ so I need that flavor of regex.
BTW my real objective is to delete everything that's not an ID selector from the file, so I end up with just a list of selectors. My first try was
Find: [^#]*(#\w+)
Replace: \1\r\n
... and then hit Replace All.
But then I ran into the color problem.
Update
Someone asks for an example. Ok:
Input:
.foo {max-width: 500px;}
#bar {text-align: left;}
.splunge, #plugh {color: #ff0088;}
Desired output:
#bar
#plugh
Note the point is that it includes the two "pound strings" that come outside of braces but not the one that comes inside braces.
What about this? You could use a lookahead expression:
#\w+(?=[^}]*?{)
It ensures that a { follows the match (indicating that the match is part of a selector), but not after a } character (excluding any matches against color declarations in the CSS).
#: match must begin with a #
\w+: match one or more word characters (might need tweaked. \w is equivalent to [A-Za-z0-9_])
(?=...): positive lookahead
[^}]*?: Any character not matching }
{: the { character
https://regex101.com/r/Di43hX/3

Creating a Regex to match "Body: Margin 0"

I want to create a regex, in order to find out if an entry exists.
The Entry is in a CSS File.
Unfortunately different developers tend to write them in different manners, so I want to create a regex, that matches all this individualities.
I hope somebody can help me.
body {
margin: 0; }
body
{
margin: 0;
}
body{margin:0;}
There are too many variables that could makes your regexp fails: body could have an id, a class, and/or be part of a bigger list. You could have comments, the ";" could be missing, you could have multiple rules inside.
Unless you want to match exactly the three strings above, I strongly suggest to use a css parser that returns an AST. Something like: https://github.com/csstree/csstree
Something like this seems to work for your examples, as well as any other valid synthax I can think of :
^\s*[\.\#]{0}body(\s|\n)*\{[^\}]*(\s|\n)*margin(\s|\n)*\:\s*0\s*\;[^\}]*\}
Try here : https://regex101.com/r/GbIbdE/1

Escaping special characters in symfony css selector or using wildcard

I am using the Symfony\Component\DomCrawler\Crawler package to find a form with a name containing a number of css special chars
<input name="myfield[0].thing">
I am using
$messageElement = $crawler->filter('input[name=myField[0].thing]');
return $messageElement->attr($attribute);
But I get the error
Symfony\Component\CssSelector\Exception\SyntaxErrorException: Expected "]", but found.
Obviously this is because the symfony css selector is using [ ] to contain the attributes. So If I try an escape all the special chars
$crawler->filter('input[name=myField\[0\]\.thing]');
I now get empty output. How can I fix this?
Bonus question: is it possible to use a wildcard instead? * doesn't seem to work for me.
If you encapsulate the field name it should work, try this:
$messageElement = $crawler->filter('input[name="myField[0].thing"]');
return $messageElement->attr($attribute);.
For the bonus question, you can use a regex match similar to suggested here: wildcard * in CSS for classes
// For matching strings starting with a certain thing notice the ^=
$messageElement = $crawler->filter('input[name^="myField[0]"]');
// For matching strings containing with a certain thing notice the *=
$messageElement = $crawler->filter('input[name*="myField[0]"]');

regex replace to match url() paths in css and replace with asset_path

I've been trying to follow this SO answer to try and write some regex to do a pattern replace with Grunt. My regex understanding is very basic so I'm pretty lost.
Matching
.selector {
background: url('../img/some.filename.png') no-repeat;
}
Output
.selector {
background: url(<%= asset_path 'some.filename.png' %>) no-repeat;
}
I understand something like /url\(.*?g'\)/ig will match the url() tag but I'm not sure how to isolate the filename from within that. Using the Grunt string-replace task to run the replace.
Any pointers?
I have conjured a beast of a regex that I believe does the job. It requires a positive lookbehind and a positive lookahead which I don't know if Grunt supports since I don't know what that is. I'm going to assume it does, otherwise I don't think it's possible without the lookaround.
I tested this regex using C#, so here it is!
Regex:
(?<=url\s*\('([\w\._-]+/)*)([\w\._-]+)(?='\))
Test String:
url ('fruit-veggie/apple_orange-pie/this.is-my_file.png')
I will break this down as it befuzzles even me. This is composed of 3 major parts.
Positive lookbehind:
(?<=url\s*\('([\w\._-]+/)*)
The (?<=) indicates whatever comes between the = and ) has to be part of the pattern that follows, but it will not be part of the match.
url\s*\(' will match url (' with or without spaces.
([\w\._-]+/)* will match any string that contains at least one word character, dot, underscore, or dash, followed by a forward slash. This will consume one folder path. The * at the end will make it consume any number of folders because you might not have a folder to begin with.
Actual file name:
([\w\._-]+)
This is identical to the folder pattern except without the forward slash at the end. This will match files without extensions.
Positive lookahead:
(?='\))
(?=) is the same as the positive lookbehind, except this is a lookahead which will check what comes after the pattern that precedes it.
'\) simply checks that the entire string is followed by a quote and a closing bracket.
For the folder/file name pattern, you will have to tweak it based on what characters would be valid in them. So if for whatever crazy reason they can contain a #, you will have to modify those portions of the regex to include that character.
Hopefully Grunt supports this regex, otherwise I will have wasted my time. But this was a fun challenge regardless!
Update
It seems JavaScript doesn't support lookbehinds. If what you're doing is specific to your current project only, why don't you try using two regex instead of one?
function GetFile (s) {
s = s.replace (/url\s*\('([\w\._-]+\/)*/g, '');
return s.match (/[\w\._-]+(?='\))/)[0];
}
var s = "url ('fruit-veggie/apple_orange-pie/this.is-my_file.png')";
console.log (GetFile (s));
This will erase everything up to but not including the first character of the file name. Then it returns the file name without the end quote and bracket, because JavaScript supports lookaheads.
You can use something like this :
(?:url\((.*?)\))
Demo
Explanation :
In javascript you can give :
var s="url('../img/some.filename.png')";
var ss= /(?:url\((.*?)\))/ ;
console.log(s.match(ss)[0]);

Create a regex for a string with 1 item that changes

I am trying to build a regex for an inline CSS code that 1 item on changes
This is the line of code in question
<div="Box1" style="background-color:Transparent;border-color:Transparent;border-style:None;height:436px;"></div>
I need to be able to pick this out but the height is different on every page
so all the rest is exactly the same but the height changes
If you got that line, you can use the following regex to get the height.:
'<div="Box1" style="background-color:Transparent;border-color:Transparent;border-style:None;height:436px;"></div>'
.match(/height:([\sa-z0-9]+);/)
This will return:
["height:436px;", "436px"]
This example is in JS, I don't know in what language you want to use the Regex? But in CSS you cant.
[0-9]+ matches an arbitrary number.
However, for the HTML part you should not use a regex at all but a HTML parser - and then only use a regex on the style attribute.

Resources