From 795f393dba2f14de59ccaa319dc3ac939f658304 Mon Sep 17 00:00:00 2001
From: Jakub Freisler <jakub@frsource.org>
Date: Wed, 29 Dec 2021 15:38:03 +0100
Subject: [PATCH 1/3] feat: add postcss 8 support

Signed-off-by: Jakub Freisler <jakub@frsource.org>
---
 lib/stylePlugins/scoped.ts | 175 +++++++++++++++++++------------------
 lib/stylePlugins/trim.ts   |  22 +++--
 package.json               |   2 +-
 test/compileStyle.spec.ts  |  14 +--
 yarn.lock                  |  31 ++++---
 5 files changed, 133 insertions(+), 111 deletions(-)

diff --git a/lib/stylePlugins/scoped.ts b/lib/stylePlugins/scoped.ts
index 14e1a2d..4c5bb89 100644
--- a/lib/stylePlugins/scoped.ts
+++ b/lib/stylePlugins/scoped.ts
@@ -1,101 +1,106 @@
-import { Root } from 'postcss'
-import * as postcss from 'postcss'
+import { Root, PluginCreator } from 'postcss'
 // postcss-selector-parser does have typings but it's problematic to work with.
 const selectorParser = require('postcss-selector-parser')
 
-export default postcss.plugin('add-id', (options: any) => (root: Root) => {
-  const id: string = options
-  const keyframes = Object.create(null)
+const pluginFn: PluginCreator<any> = options => ({
+  postcssPlugin: 'add-id',
+  Once(root: Root) {
+    const id: string = options
+    const keyframes = Object.create(null)
 
-  root.each(function rewriteSelector(node: any) {
-    if (!node.selector) {
-      // handle media queries
-      if (node.type === 'atrule') {
-        if (node.name === 'media' || node.name === 'supports') {
-          node.each(rewriteSelector)
-        } else if (/-?keyframes$/.test(node.name)) {
-          // register keyframes
-          keyframes[node.params] = node.params = node.params + '-' + id
+    root.each(function rewriteSelector(node: any) {
+      if (!node.selector) {
+        // handle media queries
+        if (node.type === 'atrule') {
+          if (node.name === 'media' || node.name === 'supports') {
+            node.each(rewriteSelector)
+          } else if (/-?keyframes$/.test(node.name)) {
+            // register keyframes
+            keyframes[node.params] = node.params = node.params + '-' + id
+          }
         }
+        return
       }
-      return
-    }
-    node.selector = selectorParser((selectors: any) => {
-      selectors.each((selector: any) => {
-        let node: any = null
+      node.selector = selectorParser((selectors: any) => {
+        selectors.each((selector: any) => {
+          let node: any = null
 
-        // find the last child node to insert attribute selector
-        selector.each((n: any) => {
-          // ">>>" combinator
-          // and /deep/ alias for >>>, since >>> doesn't work in SASS
-          if (
-            n.type === 'combinator' &&
-            (n.value === '>>>' || n.value === '/deep/')
-          ) {
-            n.value = ' '
-            n.spaces.before = n.spaces.after = ''
-            return false
-          }
+          // find the last child node to insert attribute selector
+          selector.each((n: any) => {
+            // ">>>" combinator
+            // and /deep/ alias for >>>, since >>> doesn't work in SASS
+            if (
+              n.type === 'combinator' &&
+              (n.value === '>>>' || n.value === '/deep/')
+            ) {
+              n.value = ' '
+              n.spaces.before = n.spaces.after = ''
+              return false
+            }
 
-          // in newer versions of sass, /deep/ support is also dropped, so add a ::v-deep alias
-          if (n.type === 'pseudo' && n.value === '::v-deep') {
-            n.value = n.spaces.before = n.spaces.after = ''
-            return false
-          }
+            // in newer versions of sass, /deep/ support is also dropped, so add a ::v-deep alias
+            if (n.type === 'pseudo' && n.value === '::v-deep') {
+              n.value = n.spaces.before = n.spaces.after = ''
+              return false
+            }
 
-          if (n.type !== 'pseudo' && n.type !== 'combinator') {
-            node = n
+            if (n.type !== 'pseudo' && n.type !== 'combinator') {
+              node = n
+            }
+          })
+
+          if (node) {
+            node.spaces.after = ''
+          } else {
+            // For deep selectors & standalone pseudo selectors,
+            // the attribute selectors are prepended rather than appended.
+            // So all leading spaces must be eliminated to avoid problems.
+            selector.first.spaces.before = ''
           }
+
+          selector.insertAfter(
+            node,
+            selectorParser.attribute({
+              attribute: id
+            })
+          )
         })
+      }).processSync(node.selector)
+    })
 
-        if (node) {
-          node.spaces.after = ''
-        } else {
-          // For deep selectors & standalone pseudo selectors,
-          // the attribute selectors are prepended rather than appended.
-          // So all leading spaces must be eliminated to avoid problems.
-          selector.first.spaces.before = ''
+    // If keyframes are found in this <style>, find and rewrite animation names
+    // in declarations.
+    // Caveat: this only works for keyframes and animation rules in the same
+    // <style> element.
+    if (Object.keys(keyframes).length) {
+      root.walkDecls(decl => {
+        // individual animation-name declaration
+        if (/^(-\w+-)?animation-name$/.test(decl.prop)) {
+          decl.value = decl.value
+            .split(',')
+            .map(v => keyframes[v.trim()] || v.trim())
+            .join(',')
+        }
+        // shorthand
+        if (/^(-\w+-)?animation$/.test(decl.prop)) {
+          decl.value = decl.value
+            .split(',')
+            .map(v => {
+              const vals = v.trim().split(/\s+/)
+              const i = vals.findIndex(val => keyframes[val])
+              if (i !== -1) {
+                vals.splice(i, 1, keyframes[vals[i]])
+                return vals.join(' ')
+              } else {
+                return v
+              }
+            })
+            .join(',')
         }
-
-        selector.insertAfter(
-          node,
-          selectorParser.attribute({
-            attribute: id
-          })
-        )
       })
-    }).processSync(node.selector)
-  })
-
-  // If keyframes are found in this <style>, find and rewrite animation names
-  // in declarations.
-  // Caveat: this only works for keyframes and animation rules in the same
-  // <style> element.
-  if (Object.keys(keyframes).length) {
-    root.walkDecls(decl => {
-      // individual animation-name declaration
-      if (/^(-\w+-)?animation-name$/.test(decl.prop)) {
-        decl.value = decl.value
-          .split(',')
-          .map(v => keyframes[v.trim()] || v.trim())
-          .join(',')
-      }
-      // shorthand
-      if (/^(-\w+-)?animation$/.test(decl.prop)) {
-        decl.value = decl.value
-          .split(',')
-          .map(v => {
-            const vals = v.trim().split(/\s+/)
-            const i = vals.findIndex(val => keyframes[val])
-            if (i !== -1) {
-              vals.splice(i, 1, keyframes[vals[i]])
-              return vals.join(' ')
-            } else {
-              return v
-            }
-          })
-          .join(',')
-      }
-    })
+    }
   }
 })
+
+pluginFn.postcss = true
+export default pluginFn
diff --git a/lib/stylePlugins/trim.ts b/lib/stylePlugins/trim.ts
index e4aed6a..2cfcbf0 100644
--- a/lib/stylePlugins/trim.ts
+++ b/lib/stylePlugins/trim.ts
@@ -1,11 +1,15 @@
-import { Root } from 'postcss'
-import * as postcss from 'postcss'
+import { PluginCreator, Rule, AtRule } from 'postcss'
 
-export default postcss.plugin('trim', () => (css: Root) => {
-  css.walk(({ type, raws }) => {
-    if (type === 'rule' || type === 'atrule') {
-      if (raws.before) raws.before = '\n'
-      if (raws.after) raws.after = '\n'
-    }
-  })
+const trim = function({ raws }: Rule | AtRule) {
+  if (raws.before) raws.before = '\n'
+  if (raws.after) raws.after = '\n'
+}
+
+const pluginFn: PluginCreator<void> = () => ({
+  postcssPlugin: 'trim',
+  AtRule: trim,
+  Rule: trim
 })
+
+pluginFn.postcss = true
+export default pluginFn
diff --git a/package.json b/package.json
index 69e4faa..5bcb270 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,7 @@
     "hash-sum": "^1.0.2",
     "lru-cache": "^4.1.2",
     "merge-source-map": "^1.1.0",
-    "postcss": "^7.0.36",
+    "postcss": "^8.0.0",
     "postcss-selector-parser": "^6.0.2",
     "source-map": "~0.6.1",
     "vue-template-es2015-compiler": "^1.9.0"
diff --git a/test/compileStyle.spec.ts b/test/compileStyle.spec.ts
index 58f059a..82fc693 100644
--- a/test/compileStyle.spec.ts
+++ b/test/compileStyle.spec.ts
@@ -138,9 +138,10 @@ test('async postcss plugin in sync mode', () => {
     source: '.foo { color: red }',
     scoped: false,
     postcssPlugins: [
-      require('postcss').plugin('test-plugin', () => async (result: any) =>
-        result
-      )
+      {
+        postcssPlugin: 'test-plugin',
+        Once: async (result: any) => result
+      }
     ]
   })
 
@@ -154,9 +155,10 @@ test('async postcss plugin', async () => {
     source: '.foo { color: red }',
     scoped: false,
     postcssPlugins: [
-      require('postcss').plugin('test-plugin', () => async (result: any) =>
-        result
-      )
+      {
+        postcssPlugin: 'test-plugin',
+        Once: async (result: any) => result
+      }
     ]
   })
 
diff --git a/yarn.lock b/yarn.lock
index 919f2b3..8bdbc10 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3579,6 +3579,11 @@ nan@^2.12.1:
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
   integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
 
+nanoid@^3.1.30:
+  version "3.1.30"
+  resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362"
+  integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==
+
 nanomatch@^1.2.9:
   version "1.2.13"
   resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@@ -3954,10 +3959,10 @@ performance-now@^2.1.0:
   resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
   integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
 
-picocolors@^0.2.1:
-  version "0.2.1"
-  resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f"
-  integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==
+picocolors@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
+  integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
 
 picomatch@^2.0.4, picomatch@^2.2.1:
   version "2.2.2"
@@ -4031,13 +4036,14 @@ postcss-selector-parser@^6.0.2:
     indexes-of "^1.0.1"
     uniq "^1.0.1"
 
-postcss@^7.0.36:
-  version "7.0.39"
-  resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309"
-  integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==
+postcss@^8.0.0:
+  version "8.4.5"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95"
+  integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==
   dependencies:
-    picocolors "^0.2.1"
-    source-map "^0.6.1"
+    nanoid "^3.1.30"
+    picocolors "^1.0.0"
+    source-map-js "^1.0.1"
 
 prelude-ls@~1.1.2:
   version "1.1.2"
@@ -4692,6 +4698,11 @@ snapdragon@^0.8.1:
     source-map-resolve "^0.5.0"
     use "^3.1.0"
 
+source-map-js@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf"
+  integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==
+
 source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
   version "0.5.3"
   resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"

From 18a0ce3ebbacc6b8b3571276eddf1e7388d363a7 Mon Sep 17 00:00:00 2001
From: Jakub Freisler <jakub@frsource.org>
Date: Fri, 4 Feb 2022 16:43:29 +0100
Subject: [PATCH 2/3] chore: raise postcss version to 8.1.3

Signed-off-by: Jakub Freisler <jakub@frsource.org>
---
 package.json |  2 +-
 yarn.lock    | 28 ++++++++++++++--------------
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/package.json b/package.json
index 5bcb270..e7c49ef 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,7 @@
     "hash-sum": "^1.0.2",
     "lru-cache": "^4.1.2",
     "merge-source-map": "^1.1.0",
-    "postcss": "^8.0.0",
+    "postcss": "^8.4.6",
     "postcss-selector-parser": "^6.0.2",
     "source-map": "~0.6.1",
     "vue-template-es2015-compiler": "^1.9.0"
diff --git a/yarn.lock b/yarn.lock
index 8bdbc10..3db47bd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3579,10 +3579,10 @@ nan@^2.12.1:
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
   integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
 
-nanoid@^3.1.30:
-  version "3.1.30"
-  resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362"
-  integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==
+nanoid@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c"
+  integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==
 
 nanomatch@^1.2.9:
   version "1.2.13"
@@ -4036,14 +4036,14 @@ postcss-selector-parser@^6.0.2:
     indexes-of "^1.0.1"
     uniq "^1.0.1"
 
-postcss@^8.0.0:
-  version "8.4.5"
-  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95"
-  integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==
+postcss@^8.4.6:
+  version "8.4.6"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1"
+  integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==
   dependencies:
-    nanoid "^3.1.30"
+    nanoid "^3.2.0"
     picocolors "^1.0.0"
-    source-map-js "^1.0.1"
+    source-map-js "^1.0.2"
 
 prelude-ls@~1.1.2:
   version "1.1.2"
@@ -4698,10 +4698,10 @@ snapdragon@^0.8.1:
     source-map-resolve "^0.5.0"
     use "^3.1.0"
 
-source-map-js@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf"
-  integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==
+source-map-js@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
+  integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
 
 source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
   version "0.5.3"

From 5859be4b76199d715d0fa2011506800e62c03d92 Mon Sep 17 00:00:00 2001
From: Jakub Freisler <jakub@frsource.org>
Date: Fri, 4 Feb 2022 16:46:40 +0100
Subject: [PATCH 3/3] feat: migrate test-plugin to new syntax

Signed-off-by: Jakub Freisler <jakub@frsource.org>
---
 test/compileStyle.spec.ts | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/test/compileStyle.spec.ts b/test/compileStyle.spec.ts
index 82fc693..dafaab9 100644
--- a/test/compileStyle.spec.ts
+++ b/test/compileStyle.spec.ts
@@ -113,7 +113,12 @@ test('custom postcss plugin', () => {
     filename: 'example.vue',
     source: '.foo { color: red }',
     scoped: false,
-    postcssPlugins: [require('postcss').plugin('test-plugin', () => spy)()]
+    postcssPlugins: [
+      {
+        postcssPlugin: 'test-plugin',
+        Once: spy
+      }
+    ]
   })
 
   expect(spy).toHaveBeenCalled()