diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index a5266f9f..a88ae9c3 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -143,3 +143,5 @@ Examples: (a?.b[c]).c(); let value = /** @type {string} */ (this.members[0]).functionCall(); ``` + +- CLI: Plugins published as a scoped NPM package (e.g.: `@name/prettier-plugin-foo`) are now automatically registered ([#5945] by [@Kocal]) diff --git a/docs/plugins.md b/docs/plugins.md index cf46fa71..a416cb93 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -11,7 +11,9 @@ Plugins are ways of adding new languages to Prettier. Prettier's own implementat ## Using Plugins -Plugins are automatically loaded if you have them installed in the same `node_modules` directory where `prettier` is located. Plugin package names must start with `@prettier/plugin-` or `prettier-plugin-` to be registered. +Plugins are automatically loaded if you have them installed in the same `node_modules` directory where `prettier` is located. Plugin package names must start with `@prettier/plugin-` or `prettier-plugin-` or `@/prettier-plugin-` to be registered. + +> `` should be replaced by a name, read more about [NPM scope](https://docs.npmjs.com/misc/scope.html). When plugins cannot be found automatically, you can load them with: @@ -33,7 +35,7 @@ When plugins cannot be found automatically, you can load them with: }); ``` -Prettier expects each of `pluginSearchDirs` to contain `node_modules` subdirectory, where `@prettier/plugin-*` and `prettier-plugin-*` will be searched. For instance, this can be your project directory or the location of global npm modules. +Prettier expects each of `pluginSearchDirs` to contain `node_modules` subdirectory, where `@prettier/plugin-*`, `@*/prettier-plugin-*` and `prettier-plugin-*` will be searched. For instance, this can be your project directory or the location of global npm modules. Providing at least one path to `--plugin-search-dir`/`pluginSearchDirs` turns off plugin autoloading in the default directory (i.e. `node_modules` above `prettier` binary). diff --git a/src/common/load-plugins.js b/src/common/load-plugins.js index 717bc5df..cdf794b1 100644 --- a/src/common/load-plugins.js +++ b/src/common/load-plugins.js @@ -95,7 +95,11 @@ function loadPlugins(plugins, pluginSearchDirs) { function findPluginsInNodeModules(nodeModulesDir) { const pluginPackageJsonPaths = globby.sync( - ["prettier-plugin-*/package.json", "@prettier/plugin-*/package.json"], + [ + "prettier-plugin-*/package.json", + "@*/prettier-plugin-*/package.json", + "@prettier/plugin-*/package.json" + ], { cwd: nodeModulesDir } ); return pluginPackageJsonPaths.map(path.dirname); diff --git a/tests_integration/__tests__/plugin-resolution.js b/tests_integration/__tests__/plugin-resolution.js index 645346a5..95d783cd 100644 --- a/tests_integration/__tests__/plugin-resolution.js +++ b/tests_integration/__tests__/plugin-resolution.js @@ -21,6 +21,15 @@ describe("automatically loads '@prettier/plugin-*'", () => { }); }); +describe("automatically loads '@/prettier-plugin-*'", () => { + runPrettier("plugins/automatic", ["file.txt", "--parser=foobar"]).test({ + stdout: "foobar+contents" + EOL, + stderr: "", + status: 0, + write: [] + }); +}); + describe("automatically loads 'prettier-plugin-*' from --plugin-search-dir (same as autoload dir)", () => { runPrettier("plugins/automatic", [ "file.txt", @@ -47,6 +56,19 @@ describe("automatically loads '@prettier/plugin-*' from --plugin-search-dir (sam }); }); +describe("automatically loads '@/prettier-plugin-*' from --plugin-search-dir (same as autoload dir)", () => { + runPrettier("plugins/automatic", [ + "file.txt", + "--parser=foobar", + "--plugin-search-dir=." + ]).test({ + stdout: "foobar+contents" + EOL, + stderr: "", + status: 0, + write: [] + }); +}); + describe("automatically loads 'prettier-plugin-*' from --plugin-search-dir (different to autoload dir)", () => { runPrettier("plugins", [ "automatic/file.txt", diff --git a/tests_integration/plugins/automatic/node_modules/@user/prettier-plugin-foobar/index.js b/tests_integration/plugins/automatic/node_modules/@user/prettier-plugin-foobar/index.js new file mode 100644 index 00000000..d27bab5c --- /dev/null +++ b/tests_integration/plugins/automatic/node_modules/@user/prettier-plugin-foobar/index.js @@ -0,0 +1,25 @@ +"use strict"; + +const prettier = require("prettier/local"); +const concat = prettier.doc.builders.concat; + +module.exports = { + languages: [ + { + name: "foobar", + parsers: ["foobar"], + extensions: [".foobar"] + } + ], + parsers: { + foobar: { + parse: text => ({ text }), + astFormat: "foobar" + } + }, + printers: { + foobar: { + print: path => concat(["foobar+", path.getValue().text]) + } + } +}; diff --git a/tests_integration/plugins/automatic/node_modules/@user/prettier-plugin-foobar/package.json b/tests_integration/plugins/automatic/node_modules/@user/prettier-plugin-foobar/package.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/tests_integration/plugins/automatic/node_modules/@user/prettier-plugin-foobar/package.json @@ -0,0 +1 @@ +{}