Repository: postcss/postcss-import (js)

Issue:
Support a way to process a URL with fragments
In Vite, we were resolving `@import '#foo'` with [subpath imports](https://nodejs.org/api/packages.html#subpath-imports). But since postcss 16.0.0 (https://github.com/postcss/postcss-import/pull/539), these URLs are filtered out before it reaches any code that the plugin user side can control. That made Vite not able to resolve these URLs (https://github.com/vitejs/vite/issues/15861).

Would it be possible to add an option to skip this default behavior?


Pull request description:
Allow urls that contain fragments, fixes #560
The intention behind ignoring urls with a fragment was to make the plugin more correct.
The thinking at the time was that these are never valid imports for a filesystem.
With nodejs subpath imports that assumption is incorrect.



Patch:
diff --git a/lib/parse-styles.js b/lib/parse-styles.js
index 68a1fef..9dd43d7 100644
--- a/lib/parse-styles.js
+++ b/lib/parse-styles.js
@@ -227,11 +227,6 @@ function isProcessableURL(uri) {
   try {
     // needs a base to parse properly
     const url = new URL(uri, "https://example.com")
-
-    if (url.hash) {
-      return false
-    }
-
     if (url.search) {
       return false
     }


Test patch:
diff --git a/test/fixtures/filter-ignore.css b/test/fixtures/filter-ignore.css
index 923d64d..f4099c8 100644
--- a/test/fixtures/filter-ignore.css
+++ b/test/fixtures/filter-ignore.css
@@ -13,5 +13,4 @@
 @import url('//css');
 @import url(//css);
 @import url('foo.css?query=string');
-@import url('foo.css#hash');
 content{}
diff --git a/test/fixtures/filter-ignore.expected.css b/test/fixtures/filter-ignore.expected.css
index 25ec93d..f16a2d7 100644
--- a/test/fixtures/filter-ignore.expected.css
+++ b/test/fixtures/filter-ignore.expected.css
@@ -14,7 +14,6 @@
 @import url('//css');
 @import url(//css);
 @import url('foo.css?query=string');
-@import url('foo.css#hash');
 @media (min-width: 25em){
 ignore{}
 }
diff --git a/test/fixtures/imports/modules/subpath/a.css b/test/fixtures/imports/modules/subpath/a.css
new file mode 100644
index 0000000..213d067
--- /dev/null
+++ b/test/fixtures/imports/modules/subpath/a.css
@@ -0,0 +1,3 @@
+.foo {
+  color: green;
+}
diff --git a/test/fixtures/imports/modules/subpath/package.json b/test/fixtures/imports/modules/subpath/package.json
new file mode 100644
index 0000000..42b36fb
--- /dev/null
+++ b/test/fixtures/imports/modules/subpath/package.json
@@ -0,0 +1,6 @@
+{
+  "style": "style.css",
+  "imports": {
+    "#a.css": "./a.css"
+  }
+}
diff --git a/test/fixtures/imports/modules/subpath/style.css b/test/fixtures/imports/modules/subpath/style.css
new file mode 100644
index 0000000..fbf0568
--- /dev/null
+++ b/test/fixtures/imports/modules/subpath/style.css
@@ -0,0 +1,1 @@
+@import '#a.css';
diff --git a/test/fixtures/subpath.css b/test/fixtures/subpath.css
new file mode 100644
index 0000000..c2cd8b6
--- /dev/null
+++ b/test/fixtures/subpath.css
@@ -0,0 +1,1 @@
+@import "subpath";
diff --git a/test/fixtures/subpath.expected.css b/test/fixtures/subpath.expected.css
new file mode 100644
index 0000000..213d067
--- /dev/null
+++ b/test/fixtures/subpath.expected.css
@@ -0,0 +1,3 @@
+.foo {
+  color: green;
+}
diff --git a/test/resolve.js b/test/resolve.js
index cde0638..53d475c 100644
--- a/test/resolve.js
+++ b/test/resolve.js
@@ -1,6 +1,8 @@
 "use strict"
 // external tooling
 const test = require("ava")
+const fs = require("fs")
+const path = require("path")
 
 // internal tooling
 const checkFixture = require("./helpers/check-fixture")
@@ -72,3 +74,24 @@ test(
   { path: null, addModulesDirectories: ["shared_modules"] },
   { from: "test/fixtures/imports/foo.css" },
 )
+
+test(
+  "should resolve modules with node subpath imports with a custom resolver",
+  checkFixture,
+  "subpath",
+  {
+    resolve: (id, basedir) => {
+      // see: https://nodejs.org/api/packages.html#subpath-imports
+      if (id.startsWith("#")) {
+        const pkgJSON = JSON.parse(
+          fs.readFileSync(path.join(basedir, "package.json")),
+        )
+
+        return path.join(basedir, pkgJSON.imports[id])
+      }
+
+      return id
+    },
+    path: "test/fixtures/imports/modules",
+  },
+)