postcss-merge-rules 8.0.1 → 8.0.3
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/LICENSE-MIT +1 -1
- package/README.md +1 -1
- package/package.json +33 -11
- package/src/index.js +171 -98
- package/src/lib/computeBrowsersToSupport.js +27 -0
- package/src/lib/ensureCompatibility.js +6 -5
- package/src/lib/getBrowsersForWebBuild.js +35 -0
- package/types/index.d.ts +9 -26
- package/types/index.d.ts.map +1 -1
- package/types/lib/computeBrowsersToSupport.d.ts +18 -0
- package/types/lib/computeBrowsersToSupport.d.ts.map +1 -0
- package/types/lib/ensureCompatibility.d.ts +62 -56
- package/types/lib/ensureCompatibility.d.ts.map +1 -1
- package/types/lib/getBrowsersForWebBuild.d.ts +3 -0
- package/types/lib/getBrowsersForWebBuild.d.ts.map +1 -0
package/LICENSE-MIT
CHANGED
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postcss-merge-rules",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.3",
|
|
4
4
|
"description": "Merge CSS rules with PostCSS.",
|
|
5
|
-
"
|
|
6
|
-
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./types/index.d.ts",
|
|
8
|
+
"default": "./src/index.js"
|
|
9
|
+
},
|
|
10
|
+
"./src": "./src/index.js",
|
|
11
|
+
"./src/index": "./src/index.js",
|
|
12
|
+
"./src/index.js": "./src/index.js",
|
|
13
|
+
"./src/lib/ensureCompatibility.js": "./src/lib/ensureCompatibility.js",
|
|
14
|
+
"./src/lib/ensureCompatibility": "./src/lib/ensureCompatibility.js",
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"imports": {
|
|
18
|
+
"#getBrowsersList": {
|
|
19
|
+
"node": "./src/lib/computeBrowsersToSupport.js",
|
|
20
|
+
"default": "./src/lib/getBrowsersForWebBuild.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
7
23
|
"files": [
|
|
8
24
|
"LICENSE-MIT",
|
|
9
25
|
"src",
|
|
@@ -20,14 +36,17 @@
|
|
|
20
36
|
"author": {
|
|
21
37
|
"name": "Ben Briggs",
|
|
22
38
|
"email": "beneb.info@gmail.com",
|
|
23
|
-
"url": "
|
|
39
|
+
"url": "https://beneb.info"
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "cssnano/cssnano"
|
|
24
44
|
},
|
|
25
|
-
"repository": "cssnano/cssnano",
|
|
26
45
|
"dependencies": {
|
|
27
|
-
"browserslist": "^4.28.
|
|
46
|
+
"browserslist": "^4.28.8",
|
|
28
47
|
"caniuse-api": "^4.0.0",
|
|
29
|
-
"postcss-selector-parser": "^7.1.
|
|
30
|
-
"cssnano-utils": "^6.0.
|
|
48
|
+
"postcss-selector-parser": "^7.1.5",
|
|
49
|
+
"cssnano-utils": "^6.0.3"
|
|
31
50
|
},
|
|
32
51
|
"bugs": {
|
|
33
52
|
"url": "https://github.com/cssnano/cssnano/issues"
|
|
@@ -36,11 +55,14 @@
|
|
|
36
55
|
"node": "^22.11.0 || ^24.11.0 || >=26.0"
|
|
37
56
|
},
|
|
38
57
|
"devDependencies": {
|
|
39
|
-
"postcss": "^8.5.
|
|
58
|
+
"postcss": "^8.5.26",
|
|
40
59
|
"postcss-simple-vars": "^7.0.1",
|
|
41
|
-
"postcss-discard-comments": "^8.0.
|
|
60
|
+
"postcss-discard-comments": "^8.0.3"
|
|
42
61
|
},
|
|
43
62
|
"peerDependencies": {
|
|
44
|
-
"postcss": "^8.5.
|
|
63
|
+
"postcss": "^8.5.26"
|
|
64
|
+
},
|
|
65
|
+
"scripts": {
|
|
66
|
+
"test": "node --test"
|
|
45
67
|
}
|
|
46
68
|
}
|
package/src/index.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
|
-
const
|
|
2
|
+
|
|
3
|
+
const getBrowsersList = require('#getBrowsersList');
|
|
4
|
+
|
|
5
|
+
/** @import browserslist from 'browserslist' */
|
|
6
|
+
|
|
4
7
|
const { sameParent } = require('cssnano-utils');
|
|
5
8
|
const {
|
|
6
9
|
ensureCompatibility,
|
|
7
10
|
sameVendor,
|
|
8
11
|
noVendor,
|
|
9
12
|
} = require('./lib/ensureCompatibility');
|
|
10
|
-
|
|
13
|
+
/** @import {Declaration, Rule} from 'postcss' */
|
|
11
14
|
/**
|
|
12
|
-
* @param {
|
|
13
|
-
* @param {
|
|
15
|
+
* @param {Declaration} a
|
|
16
|
+
* @param {Declaration} b
|
|
14
17
|
* @return {boolean}
|
|
15
18
|
*/
|
|
16
19
|
function declarationIsEqual(a, b) {
|
|
@@ -20,8 +23,8 @@ function declarationIsEqual(a, b) {
|
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
/**
|
|
23
|
-
* @param {
|
|
24
|
-
* @param {
|
|
26
|
+
* @param {Declaration[]} array
|
|
27
|
+
* @param {Declaration} decl
|
|
25
28
|
* @return {number}
|
|
26
29
|
*/
|
|
27
30
|
function indexOfDeclaration(array, decl) {
|
|
@@ -30,10 +33,10 @@ function indexOfDeclaration(array, decl) {
|
|
|
30
33
|
|
|
31
34
|
/**
|
|
32
35
|
* Returns filtered array of matched or unmatched declarations
|
|
33
|
-
* @param {
|
|
34
|
-
* @param {
|
|
36
|
+
* @param {Declaration[]} a
|
|
37
|
+
* @param {Declaration[]} b
|
|
35
38
|
* @param {boolean} [not=false]
|
|
36
|
-
* @return {
|
|
39
|
+
* @return {Declaration[]}
|
|
37
40
|
*/
|
|
38
41
|
function intersect(a, b, not) {
|
|
39
42
|
return a.filter((c) => {
|
|
@@ -43,8 +46,8 @@ function intersect(a, b, not) {
|
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
/**
|
|
46
|
-
* @param {
|
|
47
|
-
* @param {
|
|
49
|
+
* @param {Declaration[]} a
|
|
50
|
+
* @param {Declaration[]} b
|
|
48
51
|
* @return {boolean}
|
|
49
52
|
*/
|
|
50
53
|
function sameDeclarationsAndOrder(a, b) {
|
|
@@ -60,17 +63,17 @@ function sameDeclarationsAndOrder(a, b) {
|
|
|
60
63
|
*
|
|
61
64
|
* @typedef {Object} RuleMeta
|
|
62
65
|
* @property {string[]} selectors - Array of selector strings for the rule
|
|
63
|
-
* @property {
|
|
66
|
+
* @property {Declaration[]} declarations - Array of declaration nodes for the rule
|
|
64
67
|
* @property {boolean} dirty - Whether the selectors have been modified and need flushing
|
|
65
68
|
*/
|
|
66
69
|
|
|
67
70
|
/**
|
|
68
|
-
* @param {
|
|
69
|
-
* @param {
|
|
71
|
+
* @param {Rule} ruleA
|
|
72
|
+
* @param {Rule} ruleB
|
|
70
73
|
* @param {string[]} browsers
|
|
71
74
|
* @param {Map<string, boolean>} compatibilityCache
|
|
72
|
-
* @param {WeakSet<
|
|
73
|
-
* @param {WeakMap<
|
|
75
|
+
* @param {WeakSet<Rule>} ruleCache
|
|
76
|
+
* @param {WeakMap<Rule, RuleMeta>} ruleMeta
|
|
74
77
|
* @return {boolean}
|
|
75
78
|
*/
|
|
76
79
|
function canMerge(
|
|
@@ -131,7 +134,7 @@ function isRuleOrAtRule(node) {
|
|
|
131
134
|
}
|
|
132
135
|
/**
|
|
133
136
|
* @param {import('postcss').ChildNode} node
|
|
134
|
-
* @return {node is
|
|
137
|
+
* @return {node is Declaration}
|
|
135
138
|
*/
|
|
136
139
|
function isDeclaration(node) {
|
|
137
140
|
return node.type === 'decl';
|
|
@@ -143,8 +146,8 @@ function isDeclaration(node) {
|
|
|
143
146
|
* This metadata caches selectors and declarations to avoid expensive AST
|
|
144
147
|
* re-parsing, especially for the selectors.
|
|
145
148
|
*
|
|
146
|
-
* @param {
|
|
147
|
-
* @param {WeakMap<
|
|
149
|
+
* @param {Rule} rule The PostCSS rule to get metadata for.
|
|
150
|
+
* @param {WeakMap<Rule, RuleMeta>} [ruleMeta] The metadata cache.
|
|
148
151
|
* @return {RuleMeta} The rule's virtual metadata.
|
|
149
152
|
*/
|
|
150
153
|
function getMeta(rule, ruleMeta) {
|
|
@@ -170,8 +173,8 @@ function getMeta(rule, ruleMeta) {
|
|
|
170
173
|
/**
|
|
171
174
|
* Commits virtual metadata changes back to the actual PostCSS rule.
|
|
172
175
|
*
|
|
173
|
-
* @param {
|
|
174
|
-
* @param {WeakMap<
|
|
176
|
+
* @param {Rule} rule The PostCSS rule to flush.
|
|
177
|
+
* @param {WeakMap<Rule, RuleMeta>} ruleMeta The metadata cache.
|
|
175
178
|
*/
|
|
176
179
|
function flush(rule, ruleMeta) {
|
|
177
180
|
const meta = ruleMeta.get(rule);
|
|
@@ -182,15 +185,15 @@ function flush(rule, ruleMeta) {
|
|
|
182
185
|
}
|
|
183
186
|
|
|
184
187
|
/**
|
|
185
|
-
* @param {
|
|
186
|
-
* @return {
|
|
188
|
+
* @param {Rule} rule
|
|
189
|
+
* @return {Declaration[]}
|
|
187
190
|
*/
|
|
188
191
|
function getDecls(rule) {
|
|
189
192
|
return rule.nodes.filter(isDeclaration);
|
|
190
193
|
}
|
|
191
194
|
|
|
192
195
|
/**
|
|
193
|
-
* @param {...
|
|
196
|
+
* @param {...Rule} rules
|
|
194
197
|
* @return {number}
|
|
195
198
|
*/
|
|
196
199
|
function ruleLength(...rules) {
|
|
@@ -275,8 +278,8 @@ function isConflictingProp(propA, propB) {
|
|
|
275
278
|
}
|
|
276
279
|
|
|
277
280
|
/**
|
|
278
|
-
* @param {
|
|
279
|
-
* @param {
|
|
281
|
+
* @param {Rule} first
|
|
282
|
+
* @param {Rule} second
|
|
280
283
|
* @return {boolean} merged
|
|
281
284
|
*/
|
|
282
285
|
function mergeParents(first, second) {
|
|
@@ -298,31 +301,10 @@ function mergeParents(first, second) {
|
|
|
298
301
|
}
|
|
299
302
|
|
|
300
303
|
/**
|
|
301
|
-
* @param {
|
|
302
|
-
* @
|
|
303
|
-
* @param {string[]} browsers
|
|
304
|
-
* @param {Map<string, boolean>} compatibilityCache
|
|
305
|
-
* @param {WeakSet<import('postcss').Rule>} ruleCache
|
|
306
|
-
* @param {WeakMap<import('postcss').Rule, RuleMeta>} ruleMeta
|
|
307
|
-
* @return {import('postcss').Rule} mergedRule
|
|
304
|
+
* @param {Rule} second
|
|
305
|
+
* @return {Rule | null}
|
|
308
306
|
*/
|
|
309
|
-
function
|
|
310
|
-
first,
|
|
311
|
-
second,
|
|
312
|
-
browsers,
|
|
313
|
-
compatibilityCache,
|
|
314
|
-
ruleCache,
|
|
315
|
-
ruleMeta
|
|
316
|
-
) {
|
|
317
|
-
if (ruleMeta) {
|
|
318
|
-
flush(first, ruleMeta);
|
|
319
|
-
}
|
|
320
|
-
const metaFirst = getMeta(first, ruleMeta);
|
|
321
|
-
const metaSecond = getMeta(second, ruleMeta);
|
|
322
|
-
let intersection = intersect(metaFirst.declarations, metaSecond.declarations);
|
|
323
|
-
if (intersection.length === 0) {
|
|
324
|
-
return second;
|
|
325
|
-
}
|
|
307
|
+
function getNextRule(second) {
|
|
326
308
|
let nextRule = second.next();
|
|
327
309
|
if (!nextRule) {
|
|
328
310
|
// Grab next cousin
|
|
@@ -333,9 +315,32 @@ function partialMerge(
|
|
|
333
315
|
).next();
|
|
334
316
|
nextRule = parentSibling && parentSibling.nodes && parentSibling.nodes[0];
|
|
335
317
|
}
|
|
318
|
+
return nextRule?.type === 'rule' ? nextRule : null;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* @param {Rule} first
|
|
323
|
+
* @param {Rule} second
|
|
324
|
+
* @param {Declaration[]} intersection
|
|
325
|
+
* @param {string[]} browsers
|
|
326
|
+
* @param {Map<string, boolean>} compatibilityCache
|
|
327
|
+
* @param {WeakSet<Rule>} ruleCache
|
|
328
|
+
* @param {WeakMap<Rule, RuleMeta>} ruleMeta
|
|
329
|
+
* @return {{first: Rule, second: Rule, intersection: Declaration[]}}
|
|
330
|
+
*/
|
|
331
|
+
function mergeWithNextRule(
|
|
332
|
+
first,
|
|
333
|
+
second,
|
|
334
|
+
intersection,
|
|
335
|
+
browsers,
|
|
336
|
+
compatibilityCache,
|
|
337
|
+
ruleCache,
|
|
338
|
+
ruleMeta
|
|
339
|
+
) {
|
|
340
|
+
const nextRule = getNextRule(second);
|
|
336
341
|
if (
|
|
337
|
-
nextRule
|
|
338
|
-
canMerge(
|
|
342
|
+
!nextRule ||
|
|
343
|
+
!canMerge(
|
|
339
344
|
second,
|
|
340
345
|
nextRule,
|
|
341
346
|
browsers,
|
|
@@ -344,24 +349,28 @@ function partialMerge(
|
|
|
344
349
|
ruleMeta
|
|
345
350
|
)
|
|
346
351
|
) {
|
|
347
|
-
|
|
348
|
-
let nextIntersection = intersect(
|
|
349
|
-
metaSecond.declarations,
|
|
350
|
-
metaNext.declarations
|
|
351
|
-
);
|
|
352
|
-
if (nextIntersection.length > intersection.length) {
|
|
353
|
-
mergeParents(second, nextRule);
|
|
354
|
-
first = second;
|
|
355
|
-
second = nextRule;
|
|
356
|
-
intersection = nextIntersection;
|
|
357
|
-
}
|
|
352
|
+
return { first, second, intersection };
|
|
358
353
|
}
|
|
359
354
|
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
355
|
+
const nextIntersection = intersect(
|
|
356
|
+
getMeta(second, ruleMeta).declarations,
|
|
357
|
+
getMeta(nextRule, ruleMeta).declarations
|
|
358
|
+
);
|
|
359
|
+
if (nextIntersection.length <= intersection.length) {
|
|
360
|
+
return { first, second, intersection };
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
mergeParents(second, nextRule);
|
|
364
|
+
return { first: second, second: nextRule, intersection: nextIntersection };
|
|
365
|
+
}
|
|
364
366
|
|
|
367
|
+
/**
|
|
368
|
+
* @param {Declaration[]} intersection
|
|
369
|
+
* @param {Declaration[]} firstDecls
|
|
370
|
+
* @param {Declaration[]} secondDecls
|
|
371
|
+
* @return {Declaration[]}
|
|
372
|
+
*/
|
|
373
|
+
function filterIntersections(intersection, firstDecls, secondDecls) {
|
|
365
374
|
// Filter out intersections with later conflicts in First
|
|
366
375
|
intersection = intersection.filter((decl, intersectIndex) => {
|
|
367
376
|
const indexOfDecl = indexOfDeclaration(firstDecls, decl);
|
|
@@ -383,7 +392,7 @@ function partialMerge(
|
|
|
383
392
|
});
|
|
384
393
|
|
|
385
394
|
// Filter out intersections with previous conflicts in Second
|
|
386
|
-
|
|
395
|
+
return intersection.filter((decl) => {
|
|
387
396
|
const nextConflictIndex = secondDecls.findIndex((d) =>
|
|
388
397
|
isConflictingProp(d.prop, decl.prop)
|
|
389
398
|
);
|
|
@@ -405,15 +414,20 @@ function partialMerge(
|
|
|
405
414
|
secondDecls.splice(nextConflictIndex, 1);
|
|
406
415
|
return true;
|
|
407
416
|
});
|
|
417
|
+
}
|
|
408
418
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
419
|
+
/**
|
|
420
|
+
* @param {Rule} first
|
|
421
|
+
* @param {Rule} second
|
|
422
|
+
* @param {Declaration[]} intersection
|
|
423
|
+
* @param {WeakSet<Rule>} ruleCache
|
|
424
|
+
* @param {WeakMap<Rule, RuleMeta>} ruleMeta
|
|
425
|
+
* @return {Rule}
|
|
426
|
+
*/
|
|
427
|
+
function buildMergedRule(first, second, intersection, ruleCache, ruleMeta) {
|
|
414
428
|
const receivingBlock = second.clone();
|
|
415
|
-
const firstSelectors =
|
|
416
|
-
const secondSelectors =
|
|
429
|
+
const firstSelectors = getMeta(first, ruleMeta).selectors;
|
|
430
|
+
const secondSelectors = getMeta(second, ruleMeta).selectors;
|
|
417
431
|
|
|
418
432
|
receivingBlock.selector = [...firstSelectors, ...secondSelectors].join();
|
|
419
433
|
receivingBlock.nodes = [];
|
|
@@ -426,9 +440,9 @@ function partialMerge(
|
|
|
426
440
|
const secondClone = second.clone({ selectors: secondSelectors });
|
|
427
441
|
|
|
428
442
|
/**
|
|
429
|
-
* @param {
|
|
443
|
+
* @param {(decl: Declaration) => void} callback
|
|
430
444
|
* @this void
|
|
431
|
-
* @return {
|
|
445
|
+
* @return {(decl: Declaration) => void}
|
|
432
446
|
*/
|
|
433
447
|
function moveDecl(callback) {
|
|
434
448
|
return (decl) => {
|
|
@@ -438,10 +452,15 @@ function partialMerge(
|
|
|
438
452
|
};
|
|
439
453
|
}
|
|
440
454
|
firstClone.walkDecls(
|
|
441
|
-
moveDecl(
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
455
|
+
moveDecl(
|
|
456
|
+
/**
|
|
457
|
+
* @param {Declaration} decl
|
|
458
|
+
*/
|
|
459
|
+
(decl) => {
|
|
460
|
+
decl.remove();
|
|
461
|
+
receivingBlock.append(decl);
|
|
462
|
+
}
|
|
463
|
+
)
|
|
445
464
|
);
|
|
446
465
|
secondClone.walkDecls(moveDecl((decl) => decl.remove()));
|
|
447
466
|
|
|
@@ -456,11 +475,11 @@ function partialMerge(
|
|
|
456
475
|
if (merged < original) {
|
|
457
476
|
first.replaceWith(firstClone);
|
|
458
477
|
second.replaceWith(secondClone);
|
|
459
|
-
[firstClone, receivingBlock, secondClone]
|
|
478
|
+
for (const r of [firstClone, receivingBlock, secondClone]) {
|
|
460
479
|
if (r.nodes.length === 0) {
|
|
461
480
|
r.remove();
|
|
462
481
|
}
|
|
463
|
-
}
|
|
482
|
+
}
|
|
464
483
|
if (!secondClone.parent) {
|
|
465
484
|
ruleCache?.add(receivingBlock);
|
|
466
485
|
return receivingBlock;
|
|
@@ -470,21 +489,75 @@ function partialMerge(
|
|
|
470
489
|
ruleMeta?.delete(first);
|
|
471
490
|
ruleMeta?.delete(second);
|
|
472
491
|
return secondClone;
|
|
473
|
-
}
|
|
474
|
-
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
receivingBlock.remove();
|
|
495
|
+
return second;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* @param {Rule} first
|
|
500
|
+
* @param {Rule} second
|
|
501
|
+
* @param {string[]} browsers
|
|
502
|
+
* @param {Map<string, boolean>} compatibilityCache
|
|
503
|
+
* @param {WeakSet<Rule>} ruleCache
|
|
504
|
+
* @param {WeakMap<Rule, RuleMeta>} ruleMeta
|
|
505
|
+
* @return {Rule} mergedRule
|
|
506
|
+
*/
|
|
507
|
+
function partialMerge(
|
|
508
|
+
first,
|
|
509
|
+
second,
|
|
510
|
+
browsers,
|
|
511
|
+
compatibilityCache,
|
|
512
|
+
ruleCache,
|
|
513
|
+
ruleMeta
|
|
514
|
+
) {
|
|
515
|
+
if (ruleMeta) {
|
|
516
|
+
flush(first, ruleMeta);
|
|
517
|
+
}
|
|
518
|
+
const metaFirst = getMeta(first, ruleMeta);
|
|
519
|
+
const metaSecond = getMeta(second, ruleMeta);
|
|
520
|
+
let intersection = intersect(metaFirst.declarations, metaSecond.declarations);
|
|
521
|
+
if (intersection.length === 0) {
|
|
475
522
|
return second;
|
|
476
523
|
}
|
|
524
|
+
const mergedNext = mergeWithNextRule(
|
|
525
|
+
first,
|
|
526
|
+
second,
|
|
527
|
+
intersection,
|
|
528
|
+
browsers,
|
|
529
|
+
compatibilityCache,
|
|
530
|
+
ruleCache,
|
|
531
|
+
ruleMeta
|
|
532
|
+
);
|
|
533
|
+
first = mergedNext.first;
|
|
534
|
+
second = mergedNext.second;
|
|
535
|
+
intersection = mergedNext.intersection;
|
|
536
|
+
|
|
537
|
+
const metaFirstActual = getMeta(first, ruleMeta);
|
|
538
|
+
const metaSecondActual = getMeta(second, ruleMeta);
|
|
539
|
+
const firstDecls = [...metaFirstActual.declarations];
|
|
540
|
+
const secondDecls = [...metaSecondActual.declarations];
|
|
541
|
+
|
|
542
|
+
intersection = filterIntersections(intersection, firstDecls, secondDecls);
|
|
543
|
+
|
|
544
|
+
if (intersection.length === 0) {
|
|
545
|
+
// Nothing to merge
|
|
546
|
+
return second;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
return buildMergedRule(first, second, intersection, ruleCache, ruleMeta);
|
|
477
550
|
}
|
|
478
551
|
|
|
479
552
|
/**
|
|
480
553
|
* @param {string[]} browsers
|
|
481
554
|
* @param {Map<string, boolean>} compatibilityCache
|
|
482
|
-
* @param {WeakSet<
|
|
483
|
-
* @param {WeakMap<
|
|
484
|
-
* @return {{ merger:
|
|
555
|
+
* @param {WeakSet<Rule>} ruleCache
|
|
556
|
+
* @param {WeakMap<Rule, RuleMeta>} ruleMeta
|
|
557
|
+
* @return {{ merger: (rule: Rule) => void, clean: () => void }}
|
|
485
558
|
*/
|
|
486
559
|
function selectorMerger(browsers, compatibilityCache, ruleCache, ruleMeta) {
|
|
487
|
-
/** @type {
|
|
560
|
+
/** @type {Rule | null} */
|
|
488
561
|
let cache = null;
|
|
489
562
|
return {
|
|
490
563
|
merger(rule) {
|
|
@@ -550,7 +623,7 @@ function selectorMerger(browsers, compatibilityCache, ruleCache, ruleMeta) {
|
|
|
550
623
|
node.remove();
|
|
551
624
|
return;
|
|
552
625
|
}
|
|
553
|
-
/** @type {
|
|
626
|
+
/** @type {Rule} */ (cache).append(node);
|
|
554
627
|
});
|
|
555
628
|
getMeta(cache, ruleMeta).declarations = getDecls(cache);
|
|
556
629
|
rule.remove();
|
|
@@ -584,7 +657,6 @@ function selectorMerger(browsers, compatibilityCache, ruleCache, ruleMeta) {
|
|
|
584
657
|
*/
|
|
585
658
|
|
|
586
659
|
/**
|
|
587
|
-
* @type {import('postcss').PluginCreator<Options>}
|
|
588
660
|
* @param {Options} opts
|
|
589
661
|
* @return {import('postcss').Plugin}
|
|
590
662
|
*/
|
|
@@ -597,11 +669,7 @@ function pluginCreator(opts = {}) {
|
|
|
597
669
|
*/
|
|
598
670
|
prepare(result) {
|
|
599
671
|
const { stats, env, from, file } = result.opts || {};
|
|
600
|
-
const browsers =
|
|
601
|
-
stats: opts.stats || stats,
|
|
602
|
-
path: opts.path || dirname(from || file || __filename),
|
|
603
|
-
env: opts.env || env,
|
|
604
|
-
});
|
|
672
|
+
const browsers = getBrowsersList(opts, stats, from, file, env);
|
|
605
673
|
|
|
606
674
|
const compatibilityCache = new Map();
|
|
607
675
|
|
|
@@ -610,6 +678,9 @@ function pluginCreator(opts = {}) {
|
|
|
610
678
|
const ruleMeta = new WeakMap();
|
|
611
679
|
|
|
612
680
|
return {
|
|
681
|
+
/**
|
|
682
|
+
* @param {import('postcss').Root} css
|
|
683
|
+
*/
|
|
613
684
|
OnceExit(css) {
|
|
614
685
|
const { merger, clean } = selectorMerger(
|
|
615
686
|
browsers,
|
|
@@ -626,4 +697,6 @@ function pluginCreator(opts = {}) {
|
|
|
626
697
|
}
|
|
627
698
|
|
|
628
699
|
pluginCreator.postcss = true;
|
|
629
|
-
module.exports =
|
|
700
|
+
module.exports = /** @type {import('postcss').PluginCreator<Options>} */ (
|
|
701
|
+
pluginCreator
|
|
702
|
+
);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const browserslist = require('browserslist');
|
|
4
|
+
const { dirname } = require('node:path');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param {{overrideBrowserslist?: string | string[] | undefined, stats?: browserslist.Options["stats"], path?: browserslist.Options["path"], env?: browserslist.Options["env"]}} options
|
|
9
|
+
* @param {browserslist.Options["stats"]} stats
|
|
10
|
+
* @param {string|undefined} from
|
|
11
|
+
* @param {string} [file]
|
|
12
|
+
* @param {browserslist.Options["env"]} [env]
|
|
13
|
+
* @returns {string[]}
|
|
14
|
+
*/
|
|
15
|
+
module.exports = function computeBrowsersToSupport(
|
|
16
|
+
options,
|
|
17
|
+
stats,
|
|
18
|
+
from,
|
|
19
|
+
file,
|
|
20
|
+
env
|
|
21
|
+
) {
|
|
22
|
+
return browserslist(options.overrideBrowserslist, {
|
|
23
|
+
stats: options.stats || stats,
|
|
24
|
+
path: options.path || dirname(from || file || __filename),
|
|
25
|
+
env: options.env || env,
|
|
26
|
+
});
|
|
27
|
+
};
|
|
@@ -26,14 +26,15 @@ function filterPrefixes(selector) {
|
|
|
26
26
|
return selector.match(vendorPrefix);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
const inputPlaceholderRegex = /-ms-input-placeholder/i;
|
|
29
30
|
/**
|
|
30
31
|
* Internet Explorer use :-ms-input-placeholder.
|
|
31
32
|
* Microsoft Edge use ::-ms-input-placeholder.
|
|
32
33
|
*
|
|
33
|
-
* @type {(selector: string) =>
|
|
34
|
+
* @type {(selector: string) => boolean}
|
|
34
35
|
*/
|
|
35
36
|
const findMsInputPlaceholder = (selector) =>
|
|
36
|
-
|
|
37
|
+
inputPlaceholderRegex.test(selector);
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* @param {string[]} selectorsA
|
|
@@ -42,9 +43,9 @@ const findMsInputPlaceholder = (selector) =>
|
|
|
42
43
|
*/
|
|
43
44
|
function sameVendor(selectorsA, selectorsB) {
|
|
44
45
|
/** @type {(selectors: string[]) => string} */
|
|
45
|
-
|
|
46
|
+
const same = (selectors) => selectors.map(filterPrefixes).join();
|
|
46
47
|
/** @type {(selectors: string[]) => string | undefined} */
|
|
47
|
-
|
|
48
|
+
const findMsVendor = (selectors) => selectors.find(findMsInputPlaceholder);
|
|
48
49
|
return (
|
|
49
50
|
same(selectorsA) === same(selectorsB) &&
|
|
50
51
|
!(findMsVendor(selectorsA) && findMsVendor(selectorsB))
|
|
@@ -177,7 +178,7 @@ function ensureCompatibility(selectors, browsers, compatibilityCache) {
|
|
|
177
178
|
const { type, value } = node;
|
|
178
179
|
if (type === 'pseudo') {
|
|
179
180
|
const entry =
|
|
180
|
-
pseudoElements[/** @type
|
|
181
|
+
pseudoElements[/** @type keyof typeof pseudoElements*/ (value)];
|
|
181
182
|
if (!entry && noVendor(value)) {
|
|
182
183
|
compatible = false;
|
|
183
184
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = function () {
|
|
4
|
+
return [
|
|
5
|
+
'and_chr 150',
|
|
6
|
+
'and_ff 152',
|
|
7
|
+
'and_qq 14.9',
|
|
8
|
+
'and_uc 15.5',
|
|
9
|
+
'android 150',
|
|
10
|
+
'chrome 150',
|
|
11
|
+
'chrome 149',
|
|
12
|
+
'chrome 148',
|
|
13
|
+
'chrome 118',
|
|
14
|
+
'chrome 109',
|
|
15
|
+
'edge 150',
|
|
16
|
+
'edge 149',
|
|
17
|
+
'edge 148',
|
|
18
|
+
'firefox 152',
|
|
19
|
+
'firefox 151',
|
|
20
|
+
'firefox 140',
|
|
21
|
+
'ios_saf 26.5',
|
|
22
|
+
'ios_saf 26.4',
|
|
23
|
+
'ios_saf 26.3',
|
|
24
|
+
'ios_saf 18.5-18.7',
|
|
25
|
+
'kaios 3.0-3.1',
|
|
26
|
+
'op_mob 80',
|
|
27
|
+
'opera 131',
|
|
28
|
+
'opera 127',
|
|
29
|
+
'safari 26.5',
|
|
30
|
+
'safari 26.4',
|
|
31
|
+
'safari 26.3',
|
|
32
|
+
'samsung 30',
|
|
33
|
+
'samsung 29',
|
|
34
|
+
];
|
|
35
|
+
};
|
package/types/index.d.ts
CHANGED
|
@@ -1,24 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* @type {import('postcss').PluginCreator<Options>}
|
|
9
|
-
* @param {Options} opts
|
|
10
|
-
* @return {import('postcss').Plugin}
|
|
11
|
-
*/
|
|
12
|
-
declare function pluginCreator(opts?: Options): import("postcss").Plugin;
|
|
13
|
-
declare namespace pluginCreator {
|
|
14
|
-
export { postcss, RuleMeta, AutoprefixerOptions, BrowserslistOptions, Options };
|
|
15
|
-
}
|
|
16
|
-
declare var postcss: true;
|
|
17
|
-
/**
|
|
18
|
-
* RuleMeta stores metadata about a `Rule` during the merging process.
|
|
19
|
-
* It tracks selectors and declarations without re-parsing the AST many times.
|
|
20
|
-
*/
|
|
21
|
-
type RuleMeta = {
|
|
1
|
+
declare const _exports: import("postcss").PluginCreator<Options>;
|
|
2
|
+
export = _exports;
|
|
3
|
+
import type browserslist from 'browserslist';
|
|
4
|
+
import type { Declaration } from 'postcss';
|
|
5
|
+
export type RuleMeta = {
|
|
22
6
|
/**
|
|
23
7
|
* - Array of selector strings for the rule
|
|
24
8
|
*/
|
|
@@ -26,16 +10,15 @@ type RuleMeta = {
|
|
|
26
10
|
/**
|
|
27
11
|
* - Array of declaration nodes for the rule
|
|
28
12
|
*/
|
|
29
|
-
declarations:
|
|
13
|
+
declarations: Declaration[];
|
|
30
14
|
/**
|
|
31
15
|
* - Whether the selectors have been modified and need flushing
|
|
32
16
|
*/
|
|
33
17
|
dirty: boolean;
|
|
34
18
|
};
|
|
35
|
-
type AutoprefixerOptions = {
|
|
19
|
+
export type AutoprefixerOptions = {
|
|
36
20
|
overrideBrowserslist?: string | string[];
|
|
37
21
|
};
|
|
38
|
-
type BrowserslistOptions = Pick<browserslist.Options,
|
|
39
|
-
type Options = AutoprefixerOptions & BrowserslistOptions;
|
|
40
|
-
import browserslist = require("browserslist");
|
|
22
|
+
export type BrowserslistOptions = Pick<browserslist.Options, 'stats' | 'path' | 'env'>;
|
|
23
|
+
export type Options = AutoprefixerOptions & BrowserslistOptions;
|
|
41
24
|
//# sourceMappingURL=index.d.ts.map
|
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":";;AAII,OAAQ,KAAA,YAAY,MAAM,cAAc,CAAA;AAQxC,OAAQ,KAAA,EAAC,WAAW,EAAO,MAAM,SAAS,CAAA;AAmD3C,YAAkB,QAAQ,GAC1B;;;;IAAqB,SAAS,EAAnB,MAAM,EAAE,CACnB;;;;IAA0B,YAAY,EAA3B,WAAW,EAAE,CACxB;;;;IAAoB,KAAK,EAAd,OAAO,CACpB;CAAA,CAAA;AA0kBE,YAAwD,mBAAmB,GAAjE;IAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE,CAAqB;AAC3E,YAAgE,mBAAmB,GAAzE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC,CAAqB;AACnF,YAAqD,OAAO,GAAlD,mBAAmB,GAAG,mBAAmB,CAAS"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export = computeBrowsersToSupport;
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param {{overrideBrowserslist?: string | string[] | undefined, stats?: browserslist.Options["stats"], path?: browserslist.Options["path"], env?: browserslist.Options["env"]}} options
|
|
5
|
+
* @param {browserslist.Options["stats"]} stats
|
|
6
|
+
* @param {string|undefined} from
|
|
7
|
+
* @param {string} [file]
|
|
8
|
+
* @param {browserslist.Options["env"]} [env]
|
|
9
|
+
* @returns {string[]}
|
|
10
|
+
*/
|
|
11
|
+
declare function computeBrowsersToSupport(options: {
|
|
12
|
+
overrideBrowserslist?: string | string[] | undefined;
|
|
13
|
+
stats?: browserslist.Options["stats"];
|
|
14
|
+
path?: browserslist.Options["path"];
|
|
15
|
+
env?: browserslist.Options["env"];
|
|
16
|
+
}, stats: browserslist.Options["stats"], from: string | undefined, file?: string, env?: browserslist.Options["env"]): string[];
|
|
17
|
+
import browserslist = require('browserslist');
|
|
18
|
+
//# sourceMappingURL=computeBrowsersToSupport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computeBrowsersToSupport.d.ts","sourceRoot":"","sources":["../../src/lib/computeBrowsersToSupport.js"],"names":[],"mappings":";AAKA;;;;;;;;GAQG;0CAED,OAAO,EARE;IAAC,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAAC,GAAG,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;CAQtK,EACP,KAAK,EARI,YAAY,CAAC,OAAO,CAAC,OAAO,CAQhC,EACL,IAAI,EARK,MAAM,GAAC,SAQZ,EACJ,IAAI,AARH,CACA,EADQ,MAQL,EACJ,GAAG,AARF,CACA,EADQ,YAAY,CAAC,OAAO,CAAC,KAAK,CAQhC,GAPQ,MAAM,EAAE;OAVf,YAAY,WAAW,cAAc"}
|
|
@@ -1,72 +1,78 @@
|
|
|
1
|
+
declare const _exports: {
|
|
2
|
+
sameVendor: typeof sameVendor;
|
|
3
|
+
noVendor: typeof noVendor;
|
|
4
|
+
pseudoElements: {
|
|
5
|
+
':active': string;
|
|
6
|
+
':after': string;
|
|
7
|
+
':any-link': string;
|
|
8
|
+
':before': string;
|
|
9
|
+
':checked': string;
|
|
10
|
+
':default': string;
|
|
11
|
+
':dir': string;
|
|
12
|
+
':disabled': string;
|
|
13
|
+
':empty': string;
|
|
14
|
+
':enabled': string;
|
|
15
|
+
':first-child': string;
|
|
16
|
+
':first-letter': string;
|
|
17
|
+
':first-line': string;
|
|
18
|
+
':first-of-type': string;
|
|
19
|
+
':focus': string;
|
|
20
|
+
':focus-within': string;
|
|
21
|
+
':focus-visible': string;
|
|
22
|
+
':has': string;
|
|
23
|
+
':hover': string;
|
|
24
|
+
':in-range': string;
|
|
25
|
+
':indeterminate': string;
|
|
26
|
+
':invalid': string;
|
|
27
|
+
':is': string;
|
|
28
|
+
':lang': string;
|
|
29
|
+
':last-child': string;
|
|
30
|
+
':last-of-type': string;
|
|
31
|
+
':link': string;
|
|
32
|
+
':matches': string;
|
|
33
|
+
':not': string;
|
|
34
|
+
':nth-child': string;
|
|
35
|
+
':nth-last-child': string;
|
|
36
|
+
':nth-last-of-type': string;
|
|
37
|
+
':nth-of-type': string;
|
|
38
|
+
':only-child': string;
|
|
39
|
+
':only-of-type': string;
|
|
40
|
+
':optional': string;
|
|
41
|
+
':out-of-range': string;
|
|
42
|
+
':placeholder-shown': string;
|
|
43
|
+
':required': string;
|
|
44
|
+
':root': string;
|
|
45
|
+
':target': string;
|
|
46
|
+
'::after': string;
|
|
47
|
+
'::backdrop': string;
|
|
48
|
+
'::before': string;
|
|
49
|
+
'::first-letter': string;
|
|
50
|
+
'::first-line': string;
|
|
51
|
+
'::marker': string;
|
|
52
|
+
'::placeholder': string;
|
|
53
|
+
'::selection': string;
|
|
54
|
+
':valid': string;
|
|
55
|
+
':visited': string;
|
|
56
|
+
};
|
|
57
|
+
ensureCompatibility: typeof ensureCompatibility;
|
|
58
|
+
};
|
|
59
|
+
export = _exports;
|
|
1
60
|
/**
|
|
2
61
|
* @param {string[]} selectorsA
|
|
3
62
|
* @param {string[]} selectorsB
|
|
4
63
|
* @return {boolean}
|
|
5
64
|
*/
|
|
6
|
-
|
|
65
|
+
declare function sameVendor(selectorsA: string[], selectorsB: string[]): boolean;
|
|
7
66
|
/**
|
|
8
67
|
* @param {string} selector
|
|
9
68
|
* @return {boolean}
|
|
10
69
|
*/
|
|
11
|
-
|
|
12
|
-
export const pseudoElements: {
|
|
13
|
-
':active': string;
|
|
14
|
-
':after': string;
|
|
15
|
-
':any-link': string;
|
|
16
|
-
':before': string;
|
|
17
|
-
':checked': string;
|
|
18
|
-
':default': string;
|
|
19
|
-
':dir': string;
|
|
20
|
-
':disabled': string;
|
|
21
|
-
':empty': string;
|
|
22
|
-
':enabled': string;
|
|
23
|
-
':first-child': string;
|
|
24
|
-
':first-letter': string;
|
|
25
|
-
':first-line': string;
|
|
26
|
-
':first-of-type': string;
|
|
27
|
-
':focus': string;
|
|
28
|
-
':focus-within': string;
|
|
29
|
-
':focus-visible': string;
|
|
30
|
-
':has': string;
|
|
31
|
-
':hover': string;
|
|
32
|
-
':in-range': string;
|
|
33
|
-
':indeterminate': string;
|
|
34
|
-
':invalid': string;
|
|
35
|
-
':is': string;
|
|
36
|
-
':lang': string;
|
|
37
|
-
':last-child': string;
|
|
38
|
-
':last-of-type': string;
|
|
39
|
-
':link': string;
|
|
40
|
-
':matches': string;
|
|
41
|
-
':not': string;
|
|
42
|
-
':nth-child': string;
|
|
43
|
-
':nth-last-child': string;
|
|
44
|
-
':nth-last-of-type': string;
|
|
45
|
-
':nth-of-type': string;
|
|
46
|
-
':only-child': string;
|
|
47
|
-
':only-of-type': string;
|
|
48
|
-
':optional': string;
|
|
49
|
-
':out-of-range': string;
|
|
50
|
-
':placeholder-shown': string;
|
|
51
|
-
':required': string;
|
|
52
|
-
':root': string;
|
|
53
|
-
':target': string;
|
|
54
|
-
'::after': string;
|
|
55
|
-
'::backdrop': string;
|
|
56
|
-
'::before': string;
|
|
57
|
-
'::first-letter': string;
|
|
58
|
-
'::first-line': string;
|
|
59
|
-
'::marker': string;
|
|
60
|
-
'::placeholder': string;
|
|
61
|
-
'::selection': string;
|
|
62
|
-
':valid': string;
|
|
63
|
-
':visited': string;
|
|
64
|
-
};
|
|
70
|
+
declare function noVendor(selector: string): boolean;
|
|
65
71
|
/**
|
|
66
72
|
* @param {string[]} selectors
|
|
67
73
|
* @param{string[]=} browsers
|
|
68
74
|
* @param{Map<string,boolean>=} compatibilityCache
|
|
69
75
|
* @return {boolean}
|
|
70
76
|
*/
|
|
71
|
-
|
|
77
|
+
declare function ensureCompatibility(selectors: string[], browsers?: string[] | undefined, compatibilityCache?: Map<string, boolean> | undefined): boolean;
|
|
72
78
|
//# sourceMappingURL=ensureCompatibility.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensureCompatibility.d.ts","sourceRoot":"","sources":["../../src/lib/ensureCompatibility.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ensureCompatibility.d.ts","sourceRoot":"","sources":["../../src/lib/ensureCompatibility.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA;;;;GAIG;AACH,iBAAS,UAAU,CAAC,UAAU,EAJnB,MAAM,EAIa,EAAE,UAAU,EAH/B,MAAM,EAGyB,GAF9B,OAAO,CAWlB;AAED;;;GAGG;AACH,iBAAS,QAAQ,CAAC,QAAQ,EAHf,MAGe,GAFd,OAAO,CAIlB;AA2FD;;;;;GAKG;AACH,iBAAS,mBAAmB,CAAC,SAAS,EAL3B,MAAM,EAKqB,EAAE,QAAQ,AAJ7C,CACA,EADO,MAAM,EAAE,YAI8B,EAAE,kBAAkB,AAHjE,CACA,EADO,GAAG,CAAC,MAAM,EAAC,OAAO,CAAC,YAGuC,GAFxD,OAAO,CA0ElB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getBrowsersForWebBuild.d.ts","sourceRoot":"","sources":["../../src/lib/getBrowsersForWebBuild.js"],"names":[],"mappings":""}
|