tailwindcss 3.0.0-alpha.1 → 3.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +67 -1
  2. package/lib/cli.js +66 -62
  3. package/lib/constants.js +1 -1
  4. package/lib/corePluginList.js +7 -1
  5. package/lib/corePlugins.js +264 -203
  6. package/lib/css/preflight.css +12 -0
  7. package/lib/featureFlags.js +10 -7
  8. package/lib/lib/collapseDuplicateDeclarations.js +29 -0
  9. package/lib/lib/evaluateTailwindFunctions.js +3 -3
  10. package/lib/lib/expandApplyAtRules.js +7 -7
  11. package/lib/lib/expandTailwindAtRules.js +2 -1
  12. package/lib/lib/generateRules.js +115 -19
  13. package/lib/lib/resolveDefaultsAtRules.js +44 -47
  14. package/lib/lib/setupContextUtils.js +72 -15
  15. package/lib/lib/setupWatchingContext.js +5 -1
  16. package/lib/lib/sharedState.js +2 -2
  17. package/lib/processTailwindFeatures.js +4 -0
  18. package/lib/util/createUtilityPlugin.js +5 -5
  19. package/lib/util/dataTypes.js +24 -4
  20. package/lib/util/formatVariantSelector.js +102 -0
  21. package/lib/util/nameClass.js +1 -1
  22. package/lib/util/negateValue.js +3 -1
  23. package/lib/util/normalizeConfig.js +22 -8
  24. package/lib/util/parseBoxShadowValue.js +77 -0
  25. package/lib/util/pluginUtils.js +62 -158
  26. package/lib/util/prefixSelector.js +1 -3
  27. package/lib/util/resolveConfig.js +13 -9
  28. package/lib/util/transformThemeValue.js +23 -13
  29. package/package.json +11 -11
  30. package/peers/index.js +873 -2505
  31. package/src/cli.js +9 -2
  32. package/src/corePluginList.js +1 -1
  33. package/src/corePlugins.js +282 -348
  34. package/src/css/preflight.css +12 -0
  35. package/src/featureFlags.js +10 -4
  36. package/src/lib/collapseDuplicateDeclarations.js +28 -0
  37. package/src/lib/expandTailwindAtRules.js +3 -2
  38. package/src/lib/generateRules.js +121 -11
  39. package/src/lib/resolveDefaultsAtRules.js +39 -43
  40. package/src/lib/setupContextUtils.js +71 -9
  41. package/src/lib/setupWatchingContext.js +7 -0
  42. package/src/lib/sharedState.js +1 -1
  43. package/src/processTailwindFeatures.js +5 -0
  44. package/src/util/createUtilityPlugin.js +2 -2
  45. package/src/util/dataTypes.js +32 -5
  46. package/src/util/formatVariantSelector.js +105 -0
  47. package/src/util/nameClass.js +1 -1
  48. package/src/util/negateValue.js +4 -2
  49. package/src/util/normalizeConfig.js +17 -1
  50. package/src/util/parseBoxShadowValue.js +71 -0
  51. package/src/util/pluginUtils.js +50 -146
  52. package/src/util/prefixSelector.js +1 -4
  53. package/src/util/resolveConfig.js +7 -1
  54. package/src/util/transformThemeValue.js +22 -7
  55. package/stubs/defaultConfig.stub.js +101 -58
  56. package/peers/.svgo.yml +0 -75
  57. package/peers/orders/concentric-css.json +0 -299
  58. package/peers/orders/smacss.json +0 -299
  59. package/peers/orders/source.json +0 -295
  60. package/src/.DS_Store +0 -0
@@ -12,6 +12,11 @@
12
12
  border-color: currentColor; /* 2 */
13
13
  }
14
14
 
15
+ ::before,
16
+ ::after {
17
+ --tw-content: '';
18
+ }
19
+
15
20
  /*
16
21
  1. Use a consistent sensible line-height in all browsers.
17
22
  2. Prevent adjustments of font size after orientation changes in iOS.
@@ -317,6 +322,13 @@ button,
317
322
  cursor: pointer;
318
323
  }
319
324
 
325
+ /*
326
+ Make sure disabled buttons don't get the pointer cursor.
327
+ */
328
+ :disabled {
329
+ cursor: default;
330
+ }
331
+
320
332
  /*
321
333
  1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
322
334
  2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
@@ -12,7 +12,10 @@ function _interopRequireDefault(obj) {
12
12
  default: obj
13
13
  };
14
14
  }
15
- const featureFlags = {
15
+ let defaults = {
16
+ optimizeUniversalDefaults: true
17
+ };
18
+ let featureFlags = {
16
19
  future: [],
17
20
  experimental: [
18
21
  'optimizeUniversalDefaults'
@@ -21,13 +24,13 @@ const featureFlags = {
21
24
  function flagEnabled(config, flag) {
22
25
  if (featureFlags.future.includes(flag)) {
23
26
  var ref;
24
- var ref1;
25
- return config.future === 'all' || ((ref1 = config === null || config === void 0 ? void 0 : (ref = config.future) === null || ref === void 0 ? void 0 : ref[flag]) !== null && ref1 !== void 0 ? ref1 : false);
27
+ var ref1, ref2;
28
+ return config.future === 'all' || ((ref2 = (ref1 = config === null || config === void 0 ? void 0 : (ref = config.future) === null || ref === void 0 ? void 0 : ref[flag]) !== null && ref1 !== void 0 ? ref1 : defaults[flag]) !== null && ref2 !== void 0 ? ref2 : false);
26
29
  }
27
30
  if (featureFlags.experimental.includes(flag)) {
28
- var ref;
29
- var ref5;
30
- return config.experimental === 'all' || ((ref5 = config === null || config === void 0 ? void 0 : (ref = config.experimental) === null || ref === void 0 ? void 0 : ref[flag]) !== null && ref5 !== void 0 ? ref5 : false);
31
+ var ref3;
32
+ var ref4, ref5;
33
+ return config.experimental === 'all' || ((ref5 = (ref4 = config === null || config === void 0 ? void 0 : (ref3 = config.experimental) === null || ref3 === void 0 ? void 0 : ref3[flag]) !== null && ref4 !== void 0 ? ref4 : defaults[flag]) !== null && ref5 !== void 0 ? ref5 : false);
31
34
  }
32
35
  return false;
33
36
  }
@@ -45,7 +48,7 @@ function issueFlagNotices(config) {
45
48
  return;
46
49
  }
47
50
  if (experimentalFlagsEnabled(config).length > 0) {
48
- const changes = experimentalFlagsEnabled(config).map((s)=>_chalk.default.yellow(s)
51
+ let changes = experimentalFlagsEnabled(config).map((s)=>_chalk.default.yellow(s)
49
52
  ).join(', ');
50
53
  _log.default.warn('experimental-flags-enabled', [
51
54
  `You have enabled experimental features: ${changes}`,
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ exports.default = collapseDuplicateDeclarations;
6
+ function collapseDuplicateDeclarations() {
7
+ return (root)=>{
8
+ root.walkRules((node)=>{
9
+ let seen = new Map();
10
+ let droppable = new Set([]);
11
+ node.walkDecls((decl)=>{
12
+ // This could happen if we have nested selectors. In that case the
13
+ // parent will loop over all its declarations but also the declarations
14
+ // of nested rules. With this we ensure that we are shallowly checking
15
+ // declarations.
16
+ if (decl.parent !== node) {
17
+ return;
18
+ }
19
+ if (seen.has(decl.prop)) {
20
+ droppable.add(seen.get(decl.prop));
21
+ }
22
+ seen.set(decl.prop, decl);
23
+ });
24
+ for (let decl1 of droppable){
25
+ decl1.remove();
26
+ }
27
+ });
28
+ };
29
+ }
@@ -112,11 +112,11 @@ function extractArgs(node, vNodes, functions) {
112
112
  let args = [
113
113
  ''
114
114
  ];
115
- for (let vNode of vNodes){
116
- if (vNode.type === 'div' && vNode.value === ',') {
115
+ for (let vNode1 of vNodes){
116
+ if (vNode1.type === 'div' && vNode1.value === ',') {
117
117
  args.push('');
118
118
  } else {
119
- args[args.length - 1] += _postcssValueParser.default.stringify(vNode);
119
+ args[args.length - 1] += _postcssValueParser.default.stringify(vNode1);
120
120
  }
121
121
  }
122
122
  return args;
@@ -12,7 +12,7 @@ function _interopRequireDefault(obj) {
12
12
  default: obj
13
13
  };
14
14
  }
15
- function prefix(context, selector) {
15
+ function prefix1(context, selector) {
16
16
  let prefix = context.tailwindConfig.prefix;
17
17
  return typeof prefix === 'function' ? prefix(selector) : prefix + selector;
18
18
  }
@@ -56,10 +56,10 @@ function partitionApplyParents(root) {
56
56
  root.walkAtRules('apply', (rule)=>{
57
57
  applyParents.add(rule.parent);
58
58
  });
59
- for (let rule of applyParents){
59
+ for (let rule1 of applyParents){
60
60
  let nodeGroups = [];
61
61
  let lastGroup = [];
62
- for (let node of rule.nodes){
62
+ for (let node of rule1.nodes){
63
63
  if (node.type === 'atrule' && node.name === 'apply') {
64
64
  if (lastGroup.length > 0) {
65
65
  nodeGroups.push(lastGroup);
@@ -81,13 +81,13 @@ function partitionApplyParents(root) {
81
81
  for (let group of [
82
82
  ...nodeGroups
83
83
  ].reverse()){
84
- let newParent = rule.clone({
84
+ let newParent = rule1.clone({
85
85
  nodes: []
86
86
  });
87
87
  newParent.append(group);
88
- rule.after(newParent);
88
+ rule1.after(newParent);
89
89
  }
90
- rule.remove();
90
+ rule1.remove();
91
91
  }
92
92
  }
93
93
  function processApply(root, context) {
@@ -156,7 +156,7 @@ function processApply(root, context) {
156
156
  }
157
157
  for (let applyCandidate of applyCandidates){
158
158
  if (!applyClassCache.has(applyCandidate)) {
159
- if (applyCandidate === prefix(context, 'group')) {
159
+ if (applyCandidate === prefix1(context, 'group')) {
160
160
  // TODO: Link to specific documentation page with error code.
161
161
  throw apply.error(`@apply should not be used with the '${applyCandidate}' utility`);
162
162
  }
@@ -42,6 +42,8 @@ const PATTERNS = [
42
42
  /([^<>"'`\s]*\[\w*"[^"`\s]*"?\])/.source,
43
43
  /([^<>"'`\s]*\[\w*\('[^"'`\s]*'\)\])/.source,
44
44
  /([^<>"'`\s]*\[\w*\("[^"'`\s]*"\)\])/.source,
45
+ /([^<>"'`\s]*\[\w*\('[^"`\s]*'\)\])/.source,
46
+ /([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source,
45
47
  /([^<>"'`\s]*\['[^"'`\s]*'\])/.source,
46
48
  /([^<>"'`\s]*\["[^"'`\s]*"\])/.source,
47
49
  /([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source,
@@ -230,7 +232,6 @@ function expandTailwindAtRules(context) {
230
232
  if (env.DEBUG) {
231
233
  console.log('Potential classes: ', candidates.size);
232
234
  console.log('Active contexts: ', sharedState.contextSourcesMap.size);
233
- console.log('Content match entries', contentMatchCache.size);
234
235
  }
235
236
  // Clear the cache for the changed files
236
237
  context.changedContent = [];
@@ -10,6 +10,7 @@ var _isPlainObject = _interopRequireDefault(require("../util/isPlainObject"));
10
10
  var _prefixSelector = _interopRequireDefault(require("../util/prefixSelector"));
11
11
  var _pluginUtils = require("../util/pluginUtils");
12
12
  var _log = _interopRequireDefault(require("../util/log"));
13
+ var _formatVariantSelector = require("../util/formatVariantSelector");
13
14
  function _interopRequireDefault(obj) {
14
15
  return obj && obj.__esModule ? obj : {
15
16
  default: obj
@@ -119,15 +120,23 @@ function applyVariant(variant, matches, context) {
119
120
  if (context.variantMap.has(variant)) {
120
121
  let variantFunctionTuples = context.variantMap.get(variant);
121
122
  let result = [];
122
- for (let [meta, rule] of matches){
123
+ for (let [meta, rule1] of matches){
123
124
  let container = _postcss.default.root({
124
125
  nodes: [
125
- rule.clone()
126
+ rule1.clone()
126
127
  ]
127
128
  });
128
129
  for (let [variantSort, variantFunction] of variantFunctionTuples){
129
130
  let clone = container.clone();
131
+ let collectedFormats = [];
132
+ let originals = new Map();
133
+ function prepareBackup() {
134
+ if (originals.size > 0) return; // Already prepared, chicken out
135
+ clone.walkRules((rule)=>originals.set(rule, rule.selector)
136
+ );
137
+ }
130
138
  function modifySelectors(modifierFunction) {
139
+ prepareBackup();
131
140
  clone.each((rule)=>{
132
141
  if (rule.type !== 'rule') {
133
142
  return;
@@ -144,19 +153,71 @@ function applyVariant(variant, matches, context) {
144
153
  return clone;
145
154
  }
146
155
  let ruleWithVariant = variantFunction({
147
- container: clone,
156
+ // Public API
157
+ get container () {
158
+ prepareBackup();
159
+ return clone;
160
+ },
148
161
  separator: context.tailwindConfig.separator,
149
- modifySelectors
162
+ modifySelectors,
163
+ // Private API for now
164
+ wrap (wrapper) {
165
+ let nodes = clone.nodes;
166
+ clone.removeAll();
167
+ wrapper.append(nodes);
168
+ clone.append(wrapper);
169
+ },
170
+ format (selectorFormat) {
171
+ collectedFormats.push(selectorFormat);
172
+ }
150
173
  });
174
+ if (typeof ruleWithVariant === 'string') {
175
+ collectedFormats.push(ruleWithVariant);
176
+ }
151
177
  if (ruleWithVariant === null) {
152
178
  continue;
153
179
  }
180
+ // We filled the `originals`, therefore we assume that somebody touched
181
+ // `container` or `modifySelectors`. Let's see if they did, so that we
182
+ // can restore the selectors, and collect the format strings.
183
+ if (originals.size > 0) {
184
+ clone.walkRules((rule)=>{
185
+ if (!originals.has(rule)) return;
186
+ let before = originals.get(rule);
187
+ if (before === rule.selector) return; // No mutation happened
188
+ let modified = rule.selector;
189
+ // Rebuild the base selector, this is what plugin authors would do
190
+ // as well. E.g.: `${variant}${separator}${className}`.
191
+ // However, plugin authors probably also prepend or append certain
192
+ // classes, pseudos, ids, ...
193
+ let rebuiltBase = (0, _postcssSelectorParser).default((selectors)=>{
194
+ selectors.walkClasses((classNode)=>{
195
+ classNode.value = `${variant}${context.tailwindConfig.separator}${classNode.value}`;
196
+ });
197
+ }).processSync(before);
198
+ // Now that we know the original selector, the new selector, and
199
+ // the rebuild part in between, we can replace the part that plugin
200
+ // authors need to rebuild with `&`, and eventually store it in the
201
+ // collectedFormats. Similar to what `format('...')` would do.
202
+ //
203
+ // E.g.:
204
+ // variant: foo
205
+ // selector: .markdown > p
206
+ // modified (by plugin): .foo .foo\\:markdown > p
207
+ // rebuiltBase (internal): .foo\\:markdown > p
208
+ // format: .foo &
209
+ collectedFormats.push(modified.replace(rebuiltBase, '&'));
210
+ rule.selector = before;
211
+ });
212
+ }
213
+ var _collectedFormats;
154
214
  let withOffset = [
155
215
  {
156
216
  ...meta,
157
- sort: variantSort | meta.sort
217
+ sort: variantSort | meta.sort,
218
+ collectedFormats: ((_collectedFormats = meta.collectedFormats) !== null && _collectedFormats !== void 0 ? _collectedFormats : []).concat(collectedFormats)
158
219
  },
159
- clone.nodes[0]
220
+ clone.nodes[0],
160
221
  ];
161
222
  result.push(withOffset);
162
223
  }
@@ -198,12 +259,18 @@ function* resolveMatchedPlugins(classCandidate, context) {
198
259
  }
199
260
  let candidatePrefix = classCandidate;
200
261
  let negative = false;
201
- const twConfigPrefix = context.tailwindConfig.prefix || '';
262
+ const twConfigPrefix = context.tailwindConfig.prefix;
202
263
  const twConfigPrefixLen = twConfigPrefix.length;
203
264
  if (candidatePrefix[twConfigPrefixLen] === '-') {
204
265
  negative = true;
205
266
  candidatePrefix = twConfigPrefix + candidatePrefix.slice(twConfigPrefixLen + 1);
206
267
  }
268
+ if (negative && context.candidateRuleMap.has(candidatePrefix)) {
269
+ yield [
270
+ context.candidateRuleMap.get(candidatePrefix),
271
+ '-DEFAULT'
272
+ ];
273
+ }
207
274
  for (let [prefix, modifier] of candidatePermutations(candidatePrefix)){
208
275
  if (context.candidateRuleMap.has(prefix)) {
209
276
  yield [
@@ -261,7 +328,7 @@ function* resolveMatches(candidate, context) {
261
328
  ]);
262
329
  }
263
330
  }
264
- } else if (modifier === 'DEFAULT') {
331
+ } else if (modifier === 'DEFAULT' || modifier === '-DEFAULT') {
265
332
  let ruleSet = plugin;
266
333
  let [rules, options] = parseRules(ruleSet, context.postCssNodeCache);
267
334
  for (let rule of rules){
@@ -286,9 +353,9 @@ function* resolveMatches(candidate, context) {
286
353
  // Only keep the result of the very first plugin if we are dealing with
287
354
  // arbitrary values, to protect against ambiguity.
288
355
  if (isArbitraryValue(modifier) && matches.length > 1) {
289
- var ref;
356
+ var ref1;
290
357
  let typesPerPlugin = matches.map((match)=>new Set([
291
- ...(ref = typesByMatches.get(match)) !== null && ref !== void 0 ? ref : []
358
+ ...(ref1 = typesByMatches.get(match)) !== null && ref1 !== void 0 ? ref1 : []
292
359
  ])
293
360
  );
294
361
  // Remove duplicates, so that we can detect proper unique types for each plugin.
@@ -333,8 +400,26 @@ function* resolveMatches(candidate, context) {
333
400
  for (let variant of variants){
334
401
  matches = applyVariant(variant, matches, context);
335
402
  }
336
- for (let match of matches){
337
- yield match;
403
+ for (let match1 of matches){
404
+ // Apply final format selector
405
+ if (match1[0].collectedFormats) {
406
+ let finalFormat = (0, _formatVariantSelector).formatVariantSelector('&', ...match1[0].collectedFormats);
407
+ let container = _postcss.default.root({
408
+ nodes: [
409
+ match1[1].clone()
410
+ ]
411
+ });
412
+ container.walkRules((rule)=>{
413
+ if (inKeyframes(rule)) return;
414
+ rule.selector = (0, _formatVariantSelector).finalizeSelector(finalFormat, {
415
+ selector: rule.selector,
416
+ candidate,
417
+ context
418
+ });
419
+ });
420
+ match1[1] = container.nodes[0];
421
+ }
422
+ yield match1;
338
423
  }
339
424
  }
340
425
  }
@@ -359,15 +444,28 @@ function generateRules(candidates, context) {
359
444
  context.classCache.set(candidate, matches);
360
445
  allRules.push(matches);
361
446
  }
362
- return allRules.flat(1).map(([{ sort , layer , options }, rule])=>{
363
- if (options.respectImportant) {
364
- if (context.tailwindConfig.important === true) {
447
+ // Strategy based on `tailwindConfig.important`
448
+ let strategy = ((important)=>{
449
+ if (important === true) {
450
+ return (rule)=>{
365
451
  rule.walkDecls((d)=>{
366
452
  if (d.parent.type === 'rule' && !inKeyframes(d.parent)) {
367
453
  d.important = true;
368
454
  }
369
455
  });
370
- } else if (typeof context.tailwindConfig.important === 'string') {
456
+ };
457
+ }
458
+ if (typeof important === 'string') {
459
+ return (rule)=>{
460
+ rule.selectors = rule.selectors.map((selector)=>{
461
+ return `${important} ${selector}`;
462
+ });
463
+ };
464
+ }
465
+ })(context.tailwindConfig.important);
466
+ return allRules.flat(1).map(([{ sort , layer , options }, rule])=>{
467
+ if (options.respectImportant) {
468
+ if (strategy) {
371
469
  let container = _postcss.default.root({
372
470
  nodes: [
373
471
  rule.clone()
@@ -377,9 +475,7 @@ function generateRules(candidates, context) {
377
475
  if (inKeyframes(r)) {
378
476
  return;
379
477
  }
380
- r.selectors = r.selectors.map((selector)=>{
381
- return `${context.tailwindConfig.important} ${selector}`;
382
- });
478
+ strategy(r);
383
479
  });
384
480
  rule = container.nodes[0];
385
481
  }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
5
  exports.default = resolveDefaultsAtRules;
6
+ exports.elementSelectorParser = void 0;
6
7
  var _postcss = _interopRequireDefault(require("postcss"));
7
8
  var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
8
9
  var _featureFlags = require("../featureFlags");
@@ -11,58 +12,53 @@ function _interopRequireDefault(obj) {
11
12
  default: obj
12
13
  };
13
14
  }
14
- function isPseudoElement(n) {
15
- if (n.type !== 'pseudo') {
16
- return false;
15
+ let getNode = {
16
+ id (node) {
17
+ return _postcssSelectorParser.default.attribute({
18
+ attribute: 'id',
19
+ operator: '=',
20
+ value: node.value,
21
+ quoteMark: '"'
22
+ });
17
23
  }
18
- return n.value.startsWith('::') || [
19
- ':before',
20
- ':after',
21
- ':first-line',
22
- ':first-letter'
23
- ].includes(n.value);
24
- }
24
+ };
25
25
  function minimumImpactSelector(nodes) {
26
- let rest = nodes// Keep all pseudo & combinator types (:not([hidden]) ~ :not([hidden]))
27
- .filter((n)=>n.type === 'pseudo' || n.type === 'combinator'
28
- )// Remove leading pseudo's (:hover, :focus, ...)
29
- .filter((n, idx, all)=>{
30
- // Keep pseudo elements
31
- if (isPseudoElement(n)) return true;
32
- if (idx === 0 && n.type === 'pseudo') return false;
33
- if (idx > 0 && n.type === 'pseudo' && all[idx - 1].type === 'pseudo') return false;
34
- return true;
35
- });
36
- let [bestNode] = nodes;
37
- for (let [type, getNode = (n)=>n
38
- ] of [
39
- [
40
- 'class'
41
- ],
42
- [
43
- 'id',
44
- (n)=>_postcssSelectorParser.default.attribute({
45
- attribute: 'id',
46
- operator: '=',
47
- value: n.value,
48
- quoteMark: '"'
49
- })
50
- ,
51
- ],
52
- [
53
- 'attribute'
54
- ],
55
- ]){
56
- let match = nodes.find((n)=>n.type === type
57
- );
58
- if (match) {
59
- bestNode = getNode(match);
60
- break;
61
- }
26
+ let rest = nodes.filter((node)=>{
27
+ // Keep non-pseudo nodes
28
+ if (node.type !== 'pseudo') return true;
29
+ // Keep pseudo nodes that have subnodes
30
+ // E.g.: `:not()` contains subnodes inside the parentheses
31
+ if (node.nodes.length > 0) return true;
32
+ // Keep pseudo `elements`
33
+ // This implicitly means that we ignore pseudo `classes`
34
+ return node.value.startsWith('::') || [
35
+ ':before',
36
+ ':after',
37
+ ':first-line',
38
+ ':first-letter'
39
+ ].includes(node.value);
40
+ }).reverse();
41
+ let searchFor = new Set([
42
+ 'tag',
43
+ 'class',
44
+ 'id',
45
+ 'attribute'
46
+ ]);
47
+ let splitPointIdx = rest.findIndex((n)=>searchFor.has(n.type)
48
+ );
49
+ if (splitPointIdx === -1) return rest.reverse().join('').trim();
50
+ let node1 = rest[splitPointIdx];
51
+ let bestNode = getNode[node1.type] ? getNode[node1.type](node1) : node1;
52
+ rest = rest.slice(0, splitPointIdx);
53
+ let combinatorIdx = rest.findIndex((n)=>n.type === 'combinator' && n.value === '>'
54
+ );
55
+ if (combinatorIdx !== -1) {
56
+ rest.splice(0, combinatorIdx);
57
+ rest.unshift(_postcssSelectorParser.default.universal());
62
58
  }
63
59
  return [
64
60
  bestNode,
65
- ...rest
61
+ ...rest.reverse()
66
62
  ].join('').trim();
67
63
  }
68
64
  let elementSelectorParser = (0, _postcssSelectorParser).default((selectors)=>{
@@ -72,6 +68,7 @@ let elementSelectorParser = (0, _postcssSelectorParser).default((selectors)=>{
72
68
  return minimumImpactSelector(nodes);
73
69
  });
74
70
  });
71
+ exports.elementSelectorParser = elementSelectorParser;
75
72
  let cache = new Map();
76
73
  function extractElementSelector(selector) {
77
74
  if (!cache.has(selector)) {