67829170a3455bebb45458f61a1f22f80202196e4fa471d649d87bcdcc8125baecd6e17a07628f6961d540786ac4d57f620c3af552e7192098ec366fa610d3 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. 'use strict';
  2. exports.__esModule = true;
  3. var _createClass = function () { function 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  4. var _dotProp = require('dot-prop');
  5. var _dotProp2 = _interopRequireDefault(_dotProp);
  6. var _indexesOf = require('indexes-of');
  7. var _indexesOf2 = _interopRequireDefault(_indexesOf);
  8. var _uniq = require('uniq');
  9. var _uniq2 = _interopRequireDefault(_uniq);
  10. var _root = require('./selectors/root');
  11. var _root2 = _interopRequireDefault(_root);
  12. var _selector = require('./selectors/selector');
  13. var _selector2 = _interopRequireDefault(_selector);
  14. var _className = require('./selectors/className');
  15. var _className2 = _interopRequireDefault(_className);
  16. var _comment = require('./selectors/comment');
  17. var _comment2 = _interopRequireDefault(_comment);
  18. var _id = require('./selectors/id');
  19. var _id2 = _interopRequireDefault(_id);
  20. var _tag = require('./selectors/tag');
  21. var _tag2 = _interopRequireDefault(_tag);
  22. var _string = require('./selectors/string');
  23. var _string2 = _interopRequireDefault(_string);
  24. var _pseudo = require('./selectors/pseudo');
  25. var _pseudo2 = _interopRequireDefault(_pseudo);
  26. var _attribute = require('./selectors/attribute');
  27. var _attribute2 = _interopRequireDefault(_attribute);
  28. var _universal = require('./selectors/universal');
  29. var _universal2 = _interopRequireDefault(_universal);
  30. var _combinator = require('./selectors/combinator');
  31. var _combinator2 = _interopRequireDefault(_combinator);
  32. var _nesting = require('./selectors/nesting');
  33. var _nesting2 = _interopRequireDefault(_nesting);
  34. var _sortAscending = require('./sortAscending');
  35. var _sortAscending2 = _interopRequireDefault(_sortAscending);
  36. var _tokenize = require('./tokenize');
  37. var _tokenize2 = _interopRequireDefault(_tokenize);
  38. var _tokenTypes = require('./tokenTypes');
  39. var tokens = _interopRequireWildcard(_tokenTypes);
  40. var _types = require('./selectors/types');
  41. var types = _interopRequireWildcard(_types);
  42. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  43. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  44. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  45. function getSource(startLine, startColumn, endLine, endColumn) {
  46. return {
  47. start: {
  48. line: startLine,
  49. column: startColumn
  50. },
  51. end: {
  52. line: endLine,
  53. column: endColumn
  54. }
  55. };
  56. }
  57. var Parser = function () {
  58. function Parser(rule) {
  59. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  60. _classCallCheck(this, Parser);
  61. this.rule = rule;
  62. this.options = Object.assign({ lossy: false, safe: false }, options);
  63. this.position = 0;
  64. this.root = new _root2.default();
  65. this.root.errorGenerator = this._errorGenerator();
  66. var selector = new _selector2.default();
  67. this.root.append(selector);
  68. this.current = selector;
  69. this.css = typeof this.rule === 'string' ? this.rule : this.rule.selector;
  70. if (this.options.lossy) {
  71. this.css = this.css.trim();
  72. }
  73. this.tokens = (0, _tokenize2.default)({
  74. css: this.css,
  75. error: this._errorGenerator(),
  76. safe: this.options.safe
  77. });
  78. this.loop();
  79. }
  80. Parser.prototype._errorGenerator = function _errorGenerator() {
  81. var _this = this;
  82. return function (message, errorOptions) {
  83. if (typeof _this.rule === 'string') {
  84. return new Error(message);
  85. }
  86. return _this.rule.error(message, errorOptions);
  87. };
  88. };
  89. Parser.prototype.attribute = function attribute() {
  90. var attr = [];
  91. var startingToken = this.currToken;
  92. this.position++;
  93. while (this.position < this.tokens.length && this.currToken[0] !== tokens.closeSquare) {
  94. attr.push(this.currToken);
  95. this.position++;
  96. }
  97. if (this.currToken[0] !== tokens.closeSquare) {
  98. return this.expected('closing square bracket', this.currToken[5]);
  99. }
  100. var len = attr.length;
  101. var node = {
  102. source: getSource(startingToken[1], startingToken[2], this.currToken[3], this.currToken[4]),
  103. sourceIndex: startingToken[5]
  104. };
  105. if (len === 1 && !~[tokens.word].indexOf(attr[0][0])) {
  106. return this.expected('attribute', attr[0][5]);
  107. }
  108. var pos = 0;
  109. var spaceBefore = '';
  110. var commentBefore = '';
  111. var lastAdded = null;
  112. var spaceAfterMeaningfulToken = false;
  113. while (pos < len) {
  114. var token = attr[pos];
  115. var content = this.content(token);
  116. var next = attr[pos + 1];
  117. switch (token[0]) {
  118. case tokens.space:
  119. if (len === 1 || pos === 0 && this.content(next) === '|') {
  120. return this.expected('attribute', token[5], content);
  121. }
  122. spaceAfterMeaningfulToken = true;
  123. if (this.options.lossy) {
  124. break;
  125. }
  126. if (lastAdded) {
  127. var spaceProp = 'spaces.' + lastAdded + '.after';
  128. _dotProp2.default.set(node, spaceProp, _dotProp2.default.get(node, spaceProp, '') + content);
  129. var commentProp = 'raws.spaces.' + lastAdded + '.after';
  130. var existingComment = _dotProp2.default.get(node, commentProp);
  131. if (existingComment) {
  132. _dotProp2.default.set(node, commentProp, existingComment + content);
  133. }
  134. } else {
  135. spaceBefore = spaceBefore + content;
  136. commentBefore = commentBefore + content;
  137. }
  138. break;
  139. case tokens.asterisk:
  140. if (next[0] === tokens.equals) {
  141. node.operator = content;
  142. lastAdded = 'operator';
  143. } else if ((!node.namespace || lastAdded === "namespace" && !spaceAfterMeaningfulToken) && next) {
  144. if (spaceBefore) {
  145. _dotProp2.default.set(node, 'spaces.attribute.before', spaceBefore);
  146. spaceBefore = '';
  147. }
  148. if (commentBefore) {
  149. _dotProp2.default.set(node, 'raws.spaces.attribute.before', spaceBefore);
  150. commentBefore = '';
  151. }
  152. node.namespace = (node.namespace || "") + content;
  153. var rawValue = _dotProp2.default.get(node, "raws.namespace");
  154. if (rawValue) {
  155. node.raws.namespace += content;
  156. }
  157. lastAdded = 'namespace';
  158. }
  159. spaceAfterMeaningfulToken = false;
  160. break;
  161. case tokens.dollar:
  162. case tokens.caret:
  163. if (next[0] === tokens.equals) {
  164. node.operator = content;
  165. lastAdded = 'operator';
  166. }
  167. spaceAfterMeaningfulToken = false;
  168. break;
  169. case tokens.combinator:
  170. if (content === '~' && next[0] === tokens.equals) {
  171. node.operator = content;
  172. lastAdded = 'operator';
  173. }
  174. if (content !== '|') {
  175. spaceAfterMeaningfulToken = false;
  176. break;
  177. }
  178. if (next[0] === tokens.equals) {
  179. node.operator = content;
  180. lastAdded = 'operator';
  181. } else if (!node.namespace && !node.attribute) {
  182. node.namespace = true;
  183. }
  184. spaceAfterMeaningfulToken = false;
  185. break;
  186. case tokens.word:
  187. if (next && this.content(next) === '|' && attr[pos + 2] && attr[pos + 2][0] !== tokens.equals && // this look-ahead probably fails with comment nodes involved.
  188. !node.operator && !node.namespace) {
  189. node.namespace = content;
  190. lastAdded = 'namespace';
  191. } else if (!node.attribute || lastAdded === "attribute" && !spaceAfterMeaningfulToken) {
  192. if (spaceBefore) {
  193. _dotProp2.default.set(node, 'spaces.attribute.before', spaceBefore);
  194. spaceBefore = '';
  195. }
  196. if (commentBefore) {
  197. _dotProp2.default.set(node, 'raws.spaces.attribute.before', commentBefore);
  198. commentBefore = '';
  199. }
  200. node.attribute = (node.attribute || "") + content;
  201. var _rawValue = _dotProp2.default.get(node, "raws.attribute");
  202. if (_rawValue) {
  203. node.raws.attribute += content;
  204. }
  205. lastAdded = 'attribute';
  206. } else if (!node.value || lastAdded === "value" && !spaceAfterMeaningfulToken) {
  207. node.value = (node.value || "") + content;
  208. var _rawValue2 = _dotProp2.default.get(node, "raws.value");
  209. if (_rawValue2) {
  210. node.raws.value += content;
  211. }
  212. lastAdded = 'value';
  213. _dotProp2.default.set(node, 'raws.unquoted', _dotProp2.default.get(node, 'raws.unquoted', '') + content);
  214. } else if (content === 'i') {
  215. if (node.value && (node.quoted || spaceAfterMeaningfulToken)) {
  216. node.insensitive = true;
  217. lastAdded = 'insensitive';
  218. if (spaceBefore) {
  219. _dotProp2.default.set(node, 'spaces.insensitive.before', spaceBefore);
  220. spaceBefore = '';
  221. }
  222. if (commentBefore) {
  223. _dotProp2.default.set(node, 'raws.spaces.insensitive.before', commentBefore);
  224. commentBefore = '';
  225. }
  226. } else if (node.value) {
  227. lastAdded = 'value';
  228. node.value += 'i';
  229. if (node.raws.value) {
  230. node.raws.value += 'i';
  231. }
  232. }
  233. }
  234. spaceAfterMeaningfulToken = false;
  235. break;
  236. case tokens.str:
  237. if (!node.attribute || !node.operator) {
  238. return this.error('Expected an attribute followed by an operator preceding the string.', {
  239. index: token[5]
  240. });
  241. }
  242. node.value = content;
  243. node.quoted = true;
  244. lastAdded = 'value';
  245. _dotProp2.default.set(node, 'raws.unquoted', content.slice(1, -1));
  246. spaceAfterMeaningfulToken = false;
  247. break;
  248. case tokens.equals:
  249. if (!node.attribute) {
  250. return this.expected('attribute', token[5], content);
  251. }
  252. if (node.value) {
  253. return this.error('Unexpected "=" found; an operator was already defined.', { index: token[5] });
  254. }
  255. node.operator = node.operator ? node.operator + content : content;
  256. lastAdded = 'operator';
  257. spaceAfterMeaningfulToken = false;
  258. break;
  259. case tokens.comment:
  260. if (lastAdded) {
  261. if (spaceAfterMeaningfulToken || next && next[0] === tokens.space) {
  262. var lastComment = _dotProp2.default.get(node, 'raws.spaces.' + lastAdded + '.after', _dotProp2.default.get(node, 'spaces.' + lastAdded + '.after', ''));
  263. _dotProp2.default.set(node, 'raws.spaces.' + lastAdded + '.after', lastComment + content);
  264. } else {
  265. var lastValue = _dotProp2.default.get(node, 'raws.' + lastAdded, _dotProp2.default.get(node, lastAdded, ''));
  266. _dotProp2.default.set(node, 'raws.' + lastAdded, lastValue + content);
  267. }
  268. } else {
  269. commentBefore = commentBefore + content;
  270. }
  271. break;
  272. default:
  273. return this.error('Unexpected "' + content + '" found.', { index: token[5] });
  274. }
  275. pos++;
  276. }
  277. this.newNode(new _attribute2.default(node));
  278. this.position++;
  279. };
  280. Parser.prototype.combinator = function combinator() {
  281. var current = this.currToken;
  282. if (this.content() === '|') {
  283. return this.namespace();
  284. }
  285. var node = new _combinator2.default({
  286. value: '',
  287. source: getSource(current[1], current[2], current[3], current[4]),
  288. sourceIndex: current[5]
  289. });
  290. while (this.position < this.tokens.length && this.currToken && (this.currToken[0] === tokens.space || this.currToken[0] === tokens.combinator)) {
  291. var content = this.content();
  292. if (this.nextToken && this.nextToken[0] === tokens.combinator) {
  293. node.spaces.before = this.parseSpace(content);
  294. node.source = getSource(this.nextToken[1], this.nextToken[2], this.nextToken[3], this.nextToken[4]);
  295. node.sourceIndex = this.nextToken[5];
  296. } else if (this.prevToken && this.prevToken[0] === tokens.combinator) {
  297. node.spaces.after = this.parseSpace(content);
  298. } else if (this.currToken[0] === tokens.combinator) {
  299. node.value = content;
  300. } else if (this.currToken[0] === tokens.space) {
  301. node.value = this.parseSpace(content, ' ');
  302. }
  303. this.position++;
  304. }
  305. return this.newNode(node);
  306. };
  307. Parser.prototype.comma = function comma() {
  308. if (this.position === this.tokens.length - 1) {
  309. this.root.trailingComma = true;
  310. this.position++;
  311. return;
  312. }
  313. var selector = new _selector2.default();
  314. this.current.parent.append(selector);
  315. this.current = selector;
  316. this.position++;
  317. };
  318. Parser.prototype.comment = function comment() {
  319. var current = this.currToken;
  320. this.newNode(new _comment2.default({
  321. value: this.content(),
  322. source: getSource(current[1], current[2], current[3], current[4]),
  323. sourceIndex: current[5]
  324. }));
  325. this.position++;
  326. };
  327. Parser.prototype.error = function error(message, opts) {
  328. throw this.root.error(message, opts);
  329. };
  330. Parser.prototype.missingBackslash = function missingBackslash() {
  331. return this.error('Expected a backslash preceding the semicolon.', {
  332. index: this.currToken[5]
  333. });
  334. };
  335. Parser.prototype.missingParenthesis = function missingParenthesis() {
  336. return this.expected('opening parenthesis', this.currToken[5]);
  337. };
  338. Parser.prototype.missingSquareBracket = function missingSquareBracket() {
  339. return this.expected('opening square bracket', this.currToken[5]);
  340. };
  341. Parser.prototype.namespace = function namespace() {
  342. var before = this.prevToken && this.content(this.prevToken) || true;
  343. if (this.nextToken[0] === tokens.word) {
  344. this.position++;
  345. return this.word(before);
  346. } else if (this.nextToken[0] === tokens.asterisk) {
  347. this.position++;
  348. return this.universal(before);
  349. }
  350. };
  351. Parser.prototype.nesting = function nesting() {
  352. var current = this.currToken;
  353. this.newNode(new _nesting2.default({
  354. value: this.content(),
  355. source: getSource(current[1], current[2], current[3], current[4]),
  356. sourceIndex: current[5]
  357. }));
  358. this.position++;
  359. };
  360. Parser.prototype.parentheses = function parentheses() {
  361. var last = this.current.last;
  362. var balanced = 1;
  363. this.position++;
  364. if (last && last.type === types.PSEUDO) {
  365. var selector = new _selector2.default();
  366. var cache = this.current;
  367. last.append(selector);
  368. this.current = selector;
  369. while (this.position < this.tokens.length && balanced) {
  370. if (this.currToken[0] === tokens.openParenthesis) {
  371. balanced++;
  372. }
  373. if (this.currToken[0] === tokens.closeParenthesis) {
  374. balanced--;
  375. }
  376. if (balanced) {
  377. this.parse();
  378. } else {
  379. selector.parent.source.end.line = this.currToken[3];
  380. selector.parent.source.end.column = this.currToken[4];
  381. this.position++;
  382. }
  383. }
  384. this.current = cache;
  385. } else {
  386. last.value += '(';
  387. while (this.position < this.tokens.length && balanced) {
  388. if (this.currToken[0] === tokens.openParenthesis) {
  389. balanced++;
  390. }
  391. if (this.currToken[0] === tokens.closeParenthesis) {
  392. balanced--;
  393. }
  394. last.value += this.parseParenthesisToken(this.currToken);
  395. this.position++;
  396. }
  397. }
  398. if (balanced) {
  399. return this.expected('closing parenthesis', this.currToken[5]);
  400. }
  401. };
  402. Parser.prototype.pseudo = function pseudo() {
  403. var _this2 = this;
  404. var pseudoStr = '';
  405. var startingToken = this.currToken;
  406. while (this.currToken && this.currToken[0] === tokens.colon) {
  407. pseudoStr += this.content();
  408. this.position++;
  409. }
  410. if (!this.currToken) {
  411. return this.expected(['pseudo-class', 'pseudo-element'], this.position - 1);
  412. }
  413. if (this.currToken[0] === tokens.word) {
  414. this.splitWord(false, function (first, length) {
  415. pseudoStr += first;
  416. _this2.newNode(new _pseudo2.default({
  417. value: pseudoStr,
  418. source: getSource(startingToken[1], startingToken[2], _this2.currToken[3], _this2.currToken[4]),
  419. sourceIndex: startingToken[5]
  420. }));
  421. if (length > 1 && _this2.nextToken && _this2.nextToken[0] === tokens.openParenthesis) {
  422. _this2.error('Misplaced parenthesis.', {
  423. index: _this2.nextToken[5]
  424. });
  425. }
  426. });
  427. } else {
  428. return this.expected(['pseudo-class', 'pseudo-element'], this.currToken[5]);
  429. }
  430. };
  431. Parser.prototype.space = function space() {
  432. var content = this.content();
  433. // Handle space before and after the selector
  434. if (this.position === 0 || this.prevToken[0] === tokens.comma || this.prevToken[0] === tokens.openParenthesis) {
  435. this.spaces = this.parseSpace(content);
  436. this.position++;
  437. } else if (this.position === this.tokens.length - 1 || this.nextToken[0] === tokens.comma || this.nextToken[0] === tokens.closeParenthesis) {
  438. this.current.last.spaces.after = this.parseSpace(content);
  439. this.position++;
  440. } else {
  441. this.combinator();
  442. }
  443. };
  444. Parser.prototype.string = function string() {
  445. var current = this.currToken;
  446. this.newNode(new _string2.default({
  447. value: this.content(),
  448. source: getSource(current[1], current[2], current[3], current[4]),
  449. sourceIndex: current[5]
  450. }));
  451. this.position++;
  452. };
  453. Parser.prototype.universal = function universal(namespace) {
  454. var nextToken = this.nextToken;
  455. if (nextToken && this.content(nextToken) === '|') {
  456. this.position++;
  457. return this.namespace();
  458. }
  459. var current = this.currToken;
  460. this.newNode(new _universal2.default({
  461. value: this.content(),
  462. source: getSource(current[1], current[2], current[3], current[4]),
  463. sourceIndex: current[5]
  464. }), namespace);
  465. this.position++;
  466. };
  467. Parser.prototype.splitWord = function splitWord(namespace, firstCallback) {
  468. var _this3 = this;
  469. var nextToken = this.nextToken;
  470. var word = this.content();
  471. while (nextToken && ~[tokens.dollar, tokens.caret, tokens.equals, tokens.word].indexOf(nextToken[0])) {
  472. this.position++;
  473. var current = this.content();
  474. word += current;
  475. if (current.lastIndexOf('\\') === current.length - 1) {
  476. var next = this.nextToken;
  477. if (next && next[0] === tokens.space) {
  478. word += this.parseSpace(this.content(next), ' ');
  479. this.position++;
  480. }
  481. }
  482. nextToken = this.nextToken;
  483. }
  484. var hasClass = (0, _indexesOf2.default)(word, '.');
  485. var hasId = (0, _indexesOf2.default)(word, '#');
  486. // Eliminate Sass interpolations from the list of id indexes
  487. var interpolations = (0, _indexesOf2.default)(word, '#{');
  488. if (interpolations.length) {
  489. hasId = hasId.filter(function (hashIndex) {
  490. return !~interpolations.indexOf(hashIndex);
  491. });
  492. }
  493. var indices = (0, _sortAscending2.default)((0, _uniq2.default)([0].concat(hasClass, hasId)));
  494. indices.forEach(function (ind, i) {
  495. var index = indices[i + 1] || word.length;
  496. var value = word.slice(ind, index);
  497. if (i === 0 && firstCallback) {
  498. return firstCallback.call(_this3, value, indices.length);
  499. }
  500. var node = void 0;
  501. var current = _this3.currToken;
  502. var sourceIndex = current[5] + indices[i];
  503. var source = getSource(current[1], current[2] + ind, current[3], current[2] + (index - 1));
  504. if (~hasClass.indexOf(ind)) {
  505. node = new _className2.default({
  506. value: value.slice(1),
  507. source: source,
  508. sourceIndex: sourceIndex
  509. });
  510. } else if (~hasId.indexOf(ind)) {
  511. node = new _id2.default({
  512. value: value.slice(1),
  513. source: source,
  514. sourceIndex: sourceIndex
  515. });
  516. } else {
  517. node = new _tag2.default({
  518. value: value,
  519. source: source,
  520. sourceIndex: sourceIndex
  521. });
  522. }
  523. _this3.newNode(node, namespace);
  524. // Ensure that the namespace is used only once
  525. namespace = null;
  526. });
  527. this.position++;
  528. };
  529. Parser.prototype.word = function word(namespace) {
  530. var nextToken = this.nextToken;
  531. if (nextToken && this.content(nextToken) === '|') {
  532. this.position++;
  533. return this.namespace();
  534. }
  535. return this.splitWord(namespace);
  536. };
  537. Parser.prototype.loop = function loop() {
  538. while (this.position < this.tokens.length) {
  539. this.parse(true);
  540. }
  541. return this.root;
  542. };
  543. Parser.prototype.parse = function parse(throwOnParenthesis) {
  544. switch (this.currToken[0]) {
  545. case tokens.space:
  546. this.space();
  547. break;
  548. case tokens.comment:
  549. this.comment();
  550. break;
  551. case tokens.openParenthesis:
  552. this.parentheses();
  553. break;
  554. case tokens.closeParenthesis:
  555. if (throwOnParenthesis) {
  556. this.missingParenthesis();
  557. }
  558. break;
  559. case tokens.openSquare:
  560. this.attribute();
  561. break;
  562. case tokens.dollar:
  563. case tokens.caret:
  564. case tokens.equals:
  565. case tokens.word:
  566. this.word();
  567. break;
  568. case tokens.colon:
  569. this.pseudo();
  570. break;
  571. case tokens.comma:
  572. this.comma();
  573. break;
  574. case tokens.asterisk:
  575. this.universal();
  576. break;
  577. case tokens.ampersand:
  578. this.nesting();
  579. break;
  580. case tokens.combinator:
  581. this.combinator();
  582. break;
  583. case tokens.str:
  584. this.string();
  585. break;
  586. // These cases throw; no break needed.
  587. case tokens.closeSquare:
  588. this.missingSquareBracket();
  589. case tokens.semicolon:
  590. this.missingBackslash();
  591. }
  592. };
  593. /**
  594. * Helpers
  595. */
  596. Parser.prototype.expected = function expected(description, index, found) {
  597. if (Array.isArray(description)) {
  598. var last = description.pop();
  599. description = description.join(', ') + ' or ' + last;
  600. }
  601. var an = /^[aeiou]/.test(description[0]) ? 'an' : 'a';
  602. if (!found) {
  603. return this.error('Expected ' + an + ' ' + description + '.', { index: index });
  604. }
  605. return this.error('Expected ' + an + ' ' + description + ', found "' + found + '" instead.', { index: index });
  606. };
  607. Parser.prototype.parseNamespace = function parseNamespace(namespace) {
  608. if (this.options.lossy && typeof namespace === 'string') {
  609. var trimmed = namespace.trim();
  610. if (!trimmed.length) {
  611. return true;
  612. }
  613. return trimmed;
  614. }
  615. return namespace;
  616. };
  617. Parser.prototype.parseSpace = function parseSpace(space) {
  618. var replacement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
  619. return this.options.lossy ? replacement : space;
  620. };
  621. Parser.prototype.parseValue = function parseValue(value) {
  622. if (!this.options.lossy || !value || typeof value !== 'string') {
  623. return value;
  624. }
  625. return value.trim();
  626. };
  627. Parser.prototype.parseParenthesisToken = function parseParenthesisToken(token) {
  628. var content = this.content(token);
  629. if (!this.options.lossy) {
  630. return content;
  631. }
  632. if (token[0] === tokens.space) {
  633. return this.parseSpace(content, ' ');
  634. }
  635. return this.parseValue(content);
  636. };
  637. Parser.prototype.newNode = function newNode(node, namespace) {
  638. if (namespace) {
  639. node.namespace = this.parseNamespace(namespace);
  640. }
  641. if (this.spaces) {
  642. node.spaces.before = this.spaces;
  643. this.spaces = '';
  644. }
  645. return this.current.append(node);
  646. };
  647. Parser.prototype.content = function content() {
  648. var token = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.currToken;
  649. return this.css.slice(token[5], token[6]);
  650. };
  651. _createClass(Parser, [{
  652. key: 'currToken',
  653. get: function get() {
  654. return this.tokens[this.position];
  655. }
  656. }, {
  657. key: 'nextToken',
  658. get: function get() {
  659. return this.tokens[this.position + 1];
  660. }
  661. }, {
  662. key: 'prevToken',
  663. get: function get() {
  664. return this.tokens[this.position - 1];
  665. }
  666. }]);
  667. return Parser;
  668. }();
  669. exports.default = Parser;
  670. module.exports = exports['default'];