source: trip-planner-front/node_modules/csso/lib/restructure/8-restructRuleset.js@ 6a3a178

Last change on this file since 6a3a178 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 6.3 KB
Line 
1var List = require('css-tree').List;
2var walk = require('css-tree').walk;
3var utils = require('./utils');
4
5function calcSelectorLength(list) {
6 var length = 0;
7
8 list.each(function(data) {
9 length += data.id.length + 1;
10 });
11
12 return length - 1;
13}
14
15function calcDeclarationsLength(tokens) {
16 var length = 0;
17
18 for (var i = 0; i < tokens.length; i++) {
19 length += tokens[i].length;
20 }
21
22 return (
23 length + // declarations
24 tokens.length - 1 // delimeters
25 );
26}
27
28function processRule(node, item, list) {
29 var avoidRulesMerge = this.block !== null ? this.block.avoidRulesMerge : false;
30 var selectors = node.prelude.children;
31 var block = node.block;
32 var disallowDownMarkers = Object.create(null);
33 var allowMergeUp = true;
34 var allowMergeDown = true;
35
36 list.prevUntil(item.prev, function(prev, prevItem) {
37 var prevBlock = prev.block;
38 var prevType = prev.type;
39
40 if (prevType !== 'Rule') {
41 var unsafe = utils.unsafeToSkipNode.call(selectors, prev);
42
43 if (!unsafe && prevType === 'Atrule' && prevBlock) {
44 walk(prevBlock, {
45 visit: 'Rule',
46 enter: function(node) {
47 node.prelude.children.each(function(data) {
48 disallowDownMarkers[data.compareMarker] = true;
49 });
50 }
51 });
52 }
53
54 return unsafe;
55 }
56
57 var prevSelectors = prev.prelude.children;
58
59 if (node.pseudoSignature !== prev.pseudoSignature) {
60 return true;
61 }
62
63 allowMergeDown = !prevSelectors.some(function(selector) {
64 return selector.compareMarker in disallowDownMarkers;
65 });
66
67 // try prev ruleset if simpleselectors has no equal specifity and element selector
68 if (!allowMergeDown && !allowMergeUp) {
69 return true;
70 }
71
72 // try to join by selectors
73 if (allowMergeUp && utils.isEqualSelectors(prevSelectors, selectors)) {
74 prevBlock.children.appendList(block.children);
75 list.remove(item);
76 return true;
77 }
78
79 // try to join by properties
80 var diff = utils.compareDeclarations(block.children, prevBlock.children);
81
82 // console.log(diff.eq, diff.ne1, diff.ne2);
83
84 if (diff.eq.length) {
85 if (!diff.ne1.length && !diff.ne2.length) {
86 // equal blocks
87 if (allowMergeDown) {
88 utils.addSelectors(selectors, prevSelectors);
89 list.remove(prevItem);
90 }
91
92 return true;
93 } else if (!avoidRulesMerge) { /* probably we don't need to prevent those merges for @keyframes
94 TODO: need to be checked */
95
96 if (diff.ne1.length && !diff.ne2.length) {
97 // prevBlock is subset block
98 var selectorLength = calcSelectorLength(selectors);
99 var blockLength = calcDeclarationsLength(diff.eq); // declarations length
100
101 if (allowMergeUp && selectorLength < blockLength) {
102 utils.addSelectors(prevSelectors, selectors);
103 block.children = new List().fromArray(diff.ne1);
104 }
105 } else if (!diff.ne1.length && diff.ne2.length) {
106 // node is subset of prevBlock
107 var selectorLength = calcSelectorLength(prevSelectors);
108 var blockLength = calcDeclarationsLength(diff.eq); // declarations length
109
110 if (allowMergeDown && selectorLength < blockLength) {
111 utils.addSelectors(selectors, prevSelectors);
112 prevBlock.children = new List().fromArray(diff.ne2);
113 }
114 } else {
115 // diff.ne1.length && diff.ne2.length
116 // extract equal block
117 var newSelector = {
118 type: 'SelectorList',
119 loc: null,
120 children: utils.addSelectors(prevSelectors.copy(), selectors)
121 };
122 var newBlockLength = calcSelectorLength(newSelector.children) + 2; // selectors length + curly braces length
123 var blockLength = calcDeclarationsLength(diff.eq); // declarations length
124
125 // create new ruleset if declarations length greater than
126 // ruleset description overhead
127 if (blockLength >= newBlockLength) {
128 var newItem = list.createItem({
129 type: 'Rule',
130 loc: null,
131 prelude: newSelector,
132 block: {
133 type: 'Block',
134 loc: null,
135 children: new List().fromArray(diff.eq)
136 },
137 pseudoSignature: node.pseudoSignature
138 });
139
140 block.children = new List().fromArray(diff.ne1);
141 prevBlock.children = new List().fromArray(diff.ne2overrided);
142
143 if (allowMergeUp) {
144 list.insert(newItem, prevItem);
145 } else {
146 list.insert(newItem, item);
147 }
148
149 return true;
150 }
151 }
152 }
153 }
154
155 if (allowMergeUp) {
156 // TODO: disallow up merge only if any property interception only (i.e. diff.ne2overrided.length > 0);
157 // await property families to find property interception correctly
158 allowMergeUp = !prevSelectors.some(function(prevSelector) {
159 return selectors.some(function(selector) {
160 return selector.compareMarker === prevSelector.compareMarker;
161 });
162 });
163 }
164
165 prevSelectors.each(function(data) {
166 disallowDownMarkers[data.compareMarker] = true;
167 });
168 });
169}
170
171module.exports = function restructRule(ast) {
172 walk(ast, {
173 visit: 'Rule',
174 reverse: true,
175 enter: processRule
176 });
177};
Note: See TracBrowser for help on using the repository browser.