From e212e979fc8b54ca77d96008f64de6afb707e485 Mon Sep 17 00:00:00 2001
From: Kendell R <KTibow@users.noreply.github.com>
Date: Thu, 12 Oct 2023 02:26:02 +0000
Subject: [PATCH 1/5] Switch to Lightning CSS

---
 build-scripts/bundle.cjs         |  12 ++--
 build-scripts/gulp/entry-html.js |   2 +
 build-scripts/lightningcss.cjs   |  55 ++++++++++++++++
 package.json                     |   1 +
 yarn.lock                        | 110 +++++++++++++++++++++++++++++++
 5 files changed, 174 insertions(+), 6 deletions(-)
 create mode 100644 build-scripts/lightningcss.cjs

diff --git a/build-scripts/bundle.cjs b/build-scripts/bundle.cjs
index b359a0737487..4870d3f0a88e 100644
--- a/build-scripts/bundle.cjs
+++ b/build-scripts/bundle.cjs
@@ -1,6 +1,7 @@
 const path = require("path");
 const env = require("./env.cjs");
 const paths = require("./paths.cjs");
+const lightningcss = require("./lightningcss.cjs");
 
 // GitHub base URL to use for production source maps
 // Nightly builds use the commit SHA, otherwise assumes there is a tag that matches the version
@@ -69,9 +70,6 @@ module.exports.htmlMinifierOptions = {
   decodeEntities: true,
   removeComments: true,
   removeRedundantAttributes: true,
-  minifyCSS: {
-    compatibility: "*,-properties.zeroUnits",
-  },
 };
 
 module.exports.terserOptions = ({ latestBuild, isTestBuild }) => ({
@@ -116,8 +114,7 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
         ignoreModuleNotFound: true,
       },
     ],
-    // Minify template literals for production
-    isProdBuild && [
+    [
       "template-html-minifier",
       {
         modules: {
@@ -129,7 +126,10 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
           "@polymer/polymer/lib/utils/html-tag": ["html"],
         },
         strictCSS: true,
-        htmlMinifier: module.exports.htmlMinifierOptions,
+        htmlMinifier: {
+          ...module.exports.htmlMinifierOptions,
+          minifyCSS: lightningcss.getMinifyCSS({ latestBuild, isProdBuild }),
+        },
         failOnError: true, // we can turn this off in case of false positives
       },
     ],
diff --git a/build-scripts/gulp/entry-html.js b/build-scripts/gulp/entry-html.js
index dd6285c3103a..a7d5dda9f9e7 100644
--- a/build-scripts/gulp/entry-html.js
+++ b/build-scripts/gulp/entry-html.js
@@ -8,6 +8,7 @@ import path from "path";
 import { htmlMinifierOptions, terserOptions } from "../bundle.cjs";
 import env from "../env.cjs";
 import paths from "../paths.cjs";
+import { getMinifyCSS } from "../lightningcss.cjs";
 
 const renderTemplate = (templateFile, data = {}) => {
   const compiled = template(
@@ -35,6 +36,7 @@ const minifyHtml = (content, ext) => {
   return minify(begTag + content + endTag, {
     ...htmlMinifierOptions,
     conservativeCollapse: false,
+    minifyCSS: getMinifyCSS({ latestBuild: false, isProdBuild: true }), // Transpile and minify
     minifyJS: terserOptions({
       latestBuild: false, // Shared scripts should be ES5
       isTestBuild: true, // Don't need source maps
diff --git a/build-scripts/lightningcss.cjs b/build-scripts/lightningcss.cjs
new file mode 100644
index 000000000000..b820d1ff0637
--- /dev/null
+++ b/build-scripts/lightningcss.cjs
@@ -0,0 +1,55 @@
+const CleanCSS = require("clean-css");
+const browserslist = require("browserslist");
+const lightningcss = require("lightningcss");
+
+const cleanCSS = new CleanCSS({ compatibility: "*,-properties.zeroUnits" });
+const decoder = new TextDecoder();
+function wrapCSS(text, type) {
+  if (type === "inline") return `#a{${text}}`;
+  if (type === "media") return `@media ${text}{#a{top:0}}`;
+  return text;
+}
+function unwrapCSS(text, type) {
+  if (type === "inline") return text.match(/^#a\{([\s\S]*)\}$/)[1];
+  if (type === "media") return text.match(/^@media ?([\s\S]*?) ?{[\s\S]*}$/)[1];
+  return text;
+}
+
+module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => {
+  const cssTargets = lightningcss.browserslistToTargets(
+    browserslist(
+      browserslist.loadConfig({
+        path: ".",
+        env: latestBuild ? "modern" : "legacy",
+      }),
+      { throwOnMissing: true, mobileToDesktop: true }
+    )
+  );
+  return (text, type) => {
+    if (!text) return text;
+    const input = wrapCSS(text, type);
+    const { styles: ccss, errors, warnings: w1 } = cleanCSS.minify(input);
+    if (errors.length > 0) {
+      console.error("[CCSS] Errors while transforming CSS:", ...errors);
+    }
+    if (w1.length > 0) {
+      console.warn("[CCSS] Warnings while transforming CSS:", ...w1);
+    }
+    if (text.includes("babel-plugin-template-html-minifier")) {
+      const output = unwrapCSS(ccss, type);
+      return output;
+    }
+    const { code, warnings: w2 } = lightningcss.transform({
+      filename: "style.css",
+      code: Buffer.from(input),
+      minify: isProdBuild,
+      targets: cssTargets,
+    });
+    if (w2.length > 0) {
+      console.warn("[LCSS] Warnings while transforming CSS:", ...w2);
+    }
+    const lcss = decoder.decode(code);
+    const output = unwrapCSS(lcss, type);
+    return output;
+  };
+};
diff --git a/package.json b/package.json
index 5434f52d3a75..e1b863e8ed31 100644
--- a/package.json
+++ b/package.json
@@ -220,6 +220,7 @@
     "husky": "8.0.3",
     "instant-mocha": "1.5.2",
     "jszip": "3.10.1",
+    "lightningcss": "1.22.0",
     "lint-staged": "14.0.1",
     "lit-analyzer": "2.0.0-pre.3",
     "lodash.template": "4.5.0",
diff --git a/yarn.lock b/yarn.lock
index 3a4c90ab742b..6e18fd574373 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7506,6 +7506,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"detect-libc@npm:^1.0.3":
+  version: 1.0.3
+  resolution: "detect-libc@npm:1.0.3"
+  bin:
+    detect-libc: ./bin/detect-libc.js
+  checksum: daaaed925ffa7889bd91d56e9624e6c8033911bb60f3a50a74a87500680652969dbaab9526d1e200a4c94acf80fc862a22131841145a0a8482d60a99c24f4a3e
+  languageName: node
+  linkType: hard
+
 "detect-node@npm:^2.0.4":
   version: 2.1.0
   resolution: "detect-node@npm:2.1.0"
@@ -9788,6 +9797,7 @@ __metadata:
     jszip: 3.10.1
     leaflet: 1.9.4
     leaflet-draw: 1.0.4
+    lightningcss: 1.22.0
     lint-staged: 14.0.1
     lit: 2.8.0
     lit-analyzer: 2.0.0-pre.3
@@ -11371,6 +11381,106 @@ __metadata:
   languageName: node
   linkType: hard
 
+"lightningcss-darwin-arm64@npm:1.22.0":
+  version: 1.22.0
+  resolution: "lightningcss-darwin-arm64@npm:1.22.0"
+  conditions: os=darwin & cpu=arm64
+  languageName: node
+  linkType: hard
+
+"lightningcss-darwin-x64@npm:1.22.0":
+  version: 1.22.0
+  resolution: "lightningcss-darwin-x64@npm:1.22.0"
+  conditions: os=darwin & cpu=x64
+  languageName: node
+  linkType: hard
+
+"lightningcss-freebsd-x64@npm:1.22.0":
+  version: 1.22.0
+  resolution: "lightningcss-freebsd-x64@npm:1.22.0"
+  conditions: os=freebsd & cpu=x64
+  languageName: node
+  linkType: hard
+
+"lightningcss-linux-arm-gnueabihf@npm:1.22.0":
+  version: 1.22.0
+  resolution: "lightningcss-linux-arm-gnueabihf@npm:1.22.0"
+  conditions: os=linux & cpu=arm
+  languageName: node
+  linkType: hard
+
+"lightningcss-linux-arm64-gnu@npm:1.22.0":
+  version: 1.22.0
+  resolution: "lightningcss-linux-arm64-gnu@npm:1.22.0"
+  conditions: os=linux & cpu=arm64 & libc=glibc
+  languageName: node
+  linkType: hard
+
+"lightningcss-linux-arm64-musl@npm:1.22.0":
+  version: 1.22.0
+  resolution: "lightningcss-linux-arm64-musl@npm:1.22.0"
+  conditions: os=linux & cpu=arm64 & libc=musl
+  languageName: node
+  linkType: hard
+
+"lightningcss-linux-x64-gnu@npm:1.22.0":
+  version: 1.22.0
+  resolution: "lightningcss-linux-x64-gnu@npm:1.22.0"
+  conditions: os=linux & cpu=x64 & libc=glibc
+  languageName: node
+  linkType: hard
+
+"lightningcss-linux-x64-musl@npm:1.22.0":
+  version: 1.22.0
+  resolution: "lightningcss-linux-x64-musl@npm:1.22.0"
+  conditions: os=linux & cpu=x64 & libc=musl
+  languageName: node
+  linkType: hard
+
+"lightningcss-win32-x64-msvc@npm:1.22.0":
+  version: 1.22.0
+  resolution: "lightningcss-win32-x64-msvc@npm:1.22.0"
+  conditions: os=win32 & cpu=x64
+  languageName: node
+  linkType: hard
+
+"lightningcss@npm:1.22.0":
+  version: 1.22.0
+  resolution: "lightningcss@npm:1.22.0"
+  dependencies:
+    detect-libc: ^1.0.3
+    lightningcss-darwin-arm64: 1.22.0
+    lightningcss-darwin-x64: 1.22.0
+    lightningcss-freebsd-x64: 1.22.0
+    lightningcss-linux-arm-gnueabihf: 1.22.0
+    lightningcss-linux-arm64-gnu: 1.22.0
+    lightningcss-linux-arm64-musl: 1.22.0
+    lightningcss-linux-x64-gnu: 1.22.0
+    lightningcss-linux-x64-musl: 1.22.0
+    lightningcss-win32-x64-msvc: 1.22.0
+  dependenciesMeta:
+    lightningcss-darwin-arm64:
+      optional: true
+    lightningcss-darwin-x64:
+      optional: true
+    lightningcss-freebsd-x64:
+      optional: true
+    lightningcss-linux-arm-gnueabihf:
+      optional: true
+    lightningcss-linux-arm64-gnu:
+      optional: true
+    lightningcss-linux-arm64-musl:
+      optional: true
+    lightningcss-linux-x64-gnu:
+      optional: true
+    lightningcss-linux-x64-musl:
+      optional: true
+    lightningcss-win32-x64-msvc:
+      optional: true
+  checksum: 6b9a04846243a2161ac12ee098f9c2143a1a06fb683228ef0433473257751a709b0bafa195efa8d3d8f1556ca60c54f5434caeb172874a8daced552dedcbed93
+  languageName: node
+  linkType: hard
+
 "lilconfig@npm:2.1.0":
   version: 2.1.0
   resolution: "lilconfig@npm:2.1.0"

From d8180851b50c21fb8112fd9755d3d4c3cf771c1d Mon Sep 17 00:00:00 2001
From: Kendell R <KTibow@users.noreply.github.com>
Date: Thu, 12 Oct 2023 02:35:56 +0000
Subject: [PATCH 2/5] Some "fixes"

---
 build-scripts/lightningcss.cjs | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/build-scripts/lightningcss.cjs b/build-scripts/lightningcss.cjs
index b820d1ff0637..109542091a53 100644
--- a/build-scripts/lightningcss.cjs
+++ b/build-scripts/lightningcss.cjs
@@ -28,16 +28,20 @@ module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => {
   return (text, type) => {
     if (!text) return text;
     const input = wrapCSS(text, type);
-    const { styles: ccss, errors, warnings: w1 } = cleanCSS.minify(input);
-    if (errors.length > 0) {
-      console.error("[CCSS] Errors while transforming CSS:", ...errors);
-    }
-    if (w1.length > 0) {
-      console.warn("[CCSS] Warnings while transforming CSS:", ...w1);
-    }
     if (text.includes("babel-plugin-template-html-minifier")) {
-      const output = unwrapCSS(ccss, type);
-      return output;
+      const { styles: ccss, errors, warnings: w1 } = cleanCSS.minify(input);
+      if (errors.length > 0) {
+        console.error("[CCSS] Errors while transforming CSS:", ...errors);
+      }
+      if (w1.length > 0) {
+        console.warn("[CCSS] Warnings while transforming CSS:", ...w1);
+      }
+      try {
+        return unwrapCSS(ccss, type);
+      } catch (e) {
+        console.error("[CCSS] Invalid output", { text, type, output: ccss });
+        return text;
+      }
     }
     const { code, warnings: w2 } = lightningcss.transform({
       filename: "style.css",
@@ -49,7 +53,11 @@ module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => {
       console.warn("[LCSS] Warnings while transforming CSS:", ...w2);
     }
     const lcss = decoder.decode(code);
-    const output = unwrapCSS(lcss, type);
-    return output;
+    try {
+      return unwrapCSS(lcss, type);
+    } catch (e) {
+      console.error("[LCSS] Invalid output", { text, type, output: lcss });
+      return text;
+    }
   };
 };

From 6a37e2257cbabb4055aa41dd45364ed5af6db8ac Mon Sep 17 00:00:00 2001
From: Kendell R <KTibow@users.noreply.github.com>
Date: Thu, 12 Oct 2023 02:54:28 +0000
Subject: [PATCH 3/5] Fix test builds

---
 build-scripts/lightningcss.cjs | 50 ++++++++++++++++++----------------
 1 file changed, 27 insertions(+), 23 deletions(-)

diff --git a/build-scripts/lightningcss.cjs b/build-scripts/lightningcss.cjs
index 109542091a53..8a82b55900be 100644
--- a/build-scripts/lightningcss.cjs
+++ b/build-scripts/lightningcss.cjs
@@ -10,8 +10,9 @@ function wrapCSS(text, type) {
   return text;
 }
 function unwrapCSS(text, type) {
-  if (type === "inline") return text.match(/^#a\{([\s\S]*)\}$/)[1];
-  if (type === "media") return text.match(/^@media ?([\s\S]*?) ?{[\s\S]*}$/)[1];
+  if (type === "inline") return text.match(/^#a ?\{([\s\S]*)\}$/m)[1];
+  if (type === "media")
+    return text.match(/^@media ?([\s\S]*?) ?{[\s\S]*}$/m)[1];
   return text;
 }
 
@@ -28,36 +29,39 @@ module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => {
   return (text, type) => {
     if (!text) return text;
     const input = wrapCSS(text, type);
-    if (text.includes("babel-plugin-template-html-minifier")) {
-      const { styles: ccss, errors, warnings: w1 } = cleanCSS.minify(input);
+    if (!text.includes("babel-plugin-template-html-minifier")) {
+      const { code, warnings: w1 } = lightningcss.transform({
+        filename: "style.css",
+        code: Buffer.from(input),
+        minify: isProdBuild,
+        targets: cssTargets,
+      });
+      if (w1.length > 0) {
+        console.warn("[LCSS] Warnings while transforming CSS:", ...w1);
+      }
+      const lcss = decoder.decode(code);
+      try {
+        return unwrapCSS(lcss, type);
+      } catch (e) {
+        console.error("[LCSS] Invalid output", { text, type, output: lcss, e });
+        return text;
+      }
+    }
+    if (isProdBuild) {
+      const { styles: ccss, errors, warnings: w2 } = cleanCSS.minify(input);
       if (errors.length > 0) {
         console.error("[CCSS] Errors while transforming CSS:", ...errors);
       }
-      if (w1.length > 0) {
-        console.warn("[CCSS] Warnings while transforming CSS:", ...w1);
+      if (w2.length > 0) {
+        console.warn("[CCSS] Warnings while transforming CSS:", ...w2);
       }
       try {
         return unwrapCSS(ccss, type);
       } catch (e) {
-        console.error("[CCSS] Invalid output", { text, type, output: ccss });
+        console.error("[CCSS] Invalid output", { text, type, output: ccss, e });
         return text;
       }
     }
-    const { code, warnings: w2 } = lightningcss.transform({
-      filename: "style.css",
-      code: Buffer.from(input),
-      minify: isProdBuild,
-      targets: cssTargets,
-    });
-    if (w2.length > 0) {
-      console.warn("[LCSS] Warnings while transforming CSS:", ...w2);
-    }
-    const lcss = decoder.decode(code);
-    try {
-      return unwrapCSS(lcss, type);
-    } catch (e) {
-      console.error("[LCSS] Invalid output", { text, type, output: lcss });
-      return text;
-    }
+    return text;
   };
 };

From be58762349e922dcfe56d9b41c62374f290c7d57 Mon Sep 17 00:00:00 2001
From: Kendell R <KTibow@users.noreply.github.com>
Date: Fri, 13 Oct 2023 00:27:58 +0000
Subject: [PATCH 4/5] Reduce output size, make code more clear

---
 build-scripts/lightningcss.cjs | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/build-scripts/lightningcss.cjs b/build-scripts/lightningcss.cjs
index 8a82b55900be..90f3a3011bee 100644
--- a/build-scripts/lightningcss.cjs
+++ b/build-scripts/lightningcss.cjs
@@ -1,6 +1,6 @@
 const CleanCSS = require("clean-css");
 const browserslist = require("browserslist");
-const lightningcss = require("lightningcss");
+const { transform, browserslistToTargets, Features } = require("lightningcss");
 
 const cleanCSS = new CleanCSS({ compatibility: "*,-properties.zeroUnits" });
 const decoder = new TextDecoder();
@@ -17,7 +17,7 @@ function unwrapCSS(text, type) {
 }
 
 module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => {
-  const cssTargets = lightningcss.browserslistToTargets(
+  const cssTargets = browserslistToTargets(
     browserslist(
       browserslist.loadConfig({
         path: ".",
@@ -30,14 +30,18 @@ module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => {
     if (!text) return text;
     const input = wrapCSS(text, type);
     if (!text.includes("babel-plugin-template-html-minifier")) {
-      const { code, warnings: w1 } = lightningcss.transform({
+      const { code, warnings: ws } = transform({
         filename: "style.css",
         code: Buffer.from(input),
         minify: isProdBuild,
         targets: cssTargets,
+        exclude: Features.DirSelector,
       });
-      if (w1.length > 0) {
-        console.warn("[LCSS] Warnings while transforming CSS:", ...w1);
+      const warnings = ws.filter(
+        (w) => w.message !== "Unknown at rule: @apply"
+      );
+      if (warnings.length > 0) {
+        console.warn("[LCSS] Warnings while transforming CSS:", ...warnings);
       }
       const lcss = decoder.decode(code);
       try {
@@ -48,12 +52,12 @@ module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => {
       }
     }
     if (isProdBuild) {
-      const { styles: ccss, errors, warnings: w2 } = cleanCSS.minify(input);
+      const { styles: ccss, errors, warnings } = cleanCSS.minify(input);
       if (errors.length > 0) {
         console.error("[CCSS] Errors while transforming CSS:", ...errors);
       }
-      if (w2.length > 0) {
-        console.warn("[CCSS] Warnings while transforming CSS:", ...w2);
+      if (warnings.length > 0) {
+        console.warn("[CCSS] Warnings while transforming CSS:", ...warnings);
       }
       try {
         return unwrapCSS(ccss, type);

From 18ef4109607fe45c4dfce8a725669a3100ad78e0 Mon Sep 17 00:00:00 2001
From: Kendell R <KTibow@users.noreply.github.com>
Date: Fri, 13 Oct 2023 01:08:38 +0000
Subject: [PATCH 5/5] Don't mess up @apply

---
 build-scripts/lightningcss.cjs | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/build-scripts/lightningcss.cjs b/build-scripts/lightningcss.cjs
index 90f3a3011bee..a90828334713 100644
--- a/build-scripts/lightningcss.cjs
+++ b/build-scripts/lightningcss.cjs
@@ -29,7 +29,10 @@ module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => {
   return (text, type) => {
     if (!text) return text;
     const input = wrapCSS(text, type);
-    if (!text.includes("babel-plugin-template-html-minifier")) {
+    if (
+      !text.includes("babel-plugin-template-html-minifier") &&
+      !text.includes("@apply")
+    ) {
       const { code, warnings: ws } = transform({
         filename: "style.css",
         code: Buffer.from(input),