| import { walk } from 'css-tree'; |
| import { |
| unsafeToSkipNode, |
| isEqualSelectors, |
| isEqualDeclarations, |
| addSelectors, |
| hasSimilarSelectors |
| } from './utils.js'; |
| |
| function processRule(node, item, list) { |
| const selectors = node.prelude.children; |
| const declarations = node.block.children; |
| |
| list.prevUntil(item.prev, function(prev) { |
| // skip non-ruleset node if safe |
| if (prev.type !== 'Rule') { |
| return unsafeToSkipNode.call(selectors, prev); |
| } |
| |
| const prevSelectors = prev.prelude.children; |
| const prevDeclarations = prev.block.children; |
| |
| // try to join rulesets with equal pseudo signature |
| if (node.pseudoSignature === prev.pseudoSignature) { |
| // try to join by selectors |
| if (isEqualSelectors(prevSelectors, selectors)) { |
| prevDeclarations.appendList(declarations); |
| list.remove(item); |
| return true; |
| } |
| |
| // try to join by declarations |
| if (isEqualDeclarations(declarations, prevDeclarations)) { |
| addSelectors(prevSelectors, selectors); |
| list.remove(item); |
| return true; |
| } |
| } |
| |
| // go to prev ruleset if has no selector similarities |
| return hasSimilarSelectors(selectors, prevSelectors); |
| }); |
| } |
| |
| // NOTE: direction should be left to right, since rulesets merge to left |
| // ruleset. When direction right to left unmerged rulesets may prevent lookup |
| // TODO: remove initial merge |
| export default function initialMergeRule(ast) { |
| walk(ast, { |
| visit: 'Rule', |
| enter: processRule |
| }); |
| }; |