Added Prefix Selector support via important config

This commit is contained in:
James Wee 2019-07-11 17:07:24 +12:00 committed by James Wee
parent c9bba9d1b1
commit 382075731d
6 changed files with 100 additions and 1 deletions

View File

@ -242,3 +242,25 @@ test('you can apply utility classes without using the given prefix when using a
expect(result.warnings().length).toBe(0)
})
})
test('you can apply utility classes without specificity prefix even if important (string) is used.', () => {
const input = `
.foo { @apply .mt-8 .mb-8; }
`
const expected = `
.foo { margin-top: 2rem; margin-bottom: 2rem; }
`
const config = resolveConfig([
{
...defaultConfig,
important: '#app',
},
])
return run(input, config, processPlugins(corePlugins(config), config).utilities).then(result => {
expect(result.css).toEqual(expected)
expect(result.warnings().length).toBe(0)
})
})

View File

@ -877,6 +877,32 @@ test('plugins respect prefix and important options by default when adding utilit
`)
})
test('plugins respect prefix and important (string) options by default when adding utilities', () => {
const { utilities } = processPlugins(
[
function({ addUtilities }) {
addUtilities({
'.rotate-90': {
transform: 'rotate(90deg)',
},
})
},
],
makeConfig({
prefix: 'tw-',
important: '#app',
})
)
expect(css(utilities)).toMatchCss(`
@variants {
#app .tw-rotate-90 {
transform: rotate(90deg)
}
}
`)
})
test('important utilities are not made double important when important option is used', () => {
const { utilities } = processPlugins(
[

View File

@ -80,6 +80,46 @@ test('important key overrides default important', () => {
})
})
test('important (string) key overrides default important', () => {
const userConfig = {
important: '#app',
}
const defaultConfig = {
prefix: '',
important: false,
separator: ':',
theme: {
screens: {
mobile: '400px',
},
},
variants: {
appearance: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
},
}
const result = resolveConfig([userConfig, defaultConfig])
expect(result).toEqual({
prefix: '',
important: '#app',
separator: ':',
theme: {
screens: {
mobile: '400px',
},
},
variants: {
appearance: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
},
})
})
test('separator key overrides default separator', () => {
const userConfig = {
separator: '__',

View File

@ -2,6 +2,7 @@ import _ from 'lodash'
import postcss from 'postcss'
import escapeClassName from '../util/escapeClassName'
import prefixSelector from '../util/prefixSelector'
import increaseSpecificity from '../util/increaseSpecificity'
function buildClassTable(css) {
const classTable = {}
@ -85,6 +86,8 @@ export default function(config, generatedUtilities) {
() => findClass(classToApply, classLookup, onError),
() => findClass(classToApply, shadowLookup, onError),
() => findClass(prefixSelector(config.prefix, classToApply), shadowLookup, onError),
// prettier-ignore
() => findClass(increaseSpecificity(config.important, classToApply), shadowLookup, onError),
() => {
// prettier-ignore
throw onError(`\`@apply\` cannot be used with \`${classToApply}\` because \`${classToApply}\` either cannot be found, or its actual definition includes a pseudo-selector like :hover, :active, etc. If you're sure that \`${classToApply}\` exists, make sure that any \`@import\` statements are being properly processed *before* Tailwind CSS sees your CSS, as \`@apply\` can only be used for classes in the same CSS tree.`)

View File

@ -0,0 +1,3 @@
export default function(importantVal, selector) {
return `${importantVal} ${selector}`
}

View File

@ -6,6 +6,7 @@ import generateVariantFunction from '../util/generateVariantFunction'
import parseObjectStyles from '../util/parseObjectStyles'
import prefixSelector from '../util/prefixSelector'
import wrapWithVariants from '../util/wrapWithVariants'
import increaseSpecificity from '../util/increaseSpecificity'
function parseStyles(styles) {
if (!Array.isArray(styles)) {
@ -55,7 +56,11 @@ export default function(plugins, config) {
}
if (options.respectImportant && _.get(config, 'important')) {
rule.walkDecls(decl => (decl.important = true))
if (config.important === true) {
rule.walkDecls(decl => (decl.important = true))
} else if (typeof config.important === 'string') {
rule.selector = increaseSpecificity(config.important, rule.selector)
}
}
})