Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
parser.js1015 linesDownload Raw Back to dist
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[0] === ' ' && _rawSpace2[0] === ' ') {
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;
codekingpro/portable-devtools · Team Ai