Automatically load plugins from package.json (#3624)
* Automatically load plugins from package.json * Fix build by adding json extension * Fixup misuse of options argument * Rewire graceful-fs to fs * Document graceful-fs issue * Alias graceful-fs to fs in Rollupmaster
parent
a4dd86436a
commit
e5d6a4704f
|
@ -14,5 +14,12 @@ module.exports = {
|
|||
"<rootDir>/src/clean-ast.js",
|
||||
"<rootDir>/src/deprecated.js"
|
||||
],
|
||||
moduleNameMapper: {
|
||||
// Jest wires `fs` to `graceful-fs`, which causes a memory leak when
|
||||
// `graceful-fs` does `require('fs')`.
|
||||
// Ref: https://github.com/facebook/jest/issues/2179#issuecomment-355231418
|
||||
// If this is removed, see also rollup.bin.config.js and rollup.index.config.js.
|
||||
"graceful-fs": "<rootDir>/tests_config/fs.js"
|
||||
},
|
||||
transform: {}
|
||||
};
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
"postcss-scss": "1.0.2",
|
||||
"postcss-selector-parser": "2.2.3",
|
||||
"postcss-values-parser": "1.3.1",
|
||||
"read-pkg-up": "3.0.0",
|
||||
"remark-frontmatter": "1.1.0",
|
||||
"remark-parse": "4.0.0",
|
||||
"resolve": "1.5.0",
|
||||
|
|
|
@ -11,9 +11,16 @@ export default Object.assign(baseConfig, {
|
|||
format: "cjs",
|
||||
banner: "#!/usr/bin/env node",
|
||||
plugins: [
|
||||
replace({ "#!/usr/bin/env node": "" }),
|
||||
replace({
|
||||
"#!/usr/bin/env node": "",
|
||||
// See comment in jest.config.js
|
||||
"require('graceful-fs')": "require('fs')"
|
||||
}),
|
||||
json(),
|
||||
resolve({ preferBuiltins: true }),
|
||||
resolve({
|
||||
preferBuiltins: true,
|
||||
extensions: [".js", ".json"]
|
||||
}),
|
||||
commonjs()
|
||||
],
|
||||
external: [
|
||||
|
|
|
@ -17,10 +17,15 @@ export default Object.assign(baseConfig, {
|
|||
format: "cjs",
|
||||
plugins: [
|
||||
replace({
|
||||
"process.env.NODE_ENV": JSON.stringify("production")
|
||||
"process.env.NODE_ENV": JSON.stringify("production"),
|
||||
// See comment in jest.config.js
|
||||
"require('graceful-fs')": "require('fs')"
|
||||
}),
|
||||
json(),
|
||||
resolve({ preferBuiltins: true }),
|
||||
resolve({
|
||||
preferBuiltins: true,
|
||||
extensions: [".js", ".json"]
|
||||
}),
|
||||
commonjs()
|
||||
],
|
||||
external,
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
"use strict";
|
||||
|
||||
const resolve = require("resolve");
|
||||
const readPkgUp = require("read-pkg-up");
|
||||
|
||||
function loadPlugins(options) {
|
||||
options = Object.assign({ plugins: [] }, options);
|
||||
function loadPlugins(plugins) {
|
||||
plugins = plugins || [];
|
||||
|
||||
const internalPlugins = [
|
||||
require("../language-js"),
|
||||
|
@ -13,20 +14,47 @@ function loadPlugins(options) {
|
|||
require("../language-markdown"),
|
||||
require("../language-html"),
|
||||
require("../language-vue")
|
||||
].filter(plugin => {
|
||||
return options.plugins.indexOf(plugin) < 0;
|
||||
});
|
||||
];
|
||||
|
||||
const externalPlugins = options.plugins.map(plugin => {
|
||||
if (typeof plugin !== "string") {
|
||||
return plugin;
|
||||
const externalPlugins = plugins
|
||||
.concat(
|
||||
getPluginsFromPackage(
|
||||
readPkgUp.sync({
|
||||
normalize: false
|
||||
}).pkg
|
||||
)
|
||||
)
|
||||
.map(plugin => {
|
||||
if (typeof plugin !== "string") {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
const pluginPath = resolve.sync(plugin, { basedir: process.cwd() });
|
||||
return eval("require")(pluginPath);
|
||||
});
|
||||
|
||||
return deduplicate(internalPlugins.concat(externalPlugins));
|
||||
}
|
||||
|
||||
function getPluginsFromPackage(pkg) {
|
||||
if (!pkg) {
|
||||
return [];
|
||||
}
|
||||
const deps = Object.assign({}, pkg.dependencies, pkg.devDependencies);
|
||||
return Object.keys(deps).filter(
|
||||
dep =>
|
||||
dep.startsWith("prettier-plugin-") || dep.startsWith("@prettier/plugin-")
|
||||
);
|
||||
}
|
||||
|
||||
function deduplicate(items) {
|
||||
const uniqItems = [];
|
||||
for (const item of items) {
|
||||
if (uniqItems.indexOf(item) < 0) {
|
||||
uniqItems.push(item);
|
||||
}
|
||||
|
||||
const pluginPath = resolve.sync(plugin, { basedir: process.cwd() });
|
||||
return eval("require")(pluginPath);
|
||||
});
|
||||
|
||||
return internalPlugins.concat(externalPlugins);
|
||||
}
|
||||
return uniqItems;
|
||||
}
|
||||
|
||||
module.exports = loadPlugins;
|
||||
|
|
|
@ -162,13 +162,21 @@ const supportOptions = {
|
|||
};
|
||||
|
||||
function getSupportInfo(version, opts) {
|
||||
opts = opts || {};
|
||||
opts = Object.assign(
|
||||
{
|
||||
plugins: [],
|
||||
pluginsLoaded: false,
|
||||
showUnreleased: false,
|
||||
showDeprecated: false
|
||||
},
|
||||
opts
|
||||
);
|
||||
|
||||
if (!version) {
|
||||
version = currentVersion;
|
||||
}
|
||||
|
||||
const plugins = loadPlugins();
|
||||
const plugins = opts.pluginsLoaded ? opts.plugins : loadPlugins(opts.plugins);
|
||||
|
||||
const options = util
|
||||
.arrayify(
|
||||
|
|
|
@ -31,7 +31,10 @@ function embed(path, print, textToDoc, options) {
|
|||
return null;
|
||||
|
||||
function getParserName(lang) {
|
||||
const supportInfo = support.getSupportInfo(undefined, options);
|
||||
const supportInfo = support.getSupportInfo(undefined, {
|
||||
plugins: options.plugins,
|
||||
pluginsLoaded: true
|
||||
});
|
||||
const language = supportInfo.languages.find(
|
||||
language =>
|
||||
language.name.toLowerCase() === lang ||
|
||||
|
|
|
@ -44,7 +44,7 @@ function normalize(options) {
|
|||
const normalized = Object.assign({}, options || {});
|
||||
const filepath = normalized.filepath;
|
||||
|
||||
normalized.plugins = loadPlugins(normalized);
|
||||
normalized.plugins = loadPlugins(normalized.plugins);
|
||||
|
||||
if (
|
||||
filepath &&
|
||||
|
@ -54,7 +54,10 @@ function normalize(options) {
|
|||
const extension = path.extname(filepath);
|
||||
const filename = path.basename(filepath).toLowerCase();
|
||||
|
||||
const language = getSupportInfo(null, normalized).languages.find(
|
||||
const language = getSupportInfo(null, {
|
||||
plugins: normalized.plugins,
|
||||
pluginsLoaded: true
|
||||
}).languages.find(
|
||||
language =>
|
||||
typeof language.since === "string" &&
|
||||
(language.extensions.indexOf(extension) > -1 ||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = require("fs");
|
|
@ -0,0 +1,12 @@
|
|||
"use strict";
|
||||
|
||||
const runPrettier = require("../runPrettier");
|
||||
|
||||
describe("uses 'extensions' from languages to determine parser", () => {
|
||||
runPrettier("plugins/extensions", ["*.foo", "--plugin=./plugin"]).test({
|
||||
stdout: "!contents\n",
|
||||
stderr: "",
|
||||
status: 0,
|
||||
write: []
|
||||
});
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
"use strict";
|
||||
|
||||
const runPrettier = require("../runPrettier");
|
||||
|
||||
describe("automatically loads 'prettier-plugin-*' from package.json devDependencies", () => {
|
||||
runPrettier("plugins/automatic", ["file.txt", "--parser=foo"]).test({
|
||||
stdout: "foo+contents\n",
|
||||
stderr: "",
|
||||
status: 0,
|
||||
write: []
|
||||
});
|
||||
});
|
||||
|
||||
describe("automatically loads '@prettier/plugin-*' from package.json dependencies", () => {
|
||||
runPrettier("plugins/automatic", ["file.txt", "--parser=bar"]).test({
|
||||
stdout: "bar+contents\n",
|
||||
stderr: "",
|
||||
status: 0,
|
||||
write: []
|
||||
});
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
contents
|
23
tests_integration/plugins/automatic/node_modules/@prettier/plugin-foo/index.js
generated
vendored
Normal file
23
tests_integration/plugins/automatic/node_modules/@prettier/plugin-foo/index.js
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
"use strict";
|
||||
|
||||
const concat = require("../../../../../../src/doc").builders.concat;
|
||||
|
||||
module.exports = {
|
||||
languages: [
|
||||
{
|
||||
name: "foo",
|
||||
parsers: ["foo"]
|
||||
}
|
||||
],
|
||||
parsers: {
|
||||
foo: {
|
||||
parse: text => ({ text }),
|
||||
astFormat: "foo"
|
||||
}
|
||||
},
|
||||
printers: {
|
||||
foo: {
|
||||
print: path => concat(["foo+", path.getValue().text])
|
||||
}
|
||||
}
|
||||
};
|
23
tests_integration/plugins/automatic/node_modules/prettier-plugin-bar/index.js
generated
vendored
Normal file
23
tests_integration/plugins/automatic/node_modules/prettier-plugin-bar/index.js
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
"use strict";
|
||||
|
||||
const concat = require("../../../../../src/doc").builders.concat;
|
||||
|
||||
module.exports = {
|
||||
languages: [
|
||||
{
|
||||
name: "bar",
|
||||
parsers: ["bar"]
|
||||
}
|
||||
],
|
||||
parsers: {
|
||||
bar: {
|
||||
parse: text => ({ text }),
|
||||
astFormat: "bar"
|
||||
}
|
||||
},
|
||||
printers: {
|
||||
bar: {
|
||||
print: path => concat(["bar+", path.getValue().text])
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@prettier/plugin-foo": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier-plugin-bar": "*"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
contents
|
|
@ -0,0 +1,25 @@
|
|||
"use strict";
|
||||
|
||||
const concat = require("../../../src/doc").builders.concat;
|
||||
|
||||
module.exports = {
|
||||
languages: [
|
||||
{
|
||||
name: "foo",
|
||||
parsers: ["foo-parser"],
|
||||
extensions: [".foo"],
|
||||
since: "1.0.0"
|
||||
}
|
||||
],
|
||||
parsers: {
|
||||
"foo-parser": {
|
||||
parse: text => ({ text }),
|
||||
astFormat: "foo-ast"
|
||||
}
|
||||
},
|
||||
printers: {
|
||||
"foo-ast": {
|
||||
print: path => concat(["!", path.getValue().text])
|
||||
}
|
||||
}
|
||||
};
|
41
yarn.lock
41
yarn.lock
|
@ -2825,6 +2825,10 @@ json-loader@^0.5.4:
|
|||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.4.tgz#8baa1365a632f58a3c46d20175fc6002c96e37de"
|
||||
|
||||
json-parse-better-errors@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a"
|
||||
|
||||
json-schema@0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
||||
|
@ -2920,6 +2924,15 @@ load-json-file@^2.0.0:
|
|||
pify "^2.0.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
load-json-file@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
|
||||
dependencies:
|
||||
graceful-fs "^4.1.2"
|
||||
parse-json "^4.0.0"
|
||||
pify "^3.0.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
loader-runner@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
|
||||
|
@ -3388,6 +3401,13 @@ parse-json@^3.0.0:
|
|||
dependencies:
|
||||
error-ex "^1.3.1"
|
||||
|
||||
parse-json@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
|
||||
dependencies:
|
||||
error-ex "^1.3.1"
|
||||
json-parse-better-errors "^1.0.1"
|
||||
|
||||
parse5@3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
|
||||
|
@ -3448,6 +3468,12 @@ path-type@^2.0.0:
|
|||
dependencies:
|
||||
pify "^2.0.0"
|
||||
|
||||
path-type@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
|
||||
dependencies:
|
||||
pify "^3.0.0"
|
||||
|
||||
pbkdf2@^3.0.3:
|
||||
version "3.0.12"
|
||||
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.12.tgz#be36785c5067ea48d806ff923288c5f750b6b8a2"
|
||||
|
@ -3681,6 +3707,13 @@ rc@^1.1.7:
|
|||
minimist "^1.2.0"
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
read-pkg-up@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
|
||||
dependencies:
|
||||
find-up "^2.0.0"
|
||||
read-pkg "^3.0.0"
|
||||
|
||||
read-pkg-up@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
|
||||
|
@ -3711,6 +3744,14 @@ read-pkg@^2.0.0:
|
|||
normalize-package-data "^2.3.2"
|
||||
path-type "^2.0.0"
|
||||
|
||||
read-pkg@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
|
||||
dependencies:
|
||||
load-json-file "^4.0.0"
|
||||
normalize-package-data "^2.3.2"
|
||||
path-type "^3.0.0"
|
||||
|
||||
readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.6:
|
||||
version "2.2.11"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.11.tgz#0796b31f8d7688007ff0b93a8088d34aa17c0f72"
|
||||
|
|
Loading…
Reference in New Issue