tailwindcss 3.3.2 → 3.3.4
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/CHANGELOG.md +50 -1
- package/lib/cli/build/plugin.js +2 -2
- package/lib/cli/build/watching.js +1 -1
- package/lib/corePlugins.js +11 -7
- package/lib/css/preflight.css +9 -0
- package/lib/lib/defaultExtractor.js +16 -22
- package/lib/lib/evaluateTailwindFunctions.js +5 -3
- package/lib/lib/expandApplyAtRules.js +6 -0
- package/lib/lib/expandTailwindAtRules.js +20 -6
- package/lib/lib/generateRules.js +34 -24
- package/lib/lib/setupContextUtils.js +53 -33
- package/lib/lib/setupTrackingContext.js +2 -1
- package/lib/oxide/cli/build/plugin.js +2 -2
- package/lib/plugin.js +3 -3
- package/lib/processTailwindFeatures.js +2 -2
- package/lib/util/color.js +1 -1
- package/lib/util/dataTypes.js +100 -16
- package/lib/util/formatVariantSelector.js +10 -3
- package/lib/util/isPlainObject.js +1 -1
- package/lib/util/prefixSelector.js +1 -1
- package/lib/util/pseudoElements.js +18 -34
- package/lib/value-parser/LICENSE +22 -0
- package/lib/value-parser/README.md +3 -0
- package/lib/value-parser/index.d.js +2 -0
- package/lib/value-parser/index.js +22 -0
- package/lib/value-parser/parse.js +259 -0
- package/lib/value-parser/stringify.js +38 -0
- package/lib/value-parser/unit.js +86 -0
- package/lib/value-parser/walk.js +16 -0
- package/nesting/index.d.ts +4 -0
- package/package.json +5 -6
- package/peers/index.js +701 -617
- package/src/cli/build/plugin.js +2 -2
- package/src/cli/build/watching.js +1 -1
- package/src/corePlugins.js +13 -7
- package/src/css/preflight.css +9 -0
- package/src/featureFlags.js +0 -1
- package/src/lib/defaultExtractor.js +12 -13
- package/src/lib/evaluateTailwindFunctions.js +4 -1
- package/src/lib/expandApplyAtRules.js +7 -0
- package/src/lib/expandTailwindAtRules.js +20 -6
- package/src/lib/generateRules.js +34 -25
- package/src/lib/setupContextUtils.js +50 -35
- package/src/lib/setupTrackingContext.js +1 -3
- package/src/oxide/cli/build/plugin.ts +2 -2
- package/src/plugin.js +3 -3
- package/src/processTailwindFeatures.js +3 -2
- package/src/util/color.js +1 -1
- package/src/util/dataTypes.js +101 -18
- package/src/util/formatVariantSelector.js +11 -3
- package/src/util/isPlainObject.js +1 -1
- package/src/util/prefixSelector.js +1 -0
- package/src/util/pseudoElements.js +14 -17
- package/src/value-parser/LICENSE +22 -0
- package/src/value-parser/README.md +3 -0
- package/src/value-parser/index.d.ts +177 -0
- package/src/value-parser/index.js +28 -0
- package/src/value-parser/parse.js +303 -0
- package/src/value-parser/stringify.js +41 -0
- package/src/value-parser/unit.js +118 -0
- package/src/value-parser/walk.js +18 -0
- package/stubs/config.full.js +1 -0
- package/types/config.d.ts +6 -6
- package/types/generated/default-theme.d.ts +1 -0
- package/types/index.d.ts +7 -3
package/src/util/dataTypes.js
CHANGED
|
@@ -10,13 +10,34 @@ function isCSSFunction(value) {
|
|
|
10
10
|
return cssFunctions.some((fn) => new RegExp(`^${fn}\\(.*\\)`).test(value))
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
// These properties accept a `<dashed-ident>` as one of the values. This means that you can use them
|
|
14
|
+
// as: `timeline-scope: --tl;`
|
|
15
|
+
//
|
|
16
|
+
// Without the `var(--tl)`, in these cases we don't want to normalize the value, and you should add
|
|
17
|
+
// the `var()` yourself.
|
|
18
|
+
//
|
|
19
|
+
// More info:
|
|
20
|
+
// - https://drafts.csswg.org/scroll-animations/#propdef-timeline-scope
|
|
21
|
+
// - https://developer.mozilla.org/en-US/docs/Web/CSS/timeline-scope#dashed-ident
|
|
22
|
+
//
|
|
23
|
+
const AUTO_VAR_INJECTION_EXCEPTIONS = new Set([
|
|
24
|
+
// Concrete properties
|
|
25
|
+
'scroll-timeline-name',
|
|
26
|
+
'timeline-scope',
|
|
27
|
+
'view-timeline-name',
|
|
28
|
+
'font-palette',
|
|
29
|
+
|
|
30
|
+
// Shorthand properties
|
|
31
|
+
'scroll-timeline',
|
|
32
|
+
'animation-timeline',
|
|
33
|
+
'view-timeline',
|
|
34
|
+
])
|
|
15
35
|
|
|
16
36
|
// This is not a data type, but rather a function that can normalize the
|
|
17
37
|
// correct values.
|
|
18
|
-
export function normalize(value, isRoot = true) {
|
|
19
|
-
|
|
38
|
+
export function normalize(value, context = null, isRoot = true) {
|
|
39
|
+
let isVarException = context && AUTO_VAR_INJECTION_EXCEPTIONS.has(context.property)
|
|
40
|
+
if (value.startsWith('--') && !isVarException) {
|
|
20
41
|
return `var(${value})`
|
|
21
42
|
}
|
|
22
43
|
|
|
@@ -30,7 +51,7 @@ export function normalize(value, isRoot = true) {
|
|
|
30
51
|
return part
|
|
31
52
|
}
|
|
32
53
|
|
|
33
|
-
return normalize(part, false)
|
|
54
|
+
return normalize(part, context, false)
|
|
34
55
|
})
|
|
35
56
|
.join('')
|
|
36
57
|
}
|
|
@@ -49,22 +70,83 @@ export function normalize(value, isRoot = true) {
|
|
|
49
70
|
value = value.trim()
|
|
50
71
|
}
|
|
51
72
|
|
|
52
|
-
|
|
53
|
-
// or '('.
|
|
54
|
-
value = value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
|
|
55
|
-
let vars = []
|
|
56
|
-
return match
|
|
57
|
-
.replace(/var\((--.+?)[,)]/g, (match, g1) => {
|
|
58
|
-
vars.push(g1)
|
|
59
|
-
return match.replace(g1, placeholder)
|
|
60
|
-
})
|
|
61
|
-
.replace(/(-?\d*\.?\d(?!\b-\d.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, '$1 $2 ')
|
|
62
|
-
.replace(placeholderRe, () => vars.shift())
|
|
63
|
-
})
|
|
73
|
+
value = normalizeMathOperatorSpacing(value)
|
|
64
74
|
|
|
65
75
|
return value
|
|
66
76
|
}
|
|
67
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Add spaces around operators inside math functions
|
|
80
|
+
* like calc() that do not follow an operator or '('.
|
|
81
|
+
*
|
|
82
|
+
* @param {string} value
|
|
83
|
+
* @returns {string}
|
|
84
|
+
*/
|
|
85
|
+
function normalizeMathOperatorSpacing(value) {
|
|
86
|
+
let preventFormattingInFunctions = ['theme']
|
|
87
|
+
|
|
88
|
+
return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
|
|
89
|
+
let result = ''
|
|
90
|
+
|
|
91
|
+
function lastChar() {
|
|
92
|
+
let char = result.trimEnd()
|
|
93
|
+
return char[char.length - 1]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
for (let i = 0; i < match.length; i++) {
|
|
97
|
+
function peek(word) {
|
|
98
|
+
return word.split('').every((char, j) => match[i + j] === char)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function consumeUntil(chars) {
|
|
102
|
+
let minIndex = Infinity
|
|
103
|
+
for (let char of chars) {
|
|
104
|
+
let index = match.indexOf(char, i)
|
|
105
|
+
if (index !== -1 && index < minIndex) {
|
|
106
|
+
minIndex = index
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let result = match.slice(i, minIndex)
|
|
111
|
+
i += result.length - 1
|
|
112
|
+
return result
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let char = match[i]
|
|
116
|
+
|
|
117
|
+
// Handle `var(--variable)`
|
|
118
|
+
if (peek('var')) {
|
|
119
|
+
// When we consume until `)`, then we are dealing with this scenario:
|
|
120
|
+
// `var(--example)`
|
|
121
|
+
//
|
|
122
|
+
// When we consume until `,`, then we are dealing with this scenario:
|
|
123
|
+
// `var(--example, 1rem)`
|
|
124
|
+
//
|
|
125
|
+
// In this case we do want to "format", the default value as well
|
|
126
|
+
result += consumeUntil([')', ','])
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Skip formatting inside known functions
|
|
130
|
+
else if (preventFormattingInFunctions.some((fn) => peek(fn))) {
|
|
131
|
+
result += consumeUntil([')'])
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Handle operators
|
|
135
|
+
else if (
|
|
136
|
+
['+', '-', '*', '/'].includes(char) &&
|
|
137
|
+
!['(', '+', '-', '*', '/'].includes(lastChar())
|
|
138
|
+
) {
|
|
139
|
+
result += ` ${char} `
|
|
140
|
+
} else {
|
|
141
|
+
result += char
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Simplify multiple spaces
|
|
146
|
+
return result.replace(/\s+/g, ' ')
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
|
|
68
150
|
export function url(value) {
|
|
69
151
|
return value.startsWith('url(')
|
|
70
152
|
}
|
|
@@ -178,11 +260,12 @@ export function image(value) {
|
|
|
178
260
|
}
|
|
179
261
|
|
|
180
262
|
let gradientTypes = new Set([
|
|
263
|
+
'conic-gradient',
|
|
181
264
|
'linear-gradient',
|
|
182
265
|
'radial-gradient',
|
|
266
|
+
'repeating-conic-gradient',
|
|
183
267
|
'repeating-linear-gradient',
|
|
184
268
|
'repeating-radial-gradient',
|
|
185
|
-
'conic-gradient',
|
|
186
269
|
])
|
|
187
270
|
export function gradient(value) {
|
|
188
271
|
value = normalize(value)
|
|
@@ -3,13 +3,14 @@ import unescape from 'postcss-selector-parser/dist/util/unesc'
|
|
|
3
3
|
import escapeClassName from '../util/escapeClassName'
|
|
4
4
|
import prefixSelector from '../util/prefixSelector'
|
|
5
5
|
import { movePseudos } from './pseudoElements'
|
|
6
|
+
import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'
|
|
6
7
|
|
|
7
8
|
/** @typedef {import('postcss-selector-parser').Root} Root */
|
|
8
9
|
/** @typedef {import('postcss-selector-parser').Selector} Selector */
|
|
9
10
|
/** @typedef {import('postcss-selector-parser').Pseudo} Pseudo */
|
|
10
11
|
/** @typedef {import('postcss-selector-parser').Node} Node */
|
|
11
12
|
|
|
12
|
-
/** @typedef {{format: string,
|
|
13
|
+
/** @typedef {{format: string, respectPrefix: boolean}[]} RawFormats */
|
|
13
14
|
/** @typedef {import('postcss-selector-parser').Root} ParsedFormats */
|
|
14
15
|
/** @typedef {RawFormats | ParsedFormats} AcceptedFormats */
|
|
15
16
|
|
|
@@ -29,7 +30,7 @@ export function formatVariantSelector(formats, { context, candidate }) {
|
|
|
29
30
|
|
|
30
31
|
return {
|
|
31
32
|
...format,
|
|
32
|
-
ast: format.
|
|
33
|
+
ast: format.respectPrefix ? prefixSelector(prefix, ast) : ast,
|
|
33
34
|
}
|
|
34
35
|
})
|
|
35
36
|
|
|
@@ -160,7 +161,7 @@ export function finalizeSelector(current, formats, { context, candidate, base })
|
|
|
160
161
|
// │ │ │ ╰── We will not split here
|
|
161
162
|
// ╰──┴─────┴─────────────── We will split here
|
|
162
163
|
//
|
|
163
|
-
base = base ?? candidate
|
|
164
|
+
base = base ?? splitAtTopLevelOnly(candidate, separator).pop()
|
|
164
165
|
|
|
165
166
|
// Parse the selector into an AST
|
|
166
167
|
let selector = selectorParser().astSync(current)
|
|
@@ -185,6 +186,13 @@ export function finalizeSelector(current, formats, { context, candidate, base })
|
|
|
185
186
|
// Remove extraneous selectors that do not include the base candidate
|
|
186
187
|
selector.each((sel) => eliminateIrrelevantSelectors(sel, base))
|
|
187
188
|
|
|
189
|
+
// If ffter eliminating irrelevant selectors, we end up with nothing
|
|
190
|
+
// Then the whole "rule" this is associated with does not need to exist
|
|
191
|
+
// We use `null` as a marker value for that case
|
|
192
|
+
if (selector.length === 0) {
|
|
193
|
+
return null
|
|
194
|
+
}
|
|
195
|
+
|
|
188
196
|
// If there are no formats that means there were no variants added to the candidate
|
|
189
197
|
// so we can just return the selector as-is
|
|
190
198
|
let formatAst = Array.isArray(formats)
|
|
@@ -17,6 +17,7 @@ export default function (prefix, selector, prependNegative = false) {
|
|
|
17
17
|
return selector
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/** @type {import('postcss-selector-parser').Root} */
|
|
20
21
|
let ast = typeof selector === 'string' ? parser().astSync(selector) : selector
|
|
21
22
|
|
|
22
23
|
ast.walkClasses((classSelector) => {
|
|
@@ -19,40 +19,37 @@
|
|
|
19
19
|
// **Jumpable**
|
|
20
20
|
// Any terminal element may "jump" over combinators when moving to the end of the selector
|
|
21
21
|
//
|
|
22
|
-
// This is a backwards-compat quirk of
|
|
22
|
+
// This is a backwards-compat quirk of pseudo element variants from earlier versions of Tailwind CSS.
|
|
23
23
|
|
|
24
24
|
/** @typedef {'terminal' | 'actionable' | 'jumpable'} PseudoProperty */
|
|
25
25
|
|
|
26
26
|
/** @type {Record<string, PseudoProperty[]>} */
|
|
27
27
|
let elementProperties = {
|
|
28
|
+
// Pseudo elements from the spec
|
|
28
29
|
'::after': ['terminal', 'jumpable'],
|
|
29
|
-
'::backdrop': ['terminal'],
|
|
30
|
+
'::backdrop': ['terminal', 'jumpable'],
|
|
30
31
|
'::before': ['terminal', 'jumpable'],
|
|
31
32
|
'::cue': ['terminal'],
|
|
32
33
|
'::cue-region': ['terminal'],
|
|
33
34
|
'::first-letter': ['terminal', 'jumpable'],
|
|
34
35
|
'::first-line': ['terminal', 'jumpable'],
|
|
35
36
|
'::grammar-error': ['terminal'],
|
|
36
|
-
'::marker': ['terminal'],
|
|
37
|
+
'::marker': ['terminal', 'jumpable'],
|
|
37
38
|
'::part': ['terminal', 'actionable'],
|
|
38
|
-
'::placeholder': ['terminal'],
|
|
39
|
-
'::selection': ['terminal'],
|
|
39
|
+
'::placeholder': ['terminal', 'jumpable'],
|
|
40
|
+
'::selection': ['terminal', 'jumpable'],
|
|
40
41
|
'::slotted': ['terminal'],
|
|
41
42
|
'::spelling-error': ['terminal'],
|
|
42
43
|
'::target-text': ['terminal'],
|
|
43
44
|
|
|
44
|
-
//
|
|
45
|
+
// Pseudo elements from the spec with special rules
|
|
45
46
|
'::file-selector-button': ['terminal', 'actionable'],
|
|
46
|
-
'::-webkit-progress-bar': ['terminal', 'actionable'],
|
|
47
47
|
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
'
|
|
51
|
-
'
|
|
52
|
-
'
|
|
53
|
-
'::-webkit-scrollbar-track-piece': ['terminal', 'actionable'],
|
|
54
|
-
'::-webkit-scrollbar-corner': ['terminal', 'actionable'],
|
|
55
|
-
'::-webkit-resizer': ['terminal', 'actionable'],
|
|
48
|
+
// Library-specific pseudo elements used by component libraries
|
|
49
|
+
// These are Shadow DOM-like
|
|
50
|
+
'::deep': ['actionable'],
|
|
51
|
+
'::v-deep': ['actionable'],
|
|
52
|
+
'::ng-deep': ['actionable'],
|
|
56
53
|
|
|
57
54
|
// Note: As a rule, double colons (::) should be used instead of a single colon
|
|
58
55
|
// (:). This distinguishes pseudo-classes from pseudo-elements. However, since
|
|
@@ -65,8 +62,8 @@ let elementProperties = {
|
|
|
65
62
|
|
|
66
63
|
// The default value is used when the pseudo-element is not recognized
|
|
67
64
|
// Because it's not recognized, we don't know if it's terminal or not
|
|
68
|
-
// So we assume it can
|
|
69
|
-
__default__: ['actionable'],
|
|
65
|
+
// So we assume it can be moved AND can have user-action pseudo classes attached to it
|
|
66
|
+
__default__: ['terminal', 'actionable'],
|
|
70
67
|
}
|
|
71
68
|
|
|
72
69
|
/**
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) Bogdan Chadkin <trysound@yandex.ru>
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
|
4
|
+
obtaining a copy of this software and associated documentation
|
|
5
|
+
files (the "Software"), to deal in the Software without
|
|
6
|
+
restriction, including without limitation the rights to use,
|
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the
|
|
9
|
+
Software is furnished to do so, subject to the following
|
|
10
|
+
conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be
|
|
13
|
+
included in all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
declare namespace postcssValueParser {
|
|
2
|
+
interface BaseNode {
|
|
3
|
+
/**
|
|
4
|
+
* The offset, inclusive, inside the CSS value at which the node starts.
|
|
5
|
+
*/
|
|
6
|
+
sourceIndex: number
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The offset, exclusive, inside the CSS value at which the node ends.
|
|
10
|
+
*/
|
|
11
|
+
sourceEndIndex: number
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The node's characteristic value
|
|
15
|
+
*/
|
|
16
|
+
value: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface ClosableNode {
|
|
20
|
+
/**
|
|
21
|
+
* Whether the parsed CSS value ended before the node was properly closed
|
|
22
|
+
*/
|
|
23
|
+
unclosed?: true
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface AdjacentAwareNode {
|
|
27
|
+
/**
|
|
28
|
+
* The token at the start of the node
|
|
29
|
+
*/
|
|
30
|
+
before: string
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The token at the end of the node
|
|
34
|
+
*/
|
|
35
|
+
after: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface CommentNode extends BaseNode, ClosableNode {
|
|
39
|
+
type: 'comment'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface DivNode extends BaseNode, AdjacentAwareNode {
|
|
43
|
+
type: 'div'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface FunctionNode extends BaseNode, ClosableNode, AdjacentAwareNode {
|
|
47
|
+
type: 'function'
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Nodes inside the function
|
|
51
|
+
*/
|
|
52
|
+
nodes: Node[]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface SpaceNode extends BaseNode {
|
|
56
|
+
type: 'space'
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface StringNode extends BaseNode, ClosableNode {
|
|
60
|
+
type: 'string'
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The quote type delimiting the string
|
|
64
|
+
*/
|
|
65
|
+
quote: '"' | "'"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface UnicodeRangeNode extends BaseNode {
|
|
69
|
+
type: 'unicode-range'
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
interface WordNode extends BaseNode {
|
|
73
|
+
type: 'word'
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Any node parsed from a CSS value
|
|
78
|
+
*/
|
|
79
|
+
type Node =
|
|
80
|
+
| CommentNode
|
|
81
|
+
| DivNode
|
|
82
|
+
| FunctionNode
|
|
83
|
+
| SpaceNode
|
|
84
|
+
| StringNode
|
|
85
|
+
| UnicodeRangeNode
|
|
86
|
+
| WordNode
|
|
87
|
+
|
|
88
|
+
interface CustomStringifierCallback {
|
|
89
|
+
/**
|
|
90
|
+
* @param node The node to stringify
|
|
91
|
+
* @returns The serialized CSS representation of the node
|
|
92
|
+
*/
|
|
93
|
+
(nodes: Node): string | undefined
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
interface WalkCallback {
|
|
97
|
+
/**
|
|
98
|
+
* @param node The currently visited node
|
|
99
|
+
* @param index The index of the node in the series of parsed nodes
|
|
100
|
+
* @param nodes The series of parsed nodes
|
|
101
|
+
* @returns Returning `false` will prevent traversal of descendant nodes (only applies if `bubble` was set to `true` in the `walk()` call)
|
|
102
|
+
*/
|
|
103
|
+
(node: Node, index: number, nodes: Node[]): void | boolean
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* A CSS dimension, decomposed into its numeric and unit parts
|
|
108
|
+
*/
|
|
109
|
+
interface Dimension {
|
|
110
|
+
number: string
|
|
111
|
+
unit: string
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* A wrapper around a parsed CSS value that allows for inspecting and walking nodes
|
|
116
|
+
*/
|
|
117
|
+
interface ParsedValue {
|
|
118
|
+
/**
|
|
119
|
+
* The series of parsed nodes
|
|
120
|
+
*/
|
|
121
|
+
nodes: Node[]
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Walk all parsed nodes, applying a callback
|
|
125
|
+
*
|
|
126
|
+
* @param callback A visitor callback that will be executed for each node
|
|
127
|
+
* @param bubble When set to `true`, walking will be done inside-out instead of outside-in
|
|
128
|
+
*/
|
|
129
|
+
walk(callback: WalkCallback, bubble?: boolean): this
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
interface ValueParser {
|
|
133
|
+
/**
|
|
134
|
+
* Decompose a CSS dimension into its numeric and unit part
|
|
135
|
+
*
|
|
136
|
+
* @param value The dimension to decompose
|
|
137
|
+
* @returns An object representing `number` and `unit` part of the dimension or `false` if the decomposing fails
|
|
138
|
+
*/
|
|
139
|
+
unit(value: string): Dimension | false
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Serialize a series of nodes into a CSS value
|
|
143
|
+
*
|
|
144
|
+
* @param nodes The nodes to stringify
|
|
145
|
+
* @param custom A custom stringifier callback
|
|
146
|
+
* @returns The generated CSS value
|
|
147
|
+
*/
|
|
148
|
+
stringify(nodes: Node | Node[], custom?: CustomStringifierCallback): string
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Walk a series of nodes, applying a callback
|
|
152
|
+
*
|
|
153
|
+
* @param nodes The nodes to walk
|
|
154
|
+
* @param callback A visitor callback that will be executed for each node
|
|
155
|
+
* @param bubble When set to `true`, walking will be done inside-out instead of outside-in
|
|
156
|
+
*/
|
|
157
|
+
walk(nodes: Node[], callback: WalkCallback, bubble?: boolean): void
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Parse a CSS value into a series of nodes to operate on
|
|
161
|
+
*
|
|
162
|
+
* @param value The value to parse
|
|
163
|
+
*/
|
|
164
|
+
new (value: string): ParsedValue
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Parse a CSS value into a series of nodes to operate on
|
|
168
|
+
*
|
|
169
|
+
* @param value The value to parse
|
|
170
|
+
*/
|
|
171
|
+
(value: string): ParsedValue
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
declare const postcssValueParser: postcssValueParser.ValueParser
|
|
176
|
+
|
|
177
|
+
export = postcssValueParser
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
var parse = require('./parse')
|
|
2
|
+
var walk = require('./walk')
|
|
3
|
+
var stringify = require('./stringify')
|
|
4
|
+
|
|
5
|
+
function ValueParser(value) {
|
|
6
|
+
if (this instanceof ValueParser) {
|
|
7
|
+
this.nodes = parse(value)
|
|
8
|
+
return this
|
|
9
|
+
}
|
|
10
|
+
return new ValueParser(value)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
ValueParser.prototype.toString = function () {
|
|
14
|
+
return Array.isArray(this.nodes) ? stringify(this.nodes) : ''
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
ValueParser.prototype.walk = function (cb, bubble) {
|
|
18
|
+
walk(this.nodes, cb, bubble)
|
|
19
|
+
return this
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
ValueParser.unit = require('./unit')
|
|
23
|
+
|
|
24
|
+
ValueParser.walk = walk
|
|
25
|
+
|
|
26
|
+
ValueParser.stringify = stringify
|
|
27
|
+
|
|
28
|
+
module.exports = ValueParser
|