postcss-merge-rules 5.0.5 → 5.0.6

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.
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "postcss-merge-rules",
3
- "version": "5.0.5",
3
+ "version": "5.0.6",
4
4
  "description": "Merge CSS rules with PostCSS.",
5
- "main": "dist/index.js",
5
+ "main": "src/index.js",
6
6
  "files": [
7
7
  "LICENSE-MIT",
8
- "dist"
8
+ "src"
9
9
  ],
10
10
  "keywords": [
11
11
  "css",
@@ -24,7 +24,7 @@
24
24
  "dependencies": {
25
25
  "browserslist": "^4.16.6",
26
26
  "caniuse-api": "^3.0.0",
27
- "cssnano-utils": "^3.0.1",
27
+ "cssnano-utils": "^3.0.2",
28
28
  "postcss-selector-parser": "^6.0.5"
29
29
  },
30
30
  "bugs": {
@@ -35,14 +35,10 @@
35
35
  },
36
36
  "devDependencies": {
37
37
  "postcss": "^8.2.15",
38
- "postcss-discard-comments": "^5.0.2"
38
+ "postcss-discard-comments": "^5.0.3"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "postcss": "^8.2.15"
42
42
  },
43
- "scripts": {
44
- "prebuild": "rimraf dist",
45
- "build": "babel src --config-file ../../babel.config.json --out-dir dist --ignore \"**/__tests__/\""
46
- },
47
43
  "readme": "# [postcss][postcss]-merge-rules\n\n> Merge CSS rules with PostCSS.\n\n## Install\n\nWith [npm](https://npmjs.org/package/postcss-merge-rules) do:\n\n```\nnpm install postcss-merge-rules --save\n```\n\n## Examples\n\nThis module will attempt to merge *adjacent* CSS rules:\n\n### By declarations\n\n#### Input\n\n```css\na {\n color: blue;\n font-weight: bold\n}\n\np {\n color: blue;\n font-weight: bold\n}\n```\n\n#### Output\n\n```css\na,p {\n color: blue;\n font-weight: bold\n}\n```\n\n### By selectors\n\n#### Input\n\n```css\na {\n color: blue\n}\n\na {\n font-weight: bold\n}\n```\n\n#### Output\n\n```css\na {\n color: blue;\n font-weight: bold\n}\n```\n\n### By partial declarations\n\n#### Input\n\n```css\na {\n font-weight: bold\n}\n\np {\n color: blue;\n font-weight: bold\n}\n```\n\n#### Output\n\n```css\na,p {\n font-weight: bold\n}\n\np {\n color: blue\n}\n```\n\n## Usage\n\nSee the [PostCSS documentation](https://github.com/postcss/postcss#usage) for\nexamples for your environment.\n\n## Contributors\n\nSee [CONTRIBUTORS.md](https://github.com/cssnano/cssnano/blob/master/CONTRIBUTORS.md).\n\n## License\n\nMIT © [Ben Briggs](http://beneb.info)\n\n[postcss]: https://github.com/postcss/postcss\n"
48
44
  }
@@ -1,17 +1,11 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
-
8
- var _browserslist = _interopRequireDefault(require("browserslist"));
9
-
10
- var _cssnanoUtils = require("cssnano-utils");
11
-
12
- var _ensureCompatibility = require("./lib/ensureCompatibility");
13
-
14
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1
+ 'use strict';
2
+ const browserslist = require('browserslist');
3
+ const { sameParent } = require('cssnano-utils');
4
+ const {
5
+ ensureCompatibility,
6
+ sameVendor,
7
+ noVendor,
8
+ } = require('./lib/ensureCompatibility');
15
9
 
16
10
  /**
17
11
  * @param {postcss.Declaration} a
@@ -19,18 +13,20 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
19
13
  * @return {boolean}
20
14
  */
21
15
  function declarationIsEqual(a, b) {
22
- return a.important === b.important && a.prop === b.prop && a.value === b.value;
16
+ return (
17
+ a.important === b.important && a.prop === b.prop && a.value === b.value
18
+ );
23
19
  }
20
+
24
21
  /**
25
22
  * @param {postcss.Declaration[]} array
26
23
  * @param {postcss.Declaration} decl
27
24
  * @return {number}
28
25
  */
29
-
30
-
31
26
  function indexOfDeclaration(array, decl) {
32
- return array.findIndex(d => declarationIsEqual(d, decl));
27
+ return array.findIndex((d) => declarationIsEqual(d, decl));
33
28
  }
29
+
34
30
  /**
35
31
  * Returns filtered array of matched or unmatched declarations
36
32
  * @param {postcss.Declaration[]} a
@@ -38,28 +34,25 @@ function indexOfDeclaration(array, decl) {
38
34
  * @param {boolean} [not=false]
39
35
  * @return {postcss.Declaration[]}
40
36
  */
41
-
42
-
43
37
  function intersect(a, b, not) {
44
- return a.filter(c => {
38
+ return a.filter((c) => {
45
39
  const index = ~indexOfDeclaration(b, c);
46
40
  return not ? !index : index;
47
41
  });
48
42
  }
43
+
49
44
  /**
50
45
  * @param {postcss.Declaration[]} a
51
46
  * @param {postcss.Declaration[]} b
52
47
  * @return {boolean}
53
48
  */
54
-
55
-
56
49
  function sameDeclarationsAndOrder(a, b) {
57
50
  if (a.length !== b.length) {
58
51
  return false;
59
52
  }
60
-
61
53
  return a.every((d, index) => declarationIsEqual(d, b[index]));
62
54
  }
55
+
63
56
  /**
64
57
  * @param {postcss.Rule} ruleA
65
58
  * @param {postcss.Rule} ruleB
@@ -67,160 +60,141 @@ function sameDeclarationsAndOrder(a, b) {
67
60
  * @param {Map<string, boolean>=} compatibilityCache
68
61
  * @return {boolean}
69
62
  */
70
-
71
-
72
63
  function canMerge(ruleA, ruleB, browsers, compatibilityCache) {
73
64
  const a = ruleA.selectors;
74
65
  const b = ruleB.selectors;
66
+
75
67
  const selectors = a.concat(b);
76
68
 
77
- if (!(0, _ensureCompatibility.ensureCompatibility)(selectors, browsers, compatibilityCache)) {
69
+ if (!ensureCompatibility(selectors, browsers, compatibilityCache)) {
78
70
  return false;
79
71
  }
80
72
 
81
- const parent = (0, _cssnanoUtils.sameParent)(ruleA, ruleB);
82
- const {
83
- name
84
- } = ruleA.parent;
85
-
73
+ const parent = sameParent(ruleA, ruleB);
74
+ const { name } = ruleA.parent;
86
75
  if (parent && name && name.includes('keyframes')) {
87
76
  return false;
88
77
  }
89
-
90
- return parent && (selectors.every(_ensureCompatibility.noVendor) || (0, _ensureCompatibility.sameVendor)(a, b));
78
+ return parent && (selectors.every(noVendor) || sameVendor(a, b));
91
79
  }
80
+
92
81
  /**
93
82
  * @param {postcss.Rule} rule
94
83
  * @return {postcss.Declaration[]}
95
84
  */
96
-
97
-
98
85
  function getDecls(rule) {
99
- return rule.nodes.filter(node => node.type === 'decl');
86
+ return rule.nodes.filter((node) => node.type === 'decl');
100
87
  }
101
88
 
102
- const joinSelectors = (...rules) => rules.map(s => s.selector).join();
89
+ const joinSelectors = (...rules) => rules.map((s) => s.selector).join();
103
90
 
104
91
  function ruleLength(...rules) {
105
- return rules.map(r => r.nodes.length ? String(r) : '').join('').length;
92
+ return rules.map((r) => (r.nodes.length ? String(r) : '')).join('').length;
106
93
  }
94
+
107
95
  /**
108
96
  * @param {string} prop
109
97
  * @return {{prefix: string, base:string, rest:string[]}}
110
98
  */
111
-
112
-
113
99
  function splitProp(prop) {
114
100
  // Treat vendor prefixed properties as if they were unprefixed;
115
101
  // moving them when combined with non-prefixed properties can
116
102
  // cause issues. e.g. moving -webkit-background-clip when there
117
103
  // is a background shorthand definition.
118
- const parts = prop.split('-');
119
104
 
105
+ const parts = prop.split('-');
120
106
  if (prop[0] !== '-') {
121
107
  return {
122
108
  prefix: '',
123
109
  base: parts[0],
124
- rest: parts.slice(1)
110
+ rest: parts.slice(1),
125
111
  };
126
- } // Don't split css variables
127
-
128
-
112
+ }
113
+ // Don't split css variables
129
114
  if (prop[1] === '-') {
130
115
  return {
131
116
  prefix: null,
132
117
  base: null,
133
- rest: [prop]
118
+ rest: [prop],
134
119
  };
135
- } // Found prefix
136
-
137
-
120
+ }
121
+ // Found prefix
138
122
  return {
139
123
  prefix: parts[1],
140
124
  base: parts[2],
141
- rest: parts.slice(3)
125
+ rest: parts.slice(3),
142
126
  };
143
127
  }
128
+
144
129
  /**
145
130
  * @param {string} propA
146
131
  * @param {string} propB
147
132
  */
148
-
149
-
150
133
  function isConflictingProp(propA, propB) {
151
134
  if (propA === propB) {
152
135
  // Same specificity
153
136
  return true;
154
137
  }
155
-
156
138
  const a = splitProp(propA);
157
- const b = splitProp(propB); // Don't resort css variables
158
-
139
+ const b = splitProp(propB);
140
+ // Don't resort css variables
159
141
  if (!a.base && !b.base) {
160
142
  return true;
161
- } // Different base;
162
-
163
-
143
+ }
144
+ // Different base;
164
145
  if (a.base !== b.base) {
165
146
  return false;
166
- } // Conflict if rest-count mismatches
167
-
168
-
147
+ }
148
+ // Conflict if rest-count mismatches
169
149
  if (a.rest.length !== b.rest.length) {
170
150
  return true;
171
- } // Conflict if rest parameters are equal (same but unprefixed)
172
-
151
+ }
173
152
 
153
+ // Conflict if rest parameters are equal (same but unprefixed)
174
154
  return a.rest.every((s, index) => b.rest[index] === s);
175
155
  }
156
+
176
157
  /**
177
158
  * @param {postcss.Rule} first
178
159
  * @param {postcss.Rule} second
179
160
  * @return {boolean} merged
180
161
  */
181
-
182
-
183
162
  function mergeParents(first, second) {
184
163
  // Null check for detached rules
185
164
  if (!first.parent || !second.parent) {
186
165
  return false;
187
- } // Check if parents share node
188
-
166
+ }
189
167
 
168
+ // Check if parents share node
190
169
  if (first.parent === second.parent) {
191
170
  return false;
192
- } // sameParent() already called by canMerge()
171
+ }
193
172
 
173
+ // sameParent() already called by canMerge()
194
174
 
195
175
  second.remove();
196
176
  first.parent.append(second);
197
177
  return true;
198
178
  }
179
+
199
180
  /**
200
181
  * @param {postcss.Rule} first
201
182
  * @param {postcss.Rule} second
202
183
  * @return {postcss.Rule} mergedRule
203
184
  */
204
-
205
-
206
185
  function partialMerge(first, second) {
207
186
  let intersection = intersect(getDecls(first), getDecls(second));
208
-
209
187
  if (!intersection.length) {
210
188
  return second;
211
189
  }
212
-
213
190
  let nextRule = second.next();
214
-
215
191
  if (!nextRule) {
216
192
  // Grab next cousin
217
193
  const parentSibling = second.parent.next();
218
194
  nextRule = parentSibling && parentSibling.nodes && parentSibling.nodes[0];
219
195
  }
220
-
221
196
  if (nextRule && nextRule.type === 'rule' && canMerge(second, nextRule)) {
222
197
  let nextIntersection = intersect(getDecls(second), getDecls(nextRule));
223
-
224
198
  if (nextIntersection.length > intersection.length) {
225
199
  mergeParents(second, nextRule);
226
200
  first = second;
@@ -229,45 +203,52 @@ function partialMerge(first, second) {
229
203
  }
230
204
  }
231
205
 
232
- const firstDecls = getDecls(first); // Filter out intersections with later conflicts in First
206
+ const firstDecls = getDecls(first);
233
207
 
208
+ // Filter out intersections with later conflicts in First
234
209
  intersection = intersection.filter((decl, intersectIndex) => {
235
210
  const indexOfDecl = indexOfDeclaration(firstDecls, decl);
236
- const nextConflictInFirst = firstDecls.slice(indexOfDecl + 1).filter(d => isConflictingProp(d.prop, decl.prop));
237
-
211
+ const nextConflictInFirst = firstDecls
212
+ .slice(indexOfDecl + 1)
213
+ .filter((d) => isConflictingProp(d.prop, decl.prop));
238
214
  if (!nextConflictInFirst.length) {
239
215
  return true;
240
216
  }
241
-
242
- const nextConflictInIntersection = intersection.slice(intersectIndex + 1).filter(d => isConflictingProp(d.prop, decl.prop));
243
-
217
+ const nextConflictInIntersection = intersection
218
+ .slice(intersectIndex + 1)
219
+ .filter((d) => isConflictingProp(d.prop, decl.prop));
244
220
  if (!nextConflictInIntersection.length) {
245
221
  return false;
246
222
  }
247
-
248
223
  if (nextConflictInFirst.length !== nextConflictInIntersection.length) {
249
224
  return false;
250
225
  }
226
+ return nextConflictInFirst.every((d, index) =>
227
+ declarationIsEqual(d, nextConflictInIntersection[index])
228
+ );
229
+ });
251
230
 
252
- return nextConflictInFirst.every((d, index) => declarationIsEqual(d, nextConflictInIntersection[index]));
253
- }); // Filter out intersections with previous conflicts in Second
254
-
231
+ // Filter out intersections with previous conflicts in Second
255
232
  const secondDecls = getDecls(second);
256
- intersection = intersection.filter(decl => {
257
- const nextConflictIndex = secondDecls.findIndex(d => isConflictingProp(d.prop, decl.prop));
258
-
233
+ intersection = intersection.filter((decl) => {
234
+ const nextConflictIndex = secondDecls.findIndex((d) =>
235
+ isConflictingProp(d.prop, decl.prop)
236
+ );
259
237
  if (nextConflictIndex === -1) {
260
238
  return false;
261
239
  }
262
-
263
240
  if (!declarationIsEqual(secondDecls[nextConflictIndex], decl)) {
264
241
  return false;
265
242
  }
266
-
267
- if (decl.prop.toLowerCase() !== 'direction' && decl.prop.toLowerCase() !== 'unicode-bidi' && secondDecls.some(declaration => declaration.prop.toLowerCase() === 'all')) {
243
+ if (
244
+ decl.prop.toLowerCase() !== 'direction' &&
245
+ decl.prop.toLowerCase() !== 'unicode-bidi' &&
246
+ secondDecls.some(
247
+ (declaration) => declaration.prop.toLowerCase() === 'all'
248
+ )
249
+ ) {
268
250
  return false;
269
251
  }
270
-
271
252
  secondDecls.splice(nextConflictIndex, 1);
272
253
  return true;
273
254
  });
@@ -280,56 +261,55 @@ function partialMerge(first, second) {
280
261
  const receivingBlock = second.clone();
281
262
  receivingBlock.selector = joinSelectors(first, second);
282
263
  receivingBlock.nodes = [];
264
+
283
265
  second.parent.insertBefore(second, receivingBlock);
266
+
284
267
  const firstClone = first.clone();
285
268
  const secondClone = second.clone();
269
+
286
270
  /**
287
271
  * @param {function(postcss.Declaration):void} callback
288
272
  * @return {function(postcss.Declaration)}
289
273
  */
290
-
291
274
  function moveDecl(callback) {
292
- return decl => {
275
+ return (decl) => {
293
276
  if (~indexOfDeclaration(intersection, decl)) {
294
277
  callback.call(this, decl);
295
278
  }
296
279
  };
297
280
  }
298
-
299
- firstClone.walkDecls(moveDecl(decl => {
300
- decl.remove();
301
- receivingBlock.append(decl);
302
- }));
303
- secondClone.walkDecls(moveDecl(decl => decl.remove()));
281
+ firstClone.walkDecls(
282
+ moveDecl((decl) => {
283
+ decl.remove();
284
+ receivingBlock.append(decl);
285
+ })
286
+ );
287
+ secondClone.walkDecls(moveDecl((decl) => decl.remove()));
304
288
  const merged = ruleLength(firstClone, receivingBlock, secondClone);
305
289
  const original = ruleLength(first, second);
306
-
307
290
  if (merged < original) {
308
291
  first.replaceWith(firstClone);
309
292
  second.replaceWith(secondClone);
310
- [firstClone, receivingBlock, secondClone].forEach(r => {
293
+ [firstClone, receivingBlock, secondClone].forEach((r) => {
311
294
  if (!r.nodes.length) {
312
295
  r.remove();
313
296
  }
314
297
  });
315
-
316
298
  if (!secondClone.parent) {
317
299
  return receivingBlock;
318
300
  }
319
-
320
301
  return secondClone;
321
302
  } else {
322
303
  receivingBlock.remove();
323
304
  return second;
324
305
  }
325
306
  }
307
+
326
308
  /**
327
309
  * @param {string[]} browsers
328
310
  * @param {Map<string, boolean>} compatibilityCache
329
311
  * @return {function(postcss.Rule)}
330
312
  */
331
-
332
-
333
313
  function selectorMerger(browsers, compatibilityCache) {
334
314
  /** @type {postcss.Rule} */
335
315
  let cache = null;
@@ -339,43 +319,40 @@ function selectorMerger(browsers, compatibilityCache) {
339
319
  if (!cache || !canMerge(rule, cache, browsers, compatibilityCache)) {
340
320
  cache = rule;
341
321
  return;
342
- } // Ensure that we don't deduplicate the same rule; this is sometimes
322
+ }
323
+ // Ensure that we don't deduplicate the same rule; this is sometimes
343
324
  // caused by a partial merge
344
-
345
-
346
325
  if (cache === rule) {
347
326
  cache = rule;
348
327
  return;
349
- } // Parents merge: check if the rules have same parents, but not same parent nodes
328
+ }
350
329
 
330
+ // Parents merge: check if the rules have same parents, but not same parent nodes
331
+ mergeParents(cache, rule);
351
332
 
352
- mergeParents(cache, rule); // Merge when declarations are exactly equal
333
+ // Merge when declarations are exactly equal
353
334
  // e.g. h1 { color: red } h2 { color: red }
354
-
355
335
  if (sameDeclarationsAndOrder(getDecls(rule), getDecls(cache))) {
356
336
  rule.selector = joinSelectors(cache, rule);
357
337
  cache.remove();
358
338
  cache = rule;
359
339
  return;
360
- } // Merge when both selectors are exactly equal
340
+ }
341
+ // Merge when both selectors are exactly equal
361
342
  // e.g. a { color: blue } a { font-weight: bold }
362
-
363
-
364
343
  if (cache.selector === rule.selector) {
365
344
  const cached = getDecls(cache);
366
- rule.walk(decl => {
345
+ rule.walk((decl) => {
367
346
  if (~indexOfDeclaration(cached, decl)) {
368
347
  return decl.remove();
369
348
  }
370
-
371
349
  cache.append(decl);
372
350
  });
373
351
  rule.remove();
374
352
  return;
375
- } // Partial merge: check if the rule contains a subset of the last; if
353
+ }
354
+ // Partial merge: check if the rule contains a subset of the last; if
376
355
  // so create a joined selector with the subset, if smaller.
377
-
378
-
379
356
  cache = partialMerge(cache, rule);
380
357
  };
381
358
  }
@@ -386,24 +363,21 @@ function pluginCreator() {
386
363
 
387
364
  prepare(result) {
388
365
  const resultOpts = result.opts || {};
389
- const browsers = (0, _browserslist.default)(null, {
366
+ const browsers = browserslist(null, {
390
367
  stats: resultOpts.stats,
391
368
  path: __dirname,
392
- env: resultOpts.env
369
+ env: resultOpts.env,
393
370
  });
371
+
394
372
  const compatibilityCache = new Map();
395
373
  return {
396
374
  OnceExit(css) {
397
375
  css.walkRules(selectorMerger(browsers, compatibilityCache));
398
- }
399
-
376
+ },
400
377
  };
401
- }
402
-
378
+ },
403
379
  };
404
380
  }
405
381
 
406
382
  pluginCreator.postcss = true;
407
- var _default = pluginCreator;
408
- exports.default = _default;
409
- module.exports = exports.default;
383
+ module.exports = pluginCreator;
@@ -1,20 +1,9 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.ensureCompatibility = ensureCompatibility;
7
- exports.noVendor = noVendor;
8
- exports.pseudoElements = void 0;
9
- exports.sameVendor = sameVendor;
10
-
11
- var _caniuseApi = require("caniuse-api");
12
-
13
- var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
14
-
15
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1
+ 'use strict';
2
+ const { isSupported } = require('caniuse-api');
3
+ const selectorParser = require('postcss-selector-parser');
16
4
 
17
5
  const simpleSelectorRe = /^#?[-._a-z0-9 ]+$/i;
6
+
18
7
  const cssSel2 = 'css-sel2';
19
8
  const cssSel3 = 'css-sel3';
20
9
  const cssGencontent = 'css-gencontent';
@@ -22,33 +11,36 @@ const cssFirstLetter = 'css-first-letter';
22
11
  const cssFirstLine = 'css-first-line';
23
12
  const cssInOutOfRange = 'css-in-out-of-range';
24
13
  const formValidation = 'form-validation';
25
- const vendorPrefix = /-(ah|apple|atsc|epub|hp|khtml|moz|ms|o|rim|ro|tc|wap|webkit|xv)-/;
14
+
15
+ const vendorPrefix =
16
+ /-(ah|apple|atsc|epub|hp|khtml|moz|ms|o|rim|ro|tc|wap|webkit|xv)-/;
17
+
26
18
  /**
27
19
  * @param {string} selector
28
20
  * @return {string[]}
29
21
  */
30
-
31
22
  function filterPrefixes(selector) {
32
23
  return selector.match(vendorPrefix);
33
- } // Internet Explorer use :-ms-input-placeholder.
34
- // Microsoft Edge use ::-ms-input-placeholder.
35
-
24
+ }
36
25
 
37
- const findMsInputPlaceholder = selector => ~selector.search(/-ms-input-placeholder/i);
26
+ // Internet Explorer use :-ms-input-placeholder.
27
+ // Microsoft Edge use ::-ms-input-placeholder.
28
+ const findMsInputPlaceholder = (selector) =>
29
+ ~selector.search(/-ms-input-placeholder/i);
38
30
 
39
31
  function sameVendor(selectorsA, selectorsB) {
40
- let same = selectors => selectors.map(filterPrefixes).join();
41
-
42
- let findMsVendor = selectors => selectors.find(findMsInputPlaceholder);
43
-
44
- return same(selectorsA) === same(selectorsB) && !(findMsVendor(selectorsA) && findMsVendor(selectorsB));
32
+ let same = (selectors) => selectors.map(filterPrefixes).join();
33
+ let findMsVendor = (selectors) => selectors.find(findMsInputPlaceholder);
34
+ return (
35
+ same(selectorsA) === same(selectorsB) &&
36
+ !(findMsVendor(selectorsA) && findMsVendor(selectorsB))
37
+ );
45
38
  }
39
+
46
40
  /**
47
41
  * @param {string} selector
48
42
  * @return {boolean}
49
43
  */
50
-
51
-
52
44
  function noVendor(selector) {
53
45
  return !vendorPrefix.test(selector);
54
46
  }
@@ -104,9 +96,8 @@ const pseudoElements = {
104
96
  '::placeholder': 'css-placeholder',
105
97
  '::selection': 'css-selection',
106
98
  ':valid': formValidation,
107
- ':visited': cssSel2
99
+ ':visited': cssSel2,
108
100
  };
109
- exports.pseudoElements = pseudoElements;
110
101
 
111
102
  function isCssMixin(selector) {
112
103
  return selector[selector.length - 1] === ':';
@@ -116,17 +107,15 @@ function isHostPseudoClass(selector) {
116
107
  return selector.includes(':host');
117
108
  }
118
109
 
119
- const isSupportedCache = new Map(); // Move to util in future
110
+ const isSupportedCache = new Map();
120
111
 
112
+ // Move to util in future
121
113
  function isSupportedCached(feature, browsers) {
122
- const key = JSON.stringify({
123
- feature,
124
- browsers
125
- });
114
+ const key = JSON.stringify({ feature, browsers });
126
115
  let result = isSupportedCache.get(key);
127
116
 
128
117
  if (!result) {
129
- result = (0, _caniuseApi.isSupported)(feature, browsers);
118
+ result = isSupported(feature, browsers);
130
119
  isSupportedCache.set(key, result);
131
120
  }
132
121
 
@@ -137,52 +126,40 @@ function ensureCompatibility(selectors, browsers, compatibilityCache) {
137
126
  // Should not merge mixins
138
127
  if (selectors.some(isCssMixin)) {
139
128
  return false;
140
- } // Should not merge :host selector https://github.com/angular/angular-cli/issues/18672
141
-
129
+ }
142
130
 
131
+ // Should not merge :host selector https://github.com/angular/angular-cli/issues/18672
143
132
  if (selectors.some(isHostPseudoClass)) {
144
133
  return false;
145
134
  }
146
-
147
- return selectors.every(selector => {
135
+ return selectors.every((selector) => {
148
136
  if (simpleSelectorRe.test(selector)) {
149
137
  return true;
150
138
  }
151
-
152
139
  if (compatibilityCache && compatibilityCache.has(selector)) {
153
140
  return compatibilityCache.get(selector);
154
141
  }
155
-
156
142
  let compatible = true;
157
- (0, _postcssSelectorParser.default)(ast => {
158
- ast.walk(node => {
159
- const {
160
- type,
161
- value
162
- } = node;
163
-
143
+ selectorParser((ast) => {
144
+ ast.walk((node) => {
145
+ const { type, value } = node;
164
146
  if (type === 'pseudo') {
165
147
  const entry = pseudoElements[value];
166
-
167
148
  if (!entry && noVendor(value)) {
168
149
  compatible = false;
169
150
  }
170
-
171
151
  if (entry && compatible) {
172
152
  compatible = isSupportedCached(entry, browsers);
173
153
  }
174
154
  }
175
-
176
155
  if (type === 'combinator') {
177
156
  if (value.includes('~')) {
178
157
  compatible = isSupportedCached(cssSel3, browsers);
179
158
  }
180
-
181
159
  if (value.includes('>') || value.includes('+')) {
182
160
  compatible = isSupportedCached(cssSel2, browsers);
183
161
  }
184
162
  }
185
-
186
163
  if (type === 'attribute' && node.attribute) {
187
164
  // [foo]
188
165
  if (!node.operator) {
@@ -193,20 +170,18 @@ function ensureCompatibility(selectors, browsers, compatibilityCache) {
193
170
  // [foo="bar"], [foo~="bar"], [foo|="bar"]
194
171
  if (['=', '~=', '|='].includes(node.operator)) {
195
172
  compatible = isSupportedCached(cssSel2, browsers);
196
- } // [foo^="bar"], [foo$="bar"], [foo*="bar"]
197
-
198
-
173
+ }
174
+ // [foo^="bar"], [foo$="bar"], [foo*="bar"]
199
175
  if (['^=', '$=', '*='].includes(node.operator)) {
200
176
  compatible = isSupportedCached(cssSel3, browsers);
201
177
  }
202
- } // [foo="bar" i]
203
-
178
+ }
204
179
 
180
+ // [foo="bar" i]
205
181
  if (node.insensitive) {
206
182
  compatible = isSupportedCached('css-case-insensitive', browsers);
207
183
  }
208
184
  }
209
-
210
185
  if (!compatible) {
211
186
  // If this node was not compatible,
212
187
  // break out early from walking the rest
@@ -214,11 +189,11 @@ function ensureCompatibility(selectors, browsers, compatibilityCache) {
214
189
  }
215
190
  });
216
191
  }).processSync(selector);
217
-
218
192
  if (compatibilityCache) {
219
193
  compatibilityCache.set(selector, compatible);
220
194
  }
221
-
222
195
  return compatible;
223
196
  });
224
- }
197
+ }
198
+
199
+ module.exports = { sameVendor, noVendor, pseudoElements, ensureCompatibility };