Skip to content
This repository was archived by the owner on Apr 6, 2021. It is now read-only.

Commit 8cd714a

Browse files
committed
Fix bug where apply would populate classCache and cause utilities not to generate
1 parent dc5cc01 commit 8cd714a

File tree

4 files changed

+99
-67
lines changed

4 files changed

+99
-67
lines changed

src/lib/expandApplyAtRules.js

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,32 @@
11
const postcss = require('postcss')
2-
const generateRules = require('./generateRules')
2+
const { generateRules, resolveMatches } = require('./generateRules')
33
const { bigSign } = require('./utils')
44
const escape = require('tailwindcss/lib/util/escapeClassName').default
55

6+
function buildApplyCache(applyCandidates, context) {
7+
for (let candidate of applyCandidates) {
8+
if (context.notClassCache.has(candidate) || context.applyClassCache.has(candidate)) {
9+
continue
10+
}
11+
12+
if (context.classCache.has(candidate)) {
13+
context.applyClassCache.set(candidate, context.classCache.get(candidate))
14+
continue
15+
}
16+
17+
let matches = resolveMatches(candidate, context)
18+
19+
if (matches.length === 0) {
20+
context.notClassCache.add(candidate)
21+
continue
22+
}
23+
24+
context.applyClassCache.set(candidate, matches)
25+
}
26+
27+
return context.applyClassCache
28+
}
29+
630
function expandApplyAtRules(context) {
731
return (root) => {
832
let applyCandidates = new Set()
@@ -18,14 +42,8 @@ function expandApplyAtRules(context) {
1842

1943
// Start the @apply process if we have rules with @apply in them
2044
if (applies.length > 0) {
21-
let classCacheCount = context.classCache.size
22-
2345
// Fill up some caches!
24-
generateRules(context.tailwindConfig, applyCandidates, context)
25-
26-
if (context.classCache.size > classCacheCount) {
27-
context.stylesheetCache = null
28-
}
46+
let applyClassCache = buildApplyCache(applyCandidates, context)
2947

3048
/**
3149
* When we have an apply like this:
@@ -59,13 +77,13 @@ function expandApplyAtRules(context) {
5977
let siblings = []
6078
let applyCandidates = apply.params.split(/[\s\t\n]+/g)
6179
for (let applyCandidate of applyCandidates) {
62-
if (!context.classCache.has(applyCandidate)) {
80+
if (!applyClassCache.has(applyCandidate)) {
6381
throw new Error(
6482
`The ${applyCandidate} class does not exist. If it's a custom class, make sure it is defined within a \`@layer\` directive.`
6583
)
6684
}
6785

68-
let rules = context.classCache.get(applyCandidate)
86+
let rules = applyClassCache.get(applyCandidate)
6987

7088
for (let [meta, node] of rules) {
7189
let root = postcss.root({ nodes: [node] })

src/lib/expandTailwindAtRules.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const fs = require('fs')
22
const fastGlob = require('fast-glob')
33
const sharedState = require('./sharedState')
4-
const generateRules = require('./generateRules')
4+
const { generateRules } = require('./generateRules')
55
const { bigSign } = require('./utils')
66

77
let env = sharedState.env
@@ -150,11 +150,10 @@ function expandTailwindAtRules(context, registerDependency) {
150150
// ---
151151

152152
// Generate the actual CSS
153-
154153
let classCacheCount = context.classCache.size
155154

156155
env.DEBUG && console.time('Generate rules')
157-
let rules = generateRules(context.tailwindConfig, candidates, context)
156+
let rules = generateRules(candidates, context)
158157
env.DEBUG && console.timeEnd('Generate rules')
159158

160159
// We only ever add to the classCache, so if it didn't grow, there is nothing new.

src/lib/generateRules.js

Lines changed: 68 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -82,81 +82,96 @@ function parseRules(rule, cache, options = {}) {
8282
return [cache.get(rule), options]
8383
}
8484

85-
function generateRules(tailwindConfig, candidates, context) {
86-
let { candidateRuleMap, classCache, notClassCache, postCssNodeCache } = context
87-
let allRules = []
85+
function resolveMatchedPlugins(classCandidate, context) {
86+
if (context.candidateRuleMap.has(classCandidate)) {
87+
return [context.candidateRuleMap.get(classCandidate), 'DEFAULT']
88+
}
8889

89-
for (let candidate of candidates) {
90-
if (notClassCache.has(candidate)) {
91-
continue
92-
}
90+
let candidatePrefix = classCandidate
91+
let negative = false
9392

94-
if (classCache.has(candidate)) {
95-
allRules.push(classCache.get(candidate))
96-
continue
93+
if (candidatePrefix[0] === '-') {
94+
negative = true
95+
candidatePrefix = candidatePrefix.slice(1)
96+
}
97+
98+
for (let [prefix, modifier] of candidatePermutations(candidatePrefix)) {
99+
if (context.candidateRuleMap.has(prefix)) {
100+
return [context.candidateRuleMap.get(prefix), negative ? `-${modifier}` : modifier]
97101
}
102+
}
98103

99-
let [classCandidate, ...variants] = candidate.split(':').reverse()
100-
let matchedPlugins = null
104+
return null
105+
}
101106

102-
if (candidateRuleMap.has(classCandidate)) {
103-
matchedPlugins = [candidateRuleMap.get(classCandidate), 'DEFAULT']
104-
} else {
105-
let candidatePrefix = classCandidate
106-
let negative = false
107+
function resolveMatches(candidate, context) {
108+
let [classCandidate, ...variants] = candidate.split(':').reverse()
109+
let matchedPlugins = resolveMatchedPlugins(classCandidate, context)
107110

108-
if (candidatePrefix[0] === '-') {
109-
negative = true
110-
candidatePrefix = candidatePrefix.slice(1)
111-
}
111+
if (matchedPlugins === null) {
112+
return []
113+
}
114+
115+
let pluginHelpers = {
116+
candidate: classCandidate,
117+
theme: context.tailwindConfig.theme,
118+
}
112119

113-
for (let [prefix, modifier] of candidatePermutations(candidatePrefix)) {
114-
if (candidateRuleMap.has(prefix)) {
115-
matchedPlugins = [candidateRuleMap.get(prefix), negative ? `-${modifier}` : modifier]
116-
break
120+
let matches = []
121+
let [plugins, modifier] = matchedPlugins
122+
123+
for (let [sort, plugin] of plugins) {
124+
if (typeof plugin === 'function') {
125+
for (let ruleSet of [].concat(plugin(modifier, pluginHelpers))) {
126+
let [rules, options] = parseRules(ruleSet, context.postCssNodeCache)
127+
for (let rule of rules) {
128+
matches.push([{ ...sort, options }, rule])
117129
}
118130
}
131+
} else {
132+
let ruleSet = plugin
133+
let [rules, options] = parseRules(ruleSet, context.postCssNodeCache)
134+
for (let rule of rules) {
135+
matches.push([{ ...sort, options }, rule])
136+
}
119137
}
138+
}
139+
140+
for (let variant of variants) {
141+
matches = applyVariant(variant, matches, context)
142+
}
143+
144+
return matches
145+
}
146+
147+
function generateRules(candidates, context) {
148+
let allRules = []
120149

121-
if (matchedPlugins === null) {
122-
notClassCache.add(candidate)
150+
for (let candidate of candidates) {
151+
if (context.notClassCache.has(candidate)) {
123152
continue
124153
}
125154

126-
let pluginHelpers = {
127-
candidate: classCandidate,
128-
theme: tailwindConfig.theme,
155+
if (context.classCache.has(candidate)) {
156+
allRules.push(context.classCache.get(candidate))
157+
continue
129158
}
130159

131-
let matches = []
132-
let [plugins, modifier] = matchedPlugins
160+
let matches = resolveMatches(candidate, context)
133161

134-
for (let [sort, plugin] of plugins) {
135-
if (typeof plugin === 'function') {
136-
for (let ruleSet of [].concat(plugin(modifier, pluginHelpers))) {
137-
let [rules, options] = parseRules(ruleSet, context.newPostCssNodeCache)
138-
for (let rule of rules) {
139-
matches.push([{ ...sort, options }, rule])
140-
}
141-
}
142-
} else {
143-
let ruleSet = plugin
144-
let [rules, options] = parseRules(ruleSet, context.newPostCssNodeCache)
145-
for (let rule of rules) {
146-
matches.push([{ ...sort, options }, rule])
147-
}
148-
}
149-
}
150-
151-
for (let variant of variants) {
152-
matches = applyVariant(variant, matches, context)
162+
if (matches.length === 0) {
163+
context.notClassCache.add(candidate)
164+
continue
153165
}
154166

155-
classCache.set(candidate, matches)
167+
context.classCache.set(candidate, matches)
156168
allRules.push(matches)
157169
}
158170

159171
return allRules.flat(1).map(([{ sort, layer }, rule]) => [sort | context.layerOrder[layer], rule])
160172
}
161173

162-
module.exports = generateRules
174+
module.exports = {
175+
resolveMatches,
176+
generateRules,
177+
}

src/lib/setupContext.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,9 +617,9 @@ function setupContext(configOrPath) {
617617
scannedContent: false,
618618
touchFile: null,
619619
classCache: new Map(),
620+
applyClassCache: new Map(),
620621
notClassCache: new Set(),
621622
postCssNodeCache: new Map(),
622-
newPostCssNodeCache: new Map(),
623623
candidateRuleMap: new Map(),
624624
configPath: userConfigPath,
625625
tailwindConfig: tailwindConfig,

0 commit comments

Comments
 (0)