Complex Regex for Comments

Hey fellow devs, got a complex regex (complex for me) that I need help solving. Ideally, I wish there were an easier way to solve this (like the way babel will parse this code), however I am at a point in this to where it seems like regex will be the easiest step forward.

The goal and what I need to match:
Grab any comment (/* */, /** **/, or // — can also be new lines) that have a css class after them and grab that too (from . to {).

I have a regex here and am close, but not quite grabbing what I need to:

From this document, this is what I need to match:

/**
* Another style comment 
*/
.tester-class {
// tester comment
  .tester-child {
/* Another test comment */
  .tester-child-2 {

Each comment style along with a corresponding class right after it, and omitting anything at the top because it doesn’t have a corresponding class right after it.

maybe something like this
/\s+[.].+\s+{

but you would need to trim it

Thanks I’ll certainly check it out!

Doesn’t seem to be what I’m looking for?

What is the problem anyways? Why do you try to remove them?

Imho some context would be useful.

it is close though. You just need to enclose the class name match in brackets and it should work?

ps. once I did that, I got exactly two matches in your test set:
tester-class
tester-child-2

It’s for mapping a comment to it’s nearest class as a reference to where it is in the css file. I am in the process of rewriting css files and lose the comments, so I need this regex to splice them back in after rewriting.

1 Like

I see so you have one or several CSS files and want to process them (as you indicated) using NodeJS, and write that to a file as output ?

I am saying so bc you could write a longer logic and not rely on a single regex.

Sorry if I misunderstand the problem.

It’s pretty complicated at this point, but yes.

Understandable, but I need the comment and class.

In the script.js I’d have a logic of this sort (pseudocode):

  • Split the string at new line to get the file as an array
  • If the string starts with /** you do one thing
  • starts with /* another thing
  • starts with //

In the first 2 cases you need to keep collecting until the next closing pair, and finally, absorb the next line that is not empty.

The last one is just that single line, and the following class

Well, I only know of these comments that are next to css props, Ie:

color: black; // Use this for X

So, perhaps the regex would change for this use case, but this touches at least 800+ files and I need to be very careful.

Yeah, I had considered just doing all different regexes and adding them to an array, too.

SASS/SCSS supports // comments so maybe that is why?


You might also check the code from a lib like strip-comments

1 Like

@camperextraordinaire I’ll check out your repo that you sent over and I’ll try to figure out a working solution from those regex matches. Thank you.

If you are still trying to find a working regex for it, here you go:

/((\/\*|\/\/)([\s\S]*?)(?={| {))/g

It should grab the comment itself with the class or id selector until it reaches { with a space or without a space

Thank you, much closer, however it seems to grab everything at the top as well that doesn’t have a corresponding class:

I should at the very least account for a comment (starting with //) that could be above a class to handle the use case.

This will give me the above screenshot, still grabbing the above comments that do not have a class. Would you be able to break down this regex on how this actually works? I’ve yet to see capture groups with <comment> or <className> yet in regex. Amazing stuff and thank you for helping.

/* stylelint-disable selector-class-pattern, declaration-no-important, selector-max-id */

/* backward compatible with version 6 */
/* custom fonts can be removed after upgrade to version 7 */
@import '_default/components/font-family-miller.css';
@import '_default/components/font-family-librefranklin.css';

@import '_default/variables.css';

$font-header-miller: 400 26px/29px $miller-text-stack;
$font-text-libre: 400 14px/17px $libre-stack;


/**
* Another style comment 
*/
.tester-class {
  background-color: black;
  display: block;
  margin: 20px;

// tester comment
  .tester-child {
    margin: 40px;
  }

/* Another test comment */
  .tester-child-2 {
    color: orange;
  }
}

.another {
  color: teal;
}

@media screen and (min-width: 768px) and (max-width: 1179.9px) {
  .tester-class {
    background-color: black;
    display: block;
    margin: 40px;

    .media-child {
      color: lime;
      position: relative;
      z-index: 55;

      .nested-3-child {
        align-self: flex-start;
        display: flex;

        .nested-4-child {
          color: gold;
          display: inline;
        }
      }
    }
  }
}