1

UPDATE: I've come to the conclusion that RegExp is not a viable option for this particular problem.

Thanks for your help.

The problem

TLDR: I want to create a RegExp that can scan all nested SCSS selectors, and match everything that is not kebab-case (with the exception of pseudo selectors first-child, last-child, etc).

I am looking for a RegExp to use in combination with the selected-nested-patterns from stylelint.

I want to forbid any kebab case nested selectors in our SCSS Modules.

Unfortunately I could not manage to get a negative lookahead working.

Requirements:

  • everything that is (&:>+~*\w)+
  • not followed by one or more hyphens (?!-)+
  • not followed by one or more underscore (?!_)+
  • followed by 0 or more white space or character (?:([\w\s])*)
  • accept CSS pseudo selectors in kebab case (first-child, last-child)
class // YES
class-class // NO
class--class // NO
somethingSomething // YES
&Class // YES
&-class // NO
&--class // NO
&.class // YES
&__class // NO
input > input // YES
& > & // YES
~ class // YES
> div // YES
a,      c // YES
&.disabled:disabled:hover // YES
& > div:first-child // YES
&:last-child // YES
floroz
  • 365
  • 2
  • 16
  • **Show us what you’ve done so far** so that we have something to start with. It’s much easier for us to help you with existing code, and people are far more likely to help when they don’t have to start from zero with "How do I do this?" – Andy Lester Dec 13 '21 at 18:20
  • When you say `"// YES"` what does that mean exactly ? As it is now, to do what you say requires more info, like if the _`nots`_ pertain to the entire string. Probably your best bet, if so is to exclude the offenders as a primary approach. – sln Dec 13 '21 at 18:55
  • Can try this I guess [^(?!.*\[&:>+~*\w\]\[-_\]).*\[&:>+~*\w\].*](https://regex101.com/r/PzpHWp/1) – sln Dec 13 '21 at 19:09
  • And without the yes/no https://regex101.com/r/3asyC7/1 – sln Dec 13 '21 at 19:19
  • thank you @sln unfortunately that regex does not take into account selector such as `& > first-child` which should be valid, so just excluding `-` `_` would not work.. – floroz Dec 14 '21 at 19:39
  • But your req's `is [&:>+~*\w]` not followed by `[-_]`. Unfortunately that matches `t-` which violates the requirement. That is why I gave your required solutuin to look at. You probably need to re-evaluate the req's. – sln Dec 14 '21 at 19:42
  • Yes, unfortunately, that requirement was discovered after I wrote the question. I've updated the post to account for that. I believe at this point what I am looking for cannot really be created.. – floroz Dec 14 '21 at 19:46
  • Just a warning, this `& > div:first-child // YES` is a contradiction in the face of `class-class // NO` better to review before edits. Remember, regex doesn't know any language. – sln Dec 14 '21 at 19:52

1 Answers1

1

I'm not really sure to understand what you're looking for but it seems that the only chars you don't want is the hyphens and underscores. So we could actually use a regex as simple as ^[^_-]+$ to say you want to macht strings only containing "not underscores or hyphens".

But we could also do it the other way, by listing only the chars you want to match with ^[&.a-zA-Z>:+~,\h]+$.

You can test it here: https://regex101.com/r/LSiVju/1

  • ^ asserts position at start of a line.

  • Match a single character present in the list: [&.a-zA-Z>:+~,\h]

    -\h is a horizontal space. You could replace it by \s which also includes new lines.

    • a-z and A-Z are the ranges of alphabetical chars.
  • + is to say we want the char one and several times.

  • $ asserts position at the end of the string.

  • g modifier: global. All matches (don't return after first match)

  • m modifier: multi line. Causes ^ and $ to match the begin/end of each line instead of begin/end of string. This is just for the example with your list of cases. You won't use the m modifier.

But I don't think it's as simple as that because we can also have digits (which are not mentionned in your question).

What about these?

h1
&.class2
> one4you

If you want to match digits too then it would become ^[&.a-zA-Z0-9>:+~,\h]+$

And we also know that the class .2lines isn't a valid class since you cannot start with a digit. So the regex might get much more complex because .col-2 or .col-4 are typicall valid Bootstrap CSS classes where the digits are not at the beginning. We ideally should not match &.4you but match &.col3 or &.col-3 if you accept hyphens in CSS classes like almost all the big CSS frameworks.

Patrick Janser
  • 3,318
  • 1
  • 16
  • 18
  • Thank you. Yes it's quite tricky as I'd want all kebab-case word to be flagged, but taking into account the structure of CSS selectors whereby having a series of valid character `[&,>*'w]` followed by `:-child` is also valid. – floroz Dec 14 '21 at 19:42
  • I've updated to add the extra use-case https://regex101.com/r/NOw4Bw/1 – floroz Dec 14 '21 at 19:43