0

If i have a css file, like this (for example):

div {
  color: red;
}
a{color: red}.someClass {color: red}

.someOtherClass {
color: red;
}

@media (max-width: 767px){
 div { color: green; }
 [data-module="123"] .someOtherClass { color: green; }
}

[data-module='123'] .someRandomClass { color: red }
[data-module='123'] .someOtherRandomClass {
color: red;
}

Only these last three would match the correct usage of CSS in our company:

[data-module='123'] .someOtherClass {
[data-module="123"] .someRandomClass {
[data-module='123'] .someOtherRandomClass {

Because they start with [data-module='xxx'] (notice users can use " or ') I have been able to find/edit a REGEX that matches these last three correctly, but I need the opposite, I want to match the selectors that dont start with [data-module="xxx"]... So when I'm checking with PHP/Regex, If it matches, I will have to tell the user that he is not following the rules ... The regex has to consider that this CSS might be unorganized like in the example and also there could be media queries..

Can any magic human being help me figure this out? Cause this is magic..some kind of sourcery.. can't figure it out

EDIT: I want something like this Regex: http://regexr.com/328s7

But only match, if the selector doesnt have [data-module="xxx"] before it

  • 1
    I'm not exactly sure I know what you mean. Give us examples of things you want to catch – ctwheels Aug 22 '17 at 13:57
  • @ctwheels edited the question: I want something like this Regex: http://regexr.com/328s7 But only match, if the selector doesnt have [data-module="xxx"] before it – Pablo Camara Aug 23 '17 at 13:29
  • You don't show in your css sample what to do if multiple selectors (separated by comma) follow the `data-module`? – NetMage Aug 23 '17 at 23:06
  • Are all data-module names three characters? – NetMage Aug 23 '17 at 23:20
  • @NetMage no, it can be a number, 123 or 1234, or 12345, and it has to work with any kind of css thats the idea...I don't think any one wants to actually do this so you guys are getting lost in details – Pablo Camara Aug 28 '17 at 10:59
  • I've been working on it now and then. It presents some challenges as regex is usually used to grab everything that matches (and not the contrary). When you talk about getting all lines that don't have the `[data-module="123"]` it would get all possible lines that don't have that. So the only possible solution is to actually do a negative lookahead followed by a positive lookahead to ensure that the rest of the line is a selector of some sort (which has many rules). – ctwheels Aug 28 '17 at 16:37
  • 1
    People are asking specifics about the exact format of the part you want us to grab since you haven't added all the specs. Are the `xxx` numbers only or are they alphanumeric? Can the `xxx` be 0 characters; can it be 10 characters; is it exactly 3 characters all the time? – ctwheels Aug 28 '17 at 16:40
  • @ctwheels [0-9]+ for the number – Pablo Camara Aug 30 '17 at 19:11
  • match any CSS Selector that doesnt start with [data-module="anynumber"] @ctwheels – Pablo Camara Aug 30 '17 at 19:12
  • way too hard...for me at least – Pablo Camara Aug 30 '17 at 19:12
  • @PabloCamara it was important to declare that the numbers were of any length as this prevented any answers using the negative lookbehind method to assert that the previous encounters did not contain a specific string (since it makes it non-fixed width). My answer below should - if not answer your question - bring you one step closer to your solution – ctwheels Aug 30 '17 at 20:46

1 Answers1

0

Notes

The additional information (in comments below the question) allowed me to properly create a regex that will work for your situation.

Please note that this answer can be made better by following true CSS selector rules as well as declaration/declaration list/declaration block rules, however, considering the CSS selector syntax importance in this question, I've decided to disregard it and accept all characters (except for newline and curly brackets). This regex will not work on any lines where there is a curly bracket before the selectors (so make sure you've beautified your CSS before with some sort of auto-formatting tool if you tend to write sloppy code).

Note that the regex below requires the two following modifiers:

  • Global: g
  • Multi line: m

Answer

Regex

^([\r\n]*)((?!\[data-module=(['"])\d+\3\])[^\r\n{}])+({[\s\S]*?})$


To explain a bit of what this regex is doing:

  1. Assert position at start of a line
  2. Match between zero and unlimited times the carriage return \r or line-feed \n characters
  3. Match between one and unlimited times, but as few times as possible, characters that do not appear in the grouping (\r\n{}) and that does not contain the structure of [data-module=, followed by either a single quote ' or double quote " character, followed by between one and unlimited digits, followed by the same previously matched character (single or double quote - ensures it was properly closed), and finally by a closing square bracket ]
  4. Match the CSS declaration block by checking for an opening curly bracket { followed by any character (including new line characters) between zero and unlimited times, but as few times as possible, followed by a closing curly bracket }
  5. Assert position at the end of the line (not really needed here, but I like the conformity with the first step)

Update

Regex

^([\r\n]*)(@.*?{[\r\n]*)?((?!\[data-module=(['"])\d+\4\])[^@\r\n{}])+({[\s\S]*?})([\r\n]*})?$

This one will also catch at-rules. Note that it will not catch the initial at-rule, however.

For example if you have the following code:

@media (max-width: 767px){
   [data-module="123"] .someOtherClass { color: green; }
   .someOtherClass { color: green; }
   [data-module="123"] .someOtherClass { color: green; }
   .someOtherClass { color: green; }
}

In the above example, only the third, fifth, and sixth lines will be caught. The first line @media ... will not be captured.

ctwheels
  • 21,901
  • 9
  • 42
  • 77