tailwindcss 0.0.0-insiders.ef325ea → 0.0.0-insiders.f267d91
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 +9 -0
- package/lib/corePluginList.js +3 -0
- package/lib/corePlugins.js +96 -10
- package/lib/css/preflight.css +2 -1
- package/lib/lib/expandTailwindAtRules.js +2 -0
- package/lib/lib/generateRules.js +36 -0
- package/lib/lib/setupContextUtils.js +8 -65
- package/lib/util/formatVariantSelector.js +10 -1
- package/lib/util/isValidArbitraryValue.js +64 -0
- package/lib/util/nameClass.js +1 -0
- package/package.json +1 -1
- package/src/corePluginList.js +1 -1
- package/src/corePlugins.js +78 -11
- package/src/css/preflight.css +2 -1
- package/src/lib/expandTailwindAtRules.js +2 -0
- package/src/lib/generateRules.js +34 -0
- package/src/lib/setupContextUtils.js +6 -58
- package/src/util/formatVariantSelector.js +11 -1
- package/src/util/isValidArbitraryValue.js +61 -0
- package/src/util/nameClass.js +1 -1
- package/stubs/defaultConfig.stub.js +18 -0
package/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
15
15
|
|
|
16
16
|
- Add `placeholder` variant ([#6106](https://github.com/tailwindlabs/tailwindcss/pull/6106))
|
|
17
17
|
- Add tuple syntax for configuring screens while guaranteeing order ([#5956](https://github.com/tailwindlabs/tailwindcss/pull/5956))
|
|
18
|
+
- Add combinable `touch-action` support ([#6115](https://github.com/tailwindlabs/tailwindcss/pull/6115))
|
|
19
|
+
- Add support for "arbitrary properties" ([#6161](https://github.com/tailwindlabs/tailwindcss/pull/6161))
|
|
20
|
+
- Add `portrait` and `landscape` variants ([#6046](https://github.com/tailwindlabs/tailwindcss/pull/6046))
|
|
21
|
+
- Add `aspect-attrs` utility by default ([#6178](https://github.com/tailwindlabs/tailwindcss/pull/6178))
|
|
22
|
+
- Add `text-decoration-style`, `text-decoration-thickness`, and `text-underline-offset` utilities ([#6004](https://github.com/tailwindlabs/tailwindcss/pull/6004))
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Deprecate `decoration-slice` and `decoration-break` in favor `box-decoration-slice` and `box-decoration-break` _(non-breaking)_ ([#6004](https://github.com/tailwindlabs/tailwindcss/pull/6004))
|
|
18
27
|
|
|
19
28
|
## [3.0.0-alpha.2] - 2021-11-08
|
|
20
29
|
|
package/lib/corePluginList.js
CHANGED
package/lib/corePlugins.js
CHANGED
|
@@ -203,6 +203,10 @@ let variantPlugins = {
|
|
|
203
203
|
let query = (0, _buildMediaQuery).default(screen);
|
|
204
204
|
addVariant(screen.name, `@media ${query}`);
|
|
205
205
|
}
|
|
206
|
+
},
|
|
207
|
+
orientationVariants: ({ addVariant })=>{
|
|
208
|
+
addVariant('portrait', '@media (orientation: portrait)');
|
|
209
|
+
addVariant('landscape', '@media (orientation: landscape)');
|
|
206
210
|
}
|
|
207
211
|
};
|
|
208
212
|
exports.variantPlugins = variantPlugins;
|
|
@@ -995,7 +999,15 @@ let corePlugins1 = {
|
|
|
995
999
|
});
|
|
996
1000
|
},
|
|
997
1001
|
cursor: (0, _createUtilityPlugin).default('cursor'),
|
|
998
|
-
touchAction: ({ addUtilities })=>{
|
|
1002
|
+
touchAction: ({ addBase , addUtilities })=>{
|
|
1003
|
+
addBase({
|
|
1004
|
+
'@defaults touch-action': {
|
|
1005
|
+
'--tw-pan-x': 'var(--tw-empty,/*!*/ /*!*/)',
|
|
1006
|
+
'--tw-pan-y': 'var(--tw-empty,/*!*/ /*!*/)',
|
|
1007
|
+
'--tw-pinch-zoom': 'var(--tw-empty,/*!*/ /*!*/)',
|
|
1008
|
+
'--tw-touch-action': 'var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)'
|
|
1009
|
+
}
|
|
1010
|
+
});
|
|
999
1011
|
addUtilities({
|
|
1000
1012
|
'.touch-auto': {
|
|
1001
1013
|
'touch-action': 'auto'
|
|
@@ -1004,25 +1016,46 @@ let corePlugins1 = {
|
|
|
1004
1016
|
'touch-action': 'none'
|
|
1005
1017
|
},
|
|
1006
1018
|
'.touch-pan-x': {
|
|
1007
|
-
'touch-action':
|
|
1019
|
+
'@defaults touch-action': {
|
|
1020
|
+
},
|
|
1021
|
+
'--tw-pan-x': 'pan-x',
|
|
1022
|
+
'touch-action': 'var(--tw-touch-action)'
|
|
1008
1023
|
},
|
|
1009
1024
|
'.touch-pan-left': {
|
|
1010
|
-
'touch-action':
|
|
1025
|
+
'@defaults touch-action': {
|
|
1026
|
+
},
|
|
1027
|
+
'--tw-pan-x': 'pan-left',
|
|
1028
|
+
'touch-action': 'var(--tw-touch-action)'
|
|
1011
1029
|
},
|
|
1012
1030
|
'.touch-pan-right': {
|
|
1013
|
-
'touch-action':
|
|
1031
|
+
'@defaults touch-action': {
|
|
1032
|
+
},
|
|
1033
|
+
'--tw-pan-x': 'pan-right',
|
|
1034
|
+
'touch-action': 'var(--tw-touch-action)'
|
|
1014
1035
|
},
|
|
1015
1036
|
'.touch-pan-y': {
|
|
1016
|
-
'touch-action':
|
|
1037
|
+
'@defaults touch-action': {
|
|
1038
|
+
},
|
|
1039
|
+
'--tw-pan-y': 'pan-y',
|
|
1040
|
+
'touch-action': 'var(--tw-touch-action)'
|
|
1017
1041
|
},
|
|
1018
1042
|
'.touch-pan-up': {
|
|
1019
|
-
'touch-action':
|
|
1043
|
+
'@defaults touch-action': {
|
|
1044
|
+
},
|
|
1045
|
+
'--tw-pan-y': 'pan-up',
|
|
1046
|
+
'touch-action': 'var(--tw-touch-action)'
|
|
1020
1047
|
},
|
|
1021
1048
|
'.touch-pan-down': {
|
|
1022
|
-
'touch-action':
|
|
1049
|
+
'@defaults touch-action': {
|
|
1050
|
+
},
|
|
1051
|
+
'--tw-pan-y': 'pan-down',
|
|
1052
|
+
'touch-action': 'var(--tw-touch-action)'
|
|
1023
1053
|
},
|
|
1024
1054
|
'.touch-pinch-zoom': {
|
|
1025
|
-
'touch-action':
|
|
1055
|
+
'@defaults touch-action': {
|
|
1056
|
+
},
|
|
1057
|
+
'--tw-pinch-zoom': 'pinch-zoom',
|
|
1058
|
+
'touch-action': 'var(--tw-touch-action)'
|
|
1026
1059
|
},
|
|
1027
1060
|
'.touch-manipulation': {
|
|
1028
1061
|
'touch-action': 'manipulation'
|
|
@@ -2282,6 +2315,12 @@ let corePlugins1 = {
|
|
|
2282
2315
|
},
|
|
2283
2316
|
'.decoration-clone': {
|
|
2284
2317
|
'box-decoration-break': 'clone'
|
|
2318
|
+
},
|
|
2319
|
+
'.box-decoration-slice': {
|
|
2320
|
+
'box-decoration-break': 'slice'
|
|
2321
|
+
},
|
|
2322
|
+
'.box-decoration-clone': {
|
|
2323
|
+
'box-decoration-break': 'clone'
|
|
2285
2324
|
}
|
|
2286
2325
|
});
|
|
2287
2326
|
},
|
|
@@ -2753,6 +2792,9 @@ let corePlugins1 = {
|
|
|
2753
2792
|
'.underline': {
|
|
2754
2793
|
'text-decoration': 'underline'
|
|
2755
2794
|
},
|
|
2795
|
+
'.overline': {
|
|
2796
|
+
'text-decoration': 'overline'
|
|
2797
|
+
},
|
|
2756
2798
|
'.line-through': {
|
|
2757
2799
|
'text-decoration': 'line-through'
|
|
2758
2800
|
},
|
|
@@ -2771,11 +2813,55 @@ let corePlugins1 = {
|
|
|
2771
2813
|
}, {
|
|
2772
2814
|
values: (0, _flattenColorPalette).default(theme('textDecorationColor')),
|
|
2773
2815
|
type: [
|
|
2774
|
-
'color'
|
|
2775
|
-
'any'
|
|
2816
|
+
'color'
|
|
2776
2817
|
]
|
|
2777
2818
|
});
|
|
2778
2819
|
},
|
|
2820
|
+
textDecorationStyle: ({ addUtilities })=>{
|
|
2821
|
+
addUtilities({
|
|
2822
|
+
'.decoration-solid': {
|
|
2823
|
+
'text-decoration-style': 'solid'
|
|
2824
|
+
},
|
|
2825
|
+
'.decoration-double': {
|
|
2826
|
+
'text-decoration-style': 'double'
|
|
2827
|
+
},
|
|
2828
|
+
'.decoration-dotted': {
|
|
2829
|
+
'text-decoration-style': 'dotted'
|
|
2830
|
+
},
|
|
2831
|
+
'.decoration-dashed': {
|
|
2832
|
+
'text-decoration-style': 'dashed'
|
|
2833
|
+
},
|
|
2834
|
+
'.decoration-wavy': {
|
|
2835
|
+
'text-decoration-style': 'wavy'
|
|
2836
|
+
}
|
|
2837
|
+
});
|
|
2838
|
+
},
|
|
2839
|
+
textDecorationThickness: (0, _createUtilityPlugin).default('textDecorationThickness', [
|
|
2840
|
+
[
|
|
2841
|
+
'decoration',
|
|
2842
|
+
[
|
|
2843
|
+
'text-decoration-thickness'
|
|
2844
|
+
]
|
|
2845
|
+
]
|
|
2846
|
+
], {
|
|
2847
|
+
type: [
|
|
2848
|
+
'length',
|
|
2849
|
+
'percentage'
|
|
2850
|
+
]
|
|
2851
|
+
}),
|
|
2852
|
+
textUnderlineOffset: (0, _createUtilityPlugin).default('textUnderlineOffset', [
|
|
2853
|
+
[
|
|
2854
|
+
'underline-offset',
|
|
2855
|
+
[
|
|
2856
|
+
'text-underline-offset'
|
|
2857
|
+
]
|
|
2858
|
+
]
|
|
2859
|
+
], {
|
|
2860
|
+
type: [
|
|
2861
|
+
'length',
|
|
2862
|
+
'percentage'
|
|
2863
|
+
]
|
|
2864
|
+
}),
|
|
2779
2865
|
fontSmoothing: ({ addUtilities })=>{
|
|
2780
2866
|
addUtilities({
|
|
2781
2867
|
'.antialiased': {
|
package/lib/css/preflight.css
CHANGED
|
@@ -46,6 +46,8 @@ const PATTERNS = [
|
|
|
46
46
|
/([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source,
|
|
47
47
|
/([^<>"'`\s]*\['[^"'`\s]*'\])/.source,
|
|
48
48
|
/([^<>"'`\s]*\["[^"'`\s]*"\])/.source,
|
|
49
|
+
/([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source,
|
|
50
|
+
/([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source,
|
|
49
51
|
/([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source,
|
|
50
52
|
/([^<>"'`\s]*[^"'`\s:])/.source
|
|
51
53
|
].join('|');
|
package/lib/lib/generateRules.js
CHANGED
|
@@ -11,6 +11,9 @@ var _prefixSelector = _interopRequireDefault(require("../util/prefixSelector"));
|
|
|
11
11
|
var _pluginUtils = require("../util/pluginUtils");
|
|
12
12
|
var _log = _interopRequireDefault(require("../util/log"));
|
|
13
13
|
var _formatVariantSelector = require("../util/formatVariantSelector");
|
|
14
|
+
var _nameClass = require("../util/nameClass");
|
|
15
|
+
var _dataTypes = require("../util/dataTypes");
|
|
16
|
+
var _isValidArbitraryValue = _interopRequireDefault(require("../util/isValidArbitraryValue"));
|
|
14
17
|
function _interopRequireDefault(obj) {
|
|
15
18
|
return obj && obj.__esModule ? obj : {
|
|
16
19
|
default: obj
|
|
@@ -250,6 +253,31 @@ function parseRules(rule, cache, options = {
|
|
|
250
253
|
options
|
|
251
254
|
];
|
|
252
255
|
}
|
|
256
|
+
function extractArbitraryProperty(classCandidate, context) {
|
|
257
|
+
var ref;
|
|
258
|
+
let [, property, value] = (ref = classCandidate.match(/^\[([a-zA-Z0-9-_]+):(\S+)\]$/)) !== null && ref !== void 0 ? ref : [];
|
|
259
|
+
if (value === undefined) {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
let normalized = (0, _dataTypes).normalize(value);
|
|
263
|
+
if (!(0, _isValidArbitraryValue).default(normalized)) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
return [
|
|
267
|
+
[
|
|
268
|
+
{
|
|
269
|
+
sort: context.arbitraryPropertiesSort,
|
|
270
|
+
layer: 'utilities'
|
|
271
|
+
},
|
|
272
|
+
()=>({
|
|
273
|
+
[(0, _nameClass).asClass(classCandidate)]: {
|
|
274
|
+
[property]: normalized
|
|
275
|
+
}
|
|
276
|
+
})
|
|
277
|
+
,
|
|
278
|
+
],
|
|
279
|
+
];
|
|
280
|
+
}
|
|
253
281
|
function* resolveMatchedPlugins(classCandidate, context) {
|
|
254
282
|
if (context.candidateRuleMap.has(classCandidate)) {
|
|
255
283
|
yield [
|
|
@@ -257,6 +285,14 @@ function* resolveMatchedPlugins(classCandidate, context) {
|
|
|
257
285
|
'DEFAULT'
|
|
258
286
|
];
|
|
259
287
|
}
|
|
288
|
+
yield* (function*(arbitraryPropertyRule) {
|
|
289
|
+
if (arbitraryPropertyRule !== null) {
|
|
290
|
+
yield [
|
|
291
|
+
arbitraryPropertyRule,
|
|
292
|
+
'DEFAULT'
|
|
293
|
+
];
|
|
294
|
+
}
|
|
295
|
+
})(extractArbitraryProperty(classCandidate, context));
|
|
260
296
|
let candidatePrefix = classCandidate;
|
|
261
297
|
let negative = false;
|
|
262
298
|
const twConfigPrefix = context.tailwindConfig.prefix;
|
|
@@ -23,6 +23,7 @@ var sharedState = _interopRequireWildcard(require("./sharedState"));
|
|
|
23
23
|
var _toPath = require("../util/toPath");
|
|
24
24
|
var _log = _interopRequireDefault(require("../util/log"));
|
|
25
25
|
var _negateValue = _interopRequireDefault(require("../util/negateValue"));
|
|
26
|
+
var _isValidArbitraryValue = _interopRequireDefault(require("../util/isValidArbitraryValue"));
|
|
26
27
|
function _interopRequireDefault(obj) {
|
|
27
28
|
return obj && obj.__esModule ? obj : {
|
|
28
29
|
default: obj
|
|
@@ -160,68 +161,6 @@ function withIdentifiers(styles) {
|
|
|
160
161
|
});
|
|
161
162
|
});
|
|
162
163
|
}
|
|
163
|
-
let matchingBrackets = new Map([
|
|
164
|
-
[
|
|
165
|
-
'{',
|
|
166
|
-
'}'
|
|
167
|
-
],
|
|
168
|
-
[
|
|
169
|
-
'[',
|
|
170
|
-
']'
|
|
171
|
-
],
|
|
172
|
-
[
|
|
173
|
-
'(',
|
|
174
|
-
')'
|
|
175
|
-
],
|
|
176
|
-
]);
|
|
177
|
-
let inverseMatchingBrackets = new Map(Array.from(matchingBrackets.entries()).map(([k, v])=>[
|
|
178
|
-
v,
|
|
179
|
-
k
|
|
180
|
-
]
|
|
181
|
-
));
|
|
182
|
-
let quotes = new Set([
|
|
183
|
-
'"',
|
|
184
|
-
"'",
|
|
185
|
-
'`'
|
|
186
|
-
]);
|
|
187
|
-
// Arbitrary values must contain balanced brackets (), [] and {}. Escaped
|
|
188
|
-
// values don't count, and brackets inside quotes also don't count.
|
|
189
|
-
//
|
|
190
|
-
// E.g.: w-[this-is]w-[weird-and-invalid]
|
|
191
|
-
// E.g.: w-[this-is\\]w-\\[weird-but-valid]
|
|
192
|
-
// E.g.: content-['this-is-also-valid]-weirdly-enough']
|
|
193
|
-
function isValidArbitraryValue(value) {
|
|
194
|
-
let stack = [];
|
|
195
|
-
let inQuotes = false;
|
|
196
|
-
for(let i = 0; i < value.length; i++){
|
|
197
|
-
let char = value[i];
|
|
198
|
-
// Non-escaped quotes allow us to "allow" anything in between
|
|
199
|
-
if (quotes.has(char) && value[i - 1] !== '\\') {
|
|
200
|
-
inQuotes = !inQuotes;
|
|
201
|
-
}
|
|
202
|
-
if (inQuotes) continue;
|
|
203
|
-
if (value[i - 1] === '\\') continue; // Escaped
|
|
204
|
-
if (matchingBrackets.has(char)) {
|
|
205
|
-
stack.push(char);
|
|
206
|
-
} else if (inverseMatchingBrackets.has(char)) {
|
|
207
|
-
let inverse = inverseMatchingBrackets.get(char);
|
|
208
|
-
// Nothing to pop from, therefore it is unbalanced
|
|
209
|
-
if (stack.length <= 0) {
|
|
210
|
-
return false;
|
|
211
|
-
}
|
|
212
|
-
// Popped value must match the inverse value, otherwise it is unbalanced
|
|
213
|
-
if (stack.pop() !== inverse) {
|
|
214
|
-
return false;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
// If there is still something on the stack, it is also unbalanced
|
|
219
|
-
if (stack.length > 0) {
|
|
220
|
-
return false;
|
|
221
|
-
}
|
|
222
|
-
// All good, totally balanced!
|
|
223
|
-
return true;
|
|
224
|
-
}
|
|
225
164
|
function buildPluginApi(tailwindConfig, context, { variantList , variantMap , offsets , classList }) {
|
|
226
165
|
function getConfigValue(path, defaultValue) {
|
|
227
166
|
return path ? (0, _dlv).default(tailwindConfig, path, defaultValue) : tailwindConfig;
|
|
@@ -409,7 +348,7 @@ function buildPluginApi(tailwindConfig, context, { variantList , variantMap , of
|
|
|
409
348
|
if (!type.includes(coercedType) && !isOnlyPlugin) {
|
|
410
349
|
return [];
|
|
411
350
|
}
|
|
412
|
-
if (!
|
|
351
|
+
if (!(0, _isValidArbitraryValue).default(value)) {
|
|
413
352
|
return [];
|
|
414
353
|
}
|
|
415
354
|
let ruleSets = [].concat(rule(value)).filter(Boolean).map((declaration)=>({
|
|
@@ -466,7 +405,7 @@ function buildPluginApi(tailwindConfig, context, { variantList , variantMap , of
|
|
|
466
405
|
return [];
|
|
467
406
|
}
|
|
468
407
|
}
|
|
469
|
-
if (!
|
|
408
|
+
if (!(0, _isValidArbitraryValue).default(value)) {
|
|
470
409
|
return [];
|
|
471
410
|
}
|
|
472
411
|
let ruleSets = [].concat(rule(value)).filter(Boolean).map((declaration)=>({
|
|
@@ -608,7 +547,8 @@ function resolvePlugins(context, root) {
|
|
|
608
547
|
_corePlugins.variantPlugins['reducedMotionVariants'],
|
|
609
548
|
_corePlugins.variantPlugins['darkVariants'],
|
|
610
549
|
_corePlugins.variantPlugins['printVariant'],
|
|
611
|
-
_corePlugins.variantPlugins['screenVariants'],
|
|
550
|
+
_corePlugins.variantPlugins['screenVariants'],
|
|
551
|
+
_corePlugins.variantPlugins['orientationVariants'],
|
|
612
552
|
];
|
|
613
553
|
return [
|
|
614
554
|
...corePluginList,
|
|
@@ -652,6 +592,9 @@ function registerPlugins(plugins, context) {
|
|
|
652
592
|
offsets.user,
|
|
653
593
|
]);
|
|
654
594
|
let reservedBits = BigInt(highestOffset.toString(2).length);
|
|
595
|
+
// A number one less than the top range of the highest offset area
|
|
596
|
+
// so arbitrary properties are always sorted at the end.
|
|
597
|
+
context.arbitraryPropertiesSort = (1n << reservedBits << 0n) - 1n;
|
|
655
598
|
context.layerOrder = {
|
|
656
599
|
base: 1n << reservedBits << 0n,
|
|
657
600
|
components: 1n << reservedBits << 1n,
|
|
@@ -40,7 +40,16 @@ function formatVariantSelector(current, ...others) {
|
|
|
40
40
|
function finalizeSelector(format, { selector: selector1 , candidate , context }) {
|
|
41
41
|
var ref, ref1;
|
|
42
42
|
var ref2;
|
|
43
|
-
let
|
|
43
|
+
let separator = (ref2 = context === null || context === void 0 ? void 0 : (ref = context.tailwindConfig) === null || ref === void 0 ? void 0 : ref.separator) !== null && ref2 !== void 0 ? ref2 : ':';
|
|
44
|
+
// Split by the separator, but ignore the separator inside square brackets:
|
|
45
|
+
//
|
|
46
|
+
// E.g.: dark:lg:hover:[paint-order:markers]
|
|
47
|
+
// ┬ ┬ ┬ ┬
|
|
48
|
+
// │ │ │ ╰── We will not split here
|
|
49
|
+
// ╰──┴─────┴─────────────── We will split here
|
|
50
|
+
//
|
|
51
|
+
let splitter = new RegExp(`\\${separator}(?![^[]*\\])`);
|
|
52
|
+
let base = candidate.split(splitter).pop();
|
|
44
53
|
if (context === null || context === void 0 ? void 0 : (ref1 = context.tailwindConfig) === null || ref1 === void 0 ? void 0 : ref1.prefix) {
|
|
45
54
|
format = (0, _prefixSelector).default(context.tailwindConfig.prefix, format);
|
|
46
55
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
exports.default = isValidArbitraryValue;
|
|
6
|
+
let matchingBrackets = new Map([
|
|
7
|
+
[
|
|
8
|
+
'{',
|
|
9
|
+
'}'
|
|
10
|
+
],
|
|
11
|
+
[
|
|
12
|
+
'[',
|
|
13
|
+
']'
|
|
14
|
+
],
|
|
15
|
+
[
|
|
16
|
+
'(',
|
|
17
|
+
')'
|
|
18
|
+
],
|
|
19
|
+
]);
|
|
20
|
+
let inverseMatchingBrackets = new Map(Array.from(matchingBrackets.entries()).map(([k, v])=>[
|
|
21
|
+
v,
|
|
22
|
+
k
|
|
23
|
+
]
|
|
24
|
+
));
|
|
25
|
+
let quotes = new Set([
|
|
26
|
+
'"',
|
|
27
|
+
"'",
|
|
28
|
+
'`'
|
|
29
|
+
]);
|
|
30
|
+
function isValidArbitraryValue(value) {
|
|
31
|
+
let stack = [];
|
|
32
|
+
let inQuotes = false;
|
|
33
|
+
for(let i = 0; i < value.length; i++){
|
|
34
|
+
let char = value[i];
|
|
35
|
+
if (char === ':' && !inQuotes && stack.length === 0) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
// Non-escaped quotes allow us to "allow" anything in between
|
|
39
|
+
if (quotes.has(char) && value[i - 1] !== '\\') {
|
|
40
|
+
inQuotes = !inQuotes;
|
|
41
|
+
}
|
|
42
|
+
if (inQuotes) continue;
|
|
43
|
+
if (value[i - 1] === '\\') continue; // Escaped
|
|
44
|
+
if (matchingBrackets.has(char)) {
|
|
45
|
+
stack.push(char);
|
|
46
|
+
} else if (inverseMatchingBrackets.has(char)) {
|
|
47
|
+
let inverse = inverseMatchingBrackets.get(char);
|
|
48
|
+
// Nothing to pop from, therefore it is unbalanced
|
|
49
|
+
if (stack.length <= 0) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
// Popped value must match the inverse value, otherwise it is unbalanced
|
|
53
|
+
if (stack.pop() !== inverse) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// If there is still something on the stack, it is also unbalanced
|
|
59
|
+
if (stack.length > 0) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
// All good, totally balanced!
|
|
63
|
+
return true;
|
|
64
|
+
}
|
package/lib/util/nameClass.js
CHANGED
package/package.json
CHANGED
package/src/corePluginList.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default ["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","display","aspectRatio","height","maxHeight","minHeight","width","minWidth","maxWidth","flex","flexShrink","flexGrow","flexBasis","tableLayout","borderCollapse","transformOrigin","translate","rotate","skew","scale","transform","animation","cursor","touchAction","userSelect","resize","scrollSnapType","scrollSnapAlign","scrollSnapStop","scrollMargin","scrollPadding","listStylePosition","listStyleType","appearance","columns","breakBefore","breakInside","breakAfter","gridAutoColumns","gridAutoFlow","gridAutoRows","gridTemplateColumns","gridTemplateRows","flexDirection","flexWrap","placeContent","placeItems","alignContent","alignItems","justifyContent","justifyItems","gap","space","divideWidth","divideStyle","divideColor","divideOpacity","placeSelf","alignSelf","justifySelf","overflow","overscrollBehavior","scrollBehavior","textOverflow","whitespace","wordBreak","borderRadius","borderWidth","borderStyle","borderColor","borderOpacity","backgroundColor","backgroundOpacity","backgroundImage","gradientColorStops","boxDecorationBreak","backgroundSize","backgroundAttachment","backgroundClip","backgroundPosition","backgroundRepeat","backgroundOrigin","fill","stroke","strokeWidth","objectFit","objectPosition","padding","textAlign","textIndent","verticalAlign","fontFamily","fontSize","fontWeight","textTransform","fontStyle","fontVariantNumeric","lineHeight","letterSpacing","textColor","textOpacity","textDecoration","textDecorationColor","fontSmoothing","placeholderColor","placeholderOpacity","caretColor","accentColor","opacity","backgroundBlendMode","mixBlendMode","boxShadow","boxShadowColor","outlineStyle","outlineWidth","outlineOffset","outlineColor","ringWidth","ringColor","ringOpacity","ringOffsetWidth","ringOffsetColor","blur","brightness","contrast","dropShadow","grayscale","hueRotate","invert","saturate","sepia","filter","backdropBlur","backdropBrightness","backdropContrast","backdropGrayscale","backdropHueRotate","backdropInvert","backdropOpacity","backdropSaturate","backdropSepia","backdropFilter","transitionProperty","transitionDelay","transitionDuration","transitionTimingFunction","willChange","content"]
|
|
1
|
+
export default ["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","display","aspectRatio","height","maxHeight","minHeight","width","minWidth","maxWidth","flex","flexShrink","flexGrow","flexBasis","tableLayout","borderCollapse","transformOrigin","translate","rotate","skew","scale","transform","animation","cursor","touchAction","userSelect","resize","scrollSnapType","scrollSnapAlign","scrollSnapStop","scrollMargin","scrollPadding","listStylePosition","listStyleType","appearance","columns","breakBefore","breakInside","breakAfter","gridAutoColumns","gridAutoFlow","gridAutoRows","gridTemplateColumns","gridTemplateRows","flexDirection","flexWrap","placeContent","placeItems","alignContent","alignItems","justifyContent","justifyItems","gap","space","divideWidth","divideStyle","divideColor","divideOpacity","placeSelf","alignSelf","justifySelf","overflow","overscrollBehavior","scrollBehavior","textOverflow","whitespace","wordBreak","borderRadius","borderWidth","borderStyle","borderColor","borderOpacity","backgroundColor","backgroundOpacity","backgroundImage","gradientColorStops","boxDecorationBreak","backgroundSize","backgroundAttachment","backgroundClip","backgroundPosition","backgroundRepeat","backgroundOrigin","fill","stroke","strokeWidth","objectFit","objectPosition","padding","textAlign","textIndent","verticalAlign","fontFamily","fontSize","fontWeight","textTransform","fontStyle","fontVariantNumeric","lineHeight","letterSpacing","textColor","textOpacity","textDecoration","textDecorationColor","textDecorationStyle","textDecorationThickness","textUnderlineOffset","fontSmoothing","placeholderColor","placeholderOpacity","caretColor","accentColor","opacity","backgroundBlendMode","mixBlendMode","boxShadow","boxShadowColor","outlineStyle","outlineWidth","outlineOffset","outlineColor","ringWidth","ringColor","ringOpacity","ringOffsetWidth","ringOffsetColor","blur","brightness","contrast","dropShadow","grayscale","hueRotate","invert","saturate","sepia","filter","backdropBlur","backdropBrightness","backdropContrast","backdropGrayscale","backdropHueRotate","backdropInvert","backdropOpacity","backdropSaturate","backdropSepia","backdropFilter","transitionProperty","transitionDelay","transitionDuration","transitionTimingFunction","willChange","content"]
|
package/src/corePlugins.js
CHANGED
|
@@ -165,6 +165,11 @@ export let variantPlugins = {
|
|
|
165
165
|
addVariant(screen.name, `@media ${query}`)
|
|
166
166
|
}
|
|
167
167
|
},
|
|
168
|
+
|
|
169
|
+
orientationVariants: ({ addVariant }) => {
|
|
170
|
+
addVariant('portrait', '@media (orientation: portrait)')
|
|
171
|
+
addVariant('landscape', '@media (orientation: landscape)')
|
|
172
|
+
},
|
|
168
173
|
}
|
|
169
174
|
|
|
170
175
|
export let corePlugins = {
|
|
@@ -602,17 +607,54 @@ export let corePlugins = {
|
|
|
602
607
|
|
|
603
608
|
cursor: createUtilityPlugin('cursor'),
|
|
604
609
|
|
|
605
|
-
touchAction: ({ addUtilities }) => {
|
|
610
|
+
touchAction: ({ addBase, addUtilities }) => {
|
|
611
|
+
addBase({
|
|
612
|
+
'@defaults touch-action': {
|
|
613
|
+
'--tw-pan-x': 'var(--tw-empty,/*!*/ /*!*/)',
|
|
614
|
+
'--tw-pan-y': 'var(--tw-empty,/*!*/ /*!*/)',
|
|
615
|
+
'--tw-pinch-zoom': 'var(--tw-empty,/*!*/ /*!*/)',
|
|
616
|
+
'--tw-touch-action': 'var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)',
|
|
617
|
+
},
|
|
618
|
+
})
|
|
619
|
+
|
|
606
620
|
addUtilities({
|
|
607
621
|
'.touch-auto': { 'touch-action': 'auto' },
|
|
608
622
|
'.touch-none': { 'touch-action': 'none' },
|
|
609
|
-
'.touch-pan-x': {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
'.touch-pan-
|
|
615
|
-
|
|
623
|
+
'.touch-pan-x': {
|
|
624
|
+
'@defaults touch-action': {},
|
|
625
|
+
'--tw-pan-x': 'pan-x',
|
|
626
|
+
'touch-action': 'var(--tw-touch-action)',
|
|
627
|
+
},
|
|
628
|
+
'.touch-pan-left': {
|
|
629
|
+
'@defaults touch-action': {},
|
|
630
|
+
'--tw-pan-x': 'pan-left',
|
|
631
|
+
'touch-action': 'var(--tw-touch-action)',
|
|
632
|
+
},
|
|
633
|
+
'.touch-pan-right': {
|
|
634
|
+
'@defaults touch-action': {},
|
|
635
|
+
'--tw-pan-x': 'pan-right',
|
|
636
|
+
'touch-action': 'var(--tw-touch-action)',
|
|
637
|
+
},
|
|
638
|
+
'.touch-pan-y': {
|
|
639
|
+
'@defaults touch-action': {},
|
|
640
|
+
'--tw-pan-y': 'pan-y',
|
|
641
|
+
'touch-action': 'var(--tw-touch-action)',
|
|
642
|
+
},
|
|
643
|
+
'.touch-pan-up': {
|
|
644
|
+
'@defaults touch-action': {},
|
|
645
|
+
'--tw-pan-y': 'pan-up',
|
|
646
|
+
'touch-action': 'var(--tw-touch-action)',
|
|
647
|
+
},
|
|
648
|
+
'.touch-pan-down': {
|
|
649
|
+
'@defaults touch-action': {},
|
|
650
|
+
'--tw-pan-y': 'pan-down',
|
|
651
|
+
'touch-action': 'var(--tw-touch-action)',
|
|
652
|
+
},
|
|
653
|
+
'.touch-pinch-zoom': {
|
|
654
|
+
'@defaults touch-action': {},
|
|
655
|
+
'--tw-pinch-zoom': 'pinch-zoom',
|
|
656
|
+
'touch-action': 'var(--tw-touch-action)',
|
|
657
|
+
},
|
|
616
658
|
'.touch-manipulation': { 'touch-action': 'manipulation' },
|
|
617
659
|
})
|
|
618
660
|
},
|
|
@@ -1354,8 +1396,10 @@ export let corePlugins = {
|
|
|
1354
1396
|
|
|
1355
1397
|
boxDecorationBreak: ({ addUtilities }) => {
|
|
1356
1398
|
addUtilities({
|
|
1357
|
-
'.decoration-slice': { 'box-decoration-break': 'slice' },
|
|
1358
|
-
'.decoration-clone': { 'box-decoration-break': 'clone' },
|
|
1399
|
+
'.decoration-slice': { 'box-decoration-break': 'slice' }, // Deprecated
|
|
1400
|
+
'.decoration-clone': { 'box-decoration-break': 'clone' }, // Deprecated
|
|
1401
|
+
'.box-decoration-slice': { 'box-decoration-break': 'slice' },
|
|
1402
|
+
'.box-decoration-clone': { 'box-decoration-break': 'clone' },
|
|
1359
1403
|
})
|
|
1360
1404
|
},
|
|
1361
1405
|
|
|
@@ -1613,6 +1657,7 @@ export let corePlugins = {
|
|
|
1613
1657
|
textDecoration: ({ addUtilities }) => {
|
|
1614
1658
|
addUtilities({
|
|
1615
1659
|
'.underline': { 'text-decoration': 'underline' },
|
|
1660
|
+
'.overline': { 'text-decoration': 'overline' },
|
|
1616
1661
|
'.line-through': { 'text-decoration': 'line-through' },
|
|
1617
1662
|
'.no-underline': { 'text-decoration': 'none' },
|
|
1618
1663
|
})
|
|
@@ -1625,10 +1670,32 @@ export let corePlugins = {
|
|
|
1625
1670
|
return { 'text-decoration-color': toColorValue(value) }
|
|
1626
1671
|
},
|
|
1627
1672
|
},
|
|
1628
|
-
{ values: flattenColorPalette(theme('textDecorationColor')), type: ['color'
|
|
1673
|
+
{ values: flattenColorPalette(theme('textDecorationColor')), type: ['color'] }
|
|
1629
1674
|
)
|
|
1630
1675
|
},
|
|
1631
1676
|
|
|
1677
|
+
textDecorationStyle: ({ addUtilities }) => {
|
|
1678
|
+
addUtilities({
|
|
1679
|
+
'.decoration-solid': { 'text-decoration-style': 'solid' },
|
|
1680
|
+
'.decoration-double': { 'text-decoration-style': 'double' },
|
|
1681
|
+
'.decoration-dotted': { 'text-decoration-style': 'dotted' },
|
|
1682
|
+
'.decoration-dashed': { 'text-decoration-style': 'dashed' },
|
|
1683
|
+
'.decoration-wavy': { 'text-decoration-style': 'wavy' },
|
|
1684
|
+
})
|
|
1685
|
+
},
|
|
1686
|
+
|
|
1687
|
+
textDecorationThickness: createUtilityPlugin(
|
|
1688
|
+
'textDecorationThickness',
|
|
1689
|
+
[['decoration', ['text-decoration-thickness']]],
|
|
1690
|
+
{ type: ['length', 'percentage'] }
|
|
1691
|
+
),
|
|
1692
|
+
|
|
1693
|
+
textUnderlineOffset: createUtilityPlugin(
|
|
1694
|
+
'textUnderlineOffset',
|
|
1695
|
+
[['underline-offset', ['text-underline-offset']]],
|
|
1696
|
+
{ type: ['length', 'percentage'] }
|
|
1697
|
+
),
|
|
1698
|
+
|
|
1632
1699
|
fontSmoothing: ({ addUtilities }) => {
|
|
1633
1700
|
addUtilities({
|
|
1634
1701
|
'.antialiased': {
|
package/src/css/preflight.css
CHANGED
|
@@ -15,6 +15,8 @@ const PATTERNS = [
|
|
|
15
15
|
/([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source, // bg-[url("..."),url("...")]
|
|
16
16
|
/([^<>"'`\s]*\['[^"'`\s]*'\])/.source, // `content-['hello']` but not `content-['hello']']`
|
|
17
17
|
/([^<>"'`\s]*\["[^"'`\s]*"\])/.source, // `content-["hello"]` but not `content-["hello"]"]`
|
|
18
|
+
/([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source, // `[content:'hello']` but not `[content:"hello"]`
|
|
19
|
+
/([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source, // `[content:"hello"]` but not `[content:'hello']`
|
|
18
20
|
/([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source, // `fill-[#bada55]`, `fill-[#bada55]/50`
|
|
19
21
|
/([^<>"'`\s]*[^"'`\s:])/.source, // `px-1.5`, `uppercase` but not `uppercase:`
|
|
20
22
|
].join('|')
|
package/src/lib/generateRules.js
CHANGED
|
@@ -6,6 +6,9 @@ import prefixSelector from '../util/prefixSelector'
|
|
|
6
6
|
import { updateAllClasses } from '../util/pluginUtils'
|
|
7
7
|
import log from '../util/log'
|
|
8
8
|
import { formatVariantSelector, finalizeSelector } from '../util/formatVariantSelector'
|
|
9
|
+
import { asClass } from '../util/nameClass'
|
|
10
|
+
import { normalize } from '../util/dataTypes'
|
|
11
|
+
import isValidArbitraryValue from '../util/isValidArbitraryValue'
|
|
9
12
|
|
|
10
13
|
let classNameParser = selectorParser((selectors) => {
|
|
11
14
|
return selectors.first.filter(({ type }) => type === 'class').pop().value
|
|
@@ -245,11 +248,42 @@ function parseRules(rule, cache, options = {}) {
|
|
|
245
248
|
return [cache.get(rule), options]
|
|
246
249
|
}
|
|
247
250
|
|
|
251
|
+
function extractArbitraryProperty(classCandidate, context) {
|
|
252
|
+
let [, property, value] = classCandidate.match(/^\[([a-zA-Z0-9-_]+):(\S+)\]$/) ?? []
|
|
253
|
+
|
|
254
|
+
if (value === undefined) {
|
|
255
|
+
return null
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
let normalized = normalize(value)
|
|
259
|
+
|
|
260
|
+
if (!isValidArbitraryValue(normalized)) {
|
|
261
|
+
return null
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return [
|
|
265
|
+
[
|
|
266
|
+
{ sort: context.arbitraryPropertiesSort, layer: 'utilities' },
|
|
267
|
+
() => ({
|
|
268
|
+
[asClass(classCandidate)]: {
|
|
269
|
+
[property]: normalized,
|
|
270
|
+
},
|
|
271
|
+
}),
|
|
272
|
+
],
|
|
273
|
+
]
|
|
274
|
+
}
|
|
275
|
+
|
|
248
276
|
function* resolveMatchedPlugins(classCandidate, context) {
|
|
249
277
|
if (context.candidateRuleMap.has(classCandidate)) {
|
|
250
278
|
yield [context.candidateRuleMap.get(classCandidate), 'DEFAULT']
|
|
251
279
|
}
|
|
252
280
|
|
|
281
|
+
yield* (function* (arbitraryPropertyRule) {
|
|
282
|
+
if (arbitraryPropertyRule !== null) {
|
|
283
|
+
yield [arbitraryPropertyRule, 'DEFAULT']
|
|
284
|
+
}
|
|
285
|
+
})(extractArbitraryProperty(classCandidate, context))
|
|
286
|
+
|
|
253
287
|
let candidatePrefix = classCandidate
|
|
254
288
|
let negative = false
|
|
255
289
|
|
|
@@ -18,6 +18,7 @@ import { env } from './sharedState'
|
|
|
18
18
|
import { toPath } from '../util/toPath'
|
|
19
19
|
import log from '../util/log'
|
|
20
20
|
import negateValue from '../util/negateValue'
|
|
21
|
+
import isValidArbitraryValue from '../util/isValidArbitraryValue'
|
|
21
22
|
|
|
22
23
|
function parseVariantFormatString(input) {
|
|
23
24
|
if (input.includes('{')) {
|
|
@@ -130,64 +131,6 @@ function withIdentifiers(styles) {
|
|
|
130
131
|
})
|
|
131
132
|
}
|
|
132
133
|
|
|
133
|
-
let matchingBrackets = new Map([
|
|
134
|
-
['{', '}'],
|
|
135
|
-
['[', ']'],
|
|
136
|
-
['(', ')'],
|
|
137
|
-
])
|
|
138
|
-
let inverseMatchingBrackets = new Map(
|
|
139
|
-
Array.from(matchingBrackets.entries()).map(([k, v]) => [v, k])
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
let quotes = new Set(['"', "'", '`'])
|
|
143
|
-
|
|
144
|
-
// Arbitrary values must contain balanced brackets (), [] and {}. Escaped
|
|
145
|
-
// values don't count, and brackets inside quotes also don't count.
|
|
146
|
-
//
|
|
147
|
-
// E.g.: w-[this-is]w-[weird-and-invalid]
|
|
148
|
-
// E.g.: w-[this-is\\]w-\\[weird-but-valid]
|
|
149
|
-
// E.g.: content-['this-is-also-valid]-weirdly-enough']
|
|
150
|
-
function isValidArbitraryValue(value) {
|
|
151
|
-
let stack = []
|
|
152
|
-
let inQuotes = false
|
|
153
|
-
|
|
154
|
-
for (let i = 0; i < value.length; i++) {
|
|
155
|
-
let char = value[i]
|
|
156
|
-
|
|
157
|
-
// Non-escaped quotes allow us to "allow" anything in between
|
|
158
|
-
if (quotes.has(char) && value[i - 1] !== '\\') {
|
|
159
|
-
inQuotes = !inQuotes
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (inQuotes) continue
|
|
163
|
-
if (value[i - 1] === '\\') continue // Escaped
|
|
164
|
-
|
|
165
|
-
if (matchingBrackets.has(char)) {
|
|
166
|
-
stack.push(char)
|
|
167
|
-
} else if (inverseMatchingBrackets.has(char)) {
|
|
168
|
-
let inverse = inverseMatchingBrackets.get(char)
|
|
169
|
-
|
|
170
|
-
// Nothing to pop from, therefore it is unbalanced
|
|
171
|
-
if (stack.length <= 0) {
|
|
172
|
-
return false
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Popped value must match the inverse value, otherwise it is unbalanced
|
|
176
|
-
if (stack.pop() !== inverse) {
|
|
177
|
-
return false
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// If there is still something on the stack, it is also unbalanced
|
|
183
|
-
if (stack.length > 0) {
|
|
184
|
-
return false
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// All good, totally balanced!
|
|
188
|
-
return true
|
|
189
|
-
}
|
|
190
|
-
|
|
191
134
|
function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offsets, classList }) {
|
|
192
135
|
function getConfigValue(path, defaultValue) {
|
|
193
136
|
return path ? dlv(tailwindConfig, path, defaultValue) : tailwindConfig
|
|
@@ -575,6 +518,7 @@ function resolvePlugins(context, root) {
|
|
|
575
518
|
variantPlugins['darkVariants'],
|
|
576
519
|
variantPlugins['printVariant'],
|
|
577
520
|
variantPlugins['screenVariants'],
|
|
521
|
+
variantPlugins['orientationVariants'],
|
|
578
522
|
]
|
|
579
523
|
|
|
580
524
|
return [...corePluginList, ...beforeVariants, ...userPlugins, ...afterVariants, ...layerPlugins]
|
|
@@ -617,6 +561,10 @@ function registerPlugins(plugins, context) {
|
|
|
617
561
|
])
|
|
618
562
|
let reservedBits = BigInt(highestOffset.toString(2).length)
|
|
619
563
|
|
|
564
|
+
// A number one less than the top range of the highest offset area
|
|
565
|
+
// so arbitrary properties are always sorted at the end.
|
|
566
|
+
context.arbitraryPropertiesSort = ((1n << reservedBits) << 0n) - 1n
|
|
567
|
+
|
|
620
568
|
context.layerOrder = {
|
|
621
569
|
base: (1n << reservedBits) << 0n,
|
|
622
570
|
components: (1n << reservedBits) << 1n,
|
|
@@ -30,7 +30,17 @@ export function formatVariantSelector(current, ...others) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
export function finalizeSelector(format, { selector, candidate, context }) {
|
|
33
|
-
let
|
|
33
|
+
let separator = context?.tailwindConfig?.separator ?? ':'
|
|
34
|
+
|
|
35
|
+
// Split by the separator, but ignore the separator inside square brackets:
|
|
36
|
+
//
|
|
37
|
+
// E.g.: dark:lg:hover:[paint-order:markers]
|
|
38
|
+
// ┬ ┬ ┬ ┬
|
|
39
|
+
// │ │ │ ╰── We will not split here
|
|
40
|
+
// ╰──┴─────┴─────────────── We will split here
|
|
41
|
+
//
|
|
42
|
+
let splitter = new RegExp(`\\${separator}(?![^[]*\\])`)
|
|
43
|
+
let base = candidate.split(splitter).pop()
|
|
34
44
|
|
|
35
45
|
if (context?.tailwindConfig?.prefix) {
|
|
36
46
|
format = prefixSelector(context.tailwindConfig.prefix, format)
|
|
@@ -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
|
@@ -115,6 +115,7 @@ module.exports = {
|
|
|
115
115
|
auto: 'auto',
|
|
116
116
|
square: '1 / 1',
|
|
117
117
|
video: '16 / 9',
|
|
118
|
+
attrs: 'attr(width) / attr(height)'
|
|
118
119
|
},
|
|
119
120
|
backdropBlur: ({ theme }) => theme('blur'),
|
|
120
121
|
backdropBrightness: ({ theme }) => theme('brightness'),
|
|
@@ -797,6 +798,23 @@ module.exports = {
|
|
|
797
798
|
},
|
|
798
799
|
textColor: ({ theme }) => theme('colors'),
|
|
799
800
|
textDecorationColor: ({ theme }) => theme('colors'),
|
|
801
|
+
textDecorationThickness: {
|
|
802
|
+
auto: 'auto',
|
|
803
|
+
'from-font': 'from-font',
|
|
804
|
+
0: '0px',
|
|
805
|
+
1: '1px',
|
|
806
|
+
2: '2px',
|
|
807
|
+
4: '4px',
|
|
808
|
+
8: '8px',
|
|
809
|
+
},
|
|
810
|
+
textUnderlineOffset: {
|
|
811
|
+
auto: 'auto',
|
|
812
|
+
0: '0px',
|
|
813
|
+
1: '1px',
|
|
814
|
+
2: '2px',
|
|
815
|
+
4: '4px',
|
|
816
|
+
8: '8px',
|
|
817
|
+
},
|
|
800
818
|
textIndent: ({ theme }) => ({
|
|
801
819
|
...theme('spacing'),
|
|
802
820
|
}),
|