Repository: postcss/autoprefixer
Pull request #994 (2018-02-25 19:48:00)

[grid-area] Better grid-area (grid-column/row-end) support


Patch:
diff --git a/lib/hacks/grid-area.js b/lib/hacks/grid-area.js
index 7885361..39f2d28 100644
--- a/lib/hacks/grid-area.js
+++ b/lib/hacks/grid-area.js
@@ -11,42 +11,20 @@ class GridArea extends Declaration {
     insert(decl, prefix, prefixes) {
         if (prefix !== '-ms-') return super.insert(decl, prefix, prefixes);
 
-        if (decl.parent.some(i => i.prop === '-ms-grid-row')) {
-            return undefined;
-        }
-
         const values = utils.parse(decl);
 
         const [rowStart, rowSpan] = utils.translate(values, 0, 2);
         const [columnStart, columnSpan] = utils.translate(values, 1, 3);
 
-        if (rowStart) {
-            decl.cloneBefore({
-                prop: '-ms-grid-row',
-                value: rowStart.toString()
-            });
-        }
-
-        if (rowSpan) {
-            decl.cloneBefore({
-                prop: '-ms-grid-row-span',
-                value: rowSpan.toString()
-            });
-        }
-
-        if (columnStart) {
-            decl.cloneBefore({
-                prop: '-ms-grid-column',
-                value: columnStart.toString()
-            });
-        }
-
-        if (columnSpan) {
-            decl.cloneBefore({
-                prop: '-ms-grid-column-span',
-                value: columnSpan.toString()
-            });
-        }
+        [
+            ['grid-row', rowStart],
+            ['grid-row-span', rowSpan],
+            ['grid-column', columnStart],
+            ['grid-column-span', columnSpan]
+
+        ].forEach(([prop, value]) => {
+            utils.insertDecl(decl, prop, value);
+        });
 
         return undefined;
     }
diff --git a/lib/hacks/grid-end.js b/lib/hacks/grid-end.js
index 95fc479..9937a3f 100644
--- a/lib/hacks/grid-end.js
+++ b/lib/hacks/grid-end.js
@@ -3,43 +3,47 @@ const Declaration = require('../declaration');
 class GridEnd extends Declaration {
 
     static names = [
-        'grid-row-end', 'grid-column-end',
-        'grid-row-span', 'grid-column-span'
+        'grid-row-end', 'grid-column-end'
     ];
 
     /**
-     * Do not add prefix for unsupported value in IE
+     * Change repeating syntax for IE
      */
-    check(decl) {
-        return decl.value.indexOf('span') !== -1;
-    }
+    insert(decl, prefix, prefixes, result) {
+        if (prefix !== '-ms-') return super.insert(decl, prefix, prefixes);
 
-    /**
-     * Return a final spec property
-     */
-    normalize(prop) {
-        return prop.replace(/(-span|-end)/, '');
-    }
+        const clonedDecl = this.clone(decl);
 
-    /**
-     * Change property name for IE
-     */
-    prefixed(prop, prefix) {
-        let result = super.prefixed(prop, prefix);
-        if (prefix === '-ms-') {
-            result = result.replace('-end', '-span');
+        const startProp = decl.prop.replace(/end$/, 'start');
+        const spanProp = prefix + decl.prop.replace(/end$/, 'span');
+
+        if (decl.parent.some(i => i.prop === spanProp)) {
+            return undefined;
         }
-        return result;
-    }
 
-    /**
-     * Change repeating syntax for IE
-     */
-    set(decl, prefix) {
-        if (prefix === '-ms-') {
-            decl.value = decl.value.replace(/span\s/i, '');
+        clonedDecl.prop = spanProp;
+
+        if (decl.value.includes('span')) {
+            clonedDecl.value = decl.value.replace(/span\s/i, '');
+        } else {
+            let startDecl;
+            decl.parent.walkDecls(startProp, d => {
+                startDecl = d;
+            });
+            if (startDecl) {
+                const value = Number(decl.value) - Number(startDecl.value) + '';
+                clonedDecl.value = value;
+            } else {
+                decl.warn(
+                    result,
+                    `Can\'t prefix ${decl.prop} (${startProp} is not found).`
+                );
+            }
         }
-        return super.set(decl, prefix);
+
+        decl.cloneBefore(clonedDecl);
+
+        return undefined;
     }
 
 }
diff --git a/lib/hacks/grid-row-column.js b/lib/hacks/grid-row-column.js
index 79ae746..b2a3eef 100644
--- a/lib/hacks/grid-row-column.js
+++ b/lib/hacks/grid-row-column.js
@@ -14,19 +14,14 @@ class GridRowColumn extends Declaration {
         const values = utils.parse(decl);
         const [start, span] = utils.translate(values, 0, 1);
 
-        if (start) {
-            decl.cloneBefore({
-                prop: `-ms-${decl.prop}`,
-                value: start.toString()
-            });
-        }
-
-        if (span) {
-            decl.cloneBefore({
-                prop: `-ms-${decl.prop}-span`,
-                value: span.toString()
-            });
-        }
+
+        [
+            [decl.prop, start],
+            [`${decl.prop}-span`, span]
+
+        ].forEach(([prop, value]) => {
+            utils.insertDecl(decl, prop, value);
+        });
 
         return undefined;
     }
diff --git a/lib/hacks/grid-utils.js b/lib/hacks/grid-utils.js
index a130f7b..04e0742 100644
--- a/lib/hacks/grid-utils.js
+++ b/lib/hacks/grid-utils.js
@@ -68,6 +68,15 @@ function parse(decl) {
     return values;
 }
 
+function insertDecl(decl, prop, value) {
+    if (value && !decl.parent.some(i => i.prop === `-ms-${prop}`)) {
+        decl.cloneBefore({
+            prop: `-ms-${prop}`,
+            value: value.toString()
+        });
+    }
+}
+
 // Transform repeat
 
 function transformRepeat({ nodes }) {
@@ -248,5 +257,6 @@ module.exports = {
     changeRepeat,
     parseTemplate,
     parseGridAreas,
-    insertAreas
+    insertAreas,
+    insertDecl
 };


Test patch:
diff --git a/test/autoprefixer.test.js b/test/autoprefixer.test.js
index f435a3d..d02a36d 100644
--- a/test/autoprefixer.test.js
+++ b/test/autoprefixer.test.js
@@ -493,7 +493,7 @@ describe('hacks', () => {
 
         expect(result.css).toEqual(output);
         expect(result.warnings().map(i => i.toString())).toEqual([
-            'autoprefixer: <css input>:30:5: Can not find grid areas: ' +
+            'autoprefixer: <css input>:37:5: Can not find grid areas: ' +
             'head, nav, main, foot'
         ]);
     });
diff --git a/test/cases/grid.css b/test/cases/grid.css
index d95bcf0..77d8964 100644
--- a/test/cases/grid.css
+++ b/test/cases/grid.css
@@ -25,6 +25,13 @@
     grid-row: span 2 / 5;
 }
 
+.e {
+    grid-column-start: 1;
+    grid-column-end: 3;
+    grid-row-start: 1;
+    grid-row-end: 4;
+}
+
 .webkit {
     grid: subgrid;
     grid-template-areas: "head head"
diff --git a/test/cases/grid.disabled.css b/test/cases/grid.disabled.css
index 24cc2ad..64a5920 100644
--- a/test/cases/grid.disabled.css
+++ b/test/cases/grid.disabled.css
@@ -25,6 +25,13 @@
     grid-row: span 2 / 5;
 }
 
+.e {
+    grid-column-start: 1;
+    grid-column-end: 3;
+    grid-row-start: 1;
+    grid-row-end: 4;
+}
+
 .webkit {
     grid: subgrid;
     grid-template-areas: "head head"
diff --git a/test/cases/grid.out.css b/test/cases/grid.out.css
index 28826c4..0162499 100644
--- a/test/cases/grid.out.css
+++ b/test/cases/grid.out.css
@@ -43,6 +43,17 @@
     grid-row: span 2 / 5;
 }
 
+.e {
+    -ms-grid-column: 1;
+    grid-column-start: 1;
+    -ms-grid-column-span: 2;
+    grid-column-end: 3;
+    -ms-grid-row: 1;
+    grid-row-start: 1;
+    -ms-grid-row-span: 3;
+    grid-row-end: 4;
+}
+
 .webkit {
     grid: subgrid;
     grid-template-areas: "head head"