Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Css attribute selectors [Request] #30

Closed
yinx opened this issue Nov 27, 2017 · 19 comments
Closed

Css attribute selectors [Request] #30

yinx opened this issue Nov 27, 2017 · 19 comments
Labels

Comments

@yinx
Copy link

yinx commented Nov 27, 2017

I can't seem to find a way to get purgecss to work with css selectors like [class*="section-"] or [title~="flower"].

Is there a method I'm overlooking or if not, is there a way to implement this?

@pxwee5
Copy link

pxwee5 commented Dec 1, 2017

This is a webpack setup, but the configuration options are the same.

new PurgecssPlugin({
  whitelistPatterns: [new RegExp('frame')]
})

This will match all selectors and classes that has frame. For v0.13.1.
See here

@Ffloriel
Copy link
Member

Ffloriel commented Dec 2, 2017

There is no method to implement this but as @pxwee5 pointed out, you can specified regex to tell purgecss not to remove some selectors. See here

@pxwee5
Copy link

pxwee5 commented Dec 3, 2017

The whitelistPatterns only checks for [class*=classes] (and different types of selectors).

@Ffloriel, is there a way to match for the entire thing? E.g. [class*=classes] or is it not necessary at all? What if I want to whitelist all css class selectors?

More Info

Also, if I have these 2 classes:

.flexgrid {}
.flexgrid > [class*=w-] {}

and I am calling .flexgrid on the parent div to initiate flexgrid on my div like so:

<div class="flexgrid">
  <div class="w-6/12 md:w-3/12">Content<div>
  <div class="w-6/12 md:w-3/12">Content<div>
<div>

Only .flexgrid {} gets included into the css file, .flexgrid > [class*=w-] {} gets purged. By right .flexgrid is part of .flexgrid > [class*=w-] {} selector and should get included into the css file. Isn't that how it's supposed to work?

I have tried the following configurations and all failed:

whitelist: ['html', 'body', 'flexgrid', '.flexgrid'],
whitelistPatterns: [new RegExp('flexgrid')], 

Some help would be appreciated :)

EDIT

The following works, but man it took me abit of time to figure it out.

whitelistPatterns: [new RegExp('^w-$')]

@Ffloriel
Copy link
Member

Ffloriel commented Dec 5, 2017

I see, I think what you need is to define a custom extractor. Check this gist for using purgecss with tailwindcss
Let me know if it solves the problem.

@pxwee5
Copy link

pxwee5 commented Dec 5, 2017

According to my tests and from what I found out, a custom extractor is for custom extraction of the glob files, not the CSS files. Let me know if I'm wrong.

@Ffloriel
Copy link
Member

Ffloriel commented Dec 5, 2017

By default, selectors like md:w-3/12 are not extracted from the files (because of the characters : and /). So purgecss will not see those as used and will remove them from the css files.

@pxwee5
Copy link

pxwee5 commented Dec 6, 2017

Correct me if I'm wrong. Are you saying that the custom extractor will extract strings from both the css and the html files?

@Ffloriel
Copy link
Member

Ffloriel commented Dec 6, 2017

No. Extractors are used to extract selectors from content files (html, pug, ...)
If you have the following css:

w-6\/12 {
    color: green;
}
md\:w-3\/12 {
    color: blue;
}

and an html file:

<div class="flexgrid">
  <div class="w-6/12 md:w-3/12">Content<div>
  <div class="w-6/12 md:w-3/12">Content<div>
<div>

First, purgecss will use an extractor to determine which selectors are used. The default extractor will considered div, flexgrid but not w-6/12 or md:w-3/12.
Then, purgecss will go through the css file, look at each selector in it and simply look if the selector is also in the content files. If it's not, the css is removed. In this example with the default extractor, w-6/12 and md:w-3/12 will be removed.

@pxwee5
Copy link

pxwee5 commented Dec 6, 2017

Thanks for explaining and trying to help. However I still couldn't get the extractor to work. I still can't get it to work properly. LOL

What I am trying to do here is to get PurgeCSS to read not allow both of the following classes to pass:
.scss

.flexgrid {
  @apply .styleA;

  & > *[class*=w-] {
    @apply .styleB
  }
}

Because the usage of this is just simply using the .flexgrid on any div and no extra classes is set to its child.
.html

<div class="flexgrid">
  <div class="">Content<div>
  <div class="">Content<div>
<div>

So with this html, the extractor will only pick up the flexgrid class. And after comparing it with the css file above, only .flexgrid {} gets through. The one with a child selector gets removed.

So the question is how do I get PurgeCSS to support custom css selectors such as the css example above?

@Ffloriel
Copy link
Member

Ffloriel commented Dec 6, 2017

Thanks for the clarification. I understand the problem now.
Purgecss does not behave as expected with attribute selectors. It should leave the attributes selectors in the css. I will look into it and release a new version when the issue is fixed

@Ffloriel
Copy link
Member

Ffloriel commented Dec 7, 2017

The issue should be fix in v0.14.0. Let me know if you found any issues with it.

@pxwee5
Copy link

pxwee5 commented Dec 7, 2017

Will this only work under legacy: true? In my tests, the legacy option will not read numbers and some symbols and is quite inaccurate. The PurgeCSS (non-legacy) option is much more accurate and I think this bug should be fixed for both legacy and without (preferably).

What do you think?

@Ffloriel
Copy link
Member

Ffloriel commented Dec 7, 2017

It should work for both.
The legacy option was meant to provide a similar result as purifycss when purgecss was in an early stage. The option will be removed with the 1.0.0 version.

@pxwee5
Copy link

pxwee5 commented Dec 7, 2017

Hmm, tested it and somehow it didn't work unless legacy: true is set.

.flexgrid {
  @apply .flex .flex-wrap .-mx-4 .-mb-8;

  & > *[class*='w-'] {
    @apply .px-4 .pb-8
  }
}

Output

.flexgrid{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-left:-1rem;margin-right:-1rem;margin-bottom:-2rem}@supports(display:-ms-grid){}

The test in the test folder had legacy: true set I think.

@Ffloriel
Copy link
Member

Ffloriel commented Dec 7, 2017

There are tests for both with and without legacy.
Could you create a repo that reproduce the issue? It will be easier for me to look at the issue that way.

@pxwee5
Copy link

pxwee5 commented Dec 7, 2017

Hey @Ffloriel. Here's the repo. I hope I did it correctly, I used gulp instead of webpack.
https://github.com/pxwee5/test-purgecss/

@Ffloriel
Copy link
Member

Ffloriel commented Dec 7, 2017

@pxwee5 thank you very much.

@Ffloriel
Copy link
Member

Ffloriel commented Dec 7, 2017

gulp-purgecss was still using the v0.13.0. gulp-purgecss version is now aligned with purgecss.
The output is

.flexgrid {
  background-color: black
}

.flexgrid[class*=w] {
  background-color: blue;
}

.flexgrid>*[class*=w-] {
  background-color: yellow;
}

@pxwee5
Copy link

pxwee5 commented Dec 7, 2017

Gah. That was it! Didn't know I have to upgrade the bundler plugins as well.
Working great now! Thanks alot for the prompt replies and everything. Really appreciate the support.

@Ffloriel Ffloriel closed this as completed Dec 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants