summaryrefslogtreecommitdiff
path: root/node_modules/csso/lib/restructure/7-mergeRuleset.js
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2023-10-14 15:05:55 +0800
committerlittleblack111 <littleblack11111@gmail.com>2023-10-14 15:05:55 +0800
commitc06f7ee0a40255214c477e13d9b956a7e07c2900 (patch)
treef5982a568ef8fab865d0142e71c7494fea3e4c1b /node_modules/csso/lib/restructure/7-mergeRuleset.js
parent3fd9400d4dccc25aa29b5702216732e0b7542073 (diff)
postcss,(plugins): nanocss, postcss-preset-env
Diffstat (limited to 'node_modules/csso/lib/restructure/7-mergeRuleset.js')
-rw-r--r--node_modules/csso/lib/restructure/7-mergeRuleset.js86
1 files changed, 86 insertions, 0 deletions
diff --git a/node_modules/csso/lib/restructure/7-mergeRuleset.js b/node_modules/csso/lib/restructure/7-mergeRuleset.js
new file mode 100644
index 00000000..8a4d5438
--- /dev/null
+++ b/node_modules/csso/lib/restructure/7-mergeRuleset.js
@@ -0,0 +1,86 @@
+import { walk } from 'css-tree';
+import { unsafeToSkipNode, isEqualDeclarations} from './utils.js';
+
+/*
+ At this step all rules has single simple selector. We try to join by equal
+ declaration blocks to first rule, e.g.
+
+ .a { color: red }
+ b { ... }
+ .b { color: red }
+ ->
+ .a, .b { color: red }
+ b { ... }
+*/
+
+function processRule(node, item, list) {
+ const selectors = node.prelude.children;
+ const declarations = node.block.children;
+ const nodeCompareMarker = selectors.first.compareMarker;
+ const skippedCompareMarkers = {};
+
+ list.nextUntil(item.next, function(next, nextItem) {
+ // skip non-ruleset node if safe
+ if (next.type !== 'Rule') {
+ return unsafeToSkipNode.call(selectors, next);
+ }
+
+ if (node.pseudoSignature !== next.pseudoSignature) {
+ return true;
+ }
+
+ const nextFirstSelector = next.prelude.children.head;
+ const nextDeclarations = next.block.children;
+ const nextCompareMarker = nextFirstSelector.data.compareMarker;
+
+ // if next ruleset has same marked as one of skipped then stop joining
+ if (nextCompareMarker in skippedCompareMarkers) {
+ return true;
+ }
+
+ // try to join by selectors
+ if (selectors.head === selectors.tail) {
+ if (selectors.first.id === nextFirstSelector.data.id) {
+ declarations.appendList(nextDeclarations);
+ list.remove(nextItem);
+ return;
+ }
+ }
+
+ // try to join by properties
+ if (isEqualDeclarations(declarations, nextDeclarations)) {
+ const nextStr = nextFirstSelector.data.id;
+
+ selectors.some((data, item) => {
+ const curStr = data.id;
+
+ if (nextStr < curStr) {
+ selectors.insert(nextFirstSelector, item);
+ return true;
+ }
+
+ if (!item.next) {
+ selectors.insert(nextFirstSelector);
+ return true;
+ }
+ });
+
+ list.remove(nextItem);
+ return;
+ }
+
+ // go to next ruleset if current one can be skipped (has no equal specificity nor element selector)
+ if (nextCompareMarker === nodeCompareMarker) {
+ return true;
+ }
+
+ skippedCompareMarkers[nextCompareMarker] = true;
+ });
+}
+
+export default function mergeRule(ast) {
+ walk(ast, {
+ visit: 'Rule',
+ enter: processRule
+ });
+};