tailwindcss 3.0.0-alpha.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/colors.js +2 -1
- package/defaultConfig.js +2 -1
- package/defaultTheme.js +2 -1
- package/lib/cli.js +39 -35
- package/lib/constants.js +1 -1
- package/lib/corePluginList.js +10 -1
- package/lib/corePlugins.js +393 -259
- package/lib/css/preflight.css +14 -1
- package/lib/featureFlags.js +12 -7
- package/lib/lib/collapseDuplicateDeclarations.js +29 -0
- package/lib/lib/detectNesting.js +17 -2
- package/lib/lib/evaluateTailwindFunctions.js +9 -5
- package/lib/lib/expandApplyAtRules.js +26 -9
- package/lib/lib/expandTailwindAtRules.js +4 -1
- package/lib/lib/generateRules.js +151 -19
- package/lib/lib/resolveDefaultsAtRules.js +67 -56
- package/lib/lib/setupContextUtils.js +80 -80
- package/lib/lib/setupWatchingContext.js +5 -1
- package/lib/lib/sharedState.js +2 -2
- package/lib/lib/substituteScreenAtRules.js +7 -4
- package/lib/processTailwindFeatures.js +4 -0
- package/lib/util/buildMediaQuery.js +13 -24
- package/lib/util/createUtilityPlugin.js +5 -5
- package/lib/util/dataTypes.js +38 -7
- package/lib/util/formatVariantSelector.js +186 -0
- package/lib/util/isValidArbitraryValue.js +64 -0
- package/lib/util/nameClass.js +2 -1
- package/lib/util/negateValue.js +3 -1
- package/lib/util/normalizeConfig.js +22 -8
- package/lib/util/normalizeScreens.js +61 -0
- package/lib/util/parseBoxShadowValue.js +77 -0
- package/lib/util/pluginUtils.js +62 -158
- package/lib/util/prefixSelector.js +1 -3
- package/lib/util/resolveConfig.js +17 -13
- package/lib/util/transformThemeValue.js +23 -13
- package/package.json +15 -15
- package/peers/index.js +4456 -5450
- package/plugin.js +2 -1
- package/resolveConfig.js +2 -1
- package/src/.DS_Store +0 -0
- package/src/cli.js +9 -2
- package/src/corePluginList.js +1 -1
- package/src/corePlugins.js +392 -404
- package/src/css/preflight.css +14 -1
- package/src/featureFlags.js +14 -4
- package/src/lib/collapseDuplicateDeclarations.js +28 -0
- package/src/lib/detectNesting.js +22 -3
- package/src/lib/evaluateTailwindFunctions.js +5 -2
- package/src/lib/expandApplyAtRules.js +29 -2
- package/src/lib/expandTailwindAtRules.js +5 -2
- package/src/lib/generateRules.js +155 -11
- package/src/lib/resolveDefaultsAtRules.js +67 -50
- package/src/lib/setupContextUtils.js +77 -67
- package/src/lib/setupWatchingContext.js +7 -0
- package/src/lib/sharedState.js +1 -1
- package/src/lib/substituteScreenAtRules.js +6 -3
- package/src/processTailwindFeatures.js +5 -0
- package/src/util/buildMediaQuery.js +14 -18
- package/src/util/createUtilityPlugin.js +2 -2
- package/src/util/dataTypes.js +43 -11
- package/src/util/formatVariantSelector.js +196 -0
- package/src/util/isValidArbitraryValue.js +61 -0
- package/src/util/nameClass.js +2 -2
- package/src/util/negateValue.js +4 -2
- package/src/util/normalizeConfig.js +17 -1
- package/src/util/normalizeScreens.js +45 -0
- package/src/util/parseBoxShadowValue.js +71 -0
- package/src/util/pluginUtils.js +50 -146
- package/src/util/prefixSelector.js +1 -4
- package/src/util/resolveConfig.js +7 -1
- package/src/util/transformThemeValue.js +22 -7
- package/stubs/defaultConfig.stub.js +118 -58
- package/CHANGELOG.md +0 -1759
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
let matchingBrackets = new Map([
|
|
2
|
+
['{', '}'],
|
|
3
|
+
['[', ']'],
|
|
4
|
+
['(', ')'],
|
|
5
|
+
])
|
|
6
|
+
let inverseMatchingBrackets = new Map(
|
|
7
|
+
Array.from(matchingBrackets.entries()).map(([k, v]) => [v, k])
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
let quotes = new Set(['"', "'", '`'])
|
|
11
|
+
|
|
12
|
+
// Arbitrary values must contain balanced brackets (), [] and {}. Escaped
|
|
13
|
+
// values don't count, and brackets inside quotes also don't count.
|
|
14
|
+
//
|
|
15
|
+
// E.g.: w-[this-is]w-[weird-and-invalid]
|
|
16
|
+
// E.g.: w-[this-is\\]w-\\[weird-but-valid]
|
|
17
|
+
// E.g.: content-['this-is-also-valid]-weirdly-enough']
|
|
18
|
+
export default function isValidArbitraryValue(value) {
|
|
19
|
+
let stack = []
|
|
20
|
+
let inQuotes = false
|
|
21
|
+
|
|
22
|
+
for (let i = 0; i < value.length; i++) {
|
|
23
|
+
let char = value[i]
|
|
24
|
+
|
|
25
|
+
if (char === ':' && !inQuotes && stack.length === 0) {
|
|
26
|
+
return false
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Non-escaped quotes allow us to "allow" anything in between
|
|
30
|
+
if (quotes.has(char) && value[i - 1] !== '\\') {
|
|
31
|
+
inQuotes = !inQuotes
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (inQuotes) continue
|
|
35
|
+
if (value[i - 1] === '\\') continue // Escaped
|
|
36
|
+
|
|
37
|
+
if (matchingBrackets.has(char)) {
|
|
38
|
+
stack.push(char)
|
|
39
|
+
} else if (inverseMatchingBrackets.has(char)) {
|
|
40
|
+
let inverse = inverseMatchingBrackets.get(char)
|
|
41
|
+
|
|
42
|
+
// Nothing to pop from, therefore it is unbalanced
|
|
43
|
+
if (stack.length <= 0) {
|
|
44
|
+
return false
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Popped value must match the inverse value, otherwise it is unbalanced
|
|
48
|
+
if (stack.pop() !== inverse) {
|
|
49
|
+
return false
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// If there is still something on the stack, it is also unbalanced
|
|
55
|
+
if (stack.length > 0) {
|
|
56
|
+
return false
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// All good, totally balanced!
|
|
60
|
+
return true
|
|
61
|
+
}
|
package/src/util/nameClass.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import escapeClassName from './escapeClassName'
|
|
2
2
|
import escapeCommas from './escapeCommas'
|
|
3
3
|
|
|
4
|
-
function asClass(name) {
|
|
4
|
+
export function asClass(name) {
|
|
5
5
|
return escapeCommas(`.${escapeClassName(name)}`)
|
|
6
6
|
}
|
|
7
7
|
|
|
@@ -14,7 +14,7 @@ export function formatClass(classPrefix, key) {
|
|
|
14
14
|
return classPrefix
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
if (key === '-') {
|
|
17
|
+
if (key === '-' || key === '-DEFAULT') {
|
|
18
18
|
return `-${classPrefix}`
|
|
19
19
|
}
|
|
20
20
|
|
package/src/util/negateValue.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export default function (value) {
|
|
2
2
|
value = `${value}`
|
|
3
3
|
|
|
4
|
+
if (value === '0') {
|
|
5
|
+
return '0'
|
|
6
|
+
}
|
|
7
|
+
|
|
4
8
|
// Flip sign of numbers
|
|
5
9
|
if (/^[+-]?(\d+|\d*\.\d+)(e[+-]?\d+)?(%|\w+)?$/.test(value)) {
|
|
6
10
|
return value.replace(/^[+-]?/, (sign) => (sign === '-' ? '' : '-'))
|
|
@@ -9,6 +13,4 @@ export default function (value) {
|
|
|
9
13
|
if (value.includes('var(') || value.includes('calc(')) {
|
|
10
14
|
return `calc(${value} * -1)`
|
|
11
15
|
}
|
|
12
|
-
|
|
13
|
-
return value
|
|
14
16
|
}
|
|
@@ -140,6 +140,18 @@ export function normalizeConfig(config) {
|
|
|
140
140
|
return []
|
|
141
141
|
})()
|
|
142
142
|
|
|
143
|
+
// Normalize prefix option
|
|
144
|
+
if (typeof config.prefix === 'function') {
|
|
145
|
+
log.warn('prefix-function', [
|
|
146
|
+
'As of Tailwind CSS v3.0, `prefix` cannot be a function.',
|
|
147
|
+
'Update `prefix` in your configuration to be a string to eliminate this warning.',
|
|
148
|
+
// TODO: Add https://tw.wtf/prefix-function
|
|
149
|
+
])
|
|
150
|
+
config.prefix = ''
|
|
151
|
+
} else {
|
|
152
|
+
config.prefix = config.prefix ?? ''
|
|
153
|
+
}
|
|
154
|
+
|
|
143
155
|
// Normalize the `content`
|
|
144
156
|
config.content = {
|
|
145
157
|
files: (() => {
|
|
@@ -170,7 +182,7 @@ export function normalizeConfig(config) {
|
|
|
170
182
|
|
|
171
183
|
let extractors = {}
|
|
172
184
|
|
|
173
|
-
|
|
185
|
+
let defaultExtractor = (() => {
|
|
174
186
|
if (config.purge?.options?.defaultExtractor) {
|
|
175
187
|
return config.purge.options.defaultExtractor
|
|
176
188
|
}
|
|
@@ -182,6 +194,10 @@ export function normalizeConfig(config) {
|
|
|
182
194
|
return undefined
|
|
183
195
|
})()
|
|
184
196
|
|
|
197
|
+
if (defaultExtractor !== undefined) {
|
|
198
|
+
extractors.DEFAULT = defaultExtractor
|
|
199
|
+
}
|
|
200
|
+
|
|
185
201
|
// Functions
|
|
186
202
|
if (typeof extract === 'function') {
|
|
187
203
|
extractors.DEFAULT = extract
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A function that normalizes the various forms that the screens object can be
|
|
3
|
+
* provided in.
|
|
4
|
+
*
|
|
5
|
+
* Input(s):
|
|
6
|
+
* - ['100px', '200px'] // Raw strings
|
|
7
|
+
* - { sm: '100px', md: '200px' } // Object with string values
|
|
8
|
+
* - { sm: { min: '100px' }, md: { max: '100px' } } // Object with object values
|
|
9
|
+
* - { sm: [{ min: '100px' }, { max: '200px' }] } // Object with object array (multiple values)
|
|
10
|
+
*
|
|
11
|
+
* Output(s):
|
|
12
|
+
* - [{ name: 'sm', values: [{ min: '100px', max: '200px' }] }] // List of objects, that contains multiple values
|
|
13
|
+
*/
|
|
14
|
+
export function normalizeScreens(screens, root = true) {
|
|
15
|
+
if (Array.isArray(screens)) {
|
|
16
|
+
return screens.map((screen) => {
|
|
17
|
+
if (root && Array.isArray(screen)) {
|
|
18
|
+
throw new Error('The tuple syntax is not supported for `screens`.')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (typeof screen === 'string') {
|
|
22
|
+
return { name: screen.toString(), values: [{ min: screen, max: undefined }] }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let [name, options] = screen
|
|
26
|
+
name = name.toString()
|
|
27
|
+
|
|
28
|
+
if (typeof options === 'string') {
|
|
29
|
+
return { name, values: [{ min: options, max: undefined }] }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (Array.isArray(options)) {
|
|
33
|
+
return { name, values: options.map((option) => resolveValue(option)) }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return { name, values: [resolveValue(options)] }
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return normalizeScreens(Object.entries(screens ?? {}), false)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function resolveValue({ 'min-width': _minWidth, min = _minWidth, max, raw } = {}) {
|
|
44
|
+
return { min, max, raw }
|
|
45
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
let KEYWORDS = new Set(['inset', 'inherit', 'initial', 'revert', 'unset'])
|
|
2
|
+
let COMMA = /\,(?![^(]*\))/g // Comma separator that is not located between brackets. E.g.: `cubiz-bezier(a, b, c)` these don't count.
|
|
3
|
+
let SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead.
|
|
4
|
+
let LENGTH = /^-?(\d+)(.*?)$/g
|
|
5
|
+
|
|
6
|
+
export function parseBoxShadowValue(input) {
|
|
7
|
+
let shadows = input.split(COMMA)
|
|
8
|
+
return shadows.map((shadow) => {
|
|
9
|
+
let value = shadow.trim()
|
|
10
|
+
let result = { raw: value }
|
|
11
|
+
let parts = value.split(SPACE)
|
|
12
|
+
let seen = new Set()
|
|
13
|
+
|
|
14
|
+
for (let part of parts) {
|
|
15
|
+
// Reset index, since the regex is stateful.
|
|
16
|
+
LENGTH.lastIndex = 0
|
|
17
|
+
|
|
18
|
+
// Keyword
|
|
19
|
+
if (!seen.has('KEYWORD') && KEYWORDS.has(part)) {
|
|
20
|
+
result.keyword = part
|
|
21
|
+
seen.add('KEYWORD')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Length value
|
|
25
|
+
else if (LENGTH.test(part)) {
|
|
26
|
+
if (!seen.has('X')) {
|
|
27
|
+
result.x = part
|
|
28
|
+
seen.add('X')
|
|
29
|
+
} else if (!seen.has('Y')) {
|
|
30
|
+
result.y = part
|
|
31
|
+
seen.add('Y')
|
|
32
|
+
} else if (!seen.has('BLUR')) {
|
|
33
|
+
result.blur = part
|
|
34
|
+
seen.add('BLUR')
|
|
35
|
+
} else if (!seen.has('SPREAD')) {
|
|
36
|
+
result.spread = part
|
|
37
|
+
seen.add('SPREAD')
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Color or unknown
|
|
42
|
+
else {
|
|
43
|
+
if (!result.color) {
|
|
44
|
+
result.color = part
|
|
45
|
+
} else {
|
|
46
|
+
if (!result.unknown) result.unknown = []
|
|
47
|
+
result.unknown.push(part)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Check if valid
|
|
53
|
+
result.valid = result.x !== undefined && result.y !== undefined
|
|
54
|
+
|
|
55
|
+
return result
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function formatBoxShadowValue(shadows) {
|
|
60
|
+
return shadows
|
|
61
|
+
.map((shadow) => {
|
|
62
|
+
if (!shadow.valid) {
|
|
63
|
+
return shadow.raw
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return [shadow.keyword, shadow.x, shadow.y, shadow.blur, shadow.spread, shadow.color]
|
|
67
|
+
.filter(Boolean)
|
|
68
|
+
.join(' ')
|
|
69
|
+
})
|
|
70
|
+
.join(', ')
|
|
71
|
+
}
|
package/src/util/pluginUtils.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import selectorParser from 'postcss-selector-parser'
|
|
2
2
|
import escapeCommas from './escapeCommas'
|
|
3
3
|
import { withAlphaValue } from './withAlphaVariable'
|
|
4
|
-
import isKeyframeRule from './isKeyframeRule'
|
|
5
4
|
import {
|
|
6
5
|
normalize,
|
|
7
6
|
length,
|
|
@@ -16,36 +15,14 @@ import {
|
|
|
16
15
|
relativeSize,
|
|
17
16
|
position,
|
|
18
17
|
lineWidth,
|
|
18
|
+
shadow,
|
|
19
19
|
} from './dataTypes'
|
|
20
|
-
|
|
21
|
-
export function applyStateToMarker(selector, marker, state, join) {
|
|
22
|
-
let markerIdx = selector.search(new RegExp(`${marker}[:[]`))
|
|
23
|
-
|
|
24
|
-
if (markerIdx === -1) {
|
|
25
|
-
return join(marker + state, selector)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
let markerSelector = selector.slice(markerIdx, selector.indexOf(' ', markerIdx))
|
|
29
|
-
|
|
30
|
-
return join(
|
|
31
|
-
marker + state + markerSelector.slice(markerIdx + marker.length),
|
|
32
|
-
selector.replace(markerSelector, '')
|
|
33
|
-
)
|
|
34
|
-
}
|
|
20
|
+
import negateValue from './negateValue'
|
|
35
21
|
|
|
36
22
|
export function updateAllClasses(selectors, updateClass) {
|
|
37
23
|
let parser = selectorParser((selectors) => {
|
|
38
24
|
selectors.walkClasses((sel) => {
|
|
39
|
-
let updatedClass = updateClass(sel.value
|
|
40
|
-
withAttr(className, attr) {
|
|
41
|
-
sel.parent.insertAfter(sel, selectorParser.attribute({ attribute: attr.slice(1, -1) }))
|
|
42
|
-
return className
|
|
43
|
-
},
|
|
44
|
-
withPseudo(className, pseudo) {
|
|
45
|
-
sel.parent.insertAfter(sel, selectorParser.pseudo({ value: pseudo }))
|
|
46
|
-
return className
|
|
47
|
-
},
|
|
48
|
-
})
|
|
25
|
+
let updatedClass = updateClass(sel.value)
|
|
49
26
|
sel.value = updatedClass
|
|
50
27
|
if (sel.raws && sel.raws.value) {
|
|
51
28
|
sel.raws.value = escapeCommas(sel.raws.value)
|
|
@@ -58,133 +35,50 @@ export function updateAllClasses(selectors, updateClass) {
|
|
|
58
35
|
return result
|
|
59
36
|
}
|
|
60
37
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
let lastClass = sel.filter(({ type }) => type === 'class').pop()
|
|
65
|
-
|
|
66
|
-
if (lastClass === undefined) {
|
|
67
|
-
return
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
let updatedClass = updateClass(lastClass.value, {
|
|
71
|
-
withPseudo(className, pseudo) {
|
|
72
|
-
lastClass.parent.insertAfter(lastClass, selectorParser.pseudo({ value: `${pseudo}` }))
|
|
73
|
-
return className
|
|
74
|
-
},
|
|
75
|
-
})
|
|
76
|
-
lastClass.value = updatedClass
|
|
77
|
-
if (lastClass.raws && lastClass.raws.value) {
|
|
78
|
-
lastClass.raws.value = escapeCommas(lastClass.raws.value)
|
|
79
|
-
}
|
|
80
|
-
})
|
|
81
|
-
})
|
|
82
|
-
let result = parser.processSync(selectors)
|
|
83
|
-
|
|
84
|
-
return result
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function splitByNotEscapedCommas(str) {
|
|
88
|
-
let chunks = []
|
|
89
|
-
let currentChunk = ''
|
|
90
|
-
for (let i = 0; i < str.length; i++) {
|
|
91
|
-
if (str[i] === ',' && str[i - 1] !== '\\') {
|
|
92
|
-
chunks.push(currentChunk)
|
|
93
|
-
currentChunk = ''
|
|
94
|
-
} else {
|
|
95
|
-
currentChunk += str[i]
|
|
96
|
-
}
|
|
38
|
+
function resolveArbitraryValue(modifier, validate) {
|
|
39
|
+
if (!isArbitraryValue(modifier)) {
|
|
40
|
+
return undefined
|
|
97
41
|
}
|
|
98
|
-
chunks.push(currentChunk)
|
|
99
|
-
return chunks
|
|
100
|
-
}
|
|
101
42
|
|
|
102
|
-
|
|
103
|
-
return ({ container }) => {
|
|
104
|
-
container.walkRules((rule) => {
|
|
105
|
-
if (isKeyframeRule(rule)) {
|
|
106
|
-
return rule
|
|
107
|
-
}
|
|
108
|
-
let transformed = splitByNotEscapedCommas(rule.selector).map(transformSelector).join(',')
|
|
109
|
-
rule.selector = transformed
|
|
110
|
-
if (withRule) {
|
|
111
|
-
withRule(rule)
|
|
112
|
-
}
|
|
113
|
-
return rule
|
|
114
|
-
})
|
|
43
|
+
let value = modifier.slice(1, -1)
|
|
115
44
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
let nodes = container.nodes
|
|
119
|
-
container.removeAll()
|
|
120
|
-
wrapper.append(nodes)
|
|
121
|
-
container.append(wrapper)
|
|
122
|
-
}
|
|
45
|
+
if (!validate(value)) {
|
|
46
|
+
return undefined
|
|
123
47
|
}
|
|
48
|
+
|
|
49
|
+
return normalize(value)
|
|
124
50
|
}
|
|
125
51
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
container.walkRules((rule) => {
|
|
129
|
-
let selector = rule.selector
|
|
130
|
-
let variantSelector = updateAllClasses(selector, transformClass)
|
|
131
|
-
rule.selector = variantSelector
|
|
132
|
-
if (withRule) {
|
|
133
|
-
withRule(rule)
|
|
134
|
-
}
|
|
135
|
-
return rule
|
|
136
|
-
})
|
|
52
|
+
function asNegativeValue(modifier, lookup = {}, validate) {
|
|
53
|
+
let positiveValue = lookup[modifier]
|
|
137
54
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
let nodes = container.nodes
|
|
141
|
-
container.removeAll()
|
|
142
|
-
wrapper.append(nodes)
|
|
143
|
-
container.append(wrapper)
|
|
144
|
-
}
|
|
55
|
+
if (positiveValue !== undefined) {
|
|
56
|
+
return negateValue(positiveValue)
|
|
145
57
|
}
|
|
146
|
-
}
|
|
147
58
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
container.walkRules((rule) => {
|
|
151
|
-
let selector = rule.selector
|
|
152
|
-
let variantSelector = updateLastClasses(selector, transformClass)
|
|
153
|
-
rule.selector = variantSelector
|
|
154
|
-
if (withRule) {
|
|
155
|
-
withRule(rule)
|
|
156
|
-
}
|
|
157
|
-
return rule
|
|
158
|
-
})
|
|
59
|
+
if (isArbitraryValue(modifier)) {
|
|
60
|
+
let resolved = resolveArbitraryValue(modifier, validate)
|
|
159
61
|
|
|
160
|
-
if (
|
|
161
|
-
|
|
162
|
-
let nodes = container.nodes
|
|
163
|
-
container.removeAll()
|
|
164
|
-
wrapper.append(nodes)
|
|
165
|
-
container.append(wrapper)
|
|
62
|
+
if (resolved === undefined) {
|
|
63
|
+
return undefined
|
|
166
64
|
}
|
|
65
|
+
|
|
66
|
+
return negateValue(resolved)
|
|
167
67
|
}
|
|
168
68
|
}
|
|
169
69
|
|
|
170
|
-
export function asValue(modifier,
|
|
171
|
-
let value =
|
|
70
|
+
export function asValue(modifier, options = {}, { validate = () => true } = {}) {
|
|
71
|
+
let value = options.values?.[modifier]
|
|
172
72
|
|
|
173
73
|
if (value !== undefined) {
|
|
174
74
|
return value
|
|
175
75
|
}
|
|
176
76
|
|
|
177
|
-
if (
|
|
178
|
-
return
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
value = modifier.slice(1, -1)
|
|
182
|
-
|
|
183
|
-
if (!validate(value)) {
|
|
184
|
-
return undefined
|
|
77
|
+
if (options.supportsNegativeValues && modifier.startsWith('-')) {
|
|
78
|
+
return asNegativeValue(modifier.slice(1), options.values, validate)
|
|
185
79
|
}
|
|
186
80
|
|
|
187
|
-
return
|
|
81
|
+
return resolveArbitraryValue(modifier, validate)
|
|
188
82
|
}
|
|
189
83
|
|
|
190
84
|
function isArbitraryValue(input) {
|
|
@@ -201,16 +95,16 @@ function splitAlpha(modifier) {
|
|
|
201
95
|
return [modifier.slice(0, slashIdx), modifier.slice(slashIdx + 1)]
|
|
202
96
|
}
|
|
203
97
|
|
|
204
|
-
export function asColor(modifier,
|
|
205
|
-
if (
|
|
206
|
-
return
|
|
98
|
+
export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) {
|
|
99
|
+
if (options.values?.[modifier] !== undefined) {
|
|
100
|
+
return options.values?.[modifier]
|
|
207
101
|
}
|
|
208
102
|
|
|
209
103
|
let [color, alpha] = splitAlpha(modifier)
|
|
210
104
|
|
|
211
105
|
if (alpha !== undefined) {
|
|
212
106
|
let normalizedColor =
|
|
213
|
-
|
|
107
|
+
options.values?.[color] ?? (isArbitraryValue(color) ? color.slice(1, -1) : undefined)
|
|
214
108
|
|
|
215
109
|
if (normalizedColor === undefined) {
|
|
216
110
|
return undefined
|
|
@@ -227,16 +121,16 @@ export function asColor(modifier, lookup = {}, tailwindConfig = {}) {
|
|
|
227
121
|
return withAlphaValue(normalizedColor, tailwindConfig.theme.opacity[alpha])
|
|
228
122
|
}
|
|
229
123
|
|
|
230
|
-
return asValue(modifier,
|
|
124
|
+
return asValue(modifier, options, { validate: validateColor })
|
|
231
125
|
}
|
|
232
126
|
|
|
233
|
-
export function asLookupValue(modifier,
|
|
234
|
-
return
|
|
127
|
+
export function asLookupValue(modifier, options = {}) {
|
|
128
|
+
return options.values?.[modifier]
|
|
235
129
|
}
|
|
236
130
|
|
|
237
131
|
function guess(validate) {
|
|
238
|
-
return (modifier,
|
|
239
|
-
return asValue(modifier,
|
|
132
|
+
return (modifier, options) => {
|
|
133
|
+
return asValue(modifier, options, { validate })
|
|
240
134
|
}
|
|
241
135
|
}
|
|
242
136
|
|
|
@@ -255,6 +149,7 @@ let typeMap = {
|
|
|
255
149
|
'line-width': guess(lineWidth),
|
|
256
150
|
'absolute-size': guess(absoluteSize),
|
|
257
151
|
'relative-size': guess(relativeSize),
|
|
152
|
+
shadow: guess(shadow),
|
|
258
153
|
}
|
|
259
154
|
|
|
260
155
|
let supportedTypes = Object.keys(typeMap)
|
|
@@ -265,22 +160,31 @@ function splitAtFirst(input, delim) {
|
|
|
265
160
|
return [input.slice(0, idx), input.slice(idx + 1)]
|
|
266
161
|
}
|
|
267
162
|
|
|
268
|
-
export function coerceValue(types, modifier,
|
|
163
|
+
export function coerceValue(types, modifier, options, tailwindConfig) {
|
|
269
164
|
if (isArbitraryValue(modifier)) {
|
|
270
|
-
let
|
|
165
|
+
let arbitraryValue = modifier.slice(1, -1)
|
|
166
|
+
let [explicitType, value] = splitAtFirst(arbitraryValue, ':')
|
|
167
|
+
|
|
168
|
+
// It could be that this resolves to `url(https` which is not a valid
|
|
169
|
+
// identifier. We currently only support "simple" words with dashes or
|
|
170
|
+
// underscores. E.g.: family-name
|
|
171
|
+
if (!/^[\w-_]+$/g.test(explicitType)) {
|
|
172
|
+
value = arbitraryValue
|
|
173
|
+
}
|
|
271
174
|
|
|
272
|
-
|
|
175
|
+
//
|
|
176
|
+
else if (explicitType !== undefined && !supportedTypes.includes(explicitType)) {
|
|
273
177
|
return []
|
|
274
178
|
}
|
|
275
179
|
|
|
276
180
|
if (value.length > 0 && supportedTypes.includes(explicitType)) {
|
|
277
|
-
return [asValue(`[${value}]`,
|
|
181
|
+
return [asValue(`[${value}]`, options), explicitType]
|
|
278
182
|
}
|
|
279
183
|
}
|
|
280
184
|
|
|
281
185
|
// Find first matching type
|
|
282
186
|
for (let type of [].concat(types)) {
|
|
283
|
-
let result = typeMap[type](modifier,
|
|
187
|
+
let result = typeMap[type](modifier, options, { tailwindConfig })
|
|
284
188
|
if (result) return [result, type]
|
|
285
189
|
}
|
|
286
190
|
|
|
@@ -2,13 +2,10 @@ import parser from 'postcss-selector-parser'
|
|
|
2
2
|
import { tap } from './tap'
|
|
3
3
|
|
|
4
4
|
export default function (prefix, selector) {
|
|
5
|
-
const getPrefix =
|
|
6
|
-
typeof prefix === 'function' ? prefix : () => (prefix === undefined ? '' : prefix)
|
|
7
|
-
|
|
8
5
|
return parser((selectors) => {
|
|
9
6
|
selectors.walkClasses((classSelector) => {
|
|
10
7
|
tap(classSelector.value, (baseClass) => {
|
|
11
|
-
classSelector.value = `${
|
|
8
|
+
classSelector.value = `${prefix}${baseClass}`
|
|
12
9
|
})
|
|
13
10
|
})
|
|
14
11
|
}).processSync(selector)
|
|
@@ -40,10 +40,16 @@ function mergeWith(target, ...sources) {
|
|
|
40
40
|
const configUtils = {
|
|
41
41
|
colors,
|
|
42
42
|
negative(scale) {
|
|
43
|
+
// TODO: Log that this function isn't really needed anymore?
|
|
43
44
|
return Object.keys(scale)
|
|
44
45
|
.filter((key) => scale[key] !== '0')
|
|
45
46
|
.reduce((negativeScale, key) => {
|
|
46
|
-
|
|
47
|
+
let negativeValue = negateValue(scale[key])
|
|
48
|
+
|
|
49
|
+
if (negativeValue !== undefined) {
|
|
50
|
+
negativeScale[`-${key}`] = negativeValue
|
|
51
|
+
}
|
|
52
|
+
|
|
47
53
|
return negativeScale
|
|
48
54
|
}, {})
|
|
49
55
|
},
|
|
@@ -2,7 +2,12 @@ import postcss from 'postcss'
|
|
|
2
2
|
|
|
3
3
|
export default function transformThemeValue(themeSection) {
|
|
4
4
|
if (['fontSize', 'outline'].includes(themeSection)) {
|
|
5
|
-
return (value) =>
|
|
5
|
+
return (value) => {
|
|
6
|
+
if (typeof value === 'function') value = value({})
|
|
7
|
+
if (Array.isArray(value)) value = value[0]
|
|
8
|
+
|
|
9
|
+
return value
|
|
10
|
+
}
|
|
6
11
|
}
|
|
7
12
|
|
|
8
13
|
if (
|
|
@@ -20,18 +25,28 @@ export default function transformThemeValue(themeSection) {
|
|
|
20
25
|
'animation',
|
|
21
26
|
].includes(themeSection)
|
|
22
27
|
) {
|
|
23
|
-
return (value) =>
|
|
28
|
+
return (value) => {
|
|
29
|
+
if (typeof value === 'function') value = value({})
|
|
30
|
+
if (Array.isArray(value)) value = value.join(', ')
|
|
31
|
+
|
|
32
|
+
return value
|
|
33
|
+
}
|
|
24
34
|
}
|
|
25
35
|
|
|
26
36
|
// For backwards compatibility reasons, before we switched to underscores
|
|
27
37
|
// instead of commas for arbitrary values.
|
|
28
38
|
if (['gridTemplateColumns', 'gridTemplateRows', 'objectPosition'].includes(themeSection)) {
|
|
29
|
-
return (value) =>
|
|
30
|
-
|
|
39
|
+
return (value) => {
|
|
40
|
+
if (typeof value === 'function') value = value({})
|
|
41
|
+
if (typeof value === 'string') value = postcss.list.comma(value).join(' ')
|
|
31
42
|
|
|
32
|
-
|
|
33
|
-
|
|
43
|
+
return value
|
|
44
|
+
}
|
|
34
45
|
}
|
|
35
46
|
|
|
36
|
-
return (value) =>
|
|
47
|
+
return (value) => {
|
|
48
|
+
if (typeof value === 'function') value = value({})
|
|
49
|
+
|
|
50
|
+
return value
|
|
51
|
+
}
|
|
37
52
|
}
|