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

Commit 4a03bca

Browse files
committed
Add initial prefix support
1 parent 98ae69d commit 4a03bca

File tree

6 files changed

+247
-42
lines changed

6 files changed

+247
-42
lines changed

src/corePlugins/index.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
const postcss = require('postcss')
2-
const nameClass = require('tailwindcss/lib/util/nameClass').default
32
const buildMediaQuery = require('tailwindcss/lib/util/buildMediaQuery').default
4-
const transformThemeValue = require('tailwindcss/lib/util/transformThemeValue').default
3+
const prefixSelector = require('tailwindcss/lib/util/prefixSelector').default
54
const {
65
updateLastClasses,
76
updateAllClasses,
@@ -53,7 +52,12 @@ module.exports = {
5352
return null
5453
}
5554

56-
return `.group${config('separator')}${state} ${variantSelector}`
55+
let groupSelector = prefixSelector(
56+
config('prefix'),
57+
`.group${config('separator')}${state}`
58+
)
59+
60+
return `${groupSelector} ${variantSelector}`
5761
})
5862
)
5963
}
@@ -115,7 +119,9 @@ module.exports = {
115119
return null
116120
}
117121

118-
return `.dark ${variantSelector}`
122+
let darkSelector = prefixSelector(config('prefix'), `.dark`)
123+
124+
return `${darkSelector} ${variantSelector}`
119125
})
120126
)
121127
} else if (config('darkMode') === 'media') {

src/lib/generateRules.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
const postcss = require('postcss')
2-
const { default: parseObjectStyles } = require('tailwindcss/lib/util/parseObjectStyles')
3-
const { transformAllSelectors } = require('../pluginUtils')
4-
const { toPostCssNode, isPlainObject, bigSign } = require('./utils')
2+
const parseObjectStyles = require('tailwindcss/lib/util/parseObjectStyles').default
3+
const { isPlainObject, bigSign } = require('./utils')
54
const selectorParser = require('postcss-selector-parser')
5+
const prefixSelector = require('tailwindcss/lib/util/prefixSelector').default
66

77
let classNameParser = selectorParser((selectors) => {
88
return selectors.first.filter(({ type }) => type === 'class').pop().value
@@ -30,6 +30,25 @@ function* candidatePermutations(prefix, modifier = '') {
3030
yield* candidatePermutations(prefix, modifier)
3131
}
3232

33+
function applyPrefix(matches, context) {
34+
if (matches.length === 0 || context.tailwindConfig.prefix === '') {
35+
return matches
36+
}
37+
38+
for (let match of matches) {
39+
let [meta] = match
40+
if (meta.options.respectPrefix) {
41+
let container = postcss.root({ nodes: [match[1]] })
42+
container.walkRules((r) => {
43+
r.selector = prefixSelector(context.tailwindConfig.prefix, r.selector)
44+
})
45+
match[1] = container.nodes[0]
46+
}
47+
}
48+
49+
return matches
50+
}
51+
3352
// Takes a list of rule tuples and applies a variant like `hover`, sm`,
3453
// whatever to it. We used to do some extra caching here to avoid generating
3554
// a variant of the same rule more than once, but this was never hit because
@@ -180,6 +199,8 @@ function* resolveMatches(candidate, context) {
180199
}
181200
}
182201

202+
matches = applyPrefix(matches, context)
203+
183204
for (let variant of variants) {
184205
matches = applyVariant(variant, matches, context)
185206
}
@@ -205,8 +226,6 @@ function generateRules(candidates, context) {
205226

206227
let matches = Array.from(resolveMatches(candidate, context))
207228

208-
// apply prefix and important here?
209-
210229
if (matches.length === 0) {
211230
context.notClassCache.add(candidate)
212231
continue

src/lib/setupContext.js

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -379,13 +379,22 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
379379
},
380380
addBase(base) {
381381
for (let [identifier, rule] of withIdentifiers(base)) {
382+
let prefixedIdentifier =
383+
identifier === '*'
384+
? '*'
385+
: options.respectPrefix
386+
? context.tailwindConfig.prefix + identifier
387+
: identifier
388+
382389
let offset = offsets.base++
383390

384-
if (!context.candidateRuleMap.has(identifier)) {
385-
context.candidateRuleMap.set(identifier, [])
391+
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
392+
context.candidateRuleMap.set(prefixedIdentifier, [])
386393
}
387394

388-
context.candidateRuleMap.get(identifier).push([{ sort: offset, layer: 'base' }, rule])
395+
context.candidateRuleMap
396+
.get(prefixedIdentifier)
397+
.push([{ sort: offset, layer: 'base' }, rule])
389398
}
390399
},
391400
addComponents(components, options) {
@@ -403,14 +412,20 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
403412
)
404413

405414
for (let [identifier, rule] of withIdentifiers(components)) {
415+
let prefixedIdentifier =
416+
identifier === '*'
417+
? '*'
418+
: options.respectPrefix
419+
? context.tailwindConfig.prefix + identifier
420+
: identifier
406421
let offset = offsets.components++
407422

408-
if (!context.candidateRuleMap.has(identifier)) {
409-
context.candidateRuleMap.set(identifier, [])
423+
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
424+
context.candidateRuleMap.set(prefixedIdentifier, [])
410425
}
411426

412427
context.candidateRuleMap
413-
.get(identifier)
428+
.get(prefixedIdentifier)
414429
.push([{ sort: offset, layer: 'components', options }, rule])
415430
}
416431
},
@@ -429,30 +444,42 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
429444
)
430445

431446
for (let [identifier, rule] of withIdentifiers(utilities)) {
447+
let prefixedIdentifier =
448+
identifier === '*'
449+
? '*'
450+
: options.respectPrefix
451+
? context.tailwindConfig.prefix + identifier
452+
: identifier
432453
let offset = offsets.utilities++
433454

434-
if (!context.candidateRuleMap.has(identifier)) {
435-
context.candidateRuleMap.set(identifier, [])
455+
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
456+
context.candidateRuleMap.set(prefixedIdentifier, [])
436457
}
437458

438459
context.candidateRuleMap
439-
.get(identifier)
460+
.get(prefixedIdentifier)
440461
.push([{ sort: offset, layer: 'utilities', options }, rule])
441462
}
442463
},
443464
matchBase: function (base) {
444465
let offset = offsets.base++
445466

446467
for (let identifier in base) {
468+
let prefixedIdentifier =
469+
identifier === '*'
470+
? '*'
471+
: options.respectPrefix
472+
? context.tailwindConfig.prefix + identifier
473+
: identifier
447474
let value = [].concat(base[identifier])
448475

449476
let withOffsets = value.map((rule) => [{ sort: offset, layer: 'base' }, rule])
450477

451-
if (!context.candidateRuleMap.has(identifier)) {
452-
context.candidateRuleMap.set(identifier, [])
478+
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
479+
context.candidateRuleMap.set(prefixedIdentifier, [])
453480
}
454481

455-
context.candidateRuleMap.get(identifier).push(...withOffsets)
482+
context.candidateRuleMap.get(prefixedIdentifier).push(...withOffsets)
456483
}
457484
},
458485
matchUtilities: function (utilities, options) {
@@ -468,15 +495,22 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
468495
let offset = offsets.utilities++
469496

470497
for (let identifier in utilities) {
498+
let prefixedIdentifier =
499+
identifier === '*'
500+
? '*'
501+
: options.respectPrefix
502+
? context.tailwindConfig.prefix + identifier
503+
: identifier
504+
471505
let value = [].concat(utilities[identifier])
472506

473507
let withOffsets = value.map((rule) => [{ sort: offset, layer: 'utilities', options }, rule])
474508

475-
if (!context.candidateRuleMap.has(identifier)) {
476-
context.candidateRuleMap.set(identifier, [])
509+
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
510+
context.candidateRuleMap.set(prefixedIdentifier, [])
477511
}
478512

479-
context.candidateRuleMap.get(identifier).push(...withOffsets)
513+
context.candidateRuleMap.get(prefixedIdentifier).push(...withOffsets)
480514
}
481515
},
482516
// ---
@@ -488,21 +522,6 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
488522
insertInto(variantList, variantName, options)
489523
variantMap.set(variantName, applyVariant)
490524
},
491-
addComponents(components) {
492-
let offset = offsets.components++
493-
494-
for (let identifier in components) {
495-
let value = [].concat(components[identifier])
496-
497-
let withOffsets = value.map((rule) => [{ sort: offset, layer: 'components' }, rule])
498-
499-
if (!context.candidateRuleMap.has(identifier)) {
500-
context.candidateRuleMap.set(identifier, [])
501-
}
502-
503-
context.candidateRuleMap.get(identifier).push(...withOffsets)
504-
}
505-
},
506525
},
507526
}
508527
}
@@ -710,21 +729,21 @@ function setupContext(configOrPath) {
710729
if (layerNode.params === 'base') {
711730
for (let node of layerNode.nodes) {
712731
layerPlugins.push(function ({ addBase }) {
713-
addBase(node)
732+
addBase(node, { respectPrefix: false })
714733
})
715734
}
716735
}
717736
if (layerNode.params === 'components') {
718737
for (let node of layerNode.nodes) {
719738
layerPlugins.push(function ({ addComponents }) {
720-
addComponents(node)
739+
addComponents(node, { respectPrefix: false })
721740
})
722741
}
723742
}
724743
if (layerNode.params === 'utilities') {
725744
for (let node of layerNode.nodes) {
726745
layerPlugins.push(function ({ addUtilities }) {
727-
addUtilities(node)
746+
addUtilities(node, { respectPrefix: false })
728747
})
729748
}
730749
}

tests/04-prefix.test.css

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
* {
2+
--tw-shadow: 0 0 #0000;
3+
--tw-ring-inset: var(--tw-empty, /*!*/ /*!*/);
4+
--tw-ring-offset-width: 0px;
5+
--tw-ring-offset-color: #fff;
6+
--tw-ring-color: rgba(59, 130, 246, 0.5);
7+
--tw-ring-offset-shadow: 0 0 #0000;
8+
--tw-ring-shadow: 0 0 #0000;
9+
}
10+
.tw-container {
11+
width: 100%;
12+
}
13+
@media (min-width: 640px) {
14+
.tw-container {
15+
max-width: 640px;
16+
}
17+
}
18+
@media (min-width: 768px) {
19+
.tw-container {
20+
max-width: 768px;
21+
}
22+
}
23+
@media (min-width: 1024px) {
24+
.tw-container {
25+
max-width: 1024px;
26+
}
27+
}
28+
@media (min-width: 1280px) {
29+
.tw-container {
30+
max-width: 1280px;
31+
}
32+
}
33+
@media (min-width: 1536px) {
34+
.tw-container {
35+
max-width: 1536px;
36+
}
37+
}
38+
.tw-btn-prefix {
39+
button: yes;
40+
}
41+
.btn-no-prefix {
42+
button: yes;
43+
}
44+
.custom-component {
45+
font-weight: 700;
46+
}
47+
.tw-dark .tw-group:hover .custom-component {
48+
font-weight: 400;
49+
}
50+
.tw-font-bold {
51+
font-weight: 700;
52+
}
53+
.tw-custom-util-prefix {
54+
button: no;
55+
}
56+
.custom-util-no-prefix {
57+
button: no;
58+
}
59+
.tw-group:hover .group-hover\:focus-within\:tw-text-left:focus-within {
60+
text-align: left;
61+
}
62+
[dir='rtl'] .rtl\:active\:tw-text-center:active {
63+
text-align: center;
64+
}
65+
@media (prefers-reduced-motion: no-preference) {
66+
.motion-safe\:hover\:tw-text-center:hover {
67+
text-align: center;
68+
}
69+
}
70+
.tw-dark .dark\:focus\:tw-text-left:focus {
71+
text-align: left;
72+
}
73+
@media (min-width: 768px) {
74+
.md\:hover\:tw-text-right:hover {
75+
text-align: right;
76+
}
77+
}

tests/04-prefix.test.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<div class="tw-container"></div>
2+
<div class="btn-no-prefix"></div>
3+
<div class="tw-btn-prefix"></div>
4+
<div class="tw-custom-util-prefix"></div>
5+
<div class="custom-util-no-prefix"></div>
6+
<div class="tw-custom-component-prefix"></div>
7+
<div class="custom-component-no-prefix"></div>
8+
<div class="tw-font-bold"></div>
9+
<div class="md:hover:tw-text-right"></div>
10+
<div class="motion-safe:hover:tw-text-center"></div>
11+
<div class="dark:focus:tw-text-left"></div>
12+
<div class="group-hover:focus-within:tw-text-left"></div>
13+
<div class="rtl:active:tw-text-center"></div>

0 commit comments

Comments
 (0)