Skip to content

Commit

Permalink
Polish match APIs (tailwindlabs#5664)
Browse files Browse the repository at this point in the history
* fix incorrect logic for validating content paths

* remove `includeRules` helper

* generate keyframes as part of the animate plugin

* add matchUtilities

* splitup `variantPlugins` and `corePlugins`
  • Loading branch information
RobinMalfait authored Oct 1, 2021
1 parent d94541c commit bd21bef
Show file tree
Hide file tree
Showing 10 changed files with 331 additions and 99 deletions.
4 changes: 2 additions & 2 deletions scripts/create-plugin-list.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import corePlugins from '../src/corePlugins'
import { corePlugins } from '../src/corePlugins'
import fs from 'fs'
import path from 'path'

let corePluginList = Object.keys(corePlugins).filter((plugin) => !plugin.includes('Variants'))
let corePluginList = Object.keys(corePlugins)

fs.writeFileSync(
path.join(process.cwd(), 'src', 'corePluginList.js'),
Expand Down
39 changes: 18 additions & 21 deletions src/corePlugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ import {
import { version as tailwindVersion } from '../package.json'
import log from './util/log'

export default {
// Variant plugins
export let variantPlugins = {
pseudoElementVariants: ({ config, addVariant }) => {
addVariant(
'first-letter',
Expand Down Expand Up @@ -360,8 +359,9 @@ export default {
)
}
},
}

// Actual plugins
export let corePlugins = {
preflight: ({ addBase }) => {
let preflightStyles = postcss.parse(fs.readFileSync(`${__dirname}/css/preflight.css`, 'utf8'))

Expand Down Expand Up @@ -753,31 +753,28 @@ export default {
let prefixName = (name) => prefix(`.${name}`).slice(1)
let keyframes = Object.fromEntries(
Object.entries(theme('keyframes') ?? {}).map(([key, value]) => {
return [key, [{ [`@keyframes ${prefixName(key)}`]: value }]]
return [key, { [`@keyframes ${prefixName(key)}`]: value }]
})
)

matchUtilities(
{
animate: (value, { includeRules }) => {
animate: (value) => {
let animations = parseAnimationValue(value)

for (let { name } of animations) {
if (keyframes[name] !== undefined) {
includeRules(keyframes[name], { respectImportant: false })
}
}

return {
animation: animations
.map(({ name, value }) => {
if (name === undefined || keyframes[name] === undefined) {
return value
}
return value.replace(name, prefixName(name))
})
.join(', '),
}
return [
...animations.flatMap((animation) => keyframes[animation.name]),
{
animation: animations
.map(({ name, value }) => {
if (name === undefined || keyframes[name] === undefined) {
return value
}
return value.replace(name, prefixName(name))
})
.join(', '),
},
]
},
},
{ values: theme('animation') }
Expand Down
5 changes: 0 additions & 5 deletions src/lib/generateRules.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,6 @@ function applyVariant(variant, matches, context) {
let result = []

for (let [meta, rule] of matches) {
if (meta.options.respectVariants === false) {
result.push([meta, rule])
continue
}

let container = postcss.root({ nodes: [rule.clone()] })

for (let [variantSort, variantFunction] of variantFunctionTuples) {
Expand Down
108 changes: 76 additions & 32 deletions src/lib/setupContextUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import escapeClassName from '../util/escapeClassName'
import nameClass, { formatClass } from '../util/nameClass'
import { coerceValue } from '../util/pluginUtils'
import bigSign from '../util/bigSign'
import corePlugins from '../corePlugins'
import { variantPlugins, corePlugins } from '../corePlugins'
import * as sharedState from './sharedState'
import { env } from './sharedState'
import { toPath } from '../util/toPath'
Expand Down Expand Up @@ -237,17 +237,11 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
},
addComponents(components, options) {
let defaultOptions = {
variants: [],
respectPrefix: true,
respectImportant: false,
respectVariants: true,
}

options = Object.assign(
{},
defaultOptions,
Array.isArray(options) ? { variants: options } : options
)
options = Object.assign({}, defaultOptions, Array.isArray(options) ? {} : options)

for (let [identifier, rule] of withIdentifiers(components)) {
let prefixedIdentifier = prefixIdentifier(identifier, options)
Expand All @@ -266,17 +260,11 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
},
addUtilities(utilities, options) {
let defaultOptions = {
variants: [],
respectPrefix: true,
respectImportant: true,
respectVariants: true,
}

options = Object.assign(
{},
defaultOptions,
Array.isArray(options) ? { variants: options } : options
)
options = Object.assign({}, defaultOptions, Array.isArray(options) ? {} : options)

for (let [identifier, rule] of withIdentifiers(utilities)) {
let prefixedIdentifier = prefixIdentifier(identifier, options)
Expand All @@ -295,10 +283,8 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
},
matchUtilities: function (utilities, options) {
let defaultOptions = {
variants: [],
respectPrefix: true,
respectImportant: true,
respectVariants: true,
}

options = { ...defaultOptions, ...options }
Expand Down Expand Up @@ -338,21 +324,14 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
return []
}

let includedRules = []
let ruleSets = []
.concat(
rule(value, {
includeRules(rules) {
includedRules.push(...rules)
},
})
)
.concat(rule(value))
.filter(Boolean)
.map((declaration) => ({
[nameClass(identifier, modifier)]: declaration,
}))

return [...includedRules, ...ruleSets]
return ruleSets
}

let withOffsets = [{ sort: offset, layer: 'utilities', options }, wrapped]
Expand All @@ -361,6 +340,68 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
context.candidateRuleMap.set(prefixedIdentifier, [])
}

context.candidateRuleMap.get(prefixedIdentifier).push(withOffsets)
}
},
matchComponents: function (components, options) {
let defaultOptions = {
respectPrefix: true,
respectImportant: false,
}

options = { ...defaultOptions, ...options }

let offset = offsets.components++

for (let identifier in components) {
let prefixedIdentifier = prefixIdentifier(identifier, options)
let rule = components[identifier]

classList.add([prefixedIdentifier, options])

function wrapped(modifier, { isOnlyPlugin }) {
let { type = 'any' } = options
type = [].concat(type)
let [value, coercedType] = coerceValue(type, modifier, options.values, tailwindConfig)

if (value === undefined) {
return []
}

if (!type.includes(coercedType)) {
if (isOnlyPlugin) {
log.warn([
`Unnecessary typehint \`${coercedType}\` in \`${identifier}-${modifier}\`.`,
`You can safely update it to \`${identifier}-${modifier.replace(
coercedType + ':',
''
)}\`.`,
])
} else {
return []
}
}

if (!isValidArbitraryValue(value)) {
return []
}

let ruleSets = []
.concat(rule(value))
.filter(Boolean)
.map((declaration) => ({
[nameClass(identifier, modifier)]: declaration,
}))

return ruleSets
}

let withOffsets = [{ sort: offset, layer: 'components', options }, wrapped]

if (!context.candidateRuleMap.has(prefixedIdentifier)) {
context.candidateRuleMap.set(prefixedIdentifier, [])
}

context.candidateRuleMap.get(prefixedIdentifier).push(withOffsets)
}
},
Expand Down Expand Up @@ -457,7 +498,7 @@ function collectLayerPlugins(root) {
}

function resolvePlugins(context, root) {
let corePluginList = Object.entries(corePlugins)
let corePluginList = Object.entries({ ...variantPlugins, ...corePlugins })
.map(([name, plugin]) => {
if (!context.tailwindConfig.corePlugins.includes(name)) {
return null
Expand All @@ -479,12 +520,15 @@ function resolvePlugins(context, root) {

// TODO: This is a workaround for backwards compatibility, since custom variants
// were historically sorted before screen/stackable variants.
let beforeVariants = [corePlugins['pseudoElementVariants'], corePlugins['pseudoClassVariants']]
let beforeVariants = [
variantPlugins['pseudoElementVariants'],
variantPlugins['pseudoClassVariants'],
]
let afterVariants = [
corePlugins['directionVariants'],
corePlugins['reducedMotionVariants'],
corePlugins['darkVariants'],
corePlugins['screenVariants'],
variantPlugins['directionVariants'],
variantPlugins['reducedMotionVariants'],
variantPlugins['darkVariants'],
variantPlugins['screenVariants'],
]

return [...corePluginList, ...beforeVariants, ...userPlugins, ...afterVariants, ...layerPlugins]
Expand Down
44 changes: 21 additions & 23 deletions src/util/normalizeConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ export function normalizeConfig(config) {
*/
let valid = (() => {
// `config.purge` should not exist anymore
if (config.purge) return false
if (config.purge) {
return false
}

// `config.content` should exist
if (!config.content) return false
if (!config.content) {
return false
}

// `config.content` should be an object or an array
if (
!Array.isArray(config.content) ||
!Array.isArray(config.content) &&
!(typeof config.content === 'object' && config.content !== null)
) {
return false
Expand All @@ -38,17 +42,15 @@ export function normalizeConfig(config) {
if (typeof path === 'string') return true

// `path` can be an object { raw: string, extension?: string }
if (
// `raw` must be a string
typeof path?.raw === 'string' &&
// `extension` (if provided) should also be a string
path?.extension !== undefined &&
typeof path?.extension === 'string'
) {
return true
// `raw` must be a string
if (typeof path?.raw !== 'string') return false

// `extension` (if provided) should also be a string
if (path?.extension && typeof path?.extension !== 'string') {
return false
}

return false
return true
})
}

Expand All @@ -69,17 +71,15 @@ export function normalizeConfig(config) {
if (typeof path === 'string') return true

// `path` can be an object { raw: string, extension?: string }
if (
// `raw` must be a string
typeof path?.raw === 'string' &&
// `extension` (if provided) should also be a string
path?.extension !== undefined &&
typeof path?.extension === 'string'
) {
return true
// `raw` must be a string
if (typeof path?.raw !== 'string') return false

// `extension` (if provided) should also be a string
if (path?.extension && typeof path?.extension !== 'string') {
return false
}

return false
return true
})
) {
return false
Expand All @@ -92,7 +92,6 @@ export function normalizeConfig(config) {
return false
}
}
return false
} else if (
!(config.content.extract === undefined || typeof config.content.extract === 'function')
) {
Expand All @@ -106,7 +105,6 @@ export function normalizeConfig(config) {
return false
}
}
return false
} else if (
!(
config.content.transform === undefined || typeof config.content.transform === 'function'
Expand Down
Loading

0 comments on commit bd21bef

Please sign in to comment.