postcss-merge-rules 8.0.2 → 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/package.json +10 -7
- package/src/index.js +115 -50
- package/types/index.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
"url": "cssnano/cssnano"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"browserslist": "^4.28.
|
|
46
|
+
"browserslist": "^4.28.8",
|
|
47
47
|
"caniuse-api": "^4.0.0",
|
|
48
|
-
"postcss-selector-parser": "^7.1.
|
|
49
|
-
"cssnano-utils": "^6.0.
|
|
48
|
+
"postcss-selector-parser": "^7.1.5",
|
|
49
|
+
"cssnano-utils": "^6.0.3"
|
|
50
50
|
},
|
|
51
51
|
"bugs": {
|
|
52
52
|
"url": "https://github.com/cssnano/cssnano/issues"
|
|
@@ -55,11 +55,14 @@
|
|
|
55
55
|
"node": "^22.11.0 || ^24.11.0 || >=26.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"postcss": "^8.5.
|
|
58
|
+
"postcss": "^8.5.26",
|
|
59
59
|
"postcss-simple-vars": "^7.0.1",
|
|
60
|
-
"postcss-discard-comments": "^8.0.
|
|
60
|
+
"postcss-discard-comments": "^8.0.3"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"postcss": "^8.5.
|
|
63
|
+
"postcss": "^8.5.26"
|
|
64
|
+
},
|
|
65
|
+
"scripts": {
|
|
66
|
+
"test": "node --test"
|
|
64
67
|
}
|
|
65
68
|
}
|
package/src/index.js
CHANGED
|
@@ -300,45 +300,47 @@ function mergeParents(first, second) {
|
|
|
300
300
|
return true;
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
+
/**
|
|
304
|
+
* @param {Rule} second
|
|
305
|
+
* @return {Rule | null}
|
|
306
|
+
*/
|
|
307
|
+
function getNextRule(second) {
|
|
308
|
+
let nextRule = second.next();
|
|
309
|
+
if (!nextRule) {
|
|
310
|
+
// Grab next cousin
|
|
311
|
+
/** @type {any} */
|
|
312
|
+
const parentSibling =
|
|
313
|
+
/** @type {import('postcss').Container<import('postcss').ChildNode>} */ (
|
|
314
|
+
second.parent
|
|
315
|
+
).next();
|
|
316
|
+
nextRule = parentSibling && parentSibling.nodes && parentSibling.nodes[0];
|
|
317
|
+
}
|
|
318
|
+
return nextRule?.type === 'rule' ? nextRule : null;
|
|
319
|
+
}
|
|
320
|
+
|
|
303
321
|
/**
|
|
304
322
|
* @param {Rule} first
|
|
305
323
|
* @param {Rule} second
|
|
324
|
+
* @param {Declaration[]} intersection
|
|
306
325
|
* @param {string[]} browsers
|
|
307
326
|
* @param {Map<string, boolean>} compatibilityCache
|
|
308
327
|
* @param {WeakSet<Rule>} ruleCache
|
|
309
328
|
* @param {WeakMap<Rule, RuleMeta>} ruleMeta
|
|
310
|
-
* @return {Rule}
|
|
329
|
+
* @return {{first: Rule, second: Rule, intersection: Declaration[]}}
|
|
311
330
|
*/
|
|
312
|
-
function
|
|
331
|
+
function mergeWithNextRule(
|
|
313
332
|
first,
|
|
314
333
|
second,
|
|
334
|
+
intersection,
|
|
315
335
|
browsers,
|
|
316
336
|
compatibilityCache,
|
|
317
337
|
ruleCache,
|
|
318
338
|
ruleMeta
|
|
319
339
|
) {
|
|
320
|
-
|
|
321
|
-
flush(first, ruleMeta);
|
|
322
|
-
}
|
|
323
|
-
const metaFirst = getMeta(first, ruleMeta);
|
|
324
|
-
const metaSecond = getMeta(second, ruleMeta);
|
|
325
|
-
let intersection = intersect(metaFirst.declarations, metaSecond.declarations);
|
|
326
|
-
if (intersection.length === 0) {
|
|
327
|
-
return second;
|
|
328
|
-
}
|
|
329
|
-
let nextRule = second.next();
|
|
330
|
-
if (!nextRule) {
|
|
331
|
-
// Grab next cousin
|
|
332
|
-
/** @type {any} */
|
|
333
|
-
const parentSibling =
|
|
334
|
-
/** @type {import('postcss').Container<import('postcss').ChildNode>} */ (
|
|
335
|
-
second.parent
|
|
336
|
-
).next();
|
|
337
|
-
nextRule = parentSibling && parentSibling.nodes && parentSibling.nodes[0];
|
|
338
|
-
}
|
|
340
|
+
const nextRule = getNextRule(second);
|
|
339
341
|
if (
|
|
340
|
-
nextRule
|
|
341
|
-
canMerge(
|
|
342
|
+
!nextRule ||
|
|
343
|
+
!canMerge(
|
|
342
344
|
second,
|
|
343
345
|
nextRule,
|
|
344
346
|
browsers,
|
|
@@ -347,24 +349,28 @@ function partialMerge(
|
|
|
347
349
|
ruleMeta
|
|
348
350
|
)
|
|
349
351
|
) {
|
|
350
|
-
|
|
351
|
-
const nextIntersection = intersect(
|
|
352
|
-
metaSecond.declarations,
|
|
353
|
-
metaNext.declarations
|
|
354
|
-
);
|
|
355
|
-
if (nextIntersection.length > intersection.length) {
|
|
356
|
-
mergeParents(second, nextRule);
|
|
357
|
-
first = second;
|
|
358
|
-
second = nextRule;
|
|
359
|
-
intersection = nextIntersection;
|
|
360
|
-
}
|
|
352
|
+
return { first, second, intersection };
|
|
361
353
|
}
|
|
362
354
|
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
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
|
+
}
|
|
367
366
|
|
|
367
|
+
/**
|
|
368
|
+
* @param {Declaration[]} intersection
|
|
369
|
+
* @param {Declaration[]} firstDecls
|
|
370
|
+
* @param {Declaration[]} secondDecls
|
|
371
|
+
* @return {Declaration[]}
|
|
372
|
+
*/
|
|
373
|
+
function filterIntersections(intersection, firstDecls, secondDecls) {
|
|
368
374
|
// Filter out intersections with later conflicts in First
|
|
369
375
|
intersection = intersection.filter((decl, intersectIndex) => {
|
|
370
376
|
const indexOfDecl = indexOfDeclaration(firstDecls, decl);
|
|
@@ -386,7 +392,7 @@ function partialMerge(
|
|
|
386
392
|
});
|
|
387
393
|
|
|
388
394
|
// Filter out intersections with previous conflicts in Second
|
|
389
|
-
|
|
395
|
+
return intersection.filter((decl) => {
|
|
390
396
|
const nextConflictIndex = secondDecls.findIndex((d) =>
|
|
391
397
|
isConflictingProp(d.prop, decl.prop)
|
|
392
398
|
);
|
|
@@ -408,15 +414,20 @@ function partialMerge(
|
|
|
408
414
|
secondDecls.splice(nextConflictIndex, 1);
|
|
409
415
|
return true;
|
|
410
416
|
});
|
|
417
|
+
}
|
|
411
418
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
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) {
|
|
417
428
|
const receivingBlock = second.clone();
|
|
418
|
-
const firstSelectors =
|
|
419
|
-
const secondSelectors =
|
|
429
|
+
const firstSelectors = getMeta(first, ruleMeta).selectors;
|
|
430
|
+
const secondSelectors = getMeta(second, ruleMeta).selectors;
|
|
420
431
|
|
|
421
432
|
receivingBlock.selector = [...firstSelectors, ...secondSelectors].join();
|
|
422
433
|
receivingBlock.nodes = [];
|
|
@@ -464,11 +475,11 @@ function partialMerge(
|
|
|
464
475
|
if (merged < original) {
|
|
465
476
|
first.replaceWith(firstClone);
|
|
466
477
|
second.replaceWith(secondClone);
|
|
467
|
-
[firstClone, receivingBlock, secondClone]
|
|
478
|
+
for (const r of [firstClone, receivingBlock, secondClone]) {
|
|
468
479
|
if (r.nodes.length === 0) {
|
|
469
480
|
r.remove();
|
|
470
481
|
}
|
|
471
|
-
}
|
|
482
|
+
}
|
|
472
483
|
if (!secondClone.parent) {
|
|
473
484
|
ruleCache?.add(receivingBlock);
|
|
474
485
|
return receivingBlock;
|
|
@@ -478,10 +489,64 @@ function partialMerge(
|
|
|
478
489
|
ruleMeta?.delete(first);
|
|
479
490
|
ruleMeta?.delete(second);
|
|
480
491
|
return secondClone;
|
|
481
|
-
}
|
|
482
|
-
|
|
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) {
|
|
483
522
|
return second;
|
|
484
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);
|
|
485
550
|
}
|
|
486
551
|
|
|
487
552
|
/**
|
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
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"}
|