Rebuild CSS - Issues / Questions

Hi Matt,

I am trying to “rebuild the CSS” for prod, but it seems I’m having a few issues with getting all the correct classes into the final build. I’ve categorized the issues I think are keeping it from being correct below.

Tailwind Config Classes Not Appearing When Dev Mode Turned Off
With dev mode on everything looks as it should, but if I turn it off and press rebuild only elements with bg-primary show up. bg-secondary, bg-success etc just default to transparent.

Not Picking Up Custom Post Types
I have a plugin that creates custom HTML with tailwind classes and stores it in the post_content field. It appears that no classes listed exclusively here are added to the production build.

Vue Plugin
I have another plugin that uses vue for a specific widget. This widget uses quite a few tailwind classes. ( too many to add to the “safelist” ) is there a way where I could take the tailwind file it generates and put it somewhere in a directory to be scanned during the Rebuild process?

Would love any advice or creative solutions to get this working.

Thanks,

-Jesse

Hey Jesse

Hmm, it’s interesting about the dev mode issue. My guess would be that it’s potentially related to the next two issues somehow, but without a little more info it’s a bit tricky to know. Can you provide any more info on how the bg-secondary etc class names are being added? I.e. are you using the Gust page builder, or is that content added differently?

Not Picking Up Custom Post Types
Gust actually doesn’t reference the post_content field when scanning for class names. It stores all the ones it uses in a separate meta field. This will be why you’re not seeing those included. There are a few ways around it though, probably the easiest is to use the gust_safelist filter.

There’s a little more info here and you can check out all the available hooks and filters here.

Vue Plugin
Same as above, you can either use the gust_safelist filter to tell it explicitly what to include or, if you want Gust to just “figure it out”, you can give it a list of files to scan. Read up on working with templates here. It’s specifically about adding template files, but you can also get it to scan JS files too if that’s where you’re adding classes.

Hope that helps! I’m actually going to be out for the rest of the week so won’t be able to provide detailed support, but will keep an eye on this and drop info as I can.

Cheers!

Matt,

Thanks. That led me down the right path. I ended up writing a little powershell script that extracts all the tailwind classes from the uncompiled vue files and then added that file to the plugin package. From there I simple read that file and hook it into the safe list.

For the custom post type I just created a template and added it to the list.

However I did notice that in your get_safelist_from_templates function you had a subpar regex expression. Judging from the comment above it you already know that though. I made the following modification to ending loop. It’s a bit more accurate and robust. Maybe you could include it in the next release???

		foreach ($files as $file) {
			if (!file_exists($file)) {
				continue;
			}
			$file_content = file_get_contents($file);
			
			// Extract all class names from HTML content and remove duplicates
			preg_match_all('/(?<=class=["\'`])\s*([^"\']+\b)/s', $file_content, $matches);
			$classes = array_filter(array_unique(preg_split('/\s+/', implode(' ', $matches[1]))));

			// Add class names to safelist if any are present
			if (!empty($classes)) {
				$safelist = array_merge($safelist, $classes);
			}
		}

One last thing though every once in a while ( almost exclusively on my local environment ) I get a “There was an error rebuilding your CSS file” error. It looks like its coming from the GustWorker.compile. Any ideas as to what would be making it throw an error?

Update

This one better handles arbitrary tailwind classes and is a better choice:

preg_match_all('/(?<=class=["\'])\s*([a-zA-Z0-9_-]+(\[\w+\])*(\s+[a-zA-Z0-9_-]+(\[\w+\])*)*)/s', $file_content, $matches);

Still having a few issues.

Classes show up in safelist but not making it into css

All of my classes from the gust_safelist_files filter are not making it into the final build. Which is weird because I sorted $unique from get_class_safelist and the classes I am missing are in that array. For some reason they are omitted from the compiled file though.

This class shows up in dev mode, but not when turned off:

.entry-content > *:not(.alignwide):not(.alignfull):not(.alignleft):not(.alignright)

Thanks heaps for all the info here.

A note on the regex. At the moment you’ll see that the regex used isn’t specifically searching for anything within the class attribute, as the regex you provided does. This is because sometimes classes are declared outside of that. E.g:

$class_name = 'bg-yellow-900 p-4';
echo '<div class="' . $class_name . '">';

It’s a contrived example, but you get the idea. I actually referenced the Tailwind CSS package itself which does a similar thing for its default extractor regex. It looks like they’ve updated it significantly since I last took a look, but they have some more info here. I can definitely look at updating it though.

As for your classes showing up in the safelist but not in the final build, are you able to send me a sample of your PHP or whatever is adding it into the safelist? I’ll do some tests my end also to double check everything is working as it should my end.

Cheers

Ah yeah the class names in variables make it quite a bit harder. You could probably still keep it restricted to text inside of quotes to keep it from matching strings like <?php and what have you, but things like $col_class = ‘column-’.$col_count; would be pretty tough to tackle. I’ll go ahead and leave that in your capable hands :slight_smile:

As for my code it’s pretty basic:

  public function gust_extend_css_templates($files)
  {
    $templates = glob(MY_PLUGIN_DIR . 'templates/*.html');
    foreach ($templates as $template) {
      $files[] = $template;
    }
    return $files; // The classes from these files are getting extracted, but not making it into the prod css build
  }

  public function gust_extend_css_vue($safelist)
  {
    $file = fopen(MY_PLUGIN_DIR . 'assets/vue-class-list.csv', 'r');
    while (($line = fgetcsv($file)) !== FALSE) {
      $safelist[] = $line[0];
    }

    return $safelist; // Everything here seems to get added fine
  }

Any idea why the entry content classes aren’t being added? They load fine in dev mode.

Thanks for the help!

Also here are the filters I am using:

add_filter('gust_safelist',  [$this, 'gust_extend_css_vue']);
add_filter('gust_safelist_files',  [$this, 'gust_extend_css_templates']);

Hmmm that’s definitely a bit odd. I’ll test out the file list you’ve got there tomorrow. Also, extracting everything between quotes is a great idea, I’ll look more into that.

Just to clarify gust_extend_css_vue is working fine, but gust_extend_css_templates is only working in dev mode, correct?

Hey Matt,

It seems like most of my issues did stem from that regex statement so I took another crack at it. This is what I came up with. So far I have not had any issues with it, but let me know if you see anything I can improve on:

			// Extract all class names from HTML content, remove duplicates, and filter invalid class names
			$classes = array_filter(array_unique(preg_split('/\s+/', implode(' ', array_map(function ($str) {
				$class = substr($str, 1, -1); // Remove quotes from class list
				return (strlen($class) > 1 && preg_match('/^[a-zA-Z\-_\[]/', $class)) ? $class : null; // Only return class names that start with valid Tailwind class name characters
			}, preg_match_all('/["\']([a-zA-Z0-9_:\s\-\/]|\[[^\]]*\])+(?<!\\\\)["\']/', $file_content, $matches) ? $matches[0] : [])))));

			// Add class names to safelist if any are present
			if (!empty($classes)) {
				$safelist = array_merge($safelist, $classes);
			}

Hmm that’s super weird. I did just try it out locally and didn’t have any issues, but it could be due to the content of the HTML. So things are working as expected with your regex above?

One thing to note is that dev mode works slightly differently to rebuilding the production CSS. On dev mode, it scans the HTML on the page and builds the CSS based on that.

Another thing I should mention is that class names must be written in full. That means that things like $class_name = 'bg-' . $color; won’t work. This is detailed also in the Tailwind Docs.

Would you be able to send me the HTML used so I can test it out? I’d like to be able to replicate the issue properly before changing things. You can DM me or email support@getgust.com.