@@ -33,16 +33,20 @@ import { isAboveV3 } from "./utils/versions.js";
3333import { resolveModuleEntry } from "./utils/resolve-module-entry.js" ;
3434
3535/**
36- * Resolve plugin paths to file:// URLs that Prettier can import .
36+ * Resolve plugin paths for Prettier.
3737 * Matches Prettier CLI behavior:
3838 * - URLs pass through
39- * - Absolute paths → file:// URL
40- * - Relative paths (./plugin.js) → resolved relative to file, file:// URL
39+ * - Absolute paths → kept as-is or converted to file:// URL (for v3)
40+ * - Relative paths (./plugin.js) → resolved relative to file
4141 * - Package names → resolved from file's directory via createRequire
42+ *
43+ * @param useFileUrls - If true, converts paths to file:// URLs (needed for Prettier v3+ ESM import)
44+ * If false, returns absolute paths (for Prettier v2 require())
4245 */
4346async function resolvePluginPaths (
4447 plugins : ( string | PrettierPlugin ) [ ] | undefined ,
4548 fileName : string ,
49+ useFileUrls : boolean ,
4650) : Promise < ( string | PrettierPlugin ) [ ] > {
4751 if ( ! plugins ) {
4852 return [ ] ;
@@ -64,22 +68,25 @@ async function resolvePluginPaths(
6468 continue ;
6569 }
6670
67- // Absolute paths → file:// URL
71+ // Absolute paths
6872 if ( path . isAbsolute ( plugin ) ) {
69- resolvedPlugins . push ( pathToFileURL ( plugin ) . href ) ;
73+ resolvedPlugins . push (
74+ useFileUrls ? pathToFileURL ( plugin ) . href : plugin ,
75+ ) ;
7076 continue ;
7177 }
7278
7379 // Relative paths (./foo or ../foo) → resolve relative to file
7480 if ( plugin . startsWith ( "." ) ) {
75- resolvedPlugins . push ( pathToFileURL ( path . resolve ( dir , plugin ) ) . href ) ;
81+ const resolved = path . resolve ( dir , plugin ) ;
82+ resolvedPlugins . push ( useFileUrls ? pathToFileURL ( resolved ) . href : resolved ) ;
7683 continue ;
7784 }
7885
7986 // Package names → resolve from file's directory using createRequire
8087 try {
8188 const resolved = resolveModuleEntry ( dir , plugin ) ;
82- resolvedPlugins . push ( pathToFileURL ( resolved ) . href ) ;
89+ resolvedPlugins . push ( useFileUrls ? pathToFileURL ( resolved ) . href : resolved ) ;
8390 } catch {
8491 // If resolution fails, pass through and let Prettier handle/report the error
8592 resolvedPlugins . push ( plugin ) ;
@@ -351,9 +358,11 @@ export default class PrettierEditService implements Disposable {
351358 this . statusBar . update ( FormatterStatus . Disabled ) ;
352359 } else if ( resolvedConfig ?. plugins ) {
353360 // Resolve plugin paths so getSupportInfo can discover their languages
361+ // We're inside isAboveV3 check, so use file:// URLs for ESM import
354362 plugins = await resolvePluginPaths (
355363 resolvedConfig . plugins ,
356364 documentUri . fsPath ,
365+ true , // Use file:// URLs for Prettier v3+
357366 ) ;
358367 }
359368 }
@@ -520,10 +529,13 @@ export default class PrettierEditService implements Disposable {
520529 }
521530 }
522531
523- // Resolve plugin paths to file:// URLs for Prettier to import
532+ // Resolve plugin paths for Prettier
533+ // For v3+, use file:// URLs (ESM import); for v2, use absolute paths (require)
534+ const useFileUrls = isAboveV3 ( prettierInstance . version ) ;
524535 const resolvedPlugins = await resolvePluginPaths (
525536 resolvedConfig ?. plugins ,
526537 fileName ,
538+ useFileUrls ,
527539 ) ;
528540 this . loggingService . logInfo ( "Resolved plugins:" , resolvedPlugins ) ;
529541
0 commit comments