Skip to content

Commit c252e33

Browse files
committed
Get shadow lookup working-ish with new apply approach
1 parent 6f1fb5c commit c252e33

File tree

4 files changed

+79
-17
lines changed

4 files changed

+79
-17
lines changed

__tests__/applyComplexClasses.test.js

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,33 @@ import processPlugins from '../src/util/processPlugins'
44
import resolveConfig from '../src/util/resolveConfig'
55
import corePlugins from '../src/corePlugins'
66
import defaultConfig from '../stubs/defaultConfig.stub.js'
7+
import cloneNodes from '../src/util/cloneNodes'
78

89
const resolvedDefaultConfig = resolveConfig([defaultConfig])
910

10-
const { utilities: defaultUtilities } = processPlugins(
11-
corePlugins(resolvedDefaultConfig),
11+
const defaultProcessedPlugins = processPlugins(
12+
[...corePlugins(resolvedDefaultConfig), ...resolvedDefaultConfig.plugins],
1213
resolvedDefaultConfig
1314
)
1415

15-
function run(input, config = resolvedDefaultConfig, utilities = defaultUtilities) {
16+
const defaultGetProcessedPlugins = function() {
17+
return {
18+
...defaultProcessedPlugins,
19+
base: cloneNodes(defaultProcessedPlugins.base),
20+
components: cloneNodes(defaultProcessedPlugins.components),
21+
utilities: cloneNodes(defaultProcessedPlugins.utilities),
22+
}
23+
}
24+
25+
function run(
26+
input,
27+
config = resolvedDefaultConfig,
28+
getProcessedPlugins = defaultGetProcessedPlugins
29+
) {
1630
config.experimental = {
1731
applyComplexClasses: true,
1832
}
19-
return postcss([substituteClassApplyAtRules(config, utilities)]).process(input, {
33+
return postcss([substituteClassApplyAtRules(config, getProcessedPlugins)]).process(input, {
2034
from: undefined,
2135
})
2236
}
@@ -47,7 +61,7 @@ test('selectors with invalid characters do not need to be manually escaped', ()
4761
})
4862
})
4963

50-
test.skip('it removes important from applied classes by default', () => {
64+
test('it removes important from applied classes by default', () => {
5165
const input = `
5266
.a { color: red !important; }
5367
.b { @apply a; }
@@ -64,7 +78,7 @@ test.skip('it removes important from applied classes by default', () => {
6478
})
6579
})
6680

67-
test.skip('applied rules can be made !important', () => {
81+
test('applied rules can be made !important', () => {
6882
const input = `
6983
.a { color: red; }
7084
.b { @apply a !important; }
@@ -230,7 +244,7 @@ test('it matches classes that have multiple rules', () => {
230244
})
231245
})
232246

233-
test.skip('you can apply utility classes that do not actually exist as long as they would exist if utilities were being generated', () => {
247+
test('you can apply utility classes that do not actually exist as long as they would exist if utilities were being generated', () => {
234248
const input = `
235249
.foo { @apply mt-4; }
236250
`
@@ -293,11 +307,16 @@ test.skip('you can apply utility classes without using the given prefix when usi
293307

294308
test.skip('you can apply utility classes without specificity prefix even if important (selector) is used', () => {
295309
const input = `
296-
.foo { @apply .mt-8 .mb-8; }
310+
.foo {
311+
@apply mt-8 mb-8;
312+
}
297313
`
298314

299315
const expected = `
300-
.foo { margin-top: 2rem; margin-bottom: 2rem; }
316+
.foo {
317+
margin-top: 2rem;
318+
margin-bottom: 2rem;
319+
}
301320
`
302321

303322
const config = resolveConfig([

src/flagged/applyComplexClasses.js

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import _ from 'lodash'
22
import selectorParser from 'postcss-selector-parser'
3+
import postcss from 'postcss'
4+
import substituteTailwindAtRules from '../lib/substituteTailwindAtRules'
5+
import evaluateTailwindFunctions from '../lib/evaluateTailwindFunctions'
6+
import substituteVariantsAtRules from '../lib/substituteVariantsAtRules'
7+
import substituteResponsiveAtRules from '../lib/substituteResponsiveAtRules'
8+
import convertLayerAtRulesToControlComments from '../lib/convertLayerAtRulesToControlComments'
9+
import substituteScreenAtRules from '../lib/substituteScreenAtRules'
310

411
function hasInject(css) {
512
let foundInject = false
@@ -146,8 +153,8 @@ function makeExtractUtilityRules(css) {
146153
}
147154
}
148155

149-
export default function applyComplexClasses(css) {
150-
const extractUtilityRules = makeExtractUtilityRules(css)
156+
function themagic(css, lookupTree) {
157+
const extractUtilityRules = makeExtractUtilityRules(lookupTree)
151158

152159
while (hasInject(css)) {
153160
css.walkRules(rule => {
@@ -161,7 +168,12 @@ export default function applyComplexClasses(css) {
161168
})
162169

163170
injectRules.forEach(inject => {
164-
const injectUtilityNames = inject.params.split(' ')
171+
const [
172+
importantEntries,
173+
injectUtilityNames,
174+
important = importantEntries.length > 0,
175+
] = _.partition(inject.params.split(' '), n => n === '!important')
176+
165177
const currentUtilityNames = extractUtilityNames(rule.selector)
166178

167179
if (_.intersection(injectUtilityNames, currentUtilityNames).length > 0) {
@@ -187,7 +199,11 @@ export default function applyComplexClasses(css) {
187199
afterRule,
188200
]
189201

190-
const mergedRules = mergeAdjacentRules(rule, rulesToInsert)
202+
const root = _.tap(postcss.root({ nodes: rulesToInsert }), root =>
203+
root.walkDecls(d => (d.important = important))
204+
)
205+
206+
const mergedRules = mergeAdjacentRules(rule, root.nodes)
191207

192208
inject.remove()
193209
rule.after(mergedRules)
@@ -203,3 +219,30 @@ export default function applyComplexClasses(css) {
203219

204220
return css
205221
}
222+
223+
export default function applyComplexClasses(config, getProcessedPlugins) {
224+
return function(css) {
225+
return postcss([
226+
substituteTailwindAtRules(config, getProcessedPlugins()),
227+
evaluateTailwindFunctions(config),
228+
substituteVariantsAtRules(config, getProcessedPlugins()),
229+
substituteResponsiveAtRules(config),
230+
convertLayerAtRulesToControlComments(config),
231+
substituteScreenAtRules(config),
232+
])
233+
.process(
234+
`
235+
@tailwind base;
236+
@tailwind components;
237+
@tailwind utilities;
238+
`,
239+
{ from: undefined }
240+
)
241+
.then(result => {
242+
// if css already contains tailwind, css is the lookup tree
243+
const lookupTree = _.tap(css.clone(), tree => tree.prepend(result.root))
244+
245+
return themagic(css, lookupTree)
246+
})
247+
}
248+
}

src/lib/substituteClassApplyAtRules.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,14 @@ function findClass(classToApply, classTable, onError) {
5656
return match.clone().nodes
5757
}
5858

59-
export default function(config, generatedUtilities) {
59+
export default function(config, getProcessedPlugins) {
6060
if (flagEnabled(config, 'applyComplexClasses')) {
61-
return applyComplexClasses
61+
return applyComplexClasses(config, getProcessedPlugins)
6262
}
6363

6464
return function(css) {
6565
const classLookup = buildClassTable(css)
66-
const shadowLookup = buildShadowTable(generatedUtilities)
66+
const shadowLookup = buildShadowTable(getProcessedPlugins().utilities)
6767

6868
css.walkRules(rule => {
6969
rule.walkAtRules('apply', atRule => {

src/processTailwindFeatures.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export default function(getConfig) {
3939
substituteResponsiveAtRules(config),
4040
convertLayerAtRulesToControlComments(config),
4141
substituteScreenAtRules(config),
42-
substituteClassApplyAtRules(config, getProcessedPlugins().utilities),
42+
substituteClassApplyAtRules(config, getProcessedPlugins),
4343
purgeUnusedStyles(config),
4444
]).process(css, { from: _.get(css, 'source.input.file') })
4545
}

0 commit comments

Comments
 (0)