autoprefixer 9.1.5 → 9.3.1

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.
@@ -4,6 +4,12 @@ var parser = require('postcss-value-parser');
4
4
 
5
5
  var list = require('postcss').list;
6
6
 
7
+ var uniq = require('../utils').uniq;
8
+
9
+ var escapeRegexp = require('../utils').escapeRegexp;
10
+
11
+ var splitSelector = require('../utils').splitSelector;
12
+
7
13
  function convert(value) {
8
14
  if (value && value.length === 2 && value[0] === 'span' && parseInt(value[1], 10) > 0) {
9
15
  return [false, parseInt(value[1], 10)];
@@ -118,20 +124,36 @@ function transformRepeat(_ref3, _ref4) {
118
124
  count: []
119
125
  }),
120
126
  count = _nodes$reduce.count,
121
- size = _nodes$reduce.size;
127
+ size = _nodes$reduce.size; // insert gap values
128
+
122
129
 
123
130
  if (gap) {
124
- var val = [];
131
+ var _ret = function () {
132
+ size = size.filter(function (i) {
133
+ return i.trim();
134
+ });
135
+ var val = [];
136
+
137
+ var _loop = function _loop(i) {
138
+ size.forEach(function (item, index) {
139
+ if (index > 0 || i > 1) {
140
+ val.push(gap);
141
+ }
142
+
143
+ val.push(item);
144
+ });
145
+ };
125
146
 
126
- for (var i = 1; i <= count; i++) {
127
- if (gap && i > 1) {
128
- val.push(gap);
147
+ for (var i = 1; i <= count; i++) {
148
+ _loop(i);
129
149
  }
130
150
 
131
- val.push(size.join());
132
- }
151
+ return {
152
+ v: val.join(' ')
153
+ };
154
+ }();
133
155
 
134
- return val.join(' ');
156
+ if (typeof _ret === "object") return _ret.v;
135
157
  }
136
158
 
137
159
  return "(" + size.join('') + ")[" + count.join('') + "]";
@@ -163,98 +185,6 @@ function prefixTrackValue(_ref5) {
163
185
  return nodes.concat(node);
164
186
  }, []);
165
187
  return parser.stringify(result);
166
- }
167
- /**
168
- * Parse grid areas from declaration
169
- * @param Declaration [decl]
170
- * @return Array<String>
171
- */
172
-
173
-
174
- function parseGridTemplateStrings(decl) {
175
- var template = parseTemplate({
176
- decl: decl,
177
- gap: getGridGap(decl)
178
- });
179
- return Object.keys(template.areas);
180
- }
181
- /**
182
- * Walk through every grid-template(-areas)
183
- * declaration and try to find non-unique area names (duplicates)
184
- * @param {Declaration} decl
185
- * @param {Result} result
186
- * @return {void}
187
- */
188
-
189
-
190
- function warnDuplicateNames(_ref6) {
191
- var decl = _ref6.decl,
192
- result = _ref6.result;
193
- var rule = decl.parent;
194
- var inMediaRule = !!getParentMedia(rule);
195
- var areas = parseGridTemplateStrings(decl);
196
- var root = decl.root(); // stop if no areas found
197
-
198
- if (areas.length === 0) {
199
- return false;
200
- }
201
-
202
- root.walkDecls(/grid-template(-areas)?$/g, function (d) {
203
- var nodeRule = d.parent;
204
- var nodeRuleMedia = getParentMedia(nodeRule);
205
- var isEqual = rule.toString() === nodeRule.toString();
206
- var foundAreas = parseGridTemplateStrings(d);
207
- var maxIndex = Math.max(root.index(nodeRule), root.index(nodeRuleMedia));
208
- var isLookingDown = root.index(rule) < maxIndex; // skip node if no grid areas is found
209
-
210
- if (foundAreas.length === 0) {
211
- return true;
212
- } // abort if we outside media rule and walking below our rule
213
- // (we need to check ONLY the rules that are above)
214
-
215
-
216
- if (!inMediaRule && isLookingDown) {
217
- return false;
218
- } // abort if we're in the same rule
219
-
220
-
221
- if (isEqual) {
222
- return false;
223
- } // if we're inside media rule, we need to compare selectors
224
-
225
-
226
- if (inMediaRule) {
227
- var selectors = list.comma(nodeRule.selector);
228
- var selectorIsFound = selectors.some(function (sel) {
229
- if (sel === rule.selector) {
230
- // compare selectors as a comma list
231
- return true;
232
- } else if (nodeRule.selector === rule.selector) {
233
- // compare selectors as a whole (e.g. ".i, .j" === ".i, .j")
234
- return true;
235
- }
236
-
237
- return false;
238
- }); // stop walking if we found the selector
239
-
240
- if (selectorIsFound) {
241
- return false;
242
- }
243
- }
244
-
245
- var duplicates = areas.filter(function (area) {
246
- return foundAreas.includes(area);
247
- });
248
-
249
- if (duplicates.length > 0) {
250
- var word = duplicates.length > 1 ? 'names' : 'name';
251
- decl.warn(result, ['', " duplicate area " + word + " detected in rule: " + rule.selector, " duplicate area " + word + ": " + duplicates.join(', '), " duplicate area names cause unexpected behavior in IE"].join('\n'));
252
- return false;
253
- }
254
-
255
- return undefined;
256
- });
257
- return undefined;
258
188
  } // Parse grid-template-areas
259
189
 
260
190
 
@@ -272,9 +202,9 @@ function getColumns(line) {
272
202
  return line.trim().split(/\s+/g);
273
203
  }
274
204
 
275
- function parseGridAreas(_ref7) {
276
- var rows = _ref7.rows,
277
- gap = _ref7.gap;
205
+ function parseGridAreas(_ref6) {
206
+ var rows = _ref6.rows,
207
+ gap = _ref6.gap;
278
208
  return rows.reduce(function (areas, line, rowIndex) {
279
209
  if (gap.row) rowIndex *= 2;
280
210
  if (line.trim() === '') return areas;
@@ -316,9 +246,9 @@ function verifyRowSize(result) {
316
246
  return result;
317
247
  }
318
248
 
319
- function parseTemplate(_ref8) {
320
- var decl = _ref8.decl,
321
- gap = _ref8.gap;
249
+ function parseTemplate(_ref7) {
250
+ var decl = _ref7.decl,
251
+ gap = _ref7.gap;
322
252
  var gridTemplate = parser(decl.value).nodes.reduce(function (result, node) {
323
253
  var type = node.type,
324
254
  value = node.value;
@@ -332,7 +262,7 @@ function parseTemplate(_ref8) {
332
262
 
333
263
  if (type === 'word' || type === 'function') {
334
264
  result[result.key].push(parser.stringify(node));
335
- } // devider(/)
265
+ } // divider(/)
336
266
 
337
267
 
338
268
  if (type === 'div' && value === '/') {
@@ -365,7 +295,7 @@ function parseTemplate(_ref8) {
365
295
 
366
296
  /**
367
297
  * Get an array of -ms- prefixed props and values
368
- * @param {Object} [area] area object with columm and row data
298
+ * @param {Object} [area] area object with column and row data
369
299
  * @param {Boolean} [addRowSpan] should we add grid-column-row value?
370
300
  * @param {Boolean} [addColumnSpan] should we add grid-column-span value?
371
301
  * @return {Array<Object>}
@@ -399,167 +329,482 @@ function getMSDecls(area, addRowSpan, addColumnSpan) {
399
329
  function getParentMedia(parent) {
400
330
  if (parent.type === 'atrule' && parent.name === 'media') {
401
331
  return parent;
402
- } else if (!parent.parent) {
332
+ }
333
+
334
+ if (!parent.parent) {
403
335
  return false;
404
336
  }
405
337
 
406
338
  return getParentMedia(parent.parent);
407
339
  }
408
340
  /**
409
- * Check grid-template(-areas) rules with the same selector for
410
- * -ms-grid-(row|column)-span values. If initial and compared values are
411
- * different - return an array of boolean values which need to be updated
412
- * @param {Declaration} decl
413
- * @param {Object} area area object with column and row data
414
- * @param {String} areaName area name (e.g. "head")
415
- * @return {Array<Boolean, Boolean>}
341
+ * change selectors for rules with duplicate grid-areas.
342
+ * @param {Array<Rule>} rules
343
+ * @param {Array<String>} templateSelectors
344
+ * @return {Array<Rule>} rules with changed selectors
416
345
  */
417
346
 
418
347
 
419
- function shouldAddSpan(decl, area, areaName) {
420
- var root = decl.root();
421
- var rule = decl.parent;
422
- var overrideValues = [false, false];
423
- root.walkRules(rule.selector, function (node) {
424
- // abort if we are on the same rule
425
- if (rule.toString() === node.toString()) {
426
- return false;
348
+ function changeDuplicateAreaSelectors(ruleSelectors, templateSelectors) {
349
+ ruleSelectors = ruleSelectors.map(function (selector) {
350
+ var selectorBySpace = list.space(selector);
351
+ var selectorByComma = list.comma(selector);
352
+
353
+ if (selectorBySpace.length > selectorByComma.length) {
354
+ selector = selectorBySpace.slice(-1).join('');
427
355
  }
428
356
 
429
- node.walkDecls('grid-template', function (d) {
430
- var template = parseTemplate({
431
- decl: d,
432
- gap: getGridGap(d)
357
+ return selector;
358
+ });
359
+ return ruleSelectors.map(function (ruleSelector) {
360
+ var newSelector = templateSelectors.map(function (tplSelector, index) {
361
+ var space = index === 0 ? '' : ' ';
362
+ return "" + space + tplSelector + " > " + ruleSelector;
363
+ });
364
+ return newSelector;
365
+ });
366
+ }
367
+ /**
368
+ * check if selector of rules are equal
369
+ * @param {Rule} ruleA
370
+ * @param {Rule} ruleB
371
+ * @return {Boolean}
372
+ */
373
+
374
+
375
+ function selectorsEqual(ruleA, ruleB) {
376
+ return ruleA.selectors.some(function (sel) {
377
+ return ruleB.selectors.some(function (s) {
378
+ return s === sel;
379
+ });
380
+ });
381
+ }
382
+ /**
383
+ * Parse data from all grid-template(-areas) declarations
384
+ * @param {Root} css css root
385
+ * @return {Object} parsed data
386
+ */
387
+
388
+
389
+ function parseGridTemplatesData(css) {
390
+ var parsed = []; // we walk through every grid-template(-areas) declaration and store
391
+ // data with the same area names inside the item
392
+
393
+ css.walkDecls(/grid-template(-areas)?$/, function (d) {
394
+ var rule = d.parent;
395
+ var media = getParentMedia(rule);
396
+ var gap = getGridGap(d);
397
+ var inheritedGap = inheritGridGap(d, gap);
398
+
399
+ var _parseTemplate = parseTemplate({
400
+ decl: d,
401
+ gap: inheritedGap || gap
402
+ }),
403
+ areas = _parseTemplate.areas;
404
+
405
+ var areaNames = Object.keys(areas); // skip node if it doesn't have areas
406
+
407
+ if (areaNames.length === 0) {
408
+ return true;
409
+ } // check parsed array for item that include the same area names
410
+ // return index of that item
411
+
412
+
413
+ var index = parsed.reduce(function (acc, _ref8, idx) {
414
+ var allAreas = _ref8.allAreas;
415
+ var hasAreas = allAreas && areaNames.some(function (area) {
416
+ return allAreas.includes(area);
433
417
  });
434
- var comparedArea = template.areas[areaName];
418
+ return hasAreas ? idx : acc;
419
+ }, null);
435
420
 
436
- if (!comparedArea) {
437
- return true;
438
- }
421
+ if (index !== null) {
422
+ // index is found, add the grid-template data to that item
423
+ var _parsed$index = parsed[index],
424
+ allAreas = _parsed$index.allAreas,
425
+ rules = _parsed$index.rules; // check if rule has no duplicate area names
439
426
 
440
- if (area.row.span !== comparedArea.row.span) {
441
- overrideValues[0] = true;
442
- }
427
+ var hasNoDuplicates = rules.some(function (r) {
428
+ return r.hasDuplicates === false && selectorsEqual(r, rule);
429
+ });
430
+ var duplicatesFound = false; // check need to gather all duplicate area names
443
431
 
444
- if (area.column.span !== comparedArea.column.span) {
445
- overrideValues[1] = true;
446
- }
432
+ var duplicateAreaNames = rules.reduce(function (acc, r) {
433
+ if (!r.params && selectorsEqual(r, rule)) {
434
+ duplicatesFound = true;
435
+ return r.duplicateAreaNames;
436
+ }
437
+
438
+ if (!duplicatesFound) {
439
+ areaNames.forEach(function (name) {
440
+ if (r.areas[name]) {
441
+ acc.push(name);
442
+ }
443
+ });
444
+ }
445
+
446
+ return uniq(acc);
447
+ }, []); // update grid-row/column-span values for areas with duplicate
448
+ // area names. @see #1084 and #1146
449
+
450
+ rules.forEach(function (r) {
451
+ areaNames.forEach(function (name) {
452
+ var area = r.areas[name];
453
+
454
+ if (area && area.row.span !== areas[name].row.span) {
455
+ areas[name].row.updateSpan = true;
456
+ }
457
+
458
+ if (area && area.column.span !== areas[name].column.span) {
459
+ areas[name].column.updateSpan = true;
460
+ }
461
+ });
462
+ });
463
+ parsed[index].allAreas = uniq(allAreas.concat(areaNames));
464
+ parsed[index].rules.push({
465
+ hasDuplicates: !hasNoDuplicates,
466
+ params: media.params,
467
+ selectors: rule.selectors,
468
+ node: rule,
469
+ duplicateAreaNames: duplicateAreaNames,
470
+ areas: areas
471
+ });
472
+ } else {
473
+ // index is NOT found, push the new item to the parsed array
474
+ parsed.push({
475
+ allAreas: areaNames,
476
+ areasCount: 0,
477
+ rules: [{
478
+ hasDuplicates: false,
479
+ duplicateRules: [],
480
+ params: media.params,
481
+ selectors: rule.selectors,
482
+ node: rule,
483
+ duplicateAreaNames: [],
484
+ areas: areas
485
+ }]
486
+ });
487
+ }
447
488
 
448
- return undefined;
449
- });
450
489
  return undefined;
451
490
  });
452
- return overrideValues;
491
+ return parsed;
453
492
  }
454
493
  /**
455
- * search the next siblings and find the latest media with
456
- * the same selectors inside
457
- * @param {Rule | AtRule} rule
458
- * @param {Array<String>} selectors
459
- * @return {AtRule}
494
+ * insert prefixed grid-area declarations
495
+ * @param {Root} css css root
496
+ * @param {Function} isDisabled check if the rule is disabled
497
+ * @return {void}
460
498
  */
461
499
 
462
500
 
463
- function getLastNextSimilarMedia(rule, selectors) {
464
- if (!rule) {
465
- return false;
466
- } else if (rule.type !== 'atrule' && rule.name !== 'media') {
467
- return rule.prev();
468
- }
501
+ function insertAreas(css, isDisabled) {
502
+ // parse grid-template declarations
503
+ var gridTemplatesData = parseGridTemplatesData(css); // return undefined if no declarations found
469
504
 
470
- var selectorsToCompare = [];
471
- rule.walkRules(function (r) {
472
- return selectorsToCompare.push(r.selector);
473
- }); // check if every selector match
505
+ if (gridTemplatesData.length === 0) {
506
+ return undefined;
507
+ } // we need to store the rules that we will insert later
474
508
 
475
- var selectorsEqual = selectors.every(function (sel, index) {
476
- return sel === selectorsToCompare[index];
477
- });
478
509
 
479
- if (selectorsEqual) {
480
- // to check the next rule
481
- return getLastNextSimilarMedia(rule.next(), selectors);
482
- } else {
483
- // or return the last similar media
484
- return rule.prev();
485
- }
510
+ var rulesToInsert = {};
511
+ css.walkDecls('grid-area', function (gridArea) {
512
+ var gridAreaRule = gridArea.parent;
513
+ var hasPrefixedRow = gridAreaRule.first.prop === '-ms-grid-row';
514
+ var gridAreaMedia = getParentMedia(gridAreaRule);
515
+
516
+ if (isDisabled(gridArea)) {
517
+ return undefined;
518
+ }
519
+
520
+ var gridAreaRuleIndex = gridAreaMedia ? css.index(gridAreaMedia) : css.index(gridAreaRule);
521
+ var value = gridArea.value; // found the data that matches grid-area identifier
522
+
523
+ var data = gridTemplatesData.filter(function (d) {
524
+ return d.allAreas.includes(value);
525
+ })[0];
526
+
527
+ if (!data) {
528
+ return true;
529
+ }
530
+
531
+ var lastArea = data.allAreas[data.allAreas.length - 1];
532
+ var selectorBySpace = list.space(gridAreaRule.selector);
533
+ var selectorByComma = list.comma(gridAreaRule.selector);
534
+ var selectorIsComplex = selectorBySpace.length > 1 && selectorBySpace.length > selectorByComma.length; // prevent doubling of prefixes
535
+
536
+ if (hasPrefixedRow) {
537
+ return false;
538
+ } // create the empty object with the key as the last area name
539
+ // e.g if we have templates with "a b c" values, "c" will be the last area
540
+
541
+
542
+ if (!rulesToInsert[lastArea]) {
543
+ rulesToInsert[lastArea] = {};
544
+ } // walk through every grid-template rule data
545
+
546
+
547
+ for (var _iterator2 = data.rules, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
548
+ var _ref9;
549
+
550
+ if (_isArray2) {
551
+ if (_i2 >= _iterator2.length) break;
552
+ _ref9 = _iterator2[_i2++];
553
+ } else {
554
+ _i2 = _iterator2.next();
555
+ if (_i2.done) break;
556
+ _ref9 = _i2.value;
557
+ }
558
+
559
+ var rule = _ref9;
560
+ var area = rule.areas[value];
561
+ var hasDuplicateName = rule.duplicateAreaNames.includes(value); // if we can't find the area name, update lastRule and continue
562
+
563
+ if (!area) {
564
+ var lastRuleIndex = css.index(rulesToInsert[lastArea].lastRule);
565
+
566
+ if (gridAreaRuleIndex > lastRuleIndex) {
567
+ rulesToInsert[lastArea].lastRule = gridAreaMedia || gridAreaRule;
568
+ }
569
+
570
+ continue;
571
+ } // for grid-templates inside media rule we need to create empty
572
+ // array to push prefixed grid-area rules later
573
+
574
+
575
+ if (rule.params && !rulesToInsert[lastArea][rule.params]) {
576
+ rulesToInsert[lastArea][rule.params] = [];
577
+ }
578
+
579
+ if ((!rule.hasDuplicates || !hasDuplicateName) && !rule.params) {
580
+ // grid-template has no duplicates and not inside media rule
581
+ getMSDecls(area, false, false).reverse().forEach(function (i) {
582
+ return gridAreaRule.prepend(Object.assign(i, {
583
+ raws: {
584
+ between: gridArea.raws.between
585
+ }
586
+ }));
587
+ });
588
+ rulesToInsert[lastArea].lastRule = gridAreaRule;
589
+ } else if (rule.hasDuplicates && !rule.params && !selectorIsComplex) {
590
+ (function () {
591
+ // grid-template has duplicates and not inside media rule
592
+ var cloned = gridAreaRule.clone();
593
+ cloned.removeAll();
594
+ getMSDecls(area, area.row.updateSpan, area.column.updateSpan).reverse().forEach(function (i) {
595
+ return cloned.prepend(Object.assign(i, {
596
+ raws: {
597
+ between: gridArea.raws.between
598
+ }
599
+ }));
600
+ });
601
+ cloned.selectors = changeDuplicateAreaSelectors(cloned.selectors, rule.selectors);
602
+
603
+ if (rulesToInsert[lastArea].lastRule) {
604
+ rulesToInsert[lastArea].lastRule.after(cloned);
605
+ }
606
+
607
+ rulesToInsert[lastArea].lastRule = cloned;
608
+ })();
609
+ } else if (rule.hasDuplicates && !rule.params && selectorIsComplex && gridAreaRule.selector.includes(rule.selectors[0])) {
610
+ // grid-template has duplicates and not inside media rule
611
+ // see the bottom of grid-template-areas test case for example
612
+ gridAreaRule.walkDecls(/-ms-grid-(row|column)/, function (d) {
613
+ return d.remove();
614
+ });
615
+ getMSDecls(area, area.row.updateSpan, area.column.updateSpan).reverse().forEach(function (i) {
616
+ return gridAreaRule.prepend(Object.assign(i, {
617
+ raws: {
618
+ between: gridArea.raws.between
619
+ }
620
+ }));
621
+ });
622
+ } else if (rule.params) {
623
+ (function () {
624
+ // grid-template is inside media rule
625
+ // if we're inside media rule, we need to store prefixed rules
626
+ // inside rulesToInsert object to be able to preserve the order of media
627
+ // rules and merge them easily
628
+ var cloned = gridAreaRule.clone();
629
+ cloned.removeAll();
630
+ getMSDecls(area, area.row.updateSpan, area.column.updateSpan).reverse().forEach(function (i) {
631
+ return cloned.prepend(Object.assign(i, {
632
+ raws: {
633
+ between: gridArea.raws.between
634
+ }
635
+ }));
636
+ });
637
+
638
+ if (rule.hasDuplicates && hasDuplicateName) {
639
+ cloned.selectors = changeDuplicateAreaSelectors(cloned.selectors, rule.selectors);
640
+ }
641
+
642
+ cloned.raws = rule.node.raws;
643
+
644
+ if (css.index(rule.node.parent) > gridAreaRuleIndex) {
645
+ // append the prefixed rules right inside media rule
646
+ // with grid-template
647
+ rule.node.parent.append(cloned);
648
+ } else {
649
+ // store the rule to insert later
650
+ rulesToInsert[lastArea][rule.params].push(cloned);
651
+ }
652
+
653
+ if (gridAreaMedia) {
654
+ rulesToInsert[lastArea].lastRule = gridAreaMedia || gridAreaRule;
655
+ }
656
+ })();
657
+ }
658
+ }
659
+
660
+ return undefined;
661
+ }); // append stored rules inside the media rules
662
+
663
+ Object.keys(rulesToInsert).forEach(function (area) {
664
+ var data = rulesToInsert[area];
665
+ var lastRule = data.lastRule;
666
+ Object.keys(data).reverse().filter(function (p) {
667
+ return p !== 'lastRule';
668
+ }).forEach(function (params) {
669
+ if (data[params].length > 0 && lastRule) {
670
+ lastRule.after({
671
+ name: 'media',
672
+ params: params
673
+ });
674
+ lastRule.next().append(data[params]);
675
+ }
676
+ });
677
+ });
678
+ return undefined;
486
679
  }
680
+ /**
681
+ * Warn user if grid area identifiers are not found
682
+ * @param {Object} areas
683
+ * @param {Declaration} decl
684
+ * @param {Result} result
685
+ * @return {void}
686
+ */
487
687
 
488
- function insertAreas(areas, decl, result) {
688
+
689
+ function warnMissedAreas(areas, decl, result) {
489
690
  var missed = Object.keys(areas);
490
- var parentMedia = getParentMedia(decl.parent);
491
- var rules = [];
492
- var areasLength = Object.keys(areas).length;
493
- var areasCount = 0;
494
691
  decl.root().walkDecls('grid-area', function (gridArea) {
495
- var value = gridArea.value;
496
- var area = areas[value];
497
692
  missed = missed.filter(function (e) {
498
- return e !== value;
693
+ return e !== gridArea.value;
499
694
  });
695
+ });
500
696
 
501
- if (area && parentMedia) {
502
- // create new rule
503
- var rule = decl.parent.clone({
504
- selector: gridArea.parent.selector
505
- });
506
- rule.removeAll(); // insert prefixed decls in new rule
697
+ if (missed.length > 0) {
698
+ decl.warn(result, 'Can not find grid areas: ' + missed.join(', '));
699
+ }
700
+
701
+ return undefined;
702
+ }
703
+ /**
704
+ * compare selectors with grid-area rule and grid-template rule
705
+ * show warning if grid-template selector is not found
706
+ * (this function used for grid-area rule)
707
+ * @param {Declaration} decl
708
+ * @param {Result} result
709
+ * @return {void}
710
+ */
507
711
 
508
- var _shouldAddSpan = shouldAddSpan(decl, area, value),
509
- addRowSpan = _shouldAddSpan[0],
510
- addColumnSpan = _shouldAddSpan[1];
511
712
 
512
- getMSDecls(area, addRowSpan, addColumnSpan).forEach(function (i) {
513
- return rule.append(Object.assign(i, {
514
- raws: {
515
- between: gridArea.raws.between
516
- }
517
- }));
518
- });
519
- rules.push(rule);
520
- areasCount++;
521
-
522
- if (areasCount === areasLength) {
523
- var next = gridArea.parent.next();
524
- if (next && next.type === 'atrule' && next.name === 'media' && next.params === parentMedia.params && next.first.type === 'rule' && next.first.selector && parentMedia.first.selector && /^-ms-/.test(next.first.first.prop)) return undefined;
525
- var selectors = rules.map(function (r) {
526
- return r.selector;
527
- });
528
- var lastSimilarMedia = getLastNextSimilarMedia(next, selectors);
529
- var areaParentMedia = getParentMedia(gridArea.parent);
530
- var areaMedia = parentMedia.clone().removeAll().append(rules);
531
-
532
- if (areaParentMedia) {
533
- // insert after @media
534
- areaParentMedia.after(areaMedia);
535
- } else if (lastSimilarMedia) {
536
- // insert after the closest @media with the same selectors
537
- lastSimilarMedia.after(areaMedia);
713
+ function warnTemplateSelectorNotFound(decl, result) {
714
+ var rule = decl.parent;
715
+ var root = decl.root();
716
+ var duplicatesFound = false; // slice selector array. Remove the last part (for comparison)
717
+
718
+ var slicedSelectorArr = list.space(rule.selector).filter(function (str) {
719
+ return str !== '>';
720
+ }).slice(0, -1); // we need to compare only if selector is complex.
721
+ // e.g '.grid-cell' is simple, but '.parent > .grid-cell' is complex
722
+
723
+ if (slicedSelectorArr.length > 0) {
724
+ var gridTemplateFound = false;
725
+ var foundAreaSelector = null;
726
+ root.walkDecls(/grid-template(-areas)?$/, function (d) {
727
+ var parent = d.parent;
728
+ var templateSelectors = parent.selectors;
729
+
730
+ var _parseTemplate2 = parseTemplate({
731
+ decl: d,
732
+ gap: getGridGap(d)
733
+ }),
734
+ areas = _parseTemplate2.areas;
735
+
736
+ var hasArea = areas[decl.value]; // find the the matching selectors
737
+
738
+ for (var _iterator3 = templateSelectors, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
739
+ var _ref10;
740
+
741
+ if (_isArray3) {
742
+ if (_i3 >= _iterator3.length) break;
743
+ _ref10 = _iterator3[_i3++];
538
744
  } else {
539
- // insert after every other Rule
540
- gridArea.parent.after(areaMedia);
745
+ _i3 = _iterator3.next();
746
+ if (_i3.done) break;
747
+ _ref10 = _i3.value;
748
+ }
749
+
750
+ var tplSelector = _ref10;
751
+
752
+ if (gridTemplateFound) {
753
+ break;
541
754
  }
755
+
756
+ var tplSelectorArr = list.space(tplSelector).filter(function (str) {
757
+ return str !== '>';
758
+ });
759
+ gridTemplateFound = tplSelectorArr.every(function (item, idx) {
760
+ return item === slicedSelectorArr[idx];
761
+ });
542
762
  }
543
763
 
544
- return undefined;
545
- }
764
+ if (gridTemplateFound || !hasArea) {
765
+ return true;
766
+ }
546
767
 
547
- if (area) {
548
- gridArea.parent.walkDecls(/-ms-grid-(row|column)/, function (d) {
549
- d.remove();
550
- }); // insert prefixed decls before grid-area
768
+ if (!foundAreaSelector) {
769
+ foundAreaSelector = parent.selector;
770
+ } // if we found the duplicate area with different selector
551
771
 
552
- getMSDecls(area).forEach(function (i) {
553
- return gridArea.cloneBefore(i);
554
- });
772
+
773
+ if (foundAreaSelector && foundAreaSelector !== parent.selector) {
774
+ duplicatesFound = true;
775
+ }
776
+
777
+ return undefined;
778
+ }); // warn user if we didn't find template
779
+
780
+ if (!gridTemplateFound && duplicatesFound) {
781
+ decl.warn(result, "Autoprefixer cannot find a grid-template " + ("containing the duplicate grid-area \"" + decl.value + "\" ") + ("with full selector matching: " + slicedSelectorArr.join(' ')));
555
782
  }
783
+ }
784
+ }
785
+ /**
786
+ * warn user if both grid-area and grid-(row|column)
787
+ * declarations are present in the same rule
788
+ * @param {Declaration} decl
789
+ * @param {Result} result
790
+ * @return {void}
791
+ */
556
792
 
557
- return undefined;
793
+
794
+ function warnIfGridRowColumnExists(decl, result) {
795
+ var rule = decl.parent;
796
+ var decls = [];
797
+ rule.walkDecls(/^grid-(row|column)/, function (d) {
798
+ decls.push(d);
558
799
  });
559
800
 
560
- if (missed.length > 0) {
561
- decl.warn(result, 'Can not find grid areas: ' + missed.join(', '));
801
+ if (decls.length > 0) {
802
+ decls.forEach(function (d) {
803
+ d.warn(result, "You already have a grid-area declaration present in the rule. " + ("You should use either grid-area or " + d.prop + ", not both"));
804
+ });
562
805
  }
806
+
807
+ return undefined;
563
808
  } // Gap utils
564
809
 
565
810
 
@@ -567,9 +812,9 @@ function getGridGap(decl) {
567
812
  var gap = {}; // try to find gap
568
813
 
569
814
  var testGap = /^(grid-)?((row|column)-)?gap$/;
570
- decl.parent.walkDecls(testGap, function (_ref9) {
571
- var prop = _ref9.prop,
572
- value = _ref9.value;
815
+ decl.parent.walkDecls(testGap, function (_ref11) {
816
+ var prop = _ref11.prop,
817
+ value = _ref11.value;
573
818
 
574
819
  if (/^(grid-)?gap$/.test(prop)) {
575
820
  var _parser$nodes = parser(value).nodes,
@@ -594,6 +839,10 @@ function getGridGap(decl) {
594
839
 
595
840
 
596
841
  function parseMediaParams(params) {
842
+ if (!params) {
843
+ return false;
844
+ }
845
+
597
846
  var parsed = parser(params);
598
847
  var prop;
599
848
  var value;
@@ -606,6 +855,63 @@ function parseMediaParams(params) {
606
855
  });
607
856
  return [prop, value];
608
857
  }
858
+ /**
859
+ * Compare the selectors and decide if we
860
+ * need to inherit gap from compared selector or not.
861
+ * @type {String} selA
862
+ * @type {String} selB
863
+ * @return {Boolean}
864
+ */
865
+
866
+
867
+ function shouldInheritGap(selA, selB) {
868
+ var result; // get arrays of selector split in 3-deep array
869
+
870
+ var splitSelectorArrA = splitSelector(selA);
871
+ var splitSelectorArrB = splitSelector(selB);
872
+
873
+ if (splitSelectorArrA[0].length < splitSelectorArrB[0].length) {
874
+ // abort if selectorA has lower descendant specificity then selectorB
875
+ // (e.g '.grid' and '.hello .world .grid')
876
+ return false;
877
+ } else if (splitSelectorArrA[0].length > splitSelectorArrB[0].length) {
878
+ // if selectorA has higher descendant specificity then selectorB
879
+ // (e.g '.foo .bar .grid' and '.grid')
880
+ var idx = splitSelectorArrA[0].reduce(function (res, _ref12, index) {
881
+ var item = _ref12[0];
882
+ var firstSelectorPart = splitSelectorArrB[0][0][0];
883
+
884
+ if (item === firstSelectorPart) {
885
+ return index;
886
+ }
887
+
888
+ return false;
889
+ }, false);
890
+
891
+ if (idx) {
892
+ result = splitSelectorArrB[0].every(function (arr, index) {
893
+ return arr.every(function (part, innerIndex) {
894
+ return (// because selectorA has more space elements, we need to slice
895
+ // selectorA array by 'idx' number to compare them
896
+ splitSelectorArrA[0].slice(idx)[index][innerIndex] === part
897
+ );
898
+ });
899
+ });
900
+ }
901
+ } else {
902
+ // if selectorA has the same descendant specificity as selectorB
903
+ // this condition covers cases such as: '.grid.foo.bar' and '.grid'
904
+ result = splitSelectorArrB.some(function (byCommaArr) {
905
+ return byCommaArr.every(function (bySpaceArr, index) {
906
+ return bySpaceArr.every(function (part, innerIndex) {
907
+ return splitSelectorArrA[0][index][innerIndex] === part;
908
+ });
909
+ });
910
+ });
911
+ }
912
+
913
+ return result;
914
+ }
609
915
  /**
610
916
  * inherit grid gap values from the closest rule above
611
917
  * with the same selector
@@ -618,20 +924,27 @@ function parseMediaParams(params) {
618
924
  function inheritGridGap(decl, gap) {
619
925
  var rule = decl.parent;
620
926
  var mediaRule = getParentMedia(rule);
621
- var root = rule.root();
927
+ var root = rule.root(); // get an array of selector split in 3-deep array
622
928
 
623
- if (Object.keys(gap).length > 0 || !mediaRule) {
929
+ var splitSelectorArr = splitSelector(rule.selector); // abort if the rule already has gaps
930
+
931
+ if (Object.keys(gap).length > 0) {
624
932
  return false;
625
933
  } // e.g ['min-width']
626
934
 
627
935
 
628
936
  var _parseMediaParams = parseMediaParams(mediaRule.params),
629
- prop = _parseMediaParams[0]; // find the closest rule with the same selector
937
+ prop = _parseMediaParams[0];
938
+
939
+ var lastBySpace = splitSelectorArr[0]; // get escaped value from the selector
940
+ // if we have '.grid-2.foo.bar' selector, will be '\.grid\-2'
630
941
 
942
+ var escaped = escapeRegexp(lastBySpace[lastBySpace.length - 1][0]);
943
+ var regexp = new RegExp("(" + escaped + "$)|(" + escaped + "[,.])"); // find the closest rule with the same selector
631
944
 
632
945
  var closestRuleGap;
633
- root.walkRules(rule.selector, function (r) {
634
- var gridGap; // abort if checking the same rule
946
+ root.walkRules(regexp, function (r) {
947
+ var gridGap; // abort if are checking the same rule
635
948
 
636
949
  if (rule.toString() === r.toString()) {
637
950
  return false;
@@ -644,6 +957,11 @@ function inheritGridGap(decl, gap) {
644
957
 
645
958
  if (!gridGap || Object.keys(gridGap).length === 0) {
646
959
  return true;
960
+ } // skip rules that should not be inherited from
961
+
962
+
963
+ if (!shouldInheritGap(rule.selector, r.selector)) {
964
+ return true;
647
965
  }
648
966
 
649
967
  var media = getParentMedia(r);
@@ -667,16 +985,16 @@ function inheritGridGap(decl, gap) {
667
985
 
668
986
  if (closestRuleGap && Object.keys(closestRuleGap).length > 0) {
669
987
  return closestRuleGap;
670
- } else {
671
- return false;
672
988
  }
989
+
990
+ return false;
673
991
  }
674
992
 
675
- function warnGridGap(_ref10) {
676
- var gap = _ref10.gap,
677
- hasColumns = _ref10.hasColumns,
678
- decl = _ref10.decl,
679
- result = _ref10.result;
993
+ function warnGridGap(_ref13) {
994
+ var gap = _ref13.gap,
995
+ hasColumns = _ref13.hasColumns,
996
+ decl = _ref13.decl,
997
+ result = _ref13.result;
680
998
  var hasBothGaps = gap.row && gap.column;
681
999
 
682
1000
  if (!hasColumns && (hasBothGaps || gap.column && !gap.row)) {
@@ -690,12 +1008,14 @@ module.exports = {
690
1008
  translate: translate,
691
1009
  parseTemplate: parseTemplate,
692
1010
  parseGridAreas: parseGridAreas,
1011
+ warnMissedAreas: warnMissedAreas,
693
1012
  insertAreas: insertAreas,
694
1013
  insertDecl: insertDecl,
695
1014
  prefixTrackProp: prefixTrackProp,
696
1015
  prefixTrackValue: prefixTrackValue,
697
1016
  getGridGap: getGridGap,
698
1017
  warnGridGap: warnGridGap,
699
- warnDuplicateNames: warnDuplicateNames,
1018
+ warnTemplateSelectorNotFound: warnTemplateSelectorNotFound,
1019
+ warnIfGridRowColumnExists: warnIfGridRowColumnExists,
700
1020
  inheritGridGap: inheritGridGap
701
1021
  };