mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Reorganize prototype code
This commit is contained in:
parent
577f536eeb
commit
cef0b84abf
@ -655,7 +655,7 @@ describe('using apply with the prefix option', () => {
|
||||
},
|
||||
])
|
||||
|
||||
return run(input, config, () => processPlugins(corePlugins(config), config)).then(result => {
|
||||
return run(input, config).then(result => {
|
||||
expect(result.css).toMatchCss(expected)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
@ -679,7 +679,7 @@ describe('using apply with the prefix option', () => {
|
||||
},
|
||||
])
|
||||
|
||||
return run(input, config, () => processPlugins(corePlugins(config), config)).then(result => {
|
||||
return run(input, config).then(result => {
|
||||
expect(result.css).toMatchCss(expected)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
@ -697,7 +697,7 @@ describe('using apply with the prefix option', () => {
|
||||
},
|
||||
])
|
||||
|
||||
return run(input, config, () => processPlugins(corePlugins(config), config)).catch(e => {
|
||||
return run(input, config).catch(e => {
|
||||
expect(e).toMatchObject({ name: 'CssSyntaxError' })
|
||||
})
|
||||
})
|
||||
@ -720,7 +720,7 @@ describe('using apply with the prefix option', () => {
|
||||
},
|
||||
])
|
||||
|
||||
return run(input, config, () => processPlugins(corePlugins(config), config)).then(result => {
|
||||
return run(input, config).then(result => {
|
||||
expect(result.css).toMatchCss(expected)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
@ -744,7 +744,7 @@ describe('using apply with the prefix option', () => {
|
||||
},
|
||||
])
|
||||
|
||||
return run(input, config, () => processPlugins(corePlugins(config), config)).then(result => {
|
||||
return run(input, config).then(result => {
|
||||
expect(result.css).toMatchCss(expected)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
@ -764,16 +764,62 @@ describe('using apply with the prefix option', () => {
|
||||
|
||||
expect.assertions(1)
|
||||
|
||||
return run(input, config, () => processPlugins(corePlugins(config), config)).catch(e => {
|
||||
return run(input, config).catch(e => {
|
||||
expect(e).toMatchObject({
|
||||
name: 'CssSyntaxError',
|
||||
reason: 'The `mt-4` class does not exist, but `tw-mt-4` does. Did you forget the prefix?',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test('you can apply classes with important and a prefix enabled', () => {
|
||||
const input = `
|
||||
.foo { @apply tw-mt-4; }
|
||||
`
|
||||
|
||||
const expected = `
|
||||
.foo { margin-top: 1rem; }
|
||||
`
|
||||
|
||||
const config = resolveConfig([
|
||||
{
|
||||
...defaultConfig,
|
||||
prefix: 'tw-',
|
||||
important: true,
|
||||
},
|
||||
])
|
||||
|
||||
return run(input, config).then(result => {
|
||||
expect(result.css).toMatchCss(expected)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
test('you can apply classes with an important selector and a prefix enabled', () => {
|
||||
const input = `
|
||||
.foo { @apply tw-mt-4; }
|
||||
`
|
||||
|
||||
const expected = `
|
||||
.foo { margin-top: 1rem; }
|
||||
`
|
||||
|
||||
const config = resolveConfig([
|
||||
{
|
||||
...defaultConfig,
|
||||
prefix: 'tw-',
|
||||
important: '#app',
|
||||
},
|
||||
])
|
||||
|
||||
return run(input, config).then(result => {
|
||||
expect(result.css).toMatchCss(expected)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test.skip('you can apply utility classes when a selector is used for the important option', () => {
|
||||
test('you can apply utility classes when a selector is used for the important option', () => {
|
||||
const input = `
|
||||
.foo {
|
||||
@apply mt-8 mb-8;
|
||||
@ -794,30 +840,7 @@ test.skip('you can apply utility classes when a selector is used for the importa
|
||||
},
|
||||
])
|
||||
|
||||
return run(input, config, processPlugins(corePlugins(config), config).utilities).then(result => {
|
||||
expect(result.css).toMatchCss(expected)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
test.skip('you can apply utility classes without using the given prefix even if important (selector) is used', () => {
|
||||
const input = `
|
||||
.foo { @apply .tw-mt-4 .mb-4; }
|
||||
`
|
||||
|
||||
const expected = `
|
||||
.foo { margin-top: 1rem; margin-bottom: 1rem; }
|
||||
`
|
||||
|
||||
const config = resolveConfig([
|
||||
{
|
||||
...defaultConfig,
|
||||
prefix: 'tw-',
|
||||
important: '#app',
|
||||
},
|
||||
])
|
||||
|
||||
return run(input, config, processPlugins(corePlugins(config), config).utilities).then(result => {
|
||||
return run(input, config).then(result => {
|
||||
expect(result.css).toMatchCss(expected)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
|
||||
@ -70,8 +70,7 @@ export function issueFlagNotices(config) {
|
||||
.map(s => chalk.cyan(s))
|
||||
.join(', ')
|
||||
|
||||
console.log()
|
||||
log.info(`You have opted-in to future-facing breaking changes: ${changes}`)
|
||||
log.info(`\nYou have opted-in to future-facing breaking changes: ${changes}`)
|
||||
log.info(
|
||||
'These changes are stable and will be the default behavior in the next major version of Tailwind.'
|
||||
)
|
||||
@ -82,8 +81,7 @@ export function issueFlagNotices(config) {
|
||||
.map(s => chalk.yellow(s))
|
||||
.join(', ')
|
||||
|
||||
console.log()
|
||||
log.warn(`You have enabled experimental features: ${changes}`)
|
||||
log.warn(`\nYou have enabled experimental features: ${changes}`)
|
||||
log.warn(
|
||||
'Experimental features are not covered by semver, may introduce breaking changes, and can change at any time.'
|
||||
)
|
||||
@ -94,8 +92,7 @@ export function issueFlagNotices(config) {
|
||||
.map(s => chalk.magenta(s))
|
||||
.join(', ')
|
||||
|
||||
console.log()
|
||||
log.risk(`There are upcoming breaking changes: ${changes}`)
|
||||
log.risk(`\nThere are upcoming breaking changes: ${changes}`)
|
||||
log.risk(
|
||||
'We highly recommend opting-in to these changes now to simplify upgrading Tailwind in the future.'
|
||||
)
|
||||
|
||||
@ -210,11 +210,11 @@ function processApplyAtRules(css, lookupTree, config) {
|
||||
afterRule,
|
||||
]
|
||||
|
||||
const root = _.tap(postcss.root({ nodes: rulesToInsert }), root =>
|
||||
const { nodes } = _.tap(postcss.root({ nodes: rulesToInsert }), root =>
|
||||
root.walkDecls(d => (d.important = important))
|
||||
)
|
||||
|
||||
const mergedRules = mergeAdjacentRules(rule, root.nodes)
|
||||
const mergedRules = mergeAdjacentRules(rule, nodes)
|
||||
|
||||
inject.remove()
|
||||
rule.after(mergedRules)
|
||||
|
||||
19
src/lib/applyImportantConfiguration.js
Normal file
19
src/lib/applyImportantConfiguration.js
Normal file
@ -0,0 +1,19 @@
|
||||
export default function applyImportantConfiguration(_config) {
|
||||
return function(css) {
|
||||
css.walkRules(rule => {
|
||||
const important = rule.__tailwind ? rule.__tailwind.important : false
|
||||
|
||||
if (!important) {
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof important === 'string') {
|
||||
rule.selectors = rule.selectors.map(selector => {
|
||||
return `${rule.__tailwind.important} ${selector}`
|
||||
})
|
||||
} else {
|
||||
rule.walkDecls(decl => (decl.important = true))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,8 @@ import chalk from 'chalk'
|
||||
import { log } from '../cli/utils'
|
||||
import * as emoji from '../cli/emoji'
|
||||
|
||||
function removeTailwindComments(css) {
|
||||
function removeTailwindMarkers(css) {
|
||||
css.walkAtRules('tailwind', rule => rule.remove())
|
||||
css.walkComments(comment => {
|
||||
switch (comment.text.trim()) {
|
||||
case 'tailwind start components':
|
||||
@ -28,7 +29,7 @@ export default function purgeUnusedUtilities(config) {
|
||||
)
|
||||
|
||||
if (!purgeEnabled) {
|
||||
return removeTailwindComments
|
||||
return removeTailwindMarkers
|
||||
}
|
||||
|
||||
// Skip if `purge: []` since that's part of the default config
|
||||
@ -48,7 +49,7 @@ export default function purgeUnusedUtilities(config) {
|
||||
log(
|
||||
chalk.white('\n https://tailwindcss.com/docs/controlling-file-size/#removing-unused-css')
|
||||
)
|
||||
return removeTailwindComments
|
||||
return removeTailwindMarkers
|
||||
}
|
||||
|
||||
return postcss([
|
||||
@ -73,7 +74,7 @@ export default function purgeUnusedUtilities(config) {
|
||||
})
|
||||
}
|
||||
},
|
||||
removeTailwindComments,
|
||||
removeTailwindMarkers,
|
||||
purgecss({
|
||||
content: Array.isArray(config.purge) ? config.purge : config.purge.content,
|
||||
defaultExtractor: content => {
|
||||
|
||||
@ -8,6 +8,7 @@ import substituteResponsiveAtRules from './lib/substituteResponsiveAtRules'
|
||||
import convertLayerAtRulesToControlComments from './lib/convertLayerAtRulesToControlComments'
|
||||
import substituteScreenAtRules from './lib/substituteScreenAtRules'
|
||||
import substituteClassApplyAtRules from './lib/substituteClassApplyAtRules'
|
||||
import applyImportantConfiguration from './lib/applyImportantConfiguration'
|
||||
import purgeUnusedStyles from './lib/purgeUnusedStyles'
|
||||
|
||||
import corePlugins from './corePlugins'
|
||||
@ -40,9 +41,7 @@ export default function(getConfig) {
|
||||
convertLayerAtRulesToControlComments(config),
|
||||
substituteScreenAtRules(config),
|
||||
substituteClassApplyAtRules(config, getProcessedPlugins),
|
||||
function(css) {
|
||||
css.walkAtRules('tailwind', rule => rule.remove())
|
||||
},
|
||||
applyImportantConfiguration(config),
|
||||
purgeUnusedStyles(config),
|
||||
]).process(css, { from: _.get(css, 'source.input.file') })
|
||||
}
|
||||
|
||||
@ -9,8 +9,6 @@ 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'
|
||||
|
||||
function parseStyles(styles) {
|
||||
if (!Array.isArray(styles)) {
|
||||
@ -20,14 +18,6 @@ function parseStyles(styles) {
|
||||
return _.flatMap(styles, style => (style instanceof Node ? style : parseObjectStyles(style)))
|
||||
}
|
||||
|
||||
function containsClass(value) {
|
||||
return selectorParser(selectors => {
|
||||
let classFound = false
|
||||
selectors.walkClasses(() => (classFound = true))
|
||||
return classFound
|
||||
}).transformSync(value)
|
||||
}
|
||||
|
||||
function wrapWithLayer(rules, layer) {
|
||||
return postcss
|
||||
.atRule({
|
||||
@ -102,19 +92,10 @@ export default function(plugins, config) {
|
||||
rule.selector = applyConfiguredPrefix(rule.selector)
|
||||
}
|
||||
|
||||
if (options.respectImportant && _.get(config, 'important')) {
|
||||
if (config.important === true) {
|
||||
rule.walkDecls(decl => (decl.important = true))
|
||||
} else if (typeof config.important === 'string') {
|
||||
if (containsClass(config.important)) {
|
||||
throw rule.error(
|
||||
`Classes are not allowed when using the \`important\` option with a string argument. Please use an ID instead.`
|
||||
)
|
||||
}
|
||||
|
||||
rule.selectors = rule.selectors.map(selector => {
|
||||
return increaseSpecificity(config.important, selector)
|
||||
})
|
||||
if (options.respectImportant && config.important) {
|
||||
rule.__tailwind = {
|
||||
...rule.__tailwind,
|
||||
important: config.important,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user