Repository: tivac/modular-css
Pull request #811 (2022-02-13 07:02:46)

Ensure Regexes are escaped
<!--- Provide a general summary of your changes in the Title above -->

## Description
<!--- Describe your changes in detail -->
All `new Regexp(...)` use `escape-string-regexp` on any dynamic content within them.

## Motivation and Context
<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->
Not all `new Regexp(\`${value}\`)` were escaped, leading to issues with searching for things like `$lib`.

## How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->
Added some tests, also ran website locally and saw it working.

## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [x] My code follows the code style of this project.
- [x] My change requires a change to the documentation.
- [x] I have updated the documentation accordingly.
- [x] I have read the **CONTRIBUTING** document.
- [x] I have added tests to cover my changes.
- [x] All new and existing tests passed.



Patch:
diff --git a/package-lock.json b/package-lock.json
index 6f93864d..ba7a4a57 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -631,37 +631,6 @@
         "w3c-keyname": "^2.2.4"
       }
     },
-    "node_modules/@esbuild-plugins/node-globals-polyfill": {
-      "version": "0.1.1",
-      "dev": true,
-      "license": "ISC",
-      "peerDependencies": {
-        "esbuild": "*"
-      }
-    },
-    "node_modules/@esbuild-plugins/node-modules-polyfill": {
-      "version": "0.1.4",
-      "dev": true,
-      "license": "ISC",
-      "dependencies": {
-        "escape-string-regexp": "^4.0.0",
-        "rollup-plugin-node-polyfills": "^0.2.1"
-      },
-      "peerDependencies": {
-        "esbuild": "*"
-      }
-    },
-    "node_modules/@esbuild-plugins/node-modules-polyfill/node_modules/escape-string-regexp": {
-      "version": "4.0.0",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
     "node_modules/@eslint/eslintrc": {
       "version": "1.0.5",
       "dev": true,
@@ -3154,6 +3123,12 @@
         "@octokit/openapi-types": "^8.1.3"
       }
     },
+    "node_modules/@polka/url": {
+      "version": "1.0.0-next.21",
+      "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz",
+      "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==",
+      "dev": true
+    },
     "node_modules/@rollup/plugin-commonjs": {
       "version": "21.0.1",
       "dev": true,
@@ -11510,6 +11485,12 @@
         "node": ">=6"
       }
     },
+    "node_modules/kolorist": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.5.1.tgz",
+      "integrity": "sha512-lxpCM3HTvquGxKGzHeknB/sUjuVoUElLlfYnXZT73K8geR9jQbroGlSCFBax9/0mpGoD3kzcMLnOlGQPJJNyqQ==",
+      "dev": true
+    },
     "node_modules/labeled-stream-splicer": {
       "version": "2.0.2",
       "dev": true,
@@ -13257,6 +13238,15 @@
         "node": ">=4"
       }
     },
+    "node_modules/mrmime": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz",
+      "integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/ms": {
       "version": "2.1.2",
       "dev": true,
@@ -16219,24 +16209,6 @@
         "node": ">=0.12"
       }
     },
-    "node_modules/rollup-plugin-inject": {
-      "version": "3.0.2",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "estree-walker": "^0.6.1",
-        "magic-string": "^0.25.3",
-        "rollup-pluginutils": "^2.8.1"
-      }
-    },
-    "node_modules/rollup-plugin-node-polyfills": {
-      "version": "0.2.1",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "rollup-plugin-inject": "^3.0.0"
-      }
-    },
     "node_modules/rollup-plugin-polyfill-node": {
       "version": "0.8.0",
       "dev": true,
@@ -16522,6 +16494,20 @@
         "readable-stream": "^2.0.0"
       }
     },
+    "node_modules/sirv": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.2.tgz",
+      "integrity": "sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==",
+      "dev": true,
+      "dependencies": {
+        "@polka/url": "^1.0.0-next.20",
+        "mrmime": "^1.0.0",
+        "totalist": "^3.0.0"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
     "node_modules/sisteransi": {
       "version": "1.0.5",
       "dev": true,
@@ -17647,6 +17633,15 @@
         "node": ">=4"
       }
     },
+    "node_modules/totalist": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.0.tgz",
+      "integrity": "sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/tough-cookie": {
       "version": "4.0.0",
       "dev": true,
@@ -17802,6 +17797,12 @@
         "node": ">=4.2.0"
       }
     },
+    "node_modules/ufo": {
+      "version": "0.7.10",
+      "resolved": "https://registry.npmjs.org/ufo/-/ufo-0.7.10.tgz",
+      "integrity": "sha512-YTnDRlE1cIofRqOFN8ioAbz9qenDvkgVMSn0cnxvIDjM9sfEOMKB0ybMr+otSlCXMfQ/X35haYRoI7Nua82RrA==",
+      "dev": true
+    },
     "node_modules/uglify-js": {
       "version": "3.13.10",
       "dev": true,
@@ -18331,6 +18332,47 @@
         }
       }
     },
+    "node_modules/vite-plugin-inspect": {
+      "version": "0.3.14",
+      "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-0.3.14.tgz",
+      "integrity": "sha512-oRjltmm1nUgkHmlGLgfSAuPiXA/FqC7daURJ+faY498r3mwnXrtcfe6Bg5khANQ0iss9Cn1uV6+W9c85noVq0g==",
+      "dev": true,
+      "dependencies": {
+        "@rollup/pluginutils": "^4.1.2",
+        "debug": "^4.3.3",
+        "kolorist": "^1.5.1",
+        "sirv": "^2.0.0",
+        "ufo": "^0.7.9"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "vite": "^2.0.0"
+      }
+    },
+    "node_modules/vite-plugin-inspect/node_modules/@rollup/pluginutils": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.2.tgz",
+      "integrity": "sha512-ROn4qvkxP9SyPeHaf7uQC/GPFY6L/OWy9+bd9AwcjOAWQwxRscoEyAUD8qCY5o5iL4jqQwoLk2kaTKJPb/HwzQ==",
+      "dev": true,
+      "dependencies": {
+        "estree-walker": "^2.0.1",
+        "picomatch": "^2.2.2"
+      },
+      "engines": {
+        "node": ">= 8.0.0"
+      }
+    },
+    "node_modules/vite-plugin-inspect/node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+      "dev": true
+    },
     "node_modules/vm-browserify": {
       "version": "1.1.2",
       "dev": true,
@@ -19198,9 +19240,21 @@
       "version": "27.1.0",
       "license": "MIT",
       "dependencies": {
+        "escape-string-regexp": "^4.0.0",
         "resolve-from": "^5.0.0"
       }
     },
+    "packages/aliases/node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "packages/browserify": {
       "name": "@modular-css/browserify",
       "version": "27.1.0",
@@ -19531,7 +19585,7 @@
     },
     "packages/vite": {
       "name": "@modular-css/vite",
-      "version": "27.1.0",
+      "version": "27.1.1",
       "license": "MIT",
       "dependencies": {
         "@modular-css/css-to-js": "file:../css-to-js",
@@ -19610,13 +19664,12 @@
     },
     "packages/www": {
       "name": "@modular-css/www",
-      "version": "27.1.0",
+      "version": "27.1.1",
       "license": "MIT",
       "devDependencies": {
         "@codemirror/state": "^0.19.6",
         "@codemirror/view": "^0.19.40",
-        "@esbuild-plugins/node-globals-polyfill": "^0.1.1",
-        "@esbuild-plugins/node-modules-polyfill": "^0.1.4",
+        "@modular-css/path-aliases": "file:../aliases",
         "@modular-css/processor": "file:../processor",
         "@modular-css/svelte": "file:../svelte",
         "@modular-css/vite": "file:../vite",
@@ -19642,7 +19695,8 @@
         "to-vfile": "^7.2.3",
         "unified": "^10.1.1",
         "unist-builder": "^3.0.0",
-        "unist-util-visit": "^4.1.0"
+        "unist-util-visit": "^4.1.0",
+        "vite-plugin-inspect": "^0.3.14"
       }
     }
   },
@@ -20044,25 +20098,6 @@
         "w3c-keyname": "^2.2.4"
       }
     },
-    "@esbuild-plugins/node-globals-polyfill": {
-      "version": "0.1.1",
-      "dev": true,
-      "requires": {}
-    },
-    "@esbuild-plugins/node-modules-polyfill": {
-      "version": "0.1.4",
-      "dev": true,
-      "requires": {
-        "escape-string-regexp": "^4.0.0",
-        "rollup-plugin-node-polyfills": "^0.2.1"
-      },
-      "dependencies": {
-        "escape-string-regexp": {
-          "version": "4.0.0",
-          "dev": true
-        }
-      }
-    },
     "@eslint/eslintrc": {
       "version": "1.0.5",
       "dev": true,
@@ -21555,7 +21590,15 @@
     "@modular-css/path-aliases": {
       "version": "file:packages/aliases",
       "requires": {
+        "escape-string-regexp": "^4.0.0",
         "resolve-from": "^5.0.0"
+      },
+      "dependencies": {
+        "escape-string-regexp": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+          "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
+        }
       }
     },
     "@modular-css/path-resolver": {
@@ -21743,8 +21786,7 @@
       "requires": {
         "@codemirror/state": "^0.19.6",
         "@codemirror/view": "^0.19.40",
-        "@esbuild-plugins/node-globals-polyfill": "^0.1.1",
-        "@esbuild-plugins/node-modules-polyfill": "^0.1.4",
+        "@modular-css/path-aliases": "file:../aliases",
         "@modular-css/processor": "file:../processor",
         "@modular-css/svelte": "file:../svelte",
         "@modular-css/vite": "file:../vite",
@@ -21770,7 +21812,8 @@
         "to-vfile": "^7.2.3",
         "unified": "^10.1.1",
         "unist-builder": "^3.0.0",
-        "unist-util-visit": "^4.1.0"
+        "unist-util-visit": "^4.1.0",
+        "vite-plugin-inspect": "*"
       }
     },
     "@nodelib/fs.scandir": {
@@ -22072,6 +22115,12 @@
         "@octokit/openapi-types": "^8.1.3"
       }
     },
+    "@polka/url": {
+      "version": "1.0.0-next.21",
+      "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz",
+      "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==",
+      "dev": true
+    },
     "@rollup/plugin-commonjs": {
       "version": "21.0.1",
       "dev": true,
@@ -27805,6 +27854,12 @@
       "version": "3.0.3",
       "dev": true
     },
+    "kolorist": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.5.1.tgz",
+      "integrity": "sha512-lxpCM3HTvquGxKGzHeknB/sUjuVoUElLlfYnXZT73K8geR9jQbroGlSCFBax9/0mpGoD3kzcMLnOlGQPJJNyqQ==",
+      "dev": true
+    },
     "labeled-stream-splicer": {
       "version": "2.0.2",
       "dev": true,
@@ -28934,6 +28989,12 @@
       "version": "1.2.0",
       "dev": true
     },
+    "mrmime": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz",
+      "integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==",
+      "dev": true
+    },
     "ms": {
       "version": "2.1.2",
       "dev": true
@@ -30914,22 +30975,6 @@
       "version": "2.1.1",
       "dev": true
     },
-    "rollup-plugin-inject": {
-      "version": "3.0.2",
-      "dev": true,
-      "requires": {
-        "estree-walker": "^0.6.1",
-        "magic-string": "^0.25.3",
-        "rollup-pluginutils": "^2.8.1"
-      }
-    },
-    "rollup-plugin-node-polyfills": {
-      "version": "0.2.1",
-      "dev": true,
-      "requires": {
-        "rollup-plugin-inject": "^3.0.0"
-      }
-    },
     "rollup-plugin-polyfill-node": {
       "version": "0.8.0",
       "dev": true,
@@ -31130,6 +31175,17 @@
         "readable-stream": "^2.0.0"
       }
     },
+    "sirv": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.2.tgz",
+      "integrity": "sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==",
+      "dev": true,
+      "requires": {
+        "@polka/url": "^1.0.0-next.20",
+        "mrmime": "^1.0.0",
+        "totalist": "^3.0.0"
+      }
+    },
     "sisteransi": {
       "version": "1.0.5",
       "dev": true
@@ -31891,6 +31947,12 @@
         }
       }
     },
+    "totalist": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.0.tgz",
+      "integrity": "sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==",
+      "dev": true
+    },
     "tough-cookie": {
       "version": "4.0.0",
       "dev": true,
@@ -31985,6 +32047,12 @@
       "dev": true,
       "peer": true
     },
+    "ufo": {
+      "version": "0.7.10",
+      "resolved": "https://registry.npmjs.org/ufo/-/ufo-0.7.10.tgz",
+      "integrity": "sha512-YTnDRlE1cIofRqOFN8ioAbz9qenDvkgVMSn0cnxvIDjM9sfEOMKB0ybMr+otSlCXMfQ/X35haYRoI7Nua82RrA==",
+      "dev": true
+    },
     "uglify-js": {
       "version": "3.13.10",
       "dev": true,
@@ -32309,6 +32377,37 @@
         "rollup": "^2.59.0"
       }
     },
+    "vite-plugin-inspect": {
+      "version": "0.3.14",
+      "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-0.3.14.tgz",
+      "integrity": "sha512-oRjltmm1nUgkHmlGLgfSAuPiXA/FqC7daURJ+faY498r3mwnXrtcfe6Bg5khANQ0iss9Cn1uV6+W9c85noVq0g==",
+      "dev": true,
+      "requires": {
+        "@rollup/pluginutils": "^4.1.2",
+        "debug": "^4.3.3",
+        "kolorist": "^1.5.1",
+        "sirv": "^2.0.0",
+        "ufo": "^0.7.9"
+      },
+      "dependencies": {
+        "@rollup/pluginutils": {
+          "version": "4.1.2",
+          "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.2.tgz",
+          "integrity": "sha512-ROn4qvkxP9SyPeHaf7uQC/GPFY6L/OWy9+bd9AwcjOAWQwxRscoEyAUD8qCY5o5iL4jqQwoLk2kaTKJPb/HwzQ==",
+          "dev": true,
+          "requires": {
+            "estree-walker": "^2.0.1",
+            "picomatch": "^2.2.2"
+          }
+        },
+        "estree-walker": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+          "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+          "dev": true
+        }
+      }
+    },
     "vm-browserify": {
       "version": "1.1.2",
       "dev": true
diff --git a/packages/aliases/aliases.js b/packages/aliases/aliases.js
index eac3f8a1..f4979628 100644
--- a/packages/aliases/aliases.js
+++ b/packages/aliases/aliases.js
@@ -1,17 +1,18 @@
 "use strict";
 
 const from = require("resolve-from");
+const escape = require("escape-string-regexp");
 
-module.exports = (args) => {
+module.exports = (opts) => {
     const options = {
         __proto__ : null,
         aliases   : {},
-        ...args,
+        ...opts,
     };
 
     const aliases = Object.keys(options.aliases).map((alias) => ({
         name   : alias,
-        search : new RegExp(`^${alias}\\b`),
+        search : new RegExp(`^${escape(alias)}\\b`),
     }));
 
     return (src, file) => {
diff --git a/packages/aliases/package.json b/packages/aliases/package.json
index 2b970d2c..e4d27e7c 100644
--- a/packages/aliases/package.json
+++ b/packages/aliases/package.json
@@ -25,6 +25,7 @@
     "aliases"
   ],
   "dependencies": {
-    "resolve-from": "^5.0.0"
+    "resolve-from": "^5.0.0",
+    "escape-string-regexp": "^4.0.0"
   }
 }
diff --git a/packages/svelte/replacer.js b/packages/svelte/replacer.js
index b701631a..fc40c5a7 100644
--- a/packages/svelte/replacer.js
+++ b/packages/svelte/replacer.js
@@ -1,13 +1,16 @@
 "use strict";
 
+const escape = require("escape-string-regexp");
+
 module.exports = (source, { identifier, lookup, keys }) => {
-    const ids = keys.join("|");
+    const ids = keys.map(escape).join("|");
+    const ident = escape(identifier);
 
     return source
         // Replace {<identifier>.<key>} values
         // Note extra exclusion to avoid accidentally matching ${<identifier>.<key>}
         .replace(
-            new RegExp(`([^$]){${identifier}\\.(${ids})}`, "gm"),
+            new RegExp(`([^$]){${ident}\\.(${ids})}`, "gm"),
             (match, before, key) => {
                 const replacement = lookup[key];
 
@@ -17,7 +20,7 @@ module.exports = (source, { identifier, lookup, keys }) => {
 
         // Then any remaining <identifier>.<key> values
         .replace(
-            new RegExp(`(\\b)${identifier}\\.(${ids})(\\b)`, "gm"),
+            new RegExp(`(\\b)${ident}\\.(${ids})(\\b)`, "gm"),
             (match, before, key, suffix) => {
                 const replacement = lookup[key];
 
diff --git a/packages/svelte/svelte.js b/packages/svelte/svelte.js
index 64d40b34..9424d36f 100644
--- a/packages/svelte/svelte.js
+++ b/packages/svelte/svelte.js
@@ -229,7 +229,7 @@ module.exports = (opts = {}) => {
             log("updating source {css.<key>} references from", css);
             log(JSON.stringify(classKeys));
             
-            const selectors = [ ...classKeys, ...valueKeys ].join("|");
+            const selectors = [ ...classKeys, ...valueKeys ].map(escape).join("|");
 
             // Look for instances of class={css.foo} to warn about
             const matches = source.match(new RegExp(`class={css\\.(?:${selectors})}`, "g"));
diff --git a/packages/www/build/md/remark-import.js b/packages/www/build/md/remark-import.js
index 387d50db..566bfee1 100644
--- a/packages/www/build/md/remark-import.js
+++ b/packages/www/build/md/remark-import.js
@@ -5,10 +5,12 @@ import remarkParse from "remark-parse";
 import { visit, SKIP, CONTINUE } from "unist-util-visit";
 import { readSync } from "to-vfile";
 
-const remarkImport = () => {
+const remarkImport = (options = false) => {
     // TODO: this may need to be configurable some day
     const parser = unified().use(remarkParse);
 
+    const { imported } = options;
+
     const plugin = (tree, file) => {
         // Need history length to resolve files, if it doesn't exist we bail
         if(!file.history.length) {
@@ -33,6 +35,10 @@ const remarkImport = () => {
 
             const target = path.resolve(dir, name);
 
+            if(imported) {
+                imported(target);
+            }
+
             const md = readSync(target);
 
             const ast = parser.parse(md);
diff --git a/packages/www/package.json b/packages/www/package.json
index df36e31c..d243ccec 100644
--- a/packages/www/package.json
+++ b/packages/www/package.json
@@ -27,6 +27,7 @@
   "devDependencies": {
     "@codemirror/state": "^0.19.6",
     "@codemirror/view": "^0.19.40",
+    "@modular-css/path-aliases": "file:../aliases",
     "@modular-css/processor": "file:../processor",
     "@modular-css/svelte": "file:../svelte",
     "@modular-css/vite": "file:../vite",
@@ -52,6 +53,7 @@
     "to-vfile": "^7.2.3",
     "unified": "^10.1.1",
     "unist-builder": "^3.0.0",
-    "unist-util-visit": "^4.1.0"
+    "unist-util-visit": "^4.1.0",
+    "vite-plugin-inspect": "^0.3.14"
   }
 }
diff --git a/packages/www/src/routes/_layout/site.mcss b/packages/www/src/lib/site.mcss
similarity index 100%
rename from packages/www/src/routes/_layout/site.mcss
rename to packages/www/src/lib/site.mcss
diff --git a/packages/www/src/routes/_home/home.mcss b/packages/www/src/routes/_home/home.mcss
index 30ad70ba..57670b3c 100644
--- a/packages/www/src/routes/_home/home.mcss
+++ b/packages/www/src/routes/_home/home.mcss
@@ -1,5 +1,4 @@
-@value site: "../_layout/site.mcss";
-@value * as main from site;
+@value * as main from "$lib/site.mcss";
 
 .home {
     width: 90vw;
@@ -61,7 +60,7 @@
 }
 
 .learn {
-    composes: center from site;
+    composes: center from "$lib/site.mcss";
 
     margin-top: 1rem;
 }
@@ -71,7 +70,7 @@
 
 .cta,
 .cta:visited {
-    composes: center from site;
+    composes: center from "$lib/site.mcss";
 
     margin-top: 2rem;
 
diff --git a/packages/www/src/routes/_layout/header.mcss b/packages/www/src/routes/_layout/header.mcss
index db8a1156..94ddcbf7 100644
--- a/packages/www/src/routes/_layout/header.mcss
+++ b/packages/www/src/routes/_layout/header.mcss
@@ -1,5 +1,5 @@
-@value * as site from "./site.mcss";
-@value bigSize from "./site.mcss";
+@value * as site from "$lib/site.mcss";
+@value bigSize from "$lib/site.mcss";
 
 .header {
     composes: header from "./layout.mcss";
diff --git a/packages/www/src/routes/_layout/layout.mcss b/packages/www/src/routes/_layout/layout.mcss
index fde70ae7..99e5720d 100644
--- a/packages/www/src/routes/_layout/layout.mcss
+++ b/packages/www/src/routes/_layout/layout.mcss
@@ -1,4 +1,4 @@
-@value bigSize from "./site.mcss";
+@value bigSize from "$lib/site.mcss";
 
 .page {
     width: 100vw;
diff --git a/packages/www/src/routes/api/_content/api.md b/packages/www/src/routes/api/_content/api.md
index 9dca81f5..f63ccae7 100644
--- a/packages/www/src/routes/api/_content/api.md
+++ b/packages/www/src/routes/api/_content/api.md
@@ -2,5 +2,6 @@
 
 @import "./usage.md"
 
-@import "./extending.md"
+@import "./utilities.md"
 
+@import "./extending.md"
diff --git a/packages/www/src/routes/api/_content/extending.md b/packages/www/src/routes/api/_content/extending.md
index ba0e1575..d213007e 100644
--- a/packages/www/src/routes/api/_content/extending.md
+++ b/packages/www/src/routes/api/_content/extending.md
@@ -1,6 +1,6 @@
-## Extending
+## Lifecycle Hooks
 
-There are 4 built-in ways to extend the functionality of `modular-css`, the lifecycle hooks. They all can be used to add any number of [PostCSS Plugins](https://github.com/postcss/postcss/blob/main/docs/plugins.md) to `modular-css` at specific points in the processing cycle.
+There are 4 built-in ways to extend the functionality of `modular-css`, the **lifecycle hooks**. They all can be used to add any number of [PostCSS Plugins](https://github.com/postcss/postcss/blob/main/docs/plugins.md) to `modular-css` at specific points in the processing cycle.
 
 @import "./extending-before.md"
 
diff --git a/packages/www/src/routes/api/_content/usage-browserify.md b/packages/www/src/routes/api/_content/usage-browserify.md
index b77673e1..4a83be6a 100644
--- a/packages/www/src/routes/api/_content/usage-browserify.md
+++ b/packages/www/src/routes/api/_content/usage-browserify.md
@@ -1,6 +1,6 @@
 ### browserify
 
-Browserify support for [`modular-css`](https://github.com/tivac/modular-css).
+Browserify support for `modular-css` via `@modular-css/browserify` package.
 
 This plugin can be combined with the `factor-bundle` plugin to output a common CSS file as well as bundle-specific CSS files.
 
@@ -9,7 +9,7 @@ This plugin can be combined with the `factor-bundle` plugin to output a common C
 #### browserify Install
 
 ```shell
-$ npm i @modular-css/browserify
+$ npm i @modular-css/browserify --save-dev
 ```
 
 #### browserify Usage
diff --git a/packages/www/src/routes/api/_content/usage-cli.md b/packages/www/src/routes/api/_content/usage-cli.md
index ec34c7d9..b4e5d534 100644
--- a/packages/www/src/routes/api/_content/usage-cli.md
+++ b/packages/www/src/routes/api/_content/usage-cli.md
@@ -1,4 +1,4 @@
-## CLI
+### CLI
 
 CLI interface to [`modular-css`](https://github.com/tivac/modular-css).
 
diff --git a/packages/www/src/routes/api/_content/usage-glob-api.md b/packages/www/src/routes/api/_content/usage-glob-api.md
index 2cc6bf23..e8ba89b8 100644
--- a/packages/www/src/routes/api/_content/usage-glob-api.md
+++ b/packages/www/src/routes/api/_content/usage-glob-api.md
@@ -1,4 +1,4 @@
-### glob API
+### globbing API
 
 A JS API for using glob patterns with [`modular-css`](https://github.com/tivac/modular-css).
 
diff --git a/packages/www/src/routes/api/_content/usage-rollup.md b/packages/www/src/routes/api/_content/usage-rollup.md
index 6d8876db..e910a738 100644
--- a/packages/www/src/routes/api/_content/usage-rollup.md
+++ b/packages/www/src/routes/api/_content/usage-rollup.md
@@ -1,11 +1,11 @@
 ### rollup
 
-Rollup support for [`modular-css`](https://github.com/tivac/modular-css).
+Rollup support for modular-css is provided by the `@modular-css/rollup package`.
 
 #### rollup Install
 
 ```shell
-> npm i @modular-css/rollup
+> npm i @modular-css/rollup --save-dev
 ```
 
 #### rollup Usage
diff --git a/packages/www/src/routes/api/_content/usage-vite.md b/packages/www/src/routes/api/_content/usage-vite.md
index bddc87d8..4395a3b0 100644
--- a/packages/www/src/routes/api/_content/usage-vite.md
+++ b/packages/www/src/routes/api/_content/usage-vite.md
@@ -1,11 +1,11 @@
 ### vite
 
-Vite support for [`modular-css`](https://github.com/tivac/modular-css).
+Vite support for modular-css is provided by `@modular-css/vite`.
 
 #### vite Install
 
 ```shell
-> npm i @modular-css/vite
+> npm i @modular-css/vite --save-dev
 ```
 
 #### vite Usage
diff --git a/packages/www/src/routes/api/_content/usage-webpack.md b/packages/www/src/routes/api/_content/usage-webpack.md
index 277d139f..bd4eeb64 100644
--- a/packages/www/src/routes/api/_content/usage-webpack.md
+++ b/packages/www/src/routes/api/_content/usage-webpack.md
@@ -1,6 +1,6 @@
 ### webpack
 
-Webpack 2/3/4 support for [`modular-css`](https://github.com/tivac/modular-css).
+Webpack 2/3/4 support for modular-css is provided by `@modular-css/webpack`.
 
 This package contains two entry points, you will need to use **both** in tandem for things to work!
 
@@ -11,7 +11,7 @@ This package contains two entry points, you will need to use **both** in tandem
 #### webpack Install
 
 ```shell
-> npm i @modular-css/webpack
+> npm i @modular-css/webpack --save-dev
 ```
 
 #### Usage
diff --git a/packages/www/src/routes/api/_content/usage.md b/packages/www/src/routes/api/_content/usage.md
index 25e96178..1e1b8c52 100644
--- a/packages/www/src/routes/api/_content/usage.md
+++ b/packages/www/src/routes/api/_content/usage.md
@@ -10,20 +10,16 @@ You can use `modular-css` a variety of ways. The easiest is with one of the bund
 
 @import "./usage-browserify.md"
 
-## API
+## Direct Usage
 
 @import "./usage-js.md"
 
 @import "./usage-glob-api.md"
 
-<!-- No header -->
-
 @import "./usage-cli.md"
 
-## Other Integrations
+## Other Tools
 
 @import "./usage-svelte.md"
 
 @import "./usage-postcss.md"
-
-
diff --git a/packages/www/src/routes/api/_content/utilities-aliases.md b/packages/www/src/routes/api/_content/utilities-aliases.md
new file mode 100644
index 00000000..fa2745dd
--- /dev/null
+++ b/packages/www/src/routes/api/_content/utilities-aliases.md
@@ -0,0 +1,49 @@
+### Path Aliasing
+
+A resolver for modular-css that will let you resolve file references against named aliases. Useful to avoid code like
+
+```
+@value foo from "../../../../../../../../some/other/directory/file.css";
+```
+
+which is annoying to write, annoying to read, and also super-brittle.
+
+#### Install
+
+`$ npm i @modular-css/path-aliases --save-dev`
+
+#### Usage
+
+Pass as part of the `resolvers` array in the `modular-css` options (via JS API/Rollup/Browserify/WebPack/etc). When `modular-css` is trying to resolve `@value` or `composes` file references it'll replace the alias keys with their path value for file lookups.
+
+```js
+import  Processor from "@modular-css/processor";
+import aliases from "@modular-css/path-aliases";
+
+const processor = new Processor({
+    resolvers : [
+        aliases({
+            aliases : {
+                one  : "./path/one",
+                path : "../../some/other/path"
+            }
+        })
+    ]
+});
+```
+
+which allows you to write CSS like this.
+
+```css
+@value one from "one/one.css";
+
+.a {
+    composes: path from "path/path.css";
+}
+```
+
+#### Options
+
+##### `aliases`
+
+A `object` consisting of key/value pairs of alias names to file paths. Paths can be relative to the `cwd` of the `Processor` instance or absolute paths.
diff --git a/packages/www/src/routes/api/_content/utilities-namer.md b/packages/www/src/routes/api/_content/utilities-namer.md
new file mode 100644
index 00000000..93919853
--- /dev/null
+++ b/packages/www/src/routes/api/_content/utilities-namer.md
@@ -0,0 +1,70 @@
+### Namer
+
+Tiny classnames for [`modular-css`](https://github.com/tivac/modular-css) production builds!
+
+#### Install
+
+```bash
+> npm install @modular-css/shortnames
+```
+
+#### Usage
+
+##### JS API
+
+```js
+const Processor = require("@modular-css/processor");
+const processor = new Processor({
+    namer : require("@modular-css/shortnames")()
+});
+    
+// ...
+```
+
+##### Browserify
+
+```js
+build.plugin("@modular-css/browserify", {
+    css   : "./style.css",
+    namer : require("@modular-css/shortnames")()
+});
+
+// ...
+```
+
+##### Rollup
+
+```js
+rollup({
+    entry   : "./index.js",
+    plugins : [
+        require("@modular-css/rollup")({
+            css   : "./gen/index.css",
+            namer : require("@modular-css/shortnames")()
+        })
+    ]
+});
+```
+
+#### Example output
+
+```css
+/* one.css */
+.alert {}
+.notification {}
+
+/* two.css */
+.title {}
+.heading .subheading {}
+```
+
+becomes
+
+```css
+/* output.css */
+.AA {}
+.AB {}
+
+.BA {}
+.BB .BC {}
+```
diff --git a/packages/www/src/routes/api/_content/utilities-paths.md b/packages/www/src/routes/api/_content/utilities-paths.md
new file mode 100644
index 00000000..f7c835af
--- /dev/null
+++ b/packages/www/src/routes/api/_content/utilities-paths.md
@@ -0,0 +1,39 @@
+### Path resolver
+
+A resolver for [`modular-css`](https://github.com/tivac/modular-css) that will let you resolve file references against arbitrary paths. Useful to avoid code like
+
+```
+@value foo from "../../../../../../../../some/other/directory/file.css";
+```
+
+which is annoying to write, annoying to read, and also super-brittle.
+
+#### Install
+
+`$ npm i @modular-css/path-resolver`
+
+#### Usage
+
+Pass as part of the `resolvers` array in the `modular-css` options (via JS API/Rollup/Browserify/WebPack/etc). When `modular-css` is trying to resolve `@value` or `composes` file references it'll use the default node resolution algorithm against whichever paths you specified.
+
+```js
+const Processor = require("@modular-css/processor");
+const paths     = require("@modular-css/path-resolver");
+
+const processor = new Processor({
+    resolvers : [
+        paths({
+            paths : [
+                "./path/one",
+                "../../some/other/path"
+            ]
+        })
+    ]
+});
+```
+
+#### Options
+
+##### `paths`
+
+An array of string file paths, they can be relative to the `cwd` of the `Processor` instance or absolute paths.
diff --git a/packages/www/src/routes/api/_content/utilities.md b/packages/www/src/routes/api/_content/utilities.md
new file mode 100644
index 00000000..4dc46513
--- /dev/null
+++ b/packages/www/src/routes/api/_content/utilities.md
@@ -0,0 +1,7 @@
+## Other Utilities
+
+@import "./utilities-aliases.md"
+
+@import "./utilities-namer.md"
+
+@import "./utilities-paths.md"
\ No newline at end of file
diff --git a/packages/www/src/routes/repl/_repl.mcss b/packages/www/src/routes/repl/_repl.mcss
index a4b509a6..6c6bcd2d 100644
--- a/packages/www/src/routes/repl/_repl.mcss
+++ b/packages/www/src/routes/repl/_repl.mcss
@@ -1,5 +1,5 @@
-@value borderColor from "../_layout/site.mcss";
-@value bigSize from "../_layout/site.mcss";
+@value borderColor from "$lib/site.mcss";
+@value bigSize from "$lib/site.mcss";
 
 @value tabHeight: 2.5rem;
 
diff --git a/packages/www/src/routes/repl/_tabs.mcss b/packages/www/src/routes/repl/_tabs.mcss
index 5c2cdabb..274190d2 100644
--- a/packages/www/src/routes/repl/_tabs.mcss
+++ b/packages/www/src/routes/repl/_tabs.mcss
@@ -1,4 +1,4 @@
-@value site: "../_layout/site.mcss";
+@value site: "$lib/site.mcss";
 
 @value hoverInTime from site;
 
diff --git a/packages/www/svelte.config.js b/packages/www/svelte.config.js
index d60887b5..341435e2 100644
--- a/packages/www/svelte.config.js
+++ b/packages/www/svelte.config.js
@@ -1,8 +1,11 @@
 import path from "path";
 
 import staticAdapter from "@sveltejs/adapter-static";
+import vitePluginInspector from "vite-plugin-inspect";
+
 import preprocessor from "@modular-css/svelte";
 import mcss from "@modular-css/vite";
+import aliases from "@modular-css/path-aliases";
 import postcssNested from "postcss-nested";
 
 import viteMd from "./build/vite-md.js";
@@ -18,6 +21,18 @@ const { preprocess, processor } = preprocessor({
     // they don't make nice JS identifiers usually, so disabled
     exportGlobals : false,
 
+    // Enable for debugging, but disabled because NOISY
+    verbose : false,
+
+    // Bring sveltekit aliases into m-css
+    resolvers : [
+        aliases({
+            aliases : {
+                $lib : "./src/lib",
+            },
+        }),
+    ],
+    
     // I like nesting, so sue me
     before : [
         postcssNested(),
@@ -39,6 +54,9 @@ const config = {
 
         vite : {
             plugins : [
+                // Vite plugin inspector
+                vitePluginInspector(),
+
                 // Bundle @modular-css/processor and its dependencies via
                 // embedded rollup within rollup because vite doesn't handle
                 // cjs modules and node globals very well


Test patch:
diff --git a/packages/aliases/test/aliases.test.js b/packages/aliases/test/aliases.test.js
index 1aa62218..9d68e7db 100644
--- a/packages/aliases/test/aliases.test.js
+++ b/packages/aliases/test/aliases.test.js
@@ -28,6 +28,16 @@ describe("@modular-css/path-aliases", () => {
         expect(fn(".", "one/one.css")).toBe(require.resolve("./specimens/one/one.css"));
     });
 
+    it("should allow regex characters in keys", () => {
+        const fn = aliases({
+            aliases : {
+                $one : "./packages/aliases/test/specimens/one",
+            },
+        });
+
+        expect(fn(".", "$one/one.css")).toBe(require.resolve("./specimens/one/one.css"));
+    });
+
     it("should check multiple aliases for files & return the first match", () => {
         const fn = aliases({
             aliases : {