diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2023-10-14 15:05:55 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2023-10-14 15:05:55 +0800 |
| commit | c06f7ee0a40255214c477e13d9b956a7e07c2900 (patch) | |
| tree | f5982a568ef8fab865d0142e71c7494fea3e4c1b /node_modules/csso/lib/restructure/7-mergeRuleset.js | |
| parent | 3fd9400d4dccc25aa29b5702216732e0b7542073 (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.js | 86 |
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 + }); +}; |
