source: imaps-frontend/node_modules/clean-css/lib/optimizer/level-1/tidy-rules.js

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 4 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 8.5 KB
Line 
1var Spaces = require('../../options/format').Spaces;
2var Marker = require('../../tokenizer/marker');
3var formatPosition = require('../../utils/format-position');
4
5var CASE_ATTRIBUTE_PATTERN = /[\s"'][iI]\s*\]/;
6var CASE_RESTORE_PATTERN = /([\d\w])([iI])\]/g;
7var DOUBLE_QUOTE_CASE_PATTERN = /="([a-zA-Z][a-zA-Z\d\-_]+)"([iI])/g;
8var DOUBLE_QUOTE_PATTERN = /="([a-zA-Z][a-zA-Z\d\-_]+)"(\s|\])/g;
9var HTML_COMMENT_PATTERN = /^(?:(?:<!--|-->)\s*)+/;
10var SINGLE_QUOTE_CASE_PATTERN = /='([a-zA-Z][a-zA-Z\d\-_]+)'([iI])/g;
11var SINGLE_QUOTE_PATTERN = /='([a-zA-Z][a-zA-Z\d\-_]+)'(\s|\])/g;
12var RELATION_PATTERN = /[>+~]/;
13var WHITESPACE_PATTERN = /\s/;
14
15var ASTERISK_PLUS_HTML_HACK = '*+html ';
16var ASTERISK_FIRST_CHILD_PLUS_HTML_HACK = '*:first-child+html ';
17var LESS_THAN = '<';
18
19var PSEUDO_CLASSES_WITH_SELECTORS = [
20 ':current',
21 ':future',
22 ':has',
23 ':host',
24 ':host-context',
25 ':is',
26 ':not',
27 ':past',
28 ':where'
29];
30
31function hasInvalidCharacters(value) {
32 var isEscaped;
33 var isInvalid = false;
34 var character;
35 var isQuote = false;
36 var i, l;
37
38 for (i = 0, l = value.length; i < l; i++) {
39 character = value[i];
40
41 if (isEscaped) {
42 // continue as always
43 } else if (character == Marker.SINGLE_QUOTE || character == Marker.DOUBLE_QUOTE) {
44 isQuote = !isQuote;
45 } else if (!isQuote
46 && (character == Marker.CLOSE_CURLY_BRACKET
47 || character == Marker.EXCLAMATION
48 || character == LESS_THAN
49 || character == Marker.SEMICOLON)
50 ) {
51 isInvalid = true;
52 break;
53 } else if (!isQuote && i === 0 && RELATION_PATTERN.test(character)) {
54 isInvalid = true;
55 break;
56 }
57
58 isEscaped = character == Marker.BACK_SLASH;
59 }
60
61 return isInvalid;
62}
63
64function removeWhitespace(value, format) {
65 var stripped = [];
66 var character;
67 var isNewLineNix;
68 var isNewLineWin;
69 var isEscaped;
70 var wasEscaped;
71 var isQuoted;
72 var isSingleQuoted;
73 var isDoubleQuoted;
74 var isAttribute;
75 var isRelation;
76 var isWhitespace;
77 var isSpaceAwarePseudoClass;
78 var roundBracketLevel = 0;
79 var wasComma = false;
80 var wasRelation = false;
81 var wasWhitespace = false;
82 var withCaseAttribute = CASE_ATTRIBUTE_PATTERN.test(value);
83 var spaceAroundRelation = format && format.spaces[Spaces.AroundSelectorRelation];
84 var i, l;
85
86 for (i = 0, l = value.length; i < l; i++) {
87 character = value[i];
88
89 isNewLineNix = character == Marker.NEW_LINE_NIX;
90 isNewLineWin = character == Marker.NEW_LINE_NIX && value[i - 1] == Marker.CARRIAGE_RETURN;
91 isQuoted = isSingleQuoted || isDoubleQuoted;
92 isRelation = !isAttribute && !isEscaped && roundBracketLevel === 0 && RELATION_PATTERN.test(character);
93 isWhitespace = WHITESPACE_PATTERN.test(character);
94 isSpaceAwarePseudoClass = roundBracketLevel == 1 && character == Marker.CLOSE_ROUND_BRACKET
95 ? false
96 : isSpaceAwarePseudoClass
97 || (roundBracketLevel === 0 && character == Marker.COLON && isPseudoClassWithSelectors(value, i));
98
99 if (wasEscaped && isQuoted && isNewLineWin) {
100 // swallow escaped new windows lines in comments
101 stripped.pop();
102 stripped.pop();
103 } else if (isEscaped && isQuoted && isNewLineNix) {
104 // swallow escaped new *nix lines in comments
105 stripped.pop();
106 } else if (isEscaped) {
107 stripped.push(character);
108 } else if (character == Marker.OPEN_SQUARE_BRACKET && !isQuoted) {
109 stripped.push(character);
110 isAttribute = true;
111 } else if (character == Marker.CLOSE_SQUARE_BRACKET && !isQuoted) {
112 stripped.push(character);
113 isAttribute = false;
114 } else if (character == Marker.OPEN_ROUND_BRACKET && !isQuoted) {
115 stripped.push(character);
116 roundBracketLevel++;
117 } else if (character == Marker.CLOSE_ROUND_BRACKET && !isQuoted) {
118 stripped.push(character);
119 roundBracketLevel--;
120 } else if (character == Marker.SINGLE_QUOTE && !isQuoted) {
121 stripped.push(character);
122 isSingleQuoted = true;
123 } else if (character == Marker.DOUBLE_QUOTE && !isQuoted) {
124 stripped.push(character);
125 isDoubleQuoted = true;
126 } else if (character == Marker.SINGLE_QUOTE && isQuoted) {
127 stripped.push(character);
128 isSingleQuoted = false;
129 } else if (character == Marker.DOUBLE_QUOTE && isQuoted) {
130 stripped.push(character);
131 isDoubleQuoted = false;
132 } else if (isWhitespace && wasRelation && !spaceAroundRelation) {
133 continue;
134 } else if (!isWhitespace && wasRelation && spaceAroundRelation) {
135 stripped.push(Marker.SPACE);
136 stripped.push(character);
137 } else if (isWhitespace && !wasWhitespace && wasComma && roundBracketLevel > 0 && isSpaceAwarePseudoClass) {
138 // skip space
139 } else if (isWhitespace && !wasWhitespace && roundBracketLevel > 0 && isSpaceAwarePseudoClass) {
140 stripped.push(character);
141 } else if (isWhitespace && (isAttribute || roundBracketLevel > 0) && !isQuoted) {
142 // skip space
143 } else if (isWhitespace && wasWhitespace && !isQuoted) {
144 // skip extra space
145 } else if ((isNewLineWin || isNewLineNix) && (isAttribute || roundBracketLevel > 0) && isQuoted) {
146 // skip newline
147 } else if (isRelation && wasWhitespace && !spaceAroundRelation) {
148 stripped.pop();
149 stripped.push(character);
150 } else if (isRelation && !wasWhitespace && spaceAroundRelation) {
151 stripped.push(Marker.SPACE);
152 stripped.push(character);
153 } else if (isWhitespace) {
154 stripped.push(Marker.SPACE);
155 } else {
156 stripped.push(character);
157 }
158
159 wasEscaped = isEscaped;
160 isEscaped = character == Marker.BACK_SLASH;
161 wasRelation = isRelation;
162 wasWhitespace = isWhitespace;
163 wasComma = character == Marker.COMMA;
164 }
165
166 return withCaseAttribute
167 ? stripped.join('').replace(CASE_RESTORE_PATTERN, '$1 $2]')
168 : stripped.join('');
169}
170
171function isPseudoClassWithSelectors(value, colonPosition) {
172 var pseudoClass = value.substring(colonPosition, value.indexOf(Marker.OPEN_ROUND_BRACKET, colonPosition));
173
174 return PSEUDO_CLASSES_WITH_SELECTORS.indexOf(pseudoClass) > -1;
175}
176
177function removeQuotes(value) {
178 if (value.indexOf('\'') == -1 && value.indexOf('"') == -1) {
179 return value;
180 }
181
182 return value
183 .replace(SINGLE_QUOTE_CASE_PATTERN, '=$1 $2')
184 .replace(SINGLE_QUOTE_PATTERN, '=$1$2')
185 .replace(DOUBLE_QUOTE_CASE_PATTERN, '=$1 $2')
186 .replace(DOUBLE_QUOTE_PATTERN, '=$1$2');
187}
188
189function replacePseudoClasses(value) {
190 return value
191 .replace('nth-child(1)', 'first-child')
192 .replace('nth-of-type(1)', 'first-of-type')
193 .replace('nth-of-type(even)', 'nth-of-type(2n)')
194 .replace('nth-child(even)', 'nth-child(2n)')
195 .replace('nth-of-type(2n+1)', 'nth-of-type(odd)')
196 .replace('nth-child(2n+1)', 'nth-child(odd)')
197 .replace('nth-last-child(1)', 'last-child')
198 .replace('nth-last-of-type(1)', 'last-of-type')
199 .replace('nth-last-of-type(even)', 'nth-last-of-type(2n)')
200 .replace('nth-last-child(even)', 'nth-last-child(2n)')
201 .replace('nth-last-of-type(2n+1)', 'nth-last-of-type(odd)')
202 .replace('nth-last-child(2n+1)', 'nth-last-child(odd)');
203}
204
205function tidyRules(rules, removeUnsupported, adjacentSpace, format, warnings) {
206 var list = [];
207 var repeated = [];
208
209 function removeHTMLComment(rule, match) {
210 warnings.push('HTML comment \'' + match + '\' at ' + formatPosition(rule[2][0]) + '. Removing.');
211 return '';
212 }
213
214 for (var i = 0, l = rules.length; i < l; i++) {
215 var rule = rules[i];
216 var reduced = rule[1];
217
218 reduced = reduced.replace(HTML_COMMENT_PATTERN, removeHTMLComment.bind(null, rule));
219
220 if (hasInvalidCharacters(reduced)) {
221 warnings.push('Invalid selector \'' + rule[1] + '\' at ' + formatPosition(rule[2][0]) + '. Ignoring.');
222 continue;
223 }
224
225 reduced = removeWhitespace(reduced, format);
226 reduced = removeQuotes(reduced);
227
228 if (adjacentSpace && reduced.indexOf('nav') > 0) {
229 reduced = reduced.replace(/\+nav(\S|$)/, '+ nav$1');
230 }
231
232 if (removeUnsupported && reduced.indexOf(ASTERISK_PLUS_HTML_HACK) > -1) {
233 continue;
234 }
235
236 if (removeUnsupported && reduced.indexOf(ASTERISK_FIRST_CHILD_PLUS_HTML_HACK) > -1) {
237 continue;
238 }
239
240 if (reduced.indexOf('*') > -1) {
241 reduced = reduced
242 .replace(/\*([:#.[])/g, '$1')
243 .replace(/^(:first-child)?\+html/, '*$1+html');
244 }
245
246 if (repeated.indexOf(reduced) > -1) {
247 continue;
248 }
249
250 reduced = replacePseudoClasses(reduced);
251
252 rule[1] = reduced;
253 repeated.push(reduced);
254 list.push(rule);
255 }
256
257 if (list.length == 1 && list[0][1].length === 0) {
258 warnings.push('Empty selector \'' + list[0][1] + '\' at ' + formatPosition(list[0][2][0]) + '. Ignoring.');
259 list = [];
260 }
261
262 return list;
263}
264
265module.exports = tidyRules;
Note: See TracBrowser for help on using the repository browser.