tailwindcss 0.0.0-insiders.bb0ab67 → 0.0.0-insiders.bb4f5da
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 +12 -1
- package/lib/cli-peer-dependencies.js +4 -3
- package/lib/cli.js +38 -9
- package/lib/corePlugins.js +3 -0
- package/lib/lib/defaultExtractor.js +159 -32
- package/lib/lib/expandApplyAtRules.js +21 -3
- package/lib/lib/expandTailwindAtRules.js +4 -4
- package/lib/lib/generateRules.js +27 -2
- package/lib/lib/regex.js +53 -0
- package/lib/lib/setupContextUtils.js +70 -35
- package/lib/lib/setupTrackingContext.js +3 -0
- package/lib/util/normalizeConfig.js +0 -7
- package/lib/util/parseBoxShadowValue.js +2 -43
- package/lib/util/splitAtTopLevelOnly.js +72 -0
- package/lib/util/validateConfig.js +21 -0
- package/package.json +4 -4
- package/peers/index.js +38 -37
- package/src/cli-peer-dependencies.js +3 -1
- package/src/cli.js +44 -8
- package/src/corePlugins.js +1 -0
- package/src/lib/defaultExtractor.js +165 -35
- package/src/lib/expandApplyAtRules.js +32 -4
- package/src/lib/expandTailwindAtRules.js +4 -4
- package/src/lib/generateRules.js +27 -1
- package/src/lib/regex.js +74 -0
- package/src/lib/setupContextUtils.js +82 -36
- package/src/lib/setupTrackingContext.js +4 -0
- package/src/util/normalizeConfig.js +0 -8
- package/src/util/parseBoxShadowValue.js +3 -50
- package/src/util/splitAtTopLevelOnly.js +71 -0
- package/src/util/validateConfig.js +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -19,7 +19,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
19
19
|
- Support PostCSS config options in config file in CLI ([#8226](https://github.com/tailwindlabs/tailwindcss/pull/8226))
|
|
20
20
|
- Remove default `[hidden]` style in preflight ([#8248](https://github.com/tailwindlabs/tailwindcss/pull/8248))
|
|
21
21
|
- Only check selectors containing base apply candidates for circular dependencies ([#8222](https://github.com/tailwindlabs/tailwindcss/pull/8222))
|
|
22
|
-
-
|
|
22
|
+
- Rewrite default class extractor ([#8204](https://github.com/tailwindlabs/tailwindcss/pull/8204))
|
|
23
|
+
- Move `important` selector to the front when `@apply`-ing selector-modifying variants in custom utilities ([#8313](https://github.com/tailwindlabs/tailwindcss/pull/8313))
|
|
24
|
+
- Error when registering an invalid custom variant ([#8345](https://github.com/tailwindlabs/tailwindcss/pull/8345))
|
|
25
|
+
- Create tailwind.config.cjs file in ESM package when running init ([#8363](https://github.com/tailwindlabs/tailwindcss/pull/8363))
|
|
26
|
+
- Fix `matchVariants` that use at-rules and placeholders ([#8392](https://github.com/tailwindlabs/tailwindcss/pull/8392))
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- Try using local `postcss` installation first in the CLI ([#8270](https://github.com/tailwindlabs/tailwindcss/pull/8270))
|
|
23
31
|
|
|
24
32
|
### Added
|
|
25
33
|
|
|
@@ -34,6 +42,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
34
42
|
- Add TypeScript types for the `tailwind.config.js` file ([#7891](https://github.com/tailwindlabs/tailwindcss/pull/7891))
|
|
35
43
|
- Add `backdrop` variant ([#7924](https://github.com/tailwindlabs/tailwindcss/pull/7924))
|
|
36
44
|
- Add `grid-flow-dense` utility ([#8193](https://github.com/tailwindlabs/tailwindcss/pull/8193))
|
|
45
|
+
- Add `mix-blend-plus-lighter` utility ([#8288](https://github.com/tailwindlabs/tailwindcss/pull/8288))
|
|
46
|
+
- Add arbitrary variants ([#8299](https://github.com/tailwindlabs/tailwindcss/pull/8299))
|
|
47
|
+
- Add `matchVariant` API ([#8310](https://github.com/tailwindlabs/tailwindcss/pull/8310))
|
|
37
48
|
|
|
38
49
|
## [3.0.24] - 2022-04-12
|
|
39
50
|
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
+
exports.lazyPostcss = lazyPostcss;
|
|
5
6
|
exports.lazyAutoprefixer = lazyAutoprefixer;
|
|
6
7
|
exports.lazyCssnano = lazyCssnano;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
function lazyPostcss() {
|
|
9
|
+
return require("postcss");
|
|
10
|
+
}
|
|
10
11
|
function lazyAutoprefixer() {
|
|
11
12
|
return require("autoprefixer");
|
|
12
13
|
}
|
package/lib/cli.js
CHANGED
|
@@ -18,6 +18,7 @@ var _getModuleDependencies = _interopRequireDefault(require("./lib/getModuleDepe
|
|
|
18
18
|
var _log = _interopRequireDefault(require("./util/log"));
|
|
19
19
|
var _packageJson = _interopRequireDefault(require("../package.json"));
|
|
20
20
|
var _normalizePath = _interopRequireDefault(require("normalize-path"));
|
|
21
|
+
var _validateConfigJs = require("./util/validateConfig.js");
|
|
21
22
|
function _interopRequireDefault(obj) {
|
|
22
23
|
return obj && obj.__esModule ? obj : {
|
|
23
24
|
default: obj
|
|
@@ -26,6 +27,22 @@ function _interopRequireDefault(obj) {
|
|
|
26
27
|
let env = {
|
|
27
28
|
DEBUG: process.env.DEBUG !== undefined && process.env.DEBUG !== "0"
|
|
28
29
|
};
|
|
30
|
+
function isESM() {
|
|
31
|
+
const pkgPath = _path.default.resolve("./package.json");
|
|
32
|
+
try {
|
|
33
|
+
let pkg = JSON.parse(_fs.default.readFileSync(pkgPath, "utf8"));
|
|
34
|
+
return pkg.type && pkg.type === "module";
|
|
35
|
+
} catch (err) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
let configs = isESM() ? {
|
|
40
|
+
tailwind: "tailwind.config.cjs",
|
|
41
|
+
postcss: "postcss.config.cjs"
|
|
42
|
+
} : {
|
|
43
|
+
tailwind: "tailwind.config.js",
|
|
44
|
+
postcss: "postcss.config.js"
|
|
45
|
+
};
|
|
29
46
|
// ---
|
|
30
47
|
function indentRecursive(node, indent = 0) {
|
|
31
48
|
node.each && node.each((child, i)=>{
|
|
@@ -130,21 +147,28 @@ function oneOf(...options) {
|
|
|
130
147
|
manualParsing: true
|
|
131
148
|
});
|
|
132
149
|
}
|
|
150
|
+
function loadPostcss() {
|
|
151
|
+
// Try to load a local `postcss` version first
|
|
152
|
+
try {
|
|
153
|
+
return require("postcss");
|
|
154
|
+
} catch {}
|
|
155
|
+
return (0, _indexJs).lazyPostcss();
|
|
156
|
+
}
|
|
133
157
|
let commands = {
|
|
134
158
|
init: {
|
|
135
159
|
run: init,
|
|
136
160
|
args: {
|
|
137
161
|
"--full": {
|
|
138
162
|
type: Boolean,
|
|
139
|
-
description:
|
|
163
|
+
description: `Initialize a full \`${configs.tailwind}\` file`
|
|
140
164
|
},
|
|
141
165
|
"--postcss": {
|
|
142
166
|
type: Boolean,
|
|
143
|
-
description:
|
|
167
|
+
description: `Initialize a \`${configs.postcss}\` file`
|
|
144
168
|
},
|
|
145
169
|
"--types": {
|
|
146
170
|
type: Boolean,
|
|
147
|
-
description:
|
|
171
|
+
description: `Add TypeScript types for the \`${configs.tailwind}\` file`
|
|
148
172
|
},
|
|
149
173
|
"-f": "--full",
|
|
150
174
|
"-p": "--postcss"
|
|
@@ -328,7 +352,7 @@ run();
|
|
|
328
352
|
function init() {
|
|
329
353
|
let messages = [];
|
|
330
354
|
var ref;
|
|
331
|
-
let tailwindConfigLocation = _path.default.resolve((ref = args["_"][1]) !== null && ref !== void 0 ? ref :
|
|
355
|
+
let tailwindConfigLocation = _path.default.resolve((ref = args["_"][1]) !== null && ref !== void 0 ? ref : `./${configs.tailwind}`);
|
|
332
356
|
if (_fs.default.existsSync(tailwindConfigLocation)) {
|
|
333
357
|
messages.push(`${_path.default.basename(tailwindConfigLocation)} already exists.`);
|
|
334
358
|
} else {
|
|
@@ -343,7 +367,7 @@ function init() {
|
|
|
343
367
|
messages.push(`Created Tailwind CSS config file: ${_path.default.basename(tailwindConfigLocation)}`);
|
|
344
368
|
}
|
|
345
369
|
if (args["--postcss"]) {
|
|
346
|
-
let postcssConfigLocation = _path.default.resolve(
|
|
370
|
+
let postcssConfigLocation = _path.default.resolve(`./${configs.postcss}`);
|
|
347
371
|
if (_fs.default.existsSync(postcssConfigLocation)) {
|
|
348
372
|
messages.push(`${_path.default.basename(postcssConfigLocation)} already exists.`);
|
|
349
373
|
} else {
|
|
@@ -383,7 +407,7 @@ async function build() {
|
|
|
383
407
|
process.exit(9);
|
|
384
408
|
}
|
|
385
409
|
let configPath = args["--config"] ? args["--config"] : ((defaultPath)=>_fs.default.existsSync(defaultPath) ? defaultPath : null
|
|
386
|
-
)(_path.default.resolve(
|
|
410
|
+
)(_path.default.resolve(`./${configs.tailwind}`));
|
|
387
411
|
async function loadPostCssPlugins() {
|
|
388
412
|
let customPostCssPath = typeof args["--postcss"] === "string" ? args["--postcss"] : undefined;
|
|
389
413
|
let config1 = customPostCssPath ? await (async ()=>{
|
|
@@ -441,9 +465,12 @@ async function build() {
|
|
|
441
465
|
}
|
|
442
466
|
});
|
|
443
467
|
resolvedConfig.content.files = files;
|
|
468
|
+
resolvedConfig = (0, _validateConfigJs).validateConfig(resolvedConfig);
|
|
444
469
|
return resolvedConfig;
|
|
445
470
|
}
|
|
446
|
-
|
|
471
|
+
let resolvedConfig = (0, _resolveConfig).default(config);
|
|
472
|
+
resolvedConfig = (0, _validateConfigJs).validateConfig(resolvedConfig);
|
|
473
|
+
return resolvedConfig;
|
|
447
474
|
}
|
|
448
475
|
function extractFileGlobs(config) {
|
|
449
476
|
return config.content.files.filter((file)=>{
|
|
@@ -528,7 +555,8 @@ async function build() {
|
|
|
528
555
|
return (0, _indexJs).lazyCssnano()(options);
|
|
529
556
|
})(),
|
|
530
557
|
].filter(Boolean);
|
|
531
|
-
let
|
|
558
|
+
let postcss = loadPostcss();
|
|
559
|
+
let processor = postcss(plugins);
|
|
532
560
|
function processCSS(css) {
|
|
533
561
|
let start = process.hrtime.bigint();
|
|
534
562
|
return Promise.resolve().then(()=>output ? _fs.default.promises.mkdir(_path.default.dirname(output), {
|
|
@@ -649,7 +677,8 @@ async function build() {
|
|
|
649
677
|
let tailwindPluginIdx = plugins.indexOf("__TAILWIND_PLUGIN_POSITION__");
|
|
650
678
|
let copy = plugins.slice();
|
|
651
679
|
copy.splice(tailwindPluginIdx, 1, tailwindPlugin);
|
|
652
|
-
let
|
|
680
|
+
let postcss = loadPostcss();
|
|
681
|
+
let processor = postcss(copy);
|
|
653
682
|
function processCSS(css) {
|
|
654
683
|
let start = process.hrtime.bigint();
|
|
655
684
|
return Promise.resolve().then(()=>output ? _fs.default.promises.mkdir(_path.default.dirname(output), {
|
package/lib/corePlugins.js
CHANGED
|
@@ -3,38 +3,165 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
5
|
exports.defaultExtractor = defaultExtractor;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
6
|
+
var regex = _interopRequireWildcard(require("./regex"));
|
|
7
|
+
function _interopRequireWildcard(obj) {
|
|
8
|
+
if (obj && obj.__esModule) {
|
|
9
|
+
return obj;
|
|
10
|
+
} else {
|
|
11
|
+
var newObj = {};
|
|
12
|
+
if (obj != null) {
|
|
13
|
+
for(var key in obj){
|
|
14
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
15
|
+
var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
|
|
16
|
+
if (desc.get || desc.set) {
|
|
17
|
+
Object.defineProperty(newObj, key, desc);
|
|
18
|
+
} else {
|
|
19
|
+
newObj[key] = obj[key];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
newObj.default = obj;
|
|
25
|
+
return newObj;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function defaultExtractor(context) {
|
|
29
|
+
let patterns = Array.from(buildRegExps(context));
|
|
30
|
+
/**
|
|
31
|
+
* @param {string} content
|
|
32
|
+
*/ return (content)=>{
|
|
33
|
+
/** @type {(string|string)[]} */ let results = [];
|
|
34
|
+
for (let pattern of patterns){
|
|
35
|
+
var ref;
|
|
36
|
+
results.push(...(ref = content.match(pattern)) !== null && ref !== void 0 ? ref : []);
|
|
37
|
+
}
|
|
38
|
+
return results.filter((v)=>v !== undefined
|
|
39
|
+
).map(clipAtBalancedParens);
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function* buildRegExps(context) {
|
|
43
|
+
let separator = context.tailwindConfig.separator;
|
|
44
|
+
yield regex.pattern([
|
|
45
|
+
// Variants
|
|
46
|
+
"((?=((",
|
|
47
|
+
regex.any([
|
|
48
|
+
regex.pattern([
|
|
49
|
+
/([^\s"'\[\\]+-)?\[[^\s"'\\]+\]/,
|
|
50
|
+
separator
|
|
51
|
+
]),
|
|
52
|
+
regex.pattern([
|
|
53
|
+
/[^\s"'\[\\]+/,
|
|
54
|
+
separator
|
|
55
|
+
]),
|
|
56
|
+
], true),
|
|
57
|
+
")+))\\2)?",
|
|
58
|
+
// Important (optional)
|
|
59
|
+
/!?/,
|
|
60
|
+
regex.any([
|
|
61
|
+
// Arbitrary properties
|
|
62
|
+
/\[[^\s:'"]+:[^\s\]]+\]/,
|
|
63
|
+
// Utilities
|
|
64
|
+
regex.pattern([
|
|
65
|
+
// Utility Name / Group Name
|
|
66
|
+
/-?(?:\w+)/,
|
|
67
|
+
// Normal/Arbitrary values
|
|
68
|
+
regex.optional(regex.any([
|
|
69
|
+
regex.pattern([
|
|
70
|
+
// Arbitrary values
|
|
71
|
+
/-\[[^\s:]+\]/,
|
|
72
|
+
// Not immediately followed by an `{[(`
|
|
73
|
+
/(?![{([]])/,
|
|
74
|
+
// optionally followed by an opacity modifier
|
|
75
|
+
/(?:\/[^\s'"\\$]*)?/,
|
|
76
|
+
]),
|
|
77
|
+
regex.pattern([
|
|
78
|
+
// Arbitrary values
|
|
79
|
+
/-\[[^\s]+\]/,
|
|
80
|
+
// Not immediately followed by an `{[(`
|
|
81
|
+
/(?![{([]])/,
|
|
82
|
+
// optionally followed by an opacity modifier
|
|
83
|
+
/(?:\/[^\s'"\\$]*)?/,
|
|
84
|
+
]),
|
|
85
|
+
// Normal values w/o quotes — may include an opacity modifier
|
|
86
|
+
/[-\/][^\s'"\\$={]*/,
|
|
87
|
+
])),
|
|
88
|
+
]),
|
|
89
|
+
]),
|
|
90
|
+
]);
|
|
91
|
+
// 5. Inner matches
|
|
92
|
+
// yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
|
|
93
|
+
}
|
|
94
|
+
// We want to capture any "special" characters
|
|
95
|
+
// AND the characters immediately following them (if there is one)
|
|
96
|
+
let SPECIALS = /([\[\]'"`])([^\[\]'"`])?/g;
|
|
97
|
+
let ALLOWED_CLASS_CHARACTERS = /[^"'`\s<>\]]+/;
|
|
98
|
+
/**
|
|
99
|
+
* Clips a string ensuring that parentheses, quotes, etc… are balanced
|
|
100
|
+
* Used for arbitrary values only
|
|
101
|
+
*
|
|
102
|
+
* We will go past the end of the balanced parens until we find a non-class character
|
|
103
|
+
*
|
|
104
|
+
* Depth matching behavior:
|
|
105
|
+
* w-[calc(100%-theme('spacing[some_key][1.5]'))]']
|
|
106
|
+
* ┬ ┬ ┬┬ ┬ ┬┬ ┬┬┬┬┬┬┬
|
|
107
|
+
* 1 2 3 4 34 3 210 END
|
|
108
|
+
* ╰────┴──────────┴────────┴────────┴┴───┴─┴┴┴
|
|
109
|
+
*
|
|
110
|
+
* @param {string} input
|
|
111
|
+
*/ function clipAtBalancedParens(input) {
|
|
112
|
+
// We are care about this for arbitrary values
|
|
113
|
+
if (!input.includes("-[")) {
|
|
114
|
+
return input;
|
|
115
|
+
}
|
|
116
|
+
let depth = 0;
|
|
117
|
+
let openStringTypes = [];
|
|
118
|
+
// Find all parens, brackets, quotes, etc
|
|
119
|
+
// Stop when we end at a balanced pair
|
|
120
|
+
// This is naive and will treat mismatched parens as balanced
|
|
121
|
+
// This shouldn't be a problem in practice though
|
|
122
|
+
let matches = input.matchAll(SPECIALS);
|
|
123
|
+
// We can't use lookbehind assertions because we have to support Safari
|
|
124
|
+
// So, instead, we've emulated it using capture groups and we'll re-work the matches to accommodate
|
|
125
|
+
matches = Array.from(matches).flatMap((match)=>{
|
|
126
|
+
const [, ...groups] = match;
|
|
127
|
+
return groups.map((group, idx)=>Object.assign([], match, {
|
|
128
|
+
index: match.index + idx,
|
|
129
|
+
0: group
|
|
130
|
+
})
|
|
131
|
+
);
|
|
132
|
+
});
|
|
133
|
+
for (let match1 of matches){
|
|
134
|
+
let char = match1[0];
|
|
135
|
+
let inStringType = openStringTypes[openStringTypes.length - 1];
|
|
136
|
+
if (char === inStringType) {
|
|
137
|
+
openStringTypes.pop();
|
|
138
|
+
} else if (char === "'" || char === '"' || char === "`") {
|
|
139
|
+
openStringTypes.push(char);
|
|
140
|
+
}
|
|
141
|
+
if (inStringType) {
|
|
142
|
+
continue;
|
|
143
|
+
} else if (char === "[") {
|
|
144
|
+
depth++;
|
|
145
|
+
continue;
|
|
146
|
+
} else if (char === "]") {
|
|
147
|
+
depth--;
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
// We've gone one character past the point where we should stop
|
|
151
|
+
// This means that there was an extra closing `]`
|
|
152
|
+
// We'll clip to just before it
|
|
153
|
+
if (depth < 0) {
|
|
154
|
+
return input.substring(0, match1.index);
|
|
155
|
+
}
|
|
156
|
+
// We've finished balancing the brackets but there still may be characters that can be included
|
|
157
|
+
// For example in the class `text-[#336699]/[.35]`
|
|
158
|
+
// The depth goes to `0` at the closing `]` but goes up again at the `[`
|
|
159
|
+
// If we're at zero and encounter a non-class character then we clip the class there
|
|
160
|
+
if (depth === 0 && !ALLOWED_CLASS_CHARACTERS.test(char)) {
|
|
161
|
+
return input.substring(0, match1.index);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return input;
|
|
38
165
|
} // Regular utilities
|
|
39
166
|
// {{modifier}:}*{namespace}{-{suffix}}*{/{opacityModifier}}?
|
|
40
167
|
// Arbitrary values
|
|
@@ -47,6 +47,14 @@ function _interopRequireDefault(obj) {
|
|
|
47
47
|
groups: normalizedGroups
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
|
+
let selectorExtractor = (0, _postcssSelectorParser).default((root)=>root.nodes.map((node)=>node.toString()
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
/**
|
|
54
|
+
* @param {string} ruleSelectors
|
|
55
|
+
*/ function extractSelectors(ruleSelectors) {
|
|
56
|
+
return selectorExtractor.transformSync(ruleSelectors);
|
|
57
|
+
}
|
|
50
58
|
function extractBaseCandidates(candidates, separator) {
|
|
51
59
|
let baseClasses = new Set();
|
|
52
60
|
for (let candidate of candidates){
|
|
@@ -281,8 +289,8 @@ function processApply(root, context, localCache) {
|
|
|
281
289
|
needle1.replace(/\\2c /g, "\\,")
|
|
282
290
|
])
|
|
283
291
|
];
|
|
284
|
-
let utilitySelectorsList = utilitySelectors
|
|
285
|
-
return selector
|
|
292
|
+
let utilitySelectorsList = extractSelectors(utilitySelectors);
|
|
293
|
+
return extractSelectors(selector).map((s)=>{
|
|
286
294
|
let replaced = [];
|
|
287
295
|
for (let utilitySelector of utilitySelectorsList){
|
|
288
296
|
let replacedSelector = utilitySelector;
|
|
@@ -429,7 +437,17 @@ function processApply(root, context, localCache) {
|
|
|
429
437
|
rule.remove();
|
|
430
438
|
return;
|
|
431
439
|
}
|
|
432
|
-
|
|
440
|
+
// Strip the important selector from the parent selector if at the beginning
|
|
441
|
+
let importantSelector = typeof context.tailwindConfig.important === "string" ? context.tailwindConfig.important : null;
|
|
442
|
+
// We only want to move the "important" selector if this is a Tailwind-generated utility
|
|
443
|
+
// We do *not* want to do this for user CSS that happens to be structured the same
|
|
444
|
+
let isGenerated = parent.raws.tailwind !== undefined;
|
|
445
|
+
let parentSelector = isGenerated && importantSelector && parent.selector.indexOf(importantSelector) === 0 ? parent.selector.slice(importantSelector.length) : parent.selector;
|
|
446
|
+
rule.selector = replaceSelector(parentSelector, rule.selector, applyCandidate);
|
|
447
|
+
// And then re-add it if it was removed
|
|
448
|
+
if (importantSelector && parentSelector !== parent.selector) {
|
|
449
|
+
rule.selector = `${importantSelector} ${rule.selector}`;
|
|
450
|
+
}
|
|
433
451
|
rule.walkDecls((d)=>{
|
|
434
452
|
d.important = meta.important || important;
|
|
435
453
|
});
|
|
@@ -42,7 +42,7 @@ function expandTailwindAtRules(context) {
|
|
|
42
42
|
env.DEBUG && console.time("Reading changed files");
|
|
43
43
|
for (let { content , extension } of context.changedContent){
|
|
44
44
|
let transformer = getTransformer(context.tailwindConfig, extension);
|
|
45
|
-
let extractor = getExtractor(context
|
|
45
|
+
let extractor = getExtractor(context, extension);
|
|
46
46
|
getClassCandidates(transformer(content), extractor, candidates, seen);
|
|
47
47
|
}
|
|
48
48
|
env.DEBUG && console.timeEnd("Reading changed files");
|
|
@@ -174,9 +174,9 @@ const builtInTransformers = {
|
|
|
174
174
|
,
|
|
175
175
|
svelte: (content)=>content.replace(/(?:^|\s)class:/g, " ")
|
|
176
176
|
};
|
|
177
|
-
function getExtractor(
|
|
178
|
-
let extractors = tailwindConfig.content.extract;
|
|
179
|
-
return extractors[fileExtension] || extractors.DEFAULT || builtInExtractors[fileExtension] || builtInExtractors.DEFAULT;
|
|
177
|
+
function getExtractor(context, fileExtension) {
|
|
178
|
+
let extractors = context.tailwindConfig.content.extract;
|
|
179
|
+
return extractors[fileExtension] || extractors.DEFAULT || builtInExtractors[fileExtension] || builtInExtractors.DEFAULT(context);
|
|
180
180
|
}
|
|
181
181
|
function getTransformer(tailwindConfig, fileExtension) {
|
|
182
182
|
let transformers = tailwindConfig.content.transform;
|
package/lib/lib/generateRules.js
CHANGED
|
@@ -14,7 +14,9 @@ var sharedState = _interopRequireWildcard(require("./sharedState"));
|
|
|
14
14
|
var _formatVariantSelector = require("../util/formatVariantSelector");
|
|
15
15
|
var _nameClass = require("../util/nameClass");
|
|
16
16
|
var _dataTypes = require("../util/dataTypes");
|
|
17
|
+
var _setupContextUtils = require("./setupContextUtils");
|
|
17
18
|
var _isValidArbitraryValue = _interopRequireDefault(require("../util/isValidArbitraryValue"));
|
|
19
|
+
var _splitAtTopLevelOnlyJs = require("../util/splitAtTopLevelOnly.js");
|
|
18
20
|
function _interopRequireDefault(obj) {
|
|
19
21
|
return obj && obj.__esModule ? obj : {
|
|
20
22
|
default: obj
|
|
@@ -151,6 +153,28 @@ function applyVariant(variant, matches, context) {
|
|
|
151
153
|
if (matches.length === 0) {
|
|
152
154
|
return matches;
|
|
153
155
|
}
|
|
156
|
+
let args;
|
|
157
|
+
// Find partial arbitrary variants
|
|
158
|
+
if (variant.endsWith("]") && !variant.startsWith("[")) {
|
|
159
|
+
args = variant.slice(variant.lastIndexOf("[") + 1, -1);
|
|
160
|
+
variant = variant.slice(0, variant.indexOf(args) - 1 /* - */ - 1 /* [ */ );
|
|
161
|
+
}
|
|
162
|
+
// Register arbitrary variants
|
|
163
|
+
if (isArbitraryValue(variant) && !context.variantMap.has(variant)) {
|
|
164
|
+
let selector = (0, _dataTypes).normalize(variant.slice(1, -1));
|
|
165
|
+
if (!(0, _setupContextUtils).isValidVariantFormatString(selector)) {
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
let fn = (0, _setupContextUtils).parseVariant(selector);
|
|
169
|
+
let sort = Array.from(context.variantOrder.values()).pop() << 1n;
|
|
170
|
+
context.variantMap.set(variant, [
|
|
171
|
+
[
|
|
172
|
+
sort,
|
|
173
|
+
fn
|
|
174
|
+
]
|
|
175
|
+
]);
|
|
176
|
+
context.variantOrder.set(variant, sort);
|
|
177
|
+
}
|
|
154
178
|
if (context.variantMap.has(variant)) {
|
|
155
179
|
let variantFunctionTuples = context.variantMap.get(variant);
|
|
156
180
|
let result = [];
|
|
@@ -207,7 +231,8 @@ function applyVariant(variant, matches, context) {
|
|
|
207
231
|
},
|
|
208
232
|
format (selectorFormat) {
|
|
209
233
|
collectedFormats.push(selectorFormat);
|
|
210
|
-
}
|
|
234
|
+
},
|
|
235
|
+
args
|
|
211
236
|
});
|
|
212
237
|
if (typeof ruleWithVariant === "string") {
|
|
213
238
|
collectedFormats.push(ruleWithVariant);
|
|
@@ -416,7 +441,7 @@ function splitWithSeparator(input, separator) {
|
|
|
416
441
|
sharedState.NOT_ON_DEMAND
|
|
417
442
|
];
|
|
418
443
|
}
|
|
419
|
-
return
|
|
444
|
+
return Array.from((0, _splitAtTopLevelOnlyJs).splitAtTopLevelOnly(input, separator));
|
|
420
445
|
}
|
|
421
446
|
function* recordCandidates(matches, classCandidate) {
|
|
422
447
|
for (const match of matches){
|
package/lib/lib/regex.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
exports.pattern = pattern;
|
|
6
|
+
exports.withoutCapturing = withoutCapturing;
|
|
7
|
+
exports.any = any;
|
|
8
|
+
exports.optional = optional;
|
|
9
|
+
exports.zeroOrMore = zeroOrMore;
|
|
10
|
+
exports.nestedBrackets = nestedBrackets;
|
|
11
|
+
exports.escape = escape;
|
|
12
|
+
const REGEX_SPECIAL = /[\\^$.*+?()[\]{}|]/g;
|
|
13
|
+
const REGEX_HAS_SPECIAL = RegExp(REGEX_SPECIAL.source);
|
|
14
|
+
/**
|
|
15
|
+
* @param {string|RegExp|Array<string|RegExp>} source
|
|
16
|
+
*/ function toSource(source) {
|
|
17
|
+
source = Array.isArray(source) ? source : [
|
|
18
|
+
source
|
|
19
|
+
];
|
|
20
|
+
source = source.map((item)=>item instanceof RegExp ? item.source : item
|
|
21
|
+
);
|
|
22
|
+
return source.join("");
|
|
23
|
+
}
|
|
24
|
+
function pattern(source) {
|
|
25
|
+
return new RegExp(toSource(source), "g");
|
|
26
|
+
}
|
|
27
|
+
function withoutCapturing(source) {
|
|
28
|
+
return new RegExp(`(?:${toSource(source)})`, "g");
|
|
29
|
+
}
|
|
30
|
+
function any(sources) {
|
|
31
|
+
return `(?:${sources.map(toSource).join("|")})`;
|
|
32
|
+
}
|
|
33
|
+
function optional(source) {
|
|
34
|
+
return `(?:${toSource(source)})?`;
|
|
35
|
+
}
|
|
36
|
+
function zeroOrMore(source) {
|
|
37
|
+
return `(?:${toSource(source)})*`;
|
|
38
|
+
}
|
|
39
|
+
function nestedBrackets(open, close, depth = 1) {
|
|
40
|
+
return withoutCapturing([
|
|
41
|
+
escape(open),
|
|
42
|
+
/[^\s]*/,
|
|
43
|
+
depth === 1 ? `[^${escape(open)}${escape(close)}\s]*` : any([
|
|
44
|
+
`[^${escape(open)}${escape(close)}\s]*`,
|
|
45
|
+
nestedBrackets(open, close, depth - 1)
|
|
46
|
+
]),
|
|
47
|
+
/[^\s]*/,
|
|
48
|
+
escape(close),
|
|
49
|
+
]);
|
|
50
|
+
}
|
|
51
|
+
function escape(string) {
|
|
52
|
+
return string && REGEX_HAS_SPECIAL.test(string) ? string.replace(REGEX_SPECIAL, "\\$&") : string || "";
|
|
53
|
+
}
|