source: frontend/node_modules/postcss-selector-parser/dist/parser.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 38.2 KB
RevLine 
[9af201e]1"use strict";
2
3exports.__esModule = true;
4exports["default"] = void 0;
5var _root = _interopRequireDefault(require("./selectors/root"));
6var _selector = _interopRequireDefault(require("./selectors/selector"));
7var _className = _interopRequireDefault(require("./selectors/className"));
8var _comment = _interopRequireDefault(require("./selectors/comment"));
9var _id = _interopRequireDefault(require("./selectors/id"));
10var _tag = _interopRequireDefault(require("./selectors/tag"));
11var _string = _interopRequireDefault(require("./selectors/string"));
12var _pseudo = _interopRequireDefault(require("./selectors/pseudo"));
13var _attribute = _interopRequireWildcard(require("./selectors/attribute"));
14var _universal = _interopRequireDefault(require("./selectors/universal"));
15var _combinator = _interopRequireDefault(require("./selectors/combinator"));
16var _nesting = _interopRequireDefault(require("./selectors/nesting"));
17var _sortAscending = _interopRequireDefault(require("./sortAscending"));
18var _tokenize = _interopRequireWildcard(require("./tokenize"));
19var tokens = _interopRequireWildcard(require("./tokenTypes"));
20var types = _interopRequireWildcard(require("./selectors/types"));
21var _util = require("./util");
22var _WHITESPACE_TOKENS, _Object$assign;
23function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
24function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
25function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
26function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
27function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
28var WHITESPACE_TOKENS = (_WHITESPACE_TOKENS = {}, _WHITESPACE_TOKENS[tokens.space] = true, _WHITESPACE_TOKENS[tokens.cr] = true, _WHITESPACE_TOKENS[tokens.feed] = true, _WHITESPACE_TOKENS[tokens.newline] = true, _WHITESPACE_TOKENS[tokens.tab] = true, _WHITESPACE_TOKENS);
29var WHITESPACE_EQUIV_TOKENS = Object.assign({}, WHITESPACE_TOKENS, (_Object$assign = {}, _Object$assign[tokens.comment] = true, _Object$assign));
30function tokenStart(token) {
31 return {
32 line: token[_tokenize.FIELDS.START_LINE],
33 column: token[_tokenize.FIELDS.START_COL]
34 };
35}
36function tokenEnd(token) {
37 return {
38 line: token[_tokenize.FIELDS.END_LINE],
39 column: token[_tokenize.FIELDS.END_COL]
40 };
41}
42function getSource(startLine, startColumn, endLine, endColumn) {
43 return {
44 start: {
45 line: startLine,
46 column: startColumn
47 },
48 end: {
49 line: endLine,
50 column: endColumn
51 }
52 };
53}
54function getTokenSource(token) {
55 return getSource(token[_tokenize.FIELDS.START_LINE], token[_tokenize.FIELDS.START_COL], token[_tokenize.FIELDS.END_LINE], token[_tokenize.FIELDS.END_COL]);
56}
57function getTokenSourceSpan(startToken, endToken) {
58 if (!startToken) {
59 return undefined;
60 }
61 return getSource(startToken[_tokenize.FIELDS.START_LINE], startToken[_tokenize.FIELDS.START_COL], endToken[_tokenize.FIELDS.END_LINE], endToken[_tokenize.FIELDS.END_COL]);
62}
63function unescapeProp(node, prop) {
64 var value = node[prop];
65 if (typeof value !== "string") {
66 return;
67 }
68 if (value.indexOf("\\") !== -1) {
69 (0, _util.ensureObject)(node, 'raws');
70 node[prop] = (0, _util.unesc)(value);
71 if (node.raws[prop] === undefined) {
72 node.raws[prop] = value;
73 }
74 }
75 return node;
76}
77function indexesOf(array, item) {
78 var i = -1;
79 var indexes = [];
80 while ((i = array.indexOf(item, i + 1)) !== -1) {
81 indexes.push(i);
82 }
83 return indexes;
84}
85function uniqs() {
86 var list = Array.prototype.concat.apply([], arguments);
87 return list.filter(function (item, i) {
88 return i === list.indexOf(item);
89 });
90}
91var Parser = /*#__PURE__*/function () {
92 function Parser(rule, options) {
93 if (options === void 0) {
94 options = {};
95 }
96 this.rule = rule;
97 this.options = Object.assign({
98 lossy: false,
99 safe: false
100 }, options);
101 this.position = 0;
102 this.css = typeof this.rule === 'string' ? this.rule : this.rule.selector;
103 this.tokens = (0, _tokenize["default"])({
104 css: this.css,
105 error: this._errorGenerator(),
106 safe: this.options.safe
107 });
108 var rootSource = getTokenSourceSpan(this.tokens[0], this.tokens[this.tokens.length - 1]);
109 this.root = new _root["default"]({
110 source: rootSource
111 });
112 this.root.errorGenerator = this._errorGenerator();
113 var selector = new _selector["default"]({
114 source: {
115 start: {
116 line: 1,
117 column: 1
118 }
119 },
120 sourceIndex: 0
121 });
122 this.root.append(selector);
123 this.current = selector;
124 this.loop();
125 }
126 var _proto = Parser.prototype;
127 _proto._errorGenerator = function _errorGenerator() {
128 var _this = this;
129 return function (message, errorOptions) {
130 if (typeof _this.rule === 'string') {
131 return new Error(message);
132 }
133 return _this.rule.error(message, errorOptions);
134 };
135 };
136 _proto.attribute = function attribute() {
137 var attr = [];
138 var startingToken = this.currToken;
139 this.position++;
140 while (this.position < this.tokens.length && this.currToken[_tokenize.FIELDS.TYPE] !== tokens.closeSquare) {
141 attr.push(this.currToken);
142 this.position++;
143 }
144 if (this.currToken[_tokenize.FIELDS.TYPE] !== tokens.closeSquare) {
145 return this.expected('closing square bracket', this.currToken[_tokenize.FIELDS.START_POS]);
146 }
147 var len = attr.length;
148 var node = {
149 source: getSource(startingToken[1], startingToken[2], this.currToken[3], this.currToken[4]),
150 sourceIndex: startingToken[_tokenize.FIELDS.START_POS]
151 };
152 if (len === 1 && !~[tokens.word].indexOf(attr[0][_tokenize.FIELDS.TYPE])) {
153 return this.expected('attribute', attr[0][_tokenize.FIELDS.START_POS]);
154 }
155 var pos = 0;
156 var spaceBefore = '';
157 var commentBefore = '';
158 var lastAdded = null;
159 var spaceAfterMeaningfulToken = false;
160 while (pos < len) {
161 var token = attr[pos];
162 var content = this.content(token);
163 var next = attr[pos + 1];
164 switch (token[_tokenize.FIELDS.TYPE]) {
165 case tokens.space:
166 // if (
167 // len === 1 ||
168 // pos === 0 && this.content(next) === '|'
169 // ) {
170 // return this.expected('attribute', token[TOKEN.START_POS], content);
171 // }
172 spaceAfterMeaningfulToken = true;
173 if (this.options.lossy) {
174 break;
175 }
176 if (lastAdded) {
177 (0, _util.ensureObject)(node, 'spaces', lastAdded);
178 var prevContent = node.spaces[lastAdded].after || '';
179 node.spaces[lastAdded].after = prevContent + content;
180 var existingComment = (0, _util.getProp)(node, 'raws', 'spaces', lastAdded, 'after') || null;
181 if (existingComment) {
182 node.raws.spaces[lastAdded].after = existingComment + content;
183 }
184 } else {
185 spaceBefore = spaceBefore + content;
186 commentBefore = commentBefore + content;
187 }
188 break;
189 case tokens.asterisk:
190 if (next[_tokenize.FIELDS.TYPE] === tokens.equals) {
191 node.operator = content;
192 lastAdded = 'operator';
193 } else if ((!node.namespace || lastAdded === "namespace" && !spaceAfterMeaningfulToken) && next) {
194 if (spaceBefore) {
195 (0, _util.ensureObject)(node, 'spaces', 'attribute');
196 node.spaces.attribute.before = spaceBefore;
197 spaceBefore = '';
198 }
199 if (commentBefore) {
200 (0, _util.ensureObject)(node, 'raws', 'spaces', 'attribute');
201 node.raws.spaces.attribute.before = spaceBefore;
202 commentBefore = '';
203 }
204 node.namespace = (node.namespace || "") + content;
205 var rawValue = (0, _util.getProp)(node, 'raws', 'namespace') || null;
206 if (rawValue) {
207 node.raws.namespace += content;
208 }
209 lastAdded = 'namespace';
210 }
211 spaceAfterMeaningfulToken = false;
212 break;
213 case tokens.dollar:
214 if (lastAdded === "value") {
215 var oldRawValue = (0, _util.getProp)(node, 'raws', 'value');
216 node.value += "$";
217 if (oldRawValue) {
218 node.raws.value = oldRawValue + "$";
219 }
220 break;
221 }
222 // Falls through
223 case tokens.caret:
224 if (next[_tokenize.FIELDS.TYPE] === tokens.equals) {
225 node.operator = content;
226 lastAdded = 'operator';
227 }
228 spaceAfterMeaningfulToken = false;
229 break;
230 case tokens.combinator:
231 if (content === '~' && next[_tokenize.FIELDS.TYPE] === tokens.equals) {
232 node.operator = content;
233 lastAdded = 'operator';
234 }
235 if (content !== '|') {
236 spaceAfterMeaningfulToken = false;
237 break;
238 }
239 if (next[_tokenize.FIELDS.TYPE] === tokens.equals) {
240 node.operator = content;
241 lastAdded = 'operator';
242 } else if (!node.namespace && !node.attribute) {
243 node.namespace = true;
244 }
245 spaceAfterMeaningfulToken = false;
246 break;
247 case tokens.word:
248 if (next && this.content(next) === '|' && attr[pos + 2] && attr[pos + 2][_tokenize.FIELDS.TYPE] !== tokens.equals &&
249 // this look-ahead probably fails with comment nodes involved.
250 !node.operator && !node.namespace) {
251 node.namespace = content;
252 lastAdded = 'namespace';
253 } else if (!node.attribute || lastAdded === "attribute" && !spaceAfterMeaningfulToken) {
254 if (spaceBefore) {
255 (0, _util.ensureObject)(node, 'spaces', 'attribute');
256 node.spaces.attribute.before = spaceBefore;
257 spaceBefore = '';
258 }
259 if (commentBefore) {
260 (0, _util.ensureObject)(node, 'raws', 'spaces', 'attribute');
261 node.raws.spaces.attribute.before = commentBefore;
262 commentBefore = '';
263 }
264 node.attribute = (node.attribute || "") + content;
265 var _rawValue = (0, _util.getProp)(node, 'raws', 'attribute') || null;
266 if (_rawValue) {
267 node.raws.attribute += content;
268 }
269 lastAdded = 'attribute';
270 } else if (!node.value && node.value !== "" || lastAdded === "value" && !(spaceAfterMeaningfulToken || node.quoteMark)) {
271 var _unescaped = (0, _util.unesc)(content);
272 var _oldRawValue = (0, _util.getProp)(node, 'raws', 'value') || '';
273 var oldValue = node.value || '';
274 node.value = oldValue + _unescaped;
275 node.quoteMark = null;
276 if (_unescaped !== content || _oldRawValue) {
277 (0, _util.ensureObject)(node, 'raws');
278 node.raws.value = (_oldRawValue || oldValue) + content;
279 }
280 lastAdded = 'value';
281 } else {
282 var insensitive = content === 'i' || content === "I";
283 if ((node.value || node.value === '') && (node.quoteMark || spaceAfterMeaningfulToken)) {
284 node.insensitive = insensitive;
285 if (!insensitive || content === "I") {
286 (0, _util.ensureObject)(node, 'raws');
287 node.raws.insensitiveFlag = content;
288 }
289 lastAdded = 'insensitive';
290 if (spaceBefore) {
291 (0, _util.ensureObject)(node, 'spaces', 'insensitive');
292 node.spaces.insensitive.before = spaceBefore;
293 spaceBefore = '';
294 }
295 if (commentBefore) {
296 (0, _util.ensureObject)(node, 'raws', 'spaces', 'insensitive');
297 node.raws.spaces.insensitive.before = commentBefore;
298 commentBefore = '';
299 }
300 } else if (node.value || node.value === '') {
301 lastAdded = 'value';
302 node.value += content;
303 if (node.raws.value) {
304 node.raws.value += content;
305 }
306 }
307 }
308 spaceAfterMeaningfulToken = false;
309 break;
310 case tokens.str:
311 if (!node.attribute || !node.operator) {
312 return this.error("Expected an attribute followed by an operator preceding the string.", {
313 index: token[_tokenize.FIELDS.START_POS]
314 });
315 }
316 var _unescapeValue = (0, _attribute.unescapeValue)(content),
317 unescaped = _unescapeValue.unescaped,
318 quoteMark = _unescapeValue.quoteMark;
319 node.value = unescaped;
320 node.quoteMark = quoteMark;
321 lastAdded = 'value';
322 (0, _util.ensureObject)(node, 'raws');
323 node.raws.value = content;
324 spaceAfterMeaningfulToken = false;
325 break;
326 case tokens.equals:
327 if (!node.attribute) {
328 return this.expected('attribute', token[_tokenize.FIELDS.START_POS], content);
329 }
330 if (node.value) {
331 return this.error('Unexpected "=" found; an operator was already defined.', {
332 index: token[_tokenize.FIELDS.START_POS]
333 });
334 }
335 node.operator = node.operator ? node.operator + content : content;
336 lastAdded = 'operator';
337 spaceAfterMeaningfulToken = false;
338 break;
339 case tokens.comment:
340 if (lastAdded) {
341 if (spaceAfterMeaningfulToken || next && next[_tokenize.FIELDS.TYPE] === tokens.space || lastAdded === 'insensitive') {
342 var lastComment = (0, _util.getProp)(node, 'spaces', lastAdded, 'after') || '';
343 var rawLastComment = (0, _util.getProp)(node, 'raws', 'spaces', lastAdded, 'after') || lastComment;
344 (0, _util.ensureObject)(node, 'raws', 'spaces', lastAdded);
345 node.raws.spaces[lastAdded].after = rawLastComment + content;
346 } else {
347 var lastValue = node[lastAdded] || '';
348 var rawLastValue = (0, _util.getProp)(node, 'raws', lastAdded) || lastValue;
349 (0, _util.ensureObject)(node, 'raws');
350 node.raws[lastAdded] = rawLastValue + content;
351 }
352 } else {
353 commentBefore = commentBefore + content;
354 }
355 break;
356 default:
357 return this.error("Unexpected \"" + content + "\" found.", {
358 index: token[_tokenize.FIELDS.START_POS]
359 });
360 }
361 pos++;
362 }
363 unescapeProp(node, "attribute");
364 unescapeProp(node, "namespace");
365 this.newNode(new _attribute["default"](node));
366 this.position++;
367 }
368
369 /**
370 * return a node containing meaningless garbage up to (but not including) the specified token position.
371 * if the token position is negative, all remaining tokens are consumed.
372 *
373 * This returns an array containing a single string node if all whitespace,
374 * otherwise an array of comment nodes with space before and after.
375 *
376 * These tokens are not added to the current selector, the caller can add them or use them to amend
377 * a previous node's space metadata.
378 *
379 * In lossy mode, this returns only comments.
380 */;
381 _proto.parseWhitespaceEquivalentTokens = function parseWhitespaceEquivalentTokens(stopPosition) {
382 if (stopPosition < 0) {
383 stopPosition = this.tokens.length;
384 }
385 var startPosition = this.position;
386 var nodes = [];
387 var space = "";
388 var lastComment = undefined;
389 do {
390 if (WHITESPACE_TOKENS[this.currToken[_tokenize.FIELDS.TYPE]]) {
391 if (!this.options.lossy) {
392 space += this.content();
393 }
394 } else if (this.currToken[_tokenize.FIELDS.TYPE] === tokens.comment) {
395 var spaces = {};
396 if (space) {
397 spaces.before = space;
398 space = "";
399 }
400 lastComment = new _comment["default"]({
401 value: this.content(),
402 source: getTokenSource(this.currToken),
403 sourceIndex: this.currToken[_tokenize.FIELDS.START_POS],
404 spaces: spaces
405 });
406 nodes.push(lastComment);
407 }
408 } while (++this.position < stopPosition);
409 if (space) {
410 if (lastComment) {
411 lastComment.spaces.after = space;
412 } else if (!this.options.lossy) {
413 var firstToken = this.tokens[startPosition];
414 var lastToken = this.tokens[this.position - 1];
415 nodes.push(new _string["default"]({
416 value: '',
417 source: getSource(firstToken[_tokenize.FIELDS.START_LINE], firstToken[_tokenize.FIELDS.START_COL], lastToken[_tokenize.FIELDS.END_LINE], lastToken[_tokenize.FIELDS.END_COL]),
418 sourceIndex: firstToken[_tokenize.FIELDS.START_POS],
419 spaces: {
420 before: space,
421 after: ''
422 }
423 }));
424 }
425 }
426 return nodes;
427 }
428
429 /**
430 *
431 * @param {*} nodes
432 */;
433 _proto.convertWhitespaceNodesToSpace = function convertWhitespaceNodesToSpace(nodes, requiredSpace) {
434 var _this2 = this;
435 if (requiredSpace === void 0) {
436 requiredSpace = false;
437 }
438 var space = "";
439 var rawSpace = "";
440 nodes.forEach(function (n) {
441 var spaceBefore = _this2.lossySpace(n.spaces.before, requiredSpace);
442 var rawSpaceBefore = _this2.lossySpace(n.rawSpaceBefore, requiredSpace);
443 space += spaceBefore + _this2.lossySpace(n.spaces.after, requiredSpace && spaceBefore.length === 0);
444 rawSpace += spaceBefore + n.value + _this2.lossySpace(n.rawSpaceAfter, requiredSpace && rawSpaceBefore.length === 0);
445 });
446 if (rawSpace === space) {
447 rawSpace = undefined;
448 }
449 var result = {
450 space: space,
451 rawSpace: rawSpace
452 };
453 return result;
454 };
455 _proto.isNamedCombinator = function isNamedCombinator(position) {
456 if (position === void 0) {
457 position = this.position;
458 }
459 return this.tokens[position + 0] && this.tokens[position + 0][_tokenize.FIELDS.TYPE] === tokens.slash && this.tokens[position + 1] && this.tokens[position + 1][_tokenize.FIELDS.TYPE] === tokens.word && this.tokens[position + 2] && this.tokens[position + 2][_tokenize.FIELDS.TYPE] === tokens.slash;
460 };
461 _proto.namedCombinator = function namedCombinator() {
462 if (this.isNamedCombinator()) {
463 var nameRaw = this.content(this.tokens[this.position + 1]);
464 var name = (0, _util.unesc)(nameRaw).toLowerCase();
465 var raws = {};
466 if (name !== nameRaw) {
467 raws.value = "/" + nameRaw + "/";
468 }
469 var node = new _combinator["default"]({
470 value: "/" + name + "/",
471 source: getSource(this.currToken[_tokenize.FIELDS.START_LINE], this.currToken[_tokenize.FIELDS.START_COL], this.tokens[this.position + 2][_tokenize.FIELDS.END_LINE], this.tokens[this.position + 2][_tokenize.FIELDS.END_COL]),
472 sourceIndex: this.currToken[_tokenize.FIELDS.START_POS],
473 raws: raws
474 });
475 this.position = this.position + 3;
476 return node;
477 } else {
478 this.unexpected();
479 }
480 };
481 _proto.combinator = function combinator() {
482 var _this3 = this;
483 if (this.content() === '|') {
484 return this.namespace();
485 }
486 // We need to decide between a space that's a descendant combinator and meaningless whitespace at the end of a selector.
487 var nextSigTokenPos = this.locateNextMeaningfulToken(this.position);
488 if (nextSigTokenPos < 0 || this.tokens[nextSigTokenPos][_tokenize.FIELDS.TYPE] === tokens.comma || this.tokens[nextSigTokenPos][_tokenize.FIELDS.TYPE] === tokens.closeParenthesis) {
489 var nodes = this.parseWhitespaceEquivalentTokens(nextSigTokenPos);
490 if (nodes.length > 0) {
491 var last = this.current.last;
492 if (last) {
493 var _this$convertWhitespa = this.convertWhitespaceNodesToSpace(nodes),
494 space = _this$convertWhitespa.space,
495 rawSpace = _this$convertWhitespa.rawSpace;
496 if (rawSpace !== undefined) {
497 last.rawSpaceAfter += rawSpace;
498 }
499 last.spaces.after += space;
500 } else {
501 nodes.forEach(function (n) {
502 return _this3.newNode(n);
503 });
504 }
505 }
506 return;
507 }
508 var firstToken = this.currToken;
509 var spaceOrDescendantSelectorNodes = undefined;
510 if (nextSigTokenPos > this.position) {
511 spaceOrDescendantSelectorNodes = this.parseWhitespaceEquivalentTokens(nextSigTokenPos);
512 }
513 var node;
514 if (this.isNamedCombinator()) {
515 node = this.namedCombinator();
516 } else if (this.currToken[_tokenize.FIELDS.TYPE] === tokens.combinator) {
517 node = new _combinator["default"]({
518 value: this.content(),
519 source: getTokenSource(this.currToken),
520 sourceIndex: this.currToken[_tokenize.FIELDS.START_POS]
521 });
522 this.position++;
523 } else if (WHITESPACE_TOKENS[this.currToken[_tokenize.FIELDS.TYPE]]) {
524 // pass
525 } else if (!spaceOrDescendantSelectorNodes) {
526 this.unexpected();
527 }
528 if (node) {
529 if (spaceOrDescendantSelectorNodes) {
530 var _this$convertWhitespa2 = this.convertWhitespaceNodesToSpace(spaceOrDescendantSelectorNodes),
531 _space = _this$convertWhitespa2.space,
532 _rawSpace = _this$convertWhitespa2.rawSpace;
533 node.spaces.before = _space;
534 node.rawSpaceBefore = _rawSpace;
535 }
536 } else {
537 // descendant combinator
538 var _this$convertWhitespa3 = this.convertWhitespaceNodesToSpace(spaceOrDescendantSelectorNodes, true),
539 _space2 = _this$convertWhitespa3.space,
540 _rawSpace2 = _this$convertWhitespa3.rawSpace;
541 if (!_rawSpace2) {
542 _rawSpace2 = _space2;
543 }
544 var spaces = {};
545 var raws = {
546 spaces: {}
547 };
548 if (_space2.endsWith(' ') && _rawSpace2.endsWith(' ')) {
549 spaces.before = _space2.slice(0, _space2.length - 1);
550 raws.spaces.before = _rawSpace2.slice(0, _rawSpace2.length - 1);
551 } else if (_space2.startsWith(' ') && _rawSpace2.startsWith(' ')) {
552 spaces.after = _space2.slice(1);
553 raws.spaces.after = _rawSpace2.slice(1);
554 } else {
555 raws.value = _rawSpace2;
556 }
557 node = new _combinator["default"]({
558 value: ' ',
559 source: getTokenSourceSpan(firstToken, this.tokens[this.position - 1]),
560 sourceIndex: firstToken[_tokenize.FIELDS.START_POS],
561 spaces: spaces,
562 raws: raws
563 });
564 }
565 if (this.currToken && this.currToken[_tokenize.FIELDS.TYPE] === tokens.space) {
566 node.spaces.after = this.optionalSpace(this.content());
567 this.position++;
568 }
569 return this.newNode(node);
570 };
571 _proto.comma = function comma() {
572 if (this.position === this.tokens.length - 1) {
573 this.root.trailingComma = true;
574 this.position++;
575 return;
576 }
577 this.current._inferEndPosition();
578 var selector = new _selector["default"]({
579 source: {
580 start: tokenStart(this.tokens[this.position + 1])
581 },
582 sourceIndex: this.tokens[this.position + 1][_tokenize.FIELDS.START_POS]
583 });
584 this.current.parent.append(selector);
585 this.current = selector;
586 this.position++;
587 };
588 _proto.comment = function comment() {
589 var current = this.currToken;
590 this.newNode(new _comment["default"]({
591 value: this.content(),
592 source: getTokenSource(current),
593 sourceIndex: current[_tokenize.FIELDS.START_POS]
594 }));
595 this.position++;
596 };
597 _proto.error = function error(message, opts) {
598 throw this.root.error(message, opts);
599 };
600 _proto.missingBackslash = function missingBackslash() {
601 return this.error('Expected a backslash preceding the semicolon.', {
602 index: this.currToken[_tokenize.FIELDS.START_POS]
603 });
604 };
605 _proto.missingParenthesis = function missingParenthesis() {
606 return this.expected('opening parenthesis', this.currToken[_tokenize.FIELDS.START_POS]);
607 };
608 _proto.missingSquareBracket = function missingSquareBracket() {
609 return this.expected('opening square bracket', this.currToken[_tokenize.FIELDS.START_POS]);
610 };
611 _proto.unexpected = function unexpected() {
612 return this.error("Unexpected '" + this.content() + "'. Escaping special characters with \\ may help.", this.currToken[_tokenize.FIELDS.START_POS]);
613 };
614 _proto.unexpectedPipe = function unexpectedPipe() {
615 return this.error("Unexpected '|'.", this.currToken[_tokenize.FIELDS.START_POS]);
616 };
617 _proto.namespace = function namespace() {
618 var before = this.prevToken && this.content(this.prevToken) || true;
619 if (this.nextToken[_tokenize.FIELDS.TYPE] === tokens.word) {
620 this.position++;
621 return this.word(before);
622 } else if (this.nextToken[_tokenize.FIELDS.TYPE] === tokens.asterisk) {
623 this.position++;
624 return this.universal(before);
625 }
626 this.unexpectedPipe();
627 };
628 _proto.nesting = function nesting() {
629 if (this.nextToken) {
630 var nextContent = this.content(this.nextToken);
631 if (nextContent === "|") {
632 this.position++;
633 return;
634 }
635 }
636 var current = this.currToken;
637 this.newNode(new _nesting["default"]({
638 value: this.content(),
639 source: getTokenSource(current),
640 sourceIndex: current[_tokenize.FIELDS.START_POS]
641 }));
642 this.position++;
643 };
644 _proto.parentheses = function parentheses() {
645 var last = this.current.last;
646 var unbalanced = 1;
647 this.position++;
648 if (last && last.type === types.PSEUDO) {
649 var selector = new _selector["default"]({
650 source: {
651 start: tokenStart(this.tokens[this.position])
652 },
653 sourceIndex: this.tokens[this.position][_tokenize.FIELDS.START_POS]
654 });
655 var cache = this.current;
656 last.append(selector);
657 this.current = selector;
658 while (this.position < this.tokens.length && unbalanced) {
659 if (this.currToken[_tokenize.FIELDS.TYPE] === tokens.openParenthesis) {
660 unbalanced++;
661 }
662 if (this.currToken[_tokenize.FIELDS.TYPE] === tokens.closeParenthesis) {
663 unbalanced--;
664 }
665 if (unbalanced) {
666 this.parse();
667 } else {
668 this.current.source.end = tokenEnd(this.currToken);
669 this.current.parent.source.end = tokenEnd(this.currToken);
670 this.position++;
671 }
672 }
673 this.current = cache;
674 } else {
675 // I think this case should be an error. It's used to implement a basic parse of media queries
676 // but I don't think it's a good idea.
677 var parenStart = this.currToken;
678 var parenValue = "(";
679 var parenEnd;
680 while (this.position < this.tokens.length && unbalanced) {
681 if (this.currToken[_tokenize.FIELDS.TYPE] === tokens.openParenthesis) {
682 unbalanced++;
683 }
684 if (this.currToken[_tokenize.FIELDS.TYPE] === tokens.closeParenthesis) {
685 unbalanced--;
686 }
687 parenEnd = this.currToken;
688 parenValue += this.parseParenthesisToken(this.currToken);
689 this.position++;
690 }
691 if (last) {
692 last.appendToPropertyAndEscape("value", parenValue, parenValue);
693 } else {
694 this.newNode(new _string["default"]({
695 value: parenValue,
696 source: getSource(parenStart[_tokenize.FIELDS.START_LINE], parenStart[_tokenize.FIELDS.START_COL], parenEnd[_tokenize.FIELDS.END_LINE], parenEnd[_tokenize.FIELDS.END_COL]),
697 sourceIndex: parenStart[_tokenize.FIELDS.START_POS]
698 }));
699 }
700 }
701 if (unbalanced) {
702 return this.expected('closing parenthesis', this.currToken[_tokenize.FIELDS.START_POS]);
703 }
704 };
705 _proto.pseudo = function pseudo() {
706 var _this4 = this;
707 var pseudoStr = '';
708 var startingToken = this.currToken;
709 while (this.currToken && this.currToken[_tokenize.FIELDS.TYPE] === tokens.colon) {
710 pseudoStr += this.content();
711 this.position++;
712 }
713 if (!this.currToken) {
714 return this.expected(['pseudo-class', 'pseudo-element'], this.position - 1);
715 }
716 if (this.currToken[_tokenize.FIELDS.TYPE] === tokens.word) {
717 this.splitWord(false, function (first, length) {
718 pseudoStr += first;
719 _this4.newNode(new _pseudo["default"]({
720 value: pseudoStr,
721 source: getTokenSourceSpan(startingToken, _this4.currToken),
722 sourceIndex: startingToken[_tokenize.FIELDS.START_POS]
723 }));
724 if (length > 1 && _this4.nextToken && _this4.nextToken[_tokenize.FIELDS.TYPE] === tokens.openParenthesis) {
725 _this4.error('Misplaced parenthesis.', {
726 index: _this4.nextToken[_tokenize.FIELDS.START_POS]
727 });
728 }
729 });
730 } else {
731 return this.expected(['pseudo-class', 'pseudo-element'], this.currToken[_tokenize.FIELDS.START_POS]);
732 }
733 };
734 _proto.space = function space() {
735 var content = this.content();
736 // Handle space before and after the selector
737 if (this.position === 0 || this.prevToken[_tokenize.FIELDS.TYPE] === tokens.comma || this.prevToken[_tokenize.FIELDS.TYPE] === tokens.openParenthesis || this.current.nodes.every(function (node) {
738 return node.type === 'comment';
739 })) {
740 this.spaces = this.optionalSpace(content);
741 this.position++;
742 } else if (this.position === this.tokens.length - 1 || this.nextToken[_tokenize.FIELDS.TYPE] === tokens.comma || this.nextToken[_tokenize.FIELDS.TYPE] === tokens.closeParenthesis) {
743 this.current.last.spaces.after = this.optionalSpace(content);
744 this.position++;
745 } else {
746 this.combinator();
747 }
748 };
749 _proto.string = function string() {
750 var current = this.currToken;
751 this.newNode(new _string["default"]({
752 value: this.content(),
753 source: getTokenSource(current),
754 sourceIndex: current[_tokenize.FIELDS.START_POS]
755 }));
756 this.position++;
757 };
758 _proto.universal = function universal(namespace) {
759 var nextToken = this.nextToken;
760 if (nextToken && this.content(nextToken) === '|') {
761 this.position++;
762 return this.namespace();
763 }
764 var current = this.currToken;
765 this.newNode(new _universal["default"]({
766 value: this.content(),
767 source: getTokenSource(current),
768 sourceIndex: current[_tokenize.FIELDS.START_POS]
769 }), namespace);
770 this.position++;
771 };
772 _proto.splitWord = function splitWord(namespace, firstCallback) {
773 var _this5 = this;
774 var nextToken = this.nextToken;
775 var word = this.content();
776 while (nextToken && ~[tokens.dollar, tokens.caret, tokens.equals, tokens.word].indexOf(nextToken[_tokenize.FIELDS.TYPE])) {
777 this.position++;
778 var current = this.content();
779 word += current;
780 if (current.lastIndexOf('\\') === current.length - 1) {
781 var next = this.nextToken;
782 if (next && next[_tokenize.FIELDS.TYPE] === tokens.space) {
783 word += this.requiredSpace(this.content(next));
784 this.position++;
785 }
786 }
787 nextToken = this.nextToken;
788 }
789 var hasClass = indexesOf(word, '.').filter(function (i) {
790 // Allow escaped dot within class name
791 var escapedDot = word[i - 1] === '\\';
792 // Allow decimal numbers percent in @keyframes
793 var isKeyframesPercent = /^\d+\.\d+%$/.test(word);
794 return !escapedDot && !isKeyframesPercent;
795 });
796 var hasId = indexesOf(word, '#').filter(function (i) {
797 return word[i - 1] !== '\\';
798 });
799 // Eliminate Sass interpolations from the list of id indexes
800 var interpolations = indexesOf(word, '#{');
801 if (interpolations.length) {
802 hasId = hasId.filter(function (hashIndex) {
803 return !~interpolations.indexOf(hashIndex);
804 });
805 }
806 var indices = (0, _sortAscending["default"])(uniqs([0].concat(hasClass, hasId)));
807 indices.forEach(function (ind, i) {
808 var index = indices[i + 1] || word.length;
809 var value = word.slice(ind, index);
810 if (i === 0 && firstCallback) {
811 return firstCallback.call(_this5, value, indices.length);
812 }
813 var node;
814 var current = _this5.currToken;
815 var sourceIndex = current[_tokenize.FIELDS.START_POS] + indices[i];
816 var source = getSource(current[1], current[2] + ind, current[3], current[2] + (index - 1));
817 if (~hasClass.indexOf(ind)) {
818 var classNameOpts = {
819 value: value.slice(1),
820 source: source,
821 sourceIndex: sourceIndex
822 };
823 node = new _className["default"](unescapeProp(classNameOpts, "value"));
824 } else if (~hasId.indexOf(ind)) {
825 var idOpts = {
826 value: value.slice(1),
827 source: source,
828 sourceIndex: sourceIndex
829 };
830 node = new _id["default"](unescapeProp(idOpts, "value"));
831 } else {
832 var tagOpts = {
833 value: value,
834 source: source,
835 sourceIndex: sourceIndex
836 };
837 unescapeProp(tagOpts, "value");
838 node = new _tag["default"](tagOpts);
839 }
840 _this5.newNode(node, namespace);
841 // Ensure that the namespace is used only once
842 namespace = null;
843 });
844 this.position++;
845 };
846 _proto.word = function word(namespace) {
847 var nextToken = this.nextToken;
848 if (nextToken && this.content(nextToken) === '|') {
849 this.position++;
850 return this.namespace();
851 }
852 return this.splitWord(namespace);
853 };
854 _proto.loop = function loop() {
855 while (this.position < this.tokens.length) {
856 this.parse(true);
857 }
858 this.current._inferEndPosition();
859 return this.root;
860 };
861 _proto.parse = function parse(throwOnParenthesis) {
862 switch (this.currToken[_tokenize.FIELDS.TYPE]) {
863 case tokens.space:
864 this.space();
865 break;
866 case tokens.comment:
867 this.comment();
868 break;
869 case tokens.openParenthesis:
870 this.parentheses();
871 break;
872 case tokens.closeParenthesis:
873 if (throwOnParenthesis) {
874 this.missingParenthesis();
875 }
876 break;
877 case tokens.openSquare:
878 this.attribute();
879 break;
880 case tokens.dollar:
881 case tokens.caret:
882 case tokens.equals:
883 case tokens.word:
884 this.word();
885 break;
886 case tokens.colon:
887 this.pseudo();
888 break;
889 case tokens.comma:
890 this.comma();
891 break;
892 case tokens.asterisk:
893 this.universal();
894 break;
895 case tokens.ampersand:
896 this.nesting();
897 break;
898 case tokens.slash:
899 case tokens.combinator:
900 this.combinator();
901 break;
902 case tokens.str:
903 this.string();
904 break;
905 // These cases throw; no break needed.
906 case tokens.closeSquare:
907 this.missingSquareBracket();
908 case tokens.semicolon:
909 this.missingBackslash();
910 default:
911 this.unexpected();
912 }
913 }
914
915 /**
916 * Helpers
917 */;
918 _proto.expected = function expected(description, index, found) {
919 if (Array.isArray(description)) {
920 var last = description.pop();
921 description = description.join(', ') + " or " + last;
922 }
923 var an = /^[aeiou]/.test(description[0]) ? 'an' : 'a';
924 if (!found) {
925 return this.error("Expected " + an + " " + description + ".", {
926 index: index
927 });
928 }
929 return this.error("Expected " + an + " " + description + ", found \"" + found + "\" instead.", {
930 index: index
931 });
932 };
933 _proto.requiredSpace = function requiredSpace(space) {
934 return this.options.lossy ? ' ' : space;
935 };
936 _proto.optionalSpace = function optionalSpace(space) {
937 return this.options.lossy ? '' : space;
938 };
939 _proto.lossySpace = function lossySpace(space, required) {
940 if (this.options.lossy) {
941 return required ? ' ' : '';
942 } else {
943 return space;
944 }
945 };
946 _proto.parseParenthesisToken = function parseParenthesisToken(token) {
947 var content = this.content(token);
948 if (token[_tokenize.FIELDS.TYPE] === tokens.space) {
949 return this.requiredSpace(content);
950 } else {
951 return content;
952 }
953 };
954 _proto.newNode = function newNode(node, namespace) {
955 if (namespace) {
956 if (/^ +$/.test(namespace)) {
957 if (!this.options.lossy) {
958 this.spaces = (this.spaces || '') + namespace;
959 }
960 namespace = true;
961 }
962 node.namespace = namespace;
963 unescapeProp(node, "namespace");
964 }
965 if (this.spaces) {
966 node.spaces.before = this.spaces;
967 this.spaces = '';
968 }
969 return this.current.append(node);
970 };
971 _proto.content = function content(token) {
972 if (token === void 0) {
973 token = this.currToken;
974 }
975 return this.css.slice(token[_tokenize.FIELDS.START_POS], token[_tokenize.FIELDS.END_POS]);
976 };
977 /**
978 * returns the index of the next non-whitespace, non-comment token.
979 * returns -1 if no meaningful token is found.
980 */
981 _proto.locateNextMeaningfulToken = function locateNextMeaningfulToken(startPosition) {
982 if (startPosition === void 0) {
983 startPosition = this.position + 1;
984 }
985 var searchPosition = startPosition;
986 while (searchPosition < this.tokens.length) {
987 if (WHITESPACE_EQUIV_TOKENS[this.tokens[searchPosition][_tokenize.FIELDS.TYPE]]) {
988 searchPosition++;
989 continue;
990 } else {
991 return searchPosition;
992 }
993 }
994 return -1;
995 };
996 _createClass(Parser, [{
997 key: "currToken",
998 get: function get() {
999 return this.tokens[this.position];
1000 }
1001 }, {
1002 key: "nextToken",
1003 get: function get() {
1004 return this.tokens[this.position + 1];
1005 }
1006 }, {
1007 key: "prevToken",
1008 get: function get() {
1009 return this.tokens[this.position - 1];
1010 }
1011 }]);
1012 return Parser;
1013}();
1014exports["default"] = Parser;
1015module.exports = exports.default;
Note: See TracBrowser for help on using the repository browser.