index.js 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. module.exports = function resolveNestedSelector(selector, node) {
  2. var parent = node.parent;
  3. var parentIsNestAtRule = parent.type === 'atrule' && parent.name === 'nest';
  4. if (parent.type === 'root') return [selector];
  5. if (parent.type !== 'rule' && !parentIsNestAtRule) return resolveNestedSelector(selector, parent);
  6. var parentSelectors = (parentIsNestAtRule)
  7. ? split(parent.params, ',', false).map((x) => x.trim())
  8. : parent.selectors;
  9. var resolvedSelectors = parentSelectors.reduce(function(result, parentSelector) {
  10. if (selector.indexOf('&') !== -1) {
  11. var newlyResolvedSelectors = resolveNestedSelector(parentSelector, parent).map(function(resolvedParentSelector) {
  12. return split(selector, '&', true).join(resolvedParentSelector);
  13. });
  14. return result.concat(newlyResolvedSelectors);
  15. }
  16. var combinedSelector = [ parentSelector, selector ].join(' ');
  17. return result.concat(resolveNestedSelector(combinedSelector, parent));
  18. }, []);
  19. return resolvedSelectors;
  20. }
  21. var blockPairs = {
  22. '(': ')',
  23. '[': ']',
  24. '{': '}'
  25. };
  26. function split(string, separator, splitFunctions) {
  27. var array = [];
  28. var current = '';
  29. var split = false;
  30. var blockClose = [];
  31. var inQuote = false;
  32. var prevQuote = '';
  33. var escape = false;
  34. for (var letter of string) {
  35. if (escape) {
  36. escape = false;
  37. } else if (letter === '\\') {
  38. escape = true;
  39. } else if (inQuote) {
  40. if (letter === prevQuote) {
  41. inQuote = false;
  42. }
  43. } else if (letter === '"' || letter === "'") {
  44. inQuote = true;
  45. prevQuote = letter;
  46. } else if (letter === '(' || letter === '[' || letter === '{') {
  47. blockClose.push(blockPairs[letter]);
  48. } else if (letter === blockClose[blockClose.length - 1]) {
  49. blockClose.pop();
  50. } else if (blockClose.length === 0 || (splitFunctions && blockClose.every((x) => x === ')'))) {
  51. if (letter === separator) split = true;
  52. }
  53. if (split) {
  54. array.push(current);
  55. current = '';
  56. split = false;
  57. } else {
  58. current += letter;
  59. }
  60. }
  61. array.push(current);
  62. return array;
  63. }