Simplify implementation, remove unnecessary new features
This commit is contained in:
parent
fc1d4c4cb1
commit
4169bb1ac2
7 changed files with 29 additions and 312 deletions
|
|
@ -1,226 +0,0 @@
|
|||
import postcss from 'postcss'
|
||||
import plugin from '../src/lib/substituteTailwindAtRules'
|
||||
import processPlugins from '../src/util/processPlugins'
|
||||
import config from '../stubs/defaultConfig.stub.js'
|
||||
|
||||
function run(input, opts = config) {
|
||||
const plugins = [
|
||||
function({ addBase, addComponents, addUtilities }) {
|
||||
addBase({ base: { property: 'test' } })
|
||||
addComponents({ '.components': { property: 'test' } })
|
||||
addUtilities({ '.utilities': { property: 'test' } })
|
||||
},
|
||||
]
|
||||
return postcss([plugin(opts, processPlugins(plugins, opts))]).process(input, {
|
||||
from: undefined,
|
||||
})
|
||||
}
|
||||
|
||||
test('tailwind directives are replaced with their underlying CSS rules', () => {
|
||||
const input = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
const output = `
|
||||
/* tailwind start base */
|
||||
base { property: test }
|
||||
/* tailwind end base */
|
||||
/* tailwind start components */
|
||||
.components { property: test }
|
||||
/* tailwind end components */
|
||||
/* tailwind start screens components */
|
||||
@screens components;
|
||||
/* tailwind end screens components */
|
||||
/* tailwind start utilities */
|
||||
@variants {
|
||||
.utilities { property: test }
|
||||
}
|
||||
/* tailwind end utilities */
|
||||
/* tailwind start screens utilities */
|
||||
@screens utilities;
|
||||
/* tailwind end screens utilities */
|
||||
`
|
||||
|
||||
return run(input).then(result => {
|
||||
expect(result.css).toMatchCss(output)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
test('root-level component classes are not part of the components group', () => {
|
||||
const input = `
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
.btn { background: blue }
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
const output = `
|
||||
/* tailwind start base */
|
||||
base { property: test }
|
||||
/* tailwind end base */
|
||||
|
||||
/* tailwind start components */
|
||||
.components { property: test }
|
||||
/* tailwind end components */
|
||||
|
||||
/* tailwind start screens components */
|
||||
@screens components;
|
||||
/* tailwind end screens components */
|
||||
|
||||
.btn { background: blue }
|
||||
|
||||
/* tailwind start utilities */
|
||||
@variants {
|
||||
.utilities { property: test }
|
||||
}
|
||||
/* tailwind end utilities */
|
||||
|
||||
/* tailwind start screens utilities */
|
||||
@screens utilities;
|
||||
/* tailwind end screens utilities */
|
||||
`
|
||||
|
||||
return run(input).then(result => {
|
||||
expect(result.css).toMatchCss(output)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
test('nested rules are included in the corresponding bucket', () => {
|
||||
const input = `
|
||||
@tailwind base {
|
||||
html { font-size: 20px }
|
||||
}
|
||||
@tailwind components {
|
||||
.btn { background: blue }
|
||||
}
|
||||
@tailwind utilities {
|
||||
.tabular-nums { font-variant-numeric: tabular-nums }
|
||||
}
|
||||
`
|
||||
|
||||
const output = `
|
||||
/* tailwind start base */
|
||||
base { property: test }
|
||||
html { font-size: 20px }
|
||||
/* tailwind end base */
|
||||
|
||||
/* tailwind start components */
|
||||
.components { property: test }
|
||||
.btn { background: blue }
|
||||
/* tailwind end components */
|
||||
|
||||
/* tailwind start screens components */
|
||||
@screens components;
|
||||
/* tailwind end screens components */
|
||||
|
||||
/* tailwind start utilities */
|
||||
@variants {
|
||||
.utilities { property: test }
|
||||
}
|
||||
.tabular-nums { font-variant-numeric: tabular-nums }
|
||||
/* tailwind end utilities */
|
||||
|
||||
/* tailwind start screens utilities */
|
||||
@screens utilities
|
||||
/* tailwind end screens utilities */
|
||||
`
|
||||
|
||||
return run(input).then(result => {
|
||||
expect(result.css).toMatchCss(output)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
test('nested responsive component classes have the components argument added automatically', () => {
|
||||
const input = `
|
||||
@tailwind base;
|
||||
@tailwind components {
|
||||
@responsive {
|
||||
.btn { background: blue }
|
||||
}
|
||||
}
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
const output = `
|
||||
/* tailwind start base */
|
||||
base { property: test }
|
||||
/* tailwind end base */
|
||||
|
||||
/* tailwind start components */
|
||||
.components { property: test }
|
||||
@responsive components {
|
||||
.btn { background: blue }
|
||||
}
|
||||
/* tailwind end components */
|
||||
|
||||
/* tailwind start screens components */
|
||||
@screens components;
|
||||
/* tailwind end screens components */
|
||||
|
||||
/* tailwind start utilities */
|
||||
@variants {
|
||||
.utilities { property: test }
|
||||
}
|
||||
/* tailwind end utilities */
|
||||
|
||||
/* tailwind start screens utilities */
|
||||
@screens utilities;
|
||||
/* tailwind end screens utilities */
|
||||
`
|
||||
|
||||
return run(input).then(result => {
|
||||
expect(result.css).toMatchCss(output)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
test('nested responsive component classes authored using the variants syntax have the components argument added automatically', () => {
|
||||
const input = `
|
||||
@tailwind base;
|
||||
@tailwind components {
|
||||
@variants responsive {
|
||||
.btn { background: blue }
|
||||
}
|
||||
}
|
||||
@tailwind utilities;
|
||||
`
|
||||
|
||||
const output = `
|
||||
/* tailwind start base */
|
||||
base { property: test }
|
||||
/* tailwind end base */
|
||||
|
||||
/* tailwind start components */
|
||||
.components { property: test }
|
||||
@responsive components {
|
||||
@variants {
|
||||
.btn { background: blue }
|
||||
}
|
||||
}
|
||||
/* tailwind end components */
|
||||
|
||||
/* tailwind start screens components */
|
||||
@screens components;
|
||||
/* tailwind end screens components */
|
||||
|
||||
/* tailwind start utilities */
|
||||
@variants {
|
||||
.utilities { property: test }
|
||||
}
|
||||
/* tailwind end utilities */
|
||||
|
||||
/* tailwind start screens utilities */
|
||||
@screens utilities;
|
||||
/* tailwind end screens utilities */
|
||||
`
|
||||
|
||||
return run(input).then(result => {
|
||||
expect(result.css).toMatchCss(output)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
|
@ -11,11 +11,9 @@ function removeTailwindComments(css) {
|
|||
case 'tailwind start base':
|
||||
case 'tailwind start components':
|
||||
case 'tailwind start utilities':
|
||||
case 'tailwind start screens':
|
||||
case 'tailwind end base':
|
||||
case 'tailwind end components':
|
||||
case 'tailwind end utilities':
|
||||
case 'tailwind end screens':
|
||||
comment.remove()
|
||||
break
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -10,16 +10,12 @@ export default function(config) {
|
|||
theme: { screens },
|
||||
separator,
|
||||
} = config
|
||||
const responsiveRules = {
|
||||
components: postcss.root(),
|
||||
utilities: postcss.root(),
|
||||
}
|
||||
const responsiveRules = postcss.root()
|
||||
const finalRules = []
|
||||
|
||||
css.walkAtRules('responsive', atRule => {
|
||||
const bucket = atRule.params === 'components' ? 'components' : 'utilities'
|
||||
const nodes = atRule.nodes
|
||||
responsiveRules[bucket].append(...cloneNodes(nodes))
|
||||
responsiveRules.append(...cloneNodes(nodes))
|
||||
atRule.before(nodes)
|
||||
atRule.remove()
|
||||
})
|
||||
|
|
@ -30,10 +26,8 @@ export default function(config) {
|
|||
params: buildMediaQuery(screens[screen]),
|
||||
})
|
||||
|
||||
mediaQuery.append(postcss.comment({ text: 'tailwind start components' }))
|
||||
|
||||
mediaQuery.append(
|
||||
_.tap(responsiveRules.components.clone(), clonedRoot => {
|
||||
_.tap(responsiveRules.clone(), clonedRoot => {
|
||||
clonedRoot.walkRules(rule => {
|
||||
rule.selectors = _.map(rule.selectors, selector =>
|
||||
buildSelectorVariant(selector, screen, separator, message => {
|
||||
|
|
@ -44,24 +38,6 @@ export default function(config) {
|
|||
})
|
||||
)
|
||||
|
||||
mediaQuery.append(postcss.comment({ text: 'tailwind end components' }))
|
||||
|
||||
mediaQuery.append(postcss.comment({ text: 'tailwind start utilities' }))
|
||||
|
||||
mediaQuery.append(
|
||||
_.tap(responsiveRules.utilities.clone(), clonedRoot => {
|
||||
clonedRoot.walkRules(rule => {
|
||||
rule.selectors = _.map(rule.selectors, selector =>
|
||||
buildSelectorVariant(selector, screen, separator, message => {
|
||||
throw rule.error(message)
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
mediaQuery.append(postcss.comment({ text: 'tailwind end utilities' }))
|
||||
|
||||
finalRules.push(mediaQuery)
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -49,31 +49,6 @@ export default function(
|
|||
|
||||
let includesScreensExplicitly = false
|
||||
|
||||
function hasChildren(atRule) {
|
||||
return atRule.nodes !== undefined && atRule.nodes.length > 0
|
||||
}
|
||||
|
||||
function extractChildren(atRule, bucket) {
|
||||
if (hasChildren(atRule)) {
|
||||
atRule.walkAtRules('variants', variantsAtRule => {
|
||||
const params = postcss.list.comma(variantsAtRule.params)
|
||||
if (params.includes('responsive')) {
|
||||
variantsAtRule.params = params.filter(p => p !== 'responsive').join(', ')
|
||||
variantsAtRule.before(
|
||||
postcss.atRule({ name: 'responsive', nodes: [variantsAtRule.clone()] })
|
||||
)
|
||||
variantsAtRule.remove()
|
||||
}
|
||||
})
|
||||
|
||||
atRule.walkAtRules('responsive', responsiveAtRule => {
|
||||
responsiveAtRule.params = bucket
|
||||
})
|
||||
|
||||
atRule.before(atRule.nodes)
|
||||
}
|
||||
}
|
||||
|
||||
css.walkAtRules('tailwind', atRule => {
|
||||
if (atRule.params === 'preflight') {
|
||||
// prettier-ignore
|
||||
|
|
@ -81,26 +56,17 @@ export default function(
|
|||
}
|
||||
|
||||
if (atRule.params === 'base') {
|
||||
atRule.before(postcss.comment({ text: 'tailwind start base' }))
|
||||
atRule.before(updateSource(pluginBase, atRule.source))
|
||||
extractChildren(atRule, 'base')
|
||||
atRule.before(postcss.comment({ text: 'tailwind end base' }))
|
||||
atRule.remove()
|
||||
}
|
||||
|
||||
if (atRule.params === 'components') {
|
||||
atRule.before(postcss.comment({ text: 'tailwind start components' }))
|
||||
atRule.before(updateSource(pluginComponents, atRule.source))
|
||||
extractChildren(atRule, 'components')
|
||||
atRule.before(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))
|
||||
extractChildren(atRule, 'utilities')
|
||||
atRule.before(postcss.comment({ text: 'tailwind end utilities' }))
|
||||
atRule.remove()
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -24,6 +24,15 @@ export default function(getConfig) {
|
|||
substituteResponsiveAtRules(config),
|
||||
substituteScreenAtRules(config),
|
||||
substituteClassApplyAtRules(config, processedPlugins.utilities),
|
||||
function(css) {
|
||||
css.walkAtRules('bucket', atRule => {
|
||||
const bucket = atRule.params
|
||||
atRule.before(postcss.comment({ text: `tailwind start ${bucket}` }))
|
||||
atRule.before(atRule.nodes)
|
||||
atRule.before(postcss.comment({ text: `tailwind end ${bucket}` }))
|
||||
atRule.remove()
|
||||
})
|
||||
},
|
||||
purgeUnusedStyles(config),
|
||||
]).process(css, { from: _.get(css, 'source.input.file') })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import generateVariantFunction from '../util/generateVariantFunction'
|
|||
import parseObjectStyles from '../util/parseObjectStyles'
|
||||
import prefixSelector from '../util/prefixSelector'
|
||||
import wrapWithVariants from '../util/wrapWithVariants'
|
||||
import cloneNodes from '../util/cloneNodes'
|
||||
import increaseSpecificity from '../util/increaseSpecificity'
|
||||
import selectorParser from 'postcss-selector-parser'
|
||||
|
||||
|
|
@ -27,6 +28,15 @@ function containsClass(value) {
|
|||
}).transformSync(value)
|
||||
}
|
||||
|
||||
function wrapWithBucket(rules, bucket) {
|
||||
return postcss
|
||||
.atRule({
|
||||
name: 'bucket',
|
||||
params: bucket,
|
||||
})
|
||||
.append(cloneNodes(Array.isArray(rules) ? rules : [rules]))
|
||||
}
|
||||
|
||||
export default function(plugins, config) {
|
||||
const pluginBaseStyles = []
|
||||
const pluginComponents = []
|
||||
|
|
@ -108,7 +118,9 @@ export default function(plugins, config) {
|
|||
}
|
||||
})
|
||||
|
||||
pluginUtilities.push(wrapWithVariants(styles.nodes, options.variants))
|
||||
pluginUtilities.push(
|
||||
wrapWithVariants(wrapWithBucket(styles.nodes, 'utilities'), options.variants)
|
||||
)
|
||||
},
|
||||
addComponents: (components, options) => {
|
||||
const defaultOptions = { variants: [], respectPrefix: true }
|
||||
|
|
@ -125,11 +137,9 @@ export default function(plugins, config) {
|
|||
}
|
||||
})
|
||||
|
||||
if (options.variants.length > 0) {
|
||||
pluginComponents.push(wrapWithVariants(styles.nodes, options.variants, 'components'))
|
||||
} else {
|
||||
pluginComponents.push(...styles.nodes)
|
||||
}
|
||||
pluginComponents.push(
|
||||
wrapWithVariants(wrapWithBucket(styles.nodes, 'components'), options.variants)
|
||||
)
|
||||
},
|
||||
addBase: baseStyles => {
|
||||
pluginBaseStyles.push(...parseStyles(baseStyles))
|
||||
|
|
|
|||
|
|
@ -1,23 +1,7 @@
|
|||
import postcss from 'postcss'
|
||||
import cloneNodes from './cloneNodes'
|
||||
|
||||
export default function wrapWithVariants(rules, variants, bucket = 'utilities') {
|
||||
if (bucket === 'components' && variants.includes('responsive')) {
|
||||
return postcss
|
||||
.atRule({
|
||||
name: 'responsive',
|
||||
params: 'components',
|
||||
})
|
||||
.append(
|
||||
postcss
|
||||
.atRule({
|
||||
name: 'variants',
|
||||
params: variants.filter(v => v !== 'responsive').join(', '),
|
||||
})
|
||||
.append(cloneNodes(Array.isArray(rules) ? rules : [rules]))
|
||||
)
|
||||
}
|
||||
|
||||
export default function wrapWithVariants(rules, variants) {
|
||||
return postcss
|
||||
.atRule({
|
||||
name: 'variants',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue