mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Merge pull request #1639 from tailwindcss/purgecss
Integrate PurgeCSS directly into Tailwind
This commit is contained in:
commit
da5eaed1c7
22
__tests__/fixtures/purge-example.html
Normal file
22
__tests__/fixtures/purge-example.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!-- Basic HTML -->
|
||||
<div class="bg-red-500 md:bg-blue-300 w-1/2"></div>
|
||||
|
||||
<!-- Vue dynamic classes -->
|
||||
<span :class="{ block: enabled, 'md:flow-root': !enabled }"></span>
|
||||
|
||||
<!-- JSX with template strings -->
|
||||
<script>
|
||||
function Component() {
|
||||
return <div class={`h-screen`}></div>
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Custom classes with really weird characters -->
|
||||
<div class="min-h-(screen-4) bg-black! font-%#$@ w-(1/2+8)"></div>
|
||||
|
||||
<!-- Pug -->
|
||||
span.inline-grid.grid-cols-3(class="px-1.5")
|
||||
.col-span-2
|
||||
Hello
|
||||
.col-span-1.text-center
|
||||
World!
|
||||
274
__tests__/purgeUnusedStyles.test.js
Normal file
274
__tests__/purgeUnusedStyles.test.js
Normal file
@ -0,0 +1,274 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import postcss from 'postcss'
|
||||
import tailwind from '../src/index'
|
||||
import defaultConfig from '../stubs/defaultConfig.stub.js'
|
||||
|
||||
const config = {
|
||||
...defaultConfig,
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
'black!': '#000',
|
||||
},
|
||||
spacing: {
|
||||
'1.5': '0.375rem',
|
||||
'(1/2+8)': 'calc(50% + 2rem)',
|
||||
},
|
||||
minHeight: {
|
||||
'(screen-4)': 'calc(100vh - 1rem)',
|
||||
},
|
||||
fontFamily: {
|
||||
'%#$@': 'Comic Sans',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
test('purges unused classes', () => {
|
||||
const OLD_NODE_ENV = process.env.NODE_ENV
|
||||
process.env.NODE_ENV = 'production'
|
||||
const inputPath = path.resolve(`${__dirname}/fixtures/tailwind-input.css`)
|
||||
const input = fs.readFileSync(inputPath, 'utf8')
|
||||
|
||||
return postcss([
|
||||
tailwind({
|
||||
...config,
|
||||
purge: [path.resolve(`${__dirname}/fixtures/**/*.html`)],
|
||||
}),
|
||||
])
|
||||
.process(input, { from: inputPath })
|
||||
.then(result => {
|
||||
process.env.NODE_ENV = OLD_NODE_ENV
|
||||
|
||||
expect(result.css).not.toContain('.bg-red-600')
|
||||
expect(result.css).not.toContain('.w-1\\/3')
|
||||
expect(result.css).not.toContain('.flex')
|
||||
expect(result.css).not.toContain('.font-sans')
|
||||
expect(result.css).not.toContain('.text-right')
|
||||
expect(result.css).not.toContain('.px-4')
|
||||
expect(result.css).not.toContain('.h-full')
|
||||
|
||||
expect(result.css).toContain('.bg-red-500')
|
||||
expect(result.css).toContain('.md\\:bg-blue-300')
|
||||
expect(result.css).toContain('.w-1\\/2')
|
||||
expect(result.css).toContain('.block')
|
||||
expect(result.css).toContain('.md\\:flow-root')
|
||||
expect(result.css).toContain('.h-screen')
|
||||
expect(result.css).toContain('.min-h-\\(screen-4\\)')
|
||||
expect(result.css).toContain('.bg-black\\!')
|
||||
expect(result.css).toContain('.font-\\%\\#\\$\\@')
|
||||
expect(result.css).toContain('.w-\\(1\\/2\\+8\\)')
|
||||
expect(result.css).toContain('.inline-grid')
|
||||
expect(result.css).toContain('.grid-cols-3')
|
||||
expect(result.css).toContain('.px-1\\.5')
|
||||
expect(result.css).toContain('.col-span-2')
|
||||
expect(result.css).toContain('.col-span-1')
|
||||
expect(result.css).toContain('.text-center')
|
||||
})
|
||||
})
|
||||
|
||||
test('does not purge except in production', () => {
|
||||
const OLD_NODE_ENV = process.env.NODE_ENV
|
||||
process.env.NODE_ENV = 'development'
|
||||
const inputPath = path.resolve(`${__dirname}/fixtures/tailwind-input.css`)
|
||||
const input = fs.readFileSync(inputPath, 'utf8')
|
||||
|
||||
return postcss([
|
||||
tailwind({
|
||||
...defaultConfig,
|
||||
purge: [path.resolve(`${__dirname}/fixtures/**/*.html`)],
|
||||
}),
|
||||
])
|
||||
.process(input, { from: inputPath })
|
||||
.then(result => {
|
||||
process.env.NODE_ENV = OLD_NODE_ENV
|
||||
const expected = fs.readFileSync(
|
||||
path.resolve(`${__dirname}/fixtures/tailwind-output.css`),
|
||||
'utf8'
|
||||
)
|
||||
|
||||
expect(result.css).toBe(expected)
|
||||
})
|
||||
})
|
||||
|
||||
test('purges outside of production if explicitly enabled', () => {
|
||||
const OLD_NODE_ENV = process.env.NODE_ENV
|
||||
process.env.NODE_ENV = 'development'
|
||||
const inputPath = path.resolve(`${__dirname}/fixtures/tailwind-input.css`)
|
||||
const input = fs.readFileSync(inputPath, 'utf8')
|
||||
|
||||
return postcss([
|
||||
tailwind({
|
||||
...config,
|
||||
purge: { enabled: true, content: [path.resolve(`${__dirname}/fixtures/**/*.html`)] },
|
||||
}),
|
||||
])
|
||||
.process(input, { from: inputPath })
|
||||
.then(result => {
|
||||
process.env.NODE_ENV = OLD_NODE_ENV
|
||||
|
||||
expect(result.css).not.toContain('.bg-red-600')
|
||||
expect(result.css).not.toContain('.w-1\\/3')
|
||||
expect(result.css).not.toContain('.flex')
|
||||
expect(result.css).not.toContain('.font-sans')
|
||||
expect(result.css).not.toContain('.text-right')
|
||||
expect(result.css).not.toContain('.px-4')
|
||||
expect(result.css).not.toContain('.h-full')
|
||||
|
||||
expect(result.css).toContain('.bg-red-500')
|
||||
expect(result.css).toContain('.md\\:bg-blue-300')
|
||||
expect(result.css).toContain('.w-1\\/2')
|
||||
expect(result.css).toContain('.block')
|
||||
expect(result.css).toContain('.md\\:flow-root')
|
||||
expect(result.css).toContain('.h-screen')
|
||||
expect(result.css).toContain('.min-h-\\(screen-4\\)')
|
||||
expect(result.css).toContain('.bg-black\\!')
|
||||
expect(result.css).toContain('.font-\\%\\#\\$\\@')
|
||||
expect(result.css).toContain('.w-\\(1\\/2\\+8\\)')
|
||||
expect(result.css).toContain('.inline-grid')
|
||||
expect(result.css).toContain('.grid-cols-3')
|
||||
expect(result.css).toContain('.px-1\\.5')
|
||||
expect(result.css).toContain('.col-span-2')
|
||||
expect(result.css).toContain('.col-span-1')
|
||||
expect(result.css).toContain('.text-center')
|
||||
})
|
||||
})
|
||||
|
||||
test('purgecss options can be provided', () => {
|
||||
const inputPath = path.resolve(`${__dirname}/fixtures/tailwind-input.css`)
|
||||
const input = fs.readFileSync(inputPath, 'utf8')
|
||||
|
||||
return postcss([
|
||||
tailwind({
|
||||
...config,
|
||||
purge: {
|
||||
enabled: true,
|
||||
options: {
|
||||
content: [path.resolve(`${__dirname}/fixtures/**/*.html`)],
|
||||
whitelist: ['md:bg-green-500'],
|
||||
},
|
||||
},
|
||||
}),
|
||||
])
|
||||
.process(input, { from: inputPath })
|
||||
.then(result => {
|
||||
expect(result.css).not.toContain('.bg-red-600')
|
||||
expect(result.css).not.toContain('.w-1\\/3')
|
||||
expect(result.css).not.toContain('.flex')
|
||||
expect(result.css).not.toContain('.font-sans')
|
||||
expect(result.css).not.toContain('.text-right')
|
||||
expect(result.css).not.toContain('.px-4')
|
||||
expect(result.css).not.toContain('.h-full')
|
||||
|
||||
expect(result.css).toContain('.md\\:bg-green-500')
|
||||
expect(result.css).toContain('.bg-red-500')
|
||||
expect(result.css).toContain('.md\\:bg-blue-300')
|
||||
expect(result.css).toContain('.w-1\\/2')
|
||||
expect(result.css).toContain('.block')
|
||||
expect(result.css).toContain('.md\\:flow-root')
|
||||
expect(result.css).toContain('.h-screen')
|
||||
expect(result.css).toContain('.min-h-\\(screen-4\\)')
|
||||
expect(result.css).toContain('.bg-black\\!')
|
||||
expect(result.css).toContain('.font-\\%\\#\\$\\@')
|
||||
expect(result.css).toContain('.w-\\(1\\/2\\+8\\)')
|
||||
expect(result.css).toContain('.inline-grid')
|
||||
expect(result.css).toContain('.grid-cols-3')
|
||||
expect(result.css).toContain('.px-1\\.5')
|
||||
expect(result.css).toContain('.col-span-2')
|
||||
expect(result.css).toContain('.col-span-1')
|
||||
expect(result.css).toContain('.text-center')
|
||||
})
|
||||
})
|
||||
|
||||
test('can purge all CSS, not just Tailwind classes', () => {
|
||||
const inputPath = path.resolve(`${__dirname}/fixtures/tailwind-input.css`)
|
||||
const input = fs.readFileSync(inputPath, 'utf8')
|
||||
|
||||
return postcss([
|
||||
tailwind({
|
||||
...config,
|
||||
purge: {
|
||||
enabled: true,
|
||||
mode: 'all',
|
||||
content: [path.resolve(`${__dirname}/fixtures/**/*.html`)],
|
||||
},
|
||||
}),
|
||||
function(css) {
|
||||
// Remove any comments to avoid accidentally asserting against them
|
||||
// instead of against real CSS rules.
|
||||
css.walkComments(c => c.remove())
|
||||
},
|
||||
])
|
||||
.process(input, { from: inputPath })
|
||||
.then(result => {
|
||||
expect(result.css).not.toContain('html')
|
||||
expect(result.css).not.toContain('body')
|
||||
expect(result.css).not.toContain('button')
|
||||
expect(result.css).not.toContain('legend')
|
||||
expect(result.css).not.toContain('progress')
|
||||
|
||||
expect(result.css).toContain('.bg-red-500')
|
||||
expect(result.css).toContain('.md\\:bg-blue-300')
|
||||
expect(result.css).toContain('.w-1\\/2')
|
||||
expect(result.css).toContain('.block')
|
||||
expect(result.css).toContain('.md\\:flow-root')
|
||||
expect(result.css).toContain('.h-screen')
|
||||
expect(result.css).toContain('.min-h-\\(screen-4\\)')
|
||||
expect(result.css).toContain('.bg-black\\!')
|
||||
expect(result.css).toContain('.font-\\%\\#\\$\\@')
|
||||
expect(result.css).toContain('.w-\\(1\\/2\\+8\\)')
|
||||
expect(result.css).toContain('.inline-grid')
|
||||
expect(result.css).toContain('.grid-cols-3')
|
||||
expect(result.css).toContain('.px-1\\.5')
|
||||
expect(result.css).toContain('.col-span-2')
|
||||
expect(result.css).toContain('.col-span-1')
|
||||
expect(result.css).toContain('.text-center')
|
||||
})
|
||||
})
|
||||
|
||||
test('the `conservative` mode can be set explicitly', () => {
|
||||
const OLD_NODE_ENV = process.env.NODE_ENV
|
||||
process.env.NODE_ENV = 'production'
|
||||
const inputPath = path.resolve(`${__dirname}/fixtures/tailwind-input.css`)
|
||||
const input = fs.readFileSync(inputPath, 'utf8')
|
||||
|
||||
return postcss([
|
||||
tailwind({
|
||||
...config,
|
||||
purge: {
|
||||
mode: 'conservative',
|
||||
content: [path.resolve(`${__dirname}/fixtures/**/*.html`)],
|
||||
},
|
||||
}),
|
||||
])
|
||||
.process(input, { from: inputPath })
|
||||
.then(result => {
|
||||
process.env.NODE_ENV = OLD_NODE_ENV
|
||||
|
||||
expect(result.css).not.toContain('.bg-red-600')
|
||||
expect(result.css).not.toContain('.w-1\\/3')
|
||||
expect(result.css).not.toContain('.flex')
|
||||
expect(result.css).not.toContain('.font-sans')
|
||||
expect(result.css).not.toContain('.text-right')
|
||||
expect(result.css).not.toContain('.px-4')
|
||||
expect(result.css).not.toContain('.h-full')
|
||||
|
||||
expect(result.css).toContain('.bg-red-500')
|
||||
expect(result.css).toContain('.md\\:bg-blue-300')
|
||||
expect(result.css).toContain('.w-1\\/2')
|
||||
expect(result.css).toContain('.block')
|
||||
expect(result.css).toContain('.md\\:flow-root')
|
||||
expect(result.css).toContain('.h-screen')
|
||||
expect(result.css).toContain('.min-h-\\(screen-4\\)')
|
||||
expect(result.css).toContain('.bg-black\\!')
|
||||
expect(result.css).toContain('.font-\\%\\#\\$\\@')
|
||||
expect(result.css).toContain('.w-\\(1\\/2\\+8\\)')
|
||||
expect(result.css).toContain('.inline-grid')
|
||||
expect(result.css).toContain('.grid-cols-3')
|
||||
expect(result.css).toContain('.px-1\\.5')
|
||||
expect(result.css).toContain('.col-span-2')
|
||||
expect(result.css).toContain('.col-span-1')
|
||||
expect(result.css).toContain('.text-center')
|
||||
})
|
||||
})
|
||||
@ -12,6 +12,8 @@ test('it can generate responsive variants', () => {
|
||||
.banana { color: yellow; }
|
||||
.chocolate { color: brown; }
|
||||
}
|
||||
|
||||
@tailwind screens;
|
||||
`
|
||||
|
||||
const output = `
|
||||
@ -52,6 +54,8 @@ test('it can generate responsive variants with a custom separator', () => {
|
||||
.banana { color: yellow; }
|
||||
.chocolate { color: brown; }
|
||||
}
|
||||
|
||||
@tailwind screens;
|
||||
`
|
||||
|
||||
const output = `
|
||||
@ -92,6 +96,8 @@ test('it can generate responsive variants when classes have non-standard charact
|
||||
.hover\\:banana { color: yellow; }
|
||||
.chocolate-2\\.5 { color: brown; }
|
||||
}
|
||||
|
||||
@tailwind screens;
|
||||
`
|
||||
|
||||
const output = `
|
||||
@ -137,6 +143,8 @@ test('responsive variants are grouped', () => {
|
||||
@responsive {
|
||||
.chocolate { color: brown; }
|
||||
}
|
||||
|
||||
@tailwind screens;
|
||||
`
|
||||
|
||||
const output = `
|
||||
@ -181,6 +189,8 @@ test('it can generate responsive variants for nested at-rules', () => {
|
||||
.grid\\:banana { color: blue; }
|
||||
}
|
||||
}
|
||||
|
||||
@tailwind screens;
|
||||
`
|
||||
|
||||
const output = `
|
||||
@ -244,6 +254,8 @@ test('it can generate responsive variants for deeply nested at-rules', () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@tailwind screens;
|
||||
`
|
||||
|
||||
const output = `
|
||||
@ -307,6 +319,8 @@ test('screen prefix is only applied to the last class in a selector', () => {
|
||||
@responsive {
|
||||
.banana li * .sandwich #foo > div { color: yellow; }
|
||||
}
|
||||
|
||||
@tailwind screens;
|
||||
`
|
||||
|
||||
const output = `
|
||||
@ -342,6 +356,8 @@ test('responsive variants are generated for all selectors in a rule', () => {
|
||||
@responsive {
|
||||
.foo, .bar { color: yellow; }
|
||||
}
|
||||
|
||||
@tailwind screens;
|
||||
`
|
||||
|
||||
const output = `
|
||||
@ -377,6 +393,8 @@ test('selectors with no classes cannot be made responsive', () => {
|
||||
@responsive {
|
||||
div { color: yellow; }
|
||||
}
|
||||
|
||||
@tailwind screens;
|
||||
`
|
||||
expect.assertions(1)
|
||||
return run(input, {
|
||||
@ -398,6 +416,8 @@ test('all selectors in a rule must contain classes', () => {
|
||||
@responsive {
|
||||
.foo, div { color: yellow; }
|
||||
}
|
||||
|
||||
@tailwind screens;
|
||||
`
|
||||
expect.assertions(1)
|
||||
return run(input, {
|
||||
|
||||
@ -77,3 +77,19 @@ it('generates the right CSS with implicit screen utilities', () => {
|
||||
expect(result.css).toBe(expected)
|
||||
})
|
||||
})
|
||||
|
||||
it('generates the right CSS when "important" is enabled', () => {
|
||||
const inputPath = path.resolve(`${__dirname}/fixtures/tailwind-input.css`)
|
||||
const input = fs.readFileSync(inputPath, 'utf8')
|
||||
|
||||
return postcss([tailwind({ ...config, important: true })])
|
||||
.process(input, { from: inputPath })
|
||||
.then(result => {
|
||||
const expected = fs.readFileSync(
|
||||
path.resolve(`${__dirname}/fixtures/tailwind-output-important.css`),
|
||||
'utf8'
|
||||
)
|
||||
|
||||
expect(result.css).toBe(expected)
|
||||
})
|
||||
})
|
||||
|
||||
@ -41,6 +41,7 @@
|
||||
"rimraf": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fullhuman/postcss-purgecss": "^2.1.2",
|
||||
"autoprefixer": "^9.4.5",
|
||||
"bytes": "^3.0.0",
|
||||
"chalk": "^4.0.0",
|
||||
|
||||
73
src/lib/purgeUnusedStyles.js
Normal file
73
src/lib/purgeUnusedStyles.js
Normal file
@ -0,0 +1,73 @@
|
||||
import _ from 'lodash'
|
||||
import postcss from 'postcss'
|
||||
import purgecss from '@fullhuman/postcss-purgecss'
|
||||
|
||||
function removeTailwindComments(css) {
|
||||
css.walkComments(comment => {
|
||||
switch (comment.text.trim()) {
|
||||
case 'tailwind start components':
|
||||
case 'tailwind start utilities':
|
||||
case 'tailwind start screens':
|
||||
case 'tailwind end components':
|
||||
case 'tailwind end utilities':
|
||||
case 'tailwind end screens':
|
||||
comment.remove()
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default function purgeUnusedUtilities(config) {
|
||||
const purgeEnabled =
|
||||
_.get(config, 'purge.enabled', false) === true ||
|
||||
(config.purge !== undefined && process.env.NODE_ENV === 'production')
|
||||
|
||||
if (!purgeEnabled) {
|
||||
return removeTailwindComments
|
||||
}
|
||||
|
||||
return postcss([
|
||||
function(css) {
|
||||
const mode = _.get(config, 'purge.mode', 'conservative')
|
||||
|
||||
if (mode === 'conservative') {
|
||||
css.prepend(postcss.comment({ text: 'purgecss start ignore' }))
|
||||
css.append(postcss.comment({ text: 'purgecss end ignore' }))
|
||||
|
||||
css.walkComments(comment => {
|
||||
switch (comment.text.trim()) {
|
||||
case 'tailwind start components':
|
||||
case 'tailwind start utilities':
|
||||
case 'tailwind start screens':
|
||||
comment.text = 'purgecss end ignore'
|
||||
break
|
||||
case 'tailwind end components':
|
||||
case 'tailwind end utilities':
|
||||
case 'tailwind end screens':
|
||||
comment.text = 'purgecss start ignore'
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
} else if (mode === 'all') {
|
||||
removeTailwindComments(css)
|
||||
}
|
||||
},
|
||||
purgecss({
|
||||
content: Array.isArray(config.purge) ? config.purge : config.purge.content,
|
||||
defaultExtractor: content => {
|
||||
// Capture as liberally as possible, including things like `h-(screen-1.5)`
|
||||
const broadMatches = content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || []
|
||||
|
||||
// Capture classes within other delimiters like .block(class="w-1/2") in Pug
|
||||
const innerMatches = content.match(/[^<>"'`\s.()]*[^<>"'`\s.():]/g) || []
|
||||
|
||||
return broadMatches.concat(innerMatches)
|
||||
},
|
||||
...config.purge.options,
|
||||
}),
|
||||
])
|
||||
}
|
||||
@ -43,22 +43,16 @@ export default function(config) {
|
||||
|
||||
const hasScreenRules = finalRules.some(i => i.nodes.length !== 0)
|
||||
|
||||
if (!hasScreenRules) {
|
||||
return
|
||||
}
|
||||
|
||||
let includesScreensExplicitly = false
|
||||
|
||||
css.walkAtRules('tailwind', atRule => {
|
||||
if (atRule.params === 'screens') {
|
||||
atRule.replaceWith(finalRules)
|
||||
includesScreensExplicitly = true
|
||||
if (atRule.params !== 'screens') {
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
if (!includesScreensExplicitly) {
|
||||
css.append(finalRules)
|
||||
return
|
||||
}
|
||||
if (hasScreenRules) {
|
||||
atRule.before(finalRules)
|
||||
}
|
||||
|
||||
atRule.remove()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,6 +40,8 @@ export default function(
|
||||
}
|
||||
})
|
||||
|
||||
let includesScreensExplicitly = false
|
||||
|
||||
css.walkAtRules('tailwind', atRule => {
|
||||
if (atRule.params === 'preflight') {
|
||||
// prettier-ignore
|
||||
@ -52,14 +54,32 @@ export default function(
|
||||
}
|
||||
|
||||
if (atRule.params === 'components') {
|
||||
atRule.before(postcss.comment({ text: 'tailwind start components' }))
|
||||
atRule.before(updateSource(pluginComponents, atRule.source))
|
||||
atRule.after(postcss.comment({ text: 'tailwind end components' }))
|
||||
atRule.remove()
|
||||
}
|
||||
|
||||
if (atRule.params === 'utilities') {
|
||||
atRule.before(postcss.comment({ text: 'tailwind start utilities' }))
|
||||
atRule.before(updateSource(pluginUtilities, atRule.source))
|
||||
atRule.after(postcss.comment({ text: 'tailwind end utilities' }))
|
||||
atRule.remove()
|
||||
}
|
||||
|
||||
if (atRule.params === 'screens') {
|
||||
includesScreensExplicitly = true
|
||||
atRule.before(postcss.comment({ text: 'tailwind start screens' }))
|
||||
atRule.after(postcss.comment({ text: 'tailwind end screens' }))
|
||||
}
|
||||
})
|
||||
|
||||
if (!includesScreensExplicitly) {
|
||||
css.append([
|
||||
postcss.comment({ text: 'tailwind start screens' }),
|
||||
postcss.atRule({ name: 'tailwind', params: 'screens' }),
|
||||
postcss.comment({ text: 'tailwind end screens' }),
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import substituteVariantsAtRules from './lib/substituteVariantsAtRules'
|
||||
import substituteResponsiveAtRules from './lib/substituteResponsiveAtRules'
|
||||
import substituteScreenAtRules from './lib/substituteScreenAtRules'
|
||||
import substituteClassApplyAtRules from './lib/substituteClassApplyAtRules'
|
||||
import purgeUnusedStyles from './lib/purgeUnusedStyles'
|
||||
|
||||
import corePlugins from './corePlugins'
|
||||
import processPlugins from './util/processPlugins'
|
||||
@ -23,6 +24,7 @@ export default function(getConfig) {
|
||||
substituteResponsiveAtRules(config),
|
||||
substituteScreenAtRules(config),
|
||||
substituteClassApplyAtRules(config, processedPlugins.utilities),
|
||||
purgeUnusedStyles(config),
|
||||
]).process(css, { from: _.get(css, 'source.input.file') })
|
||||
}
|
||||
}
|
||||
|
||||
41
yarn.lock
41
yarn.lock
@ -845,6 +845,14 @@
|
||||
exec-sh "^0.3.2"
|
||||
minimist "^1.2.0"
|
||||
|
||||
"@fullhuman/postcss-purgecss@^2.1.2":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@fullhuman/postcss-purgecss/-/postcss-purgecss-2.1.2.tgz#8fe4d4ae2b58214b5452cb490a31c7146517442f"
|
||||
integrity sha512-Jf34YVBK9GtXTblpu0svNUJdA7rTQoRMz+yEJe6mwTnXDIGipWLzaX/VgU/x6IPC6WvU5SY/XlawwqhxoyFPTg==
|
||||
dependencies:
|
||||
postcss "7.0.27"
|
||||
purgecss "^2.1.2"
|
||||
|
||||
"@istanbuljs/load-nyc-config@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b"
|
||||
@ -1715,6 +1723,11 @@ commander@^4.0.1:
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-4.0.1.tgz#b67622721785993182e807f4883633e6401ba53c"
|
||||
integrity sha512-IPF4ouhCP+qdlcmCedhxX4xiGBPyigb8v5NeUp+0LyhwLgxMqyp3S0vl7TAPfS/hiP7FC3caI/PB9lTmP8r1NA==
|
||||
|
||||
commander@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
|
||||
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
|
||||
|
||||
commondir@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
||||
@ -4266,6 +4279,15 @@ postcss-value-parser@^4.0.3:
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d"
|
||||
integrity sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==
|
||||
|
||||
postcss@7.0.27, postcss@^7.0.11, postcss@^7.0.18, postcss@^7.0.21, postcss@^7.0.27:
|
||||
version "7.0.27"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9"
|
||||
integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==
|
||||
dependencies:
|
||||
chalk "^2.4.2"
|
||||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
postcss@^6.0.9:
|
||||
version "6.0.23"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
|
||||
@ -4275,15 +4297,6 @@ postcss@^6.0.9:
|
||||
source-map "^0.6.1"
|
||||
supports-color "^5.4.0"
|
||||
|
||||
postcss@^7.0.11, postcss@^7.0.18, postcss@^7.0.21, postcss@^7.0.27:
|
||||
version "7.0.27"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9"
|
||||
integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==
|
||||
dependencies:
|
||||
chalk "^2.4.2"
|
||||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
prelude-ls@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
||||
@ -4362,6 +4375,16 @@ punycode@^2.1.0, punycode@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
purgecss@^2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-2.1.2.tgz#96f666d04c56705208aaa1a544b5f22e13828955"
|
||||
integrity sha512-5oDBxiT9VonwKmEMohPFRFZrj8fdSVKxHPwq7G5Rx/2pXicZFJu+D4m5bb3NuV0sSK3ooNxq5jFIwwHzifP5FA==
|
||||
dependencies:
|
||||
commander "^5.0.0"
|
||||
glob "^7.0.0"
|
||||
postcss "7.0.27"
|
||||
postcss-selector-parser "^6.0.2"
|
||||
|
||||
qs@~6.5.2:
|
||||
version "6.5.2"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user