Use @babel/eslint-plugin-developement (#9206)
This commit is contained in:
parent
116ca22def
commit
911c2d0bf4
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"root": true,
|
"root": true,
|
||||||
"extends": "babel",
|
"extends": "babel",
|
||||||
"plugins": ["local-rules", "prettier"],
|
"plugins": ["prettier", "@babel/development"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"prettier/prettier": "error"
|
"prettier/prettier": "error"
|
||||||
},
|
},
|
||||||
@ -12,8 +12,8 @@
|
|||||||
{
|
{
|
||||||
"files": ["packages/*/src/**/*.js", "codemods/*/src/**/*.js"],
|
"files": ["packages/*/src/**/*.js", "codemods/*/src/**/*.js"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"local-rules/no-undefined-identifier": "error",
|
"@babel/development/no-undefined-identifier": "error",
|
||||||
"local-rules/no-deprecated-clone": "error"
|
"@babel/development/no-deprecated-clone": "error"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -31,7 +31,7 @@
|
|||||||
"files": ["packages/babel-plugin-*/src/index.js"],
|
"files": ["packages/babel-plugin-*/src/index.js"],
|
||||||
"excludedFiles": ["packages/babel-plugin-transform-regenerator/**/*.js"],
|
"excludedFiles": ["packages/babel-plugin-transform-regenerator/**/*.js"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"local-rules/plugin-name": "error"
|
"@babel/development/plugin-name": "error"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.2.0",
|
"@babel/cli": "^7.2.0",
|
||||||
"@babel/core": "^7.2.0",
|
"@babel/core": "^7.2.0",
|
||||||
|
"@babel/eslint-plugin-development": "^1.0.1",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.2.1",
|
"@babel/plugin-proposal-class-properties": "^7.2.1",
|
||||||
"@babel/plugin-proposal-export-namespace-from": "^7.2.0",
|
"@babel/plugin-proposal-export-namespace-from": "^7.2.0",
|
||||||
"@babel/plugin-proposal-numeric-separator": "^7.2.0",
|
"@babel/plugin-proposal-numeric-separator": "^7.2.0",
|
||||||
@ -34,7 +35,6 @@
|
|||||||
"eslint": "^5.9.0",
|
"eslint": "^5.9.0",
|
||||||
"eslint-config-babel": "^8.0.2",
|
"eslint-config-babel": "^8.0.2",
|
||||||
"eslint-plugin-flowtype": "^3.2.0",
|
"eslint-plugin-flowtype": "^3.2.0",
|
||||||
"eslint-plugin-local-rules": "0.1.0",
|
|
||||||
"eslint-plugin-prettier": "^3.0.0",
|
"eslint-plugin-prettier": "^3.0.0",
|
||||||
"flow-bin": "^0.87.0",
|
"flow-bin": "^0.87.0",
|
||||||
"graceful-fs": "^4.1.11",
|
"graceful-fs": "^4.1.11",
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
/* eslint-disable local-rules/plugin-name */
|
/* eslint-disable @babel/development/plugin-name */
|
||||||
|
|
||||||
import { declare } from "@babel/helper-plugin-utils";
|
import { declare } from "@babel/helper-plugin-utils";
|
||||||
import {
|
import {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
/* eslint-disable local-rules/plugin-name */
|
/* eslint-disable @babel/development/plugin-name */
|
||||||
|
|
||||||
import { declare } from "@babel/helper-plugin-utils";
|
import { declare } from "@babel/helper-plugin-utils";
|
||||||
import syntaxDecorators from "@babel/plugin-syntax-decorators";
|
import syntaxDecorators from "@babel/plugin-syntax-decorators";
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
/* eslint-disable local-rules/plugin-name */
|
/* eslint-disable @babel/development/plugin-name */
|
||||||
|
|
||||||
import { declare } from "@babel/helper-plugin-utils";
|
import { declare } from "@babel/helper-plugin-utils";
|
||||||
import {
|
import {
|
||||||
|
|||||||
@ -497,6 +497,7 @@ export default class Scope {
|
|||||||
if (this.hasBinding("undefined")) {
|
if (this.hasBinding("undefined")) {
|
||||||
return t.unaryExpression("void", t.numericLiteral(0), true);
|
return t.unaryExpression("void", t.numericLiteral(0), true);
|
||||||
} else {
|
} else {
|
||||||
|
// eslint-disable-next-line @babel/development/no-undefined-identifier
|
||||||
return t.identifier("undefined");
|
return t.identifier("undefined");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,104 +0,0 @@
|
|||||||
// @flow
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const getReferenceOrigin = require("./utils/get-reference-origin");
|
|
||||||
|
|
||||||
function reportError(context /*: Context */, node /*: Node */) {
|
|
||||||
const isMemberExpression = node.type === "MemberExpression";
|
|
||||||
const id = isMemberExpression ? node.property : node;
|
|
||||||
context.report({
|
|
||||||
node: id,
|
|
||||||
message: `t.${id.name}() is deprecated. Use t.cloneNode() instead.`,
|
|
||||||
fix(fixer) {
|
|
||||||
if (isMemberExpression) {
|
|
||||||
return fixer.replaceText(id, "cloneNode");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
meta: {
|
|
||||||
schema: [],
|
|
||||||
fixable: "code",
|
|
||||||
},
|
|
||||||
create(context /*: Context */) {
|
|
||||||
return {
|
|
||||||
CallExpression(node /*: Node */) {
|
|
||||||
const origin = getReferenceOrigin(node.callee, context.getScope());
|
|
||||||
|
|
||||||
if (!origin) return;
|
|
||||||
|
|
||||||
if (
|
|
||||||
origin.kind === "import" &&
|
|
||||||
(origin.name === "clone" || origin.name === "cloneDeep") &&
|
|
||||||
origin.source === "@babel/types"
|
|
||||||
) {
|
|
||||||
// imported from @babel/types
|
|
||||||
return reportError(context, node.callee);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
origin.kind === "property" &&
|
|
||||||
(origin.path === "clone" || origin.path === "cloneDeep") &&
|
|
||||||
origin.base.kind === "import" &&
|
|
||||||
origin.base.name === "types" &&
|
|
||||||
origin.base.source === "@babel/core"
|
|
||||||
) {
|
|
||||||
// imported from @babel/core
|
|
||||||
return reportError(context, node.callee);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
origin.kind === "property" &&
|
|
||||||
(origin.path === "types.clone" ||
|
|
||||||
origin.path === "types.cloneDeep") &&
|
|
||||||
origin.base.kind === "export param" &&
|
|
||||||
(origin.base.exportName === "default" ||
|
|
||||||
origin.base.exportName === "module.exports") &&
|
|
||||||
origin.base.index === 0
|
|
||||||
) {
|
|
||||||
// export default function ({ types: t }) {}
|
|
||||||
// module.exports = function ({ types: t }) {}
|
|
||||||
return reportError(context, node.callee);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/*:: // ESLint types
|
|
||||||
|
|
||||||
type Node = { type: string, [string]: any };
|
|
||||||
|
|
||||||
type Definition = {
|
|
||||||
type: "ImportedBinding",
|
|
||||||
name: Node,
|
|
||||||
node: Node,
|
|
||||||
parent: Node,
|
|
||||||
};
|
|
||||||
|
|
||||||
type Variable = {
|
|
||||||
defs: Definition[],
|
|
||||||
};
|
|
||||||
|
|
||||||
type Scope = {
|
|
||||||
set: Map<string, Variable>,
|
|
||||||
upper: ?Scope,
|
|
||||||
};
|
|
||||||
|
|
||||||
type Context = {
|
|
||||||
report(options: {
|
|
||||||
node: Node,
|
|
||||||
message: string,
|
|
||||||
fix?: (fixer: Fixer) => ?Fixer,
|
|
||||||
}): void,
|
|
||||||
|
|
||||||
getScope(): Scope,
|
|
||||||
};
|
|
||||||
|
|
||||||
type Fixer = {
|
|
||||||
replaceText(node: Node, replacement: string): Fixer,
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
function argumentsIsUndefinedString(argumentsArray) {
|
|
||||||
return (
|
|
||||||
argumentsArray.length === 1 &&
|
|
||||||
argumentsArray[0].type === "Literal" &&
|
|
||||||
argumentsArray[0].value === "undefined"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
meta: {
|
|
||||||
schema: [],
|
|
||||||
},
|
|
||||||
create: function(context) {
|
|
||||||
if (context.getFilename().indexOf("packages/babel-plugin-") === -1) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
CallExpression: function(node) {
|
|
||||||
const callee = node.callee;
|
|
||||||
|
|
||||||
if (
|
|
||||||
callee.type === "MemberExpression" &&
|
|
||||||
argumentsIsUndefinedString(node.arguments)
|
|
||||||
) {
|
|
||||||
const object = callee.object,
|
|
||||||
property = callee.property;
|
|
||||||
|
|
||||||
if (
|
|
||||||
object.type === "Identifier" &&
|
|
||||||
object.name === "t" &&
|
|
||||||
property.type === "Identifier" &&
|
|
||||||
property.name === "identifier"
|
|
||||||
) {
|
|
||||||
context.report(
|
|
||||||
node,
|
|
||||||
"Use path.scope.buildUndefinedNode() to create an undefined identifier directly."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const getReferenceOrigin = require("./utils/get-reference-origin");
|
|
||||||
|
|
||||||
function reportNoPlugin(context /*: Context */, node /*: Node */) {
|
|
||||||
context.report({
|
|
||||||
node,
|
|
||||||
message: "This file does not export a Babel plugin",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function is(type /*: string */) /*: (node: Node) => boolean */ {
|
|
||||||
return node => node.type === type;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
meta: {
|
|
||||||
schema: [],
|
|
||||||
},
|
|
||||||
create(context /*: Context */) {
|
|
||||||
return {
|
|
||||||
Program(program /*: Node */) {
|
|
||||||
if (!program.body.some(is("ExportDefaultDeclaration"))) {
|
|
||||||
return reportNoPlugin(context, program);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ExportDefaultDeclaration(exportDefaultDecl) {
|
|
||||||
let plugin = exportDefaultDecl.declaration;
|
|
||||||
|
|
||||||
if (plugin.type === "CallExpression") {
|
|
||||||
// export default declare(api => { ... });
|
|
||||||
const origin = getReferenceOrigin(plugin.callee, context.getScope());
|
|
||||||
|
|
||||||
if (
|
|
||||||
origin &&
|
|
||||||
origin.kind === "import" &&
|
|
||||||
origin.name === "declare" &&
|
|
||||||
origin.source === "@babel/helper-plugin-utils"
|
|
||||||
) {
|
|
||||||
plugin = plugin.arguments[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!plugin.type.includes("Function")) {
|
|
||||||
return reportNoPlugin(context, exportDefaultDecl.parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
const returnNode = plugin.body.body.find(is("ReturnStatement"));
|
|
||||||
if (!returnNode || returnNode.argument.type !== "ObjectExpression") {
|
|
||||||
return reportNoPlugin(context, exportDefaultDecl.parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!returnNode.argument.properties.some(p => p.key.name === "name")) {
|
|
||||||
context.report(
|
|
||||||
returnNode,
|
|
||||||
"This Babel plugin doesn't have a 'name' property."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
/*:: // ESLint types
|
|
||||||
|
|
||||||
type Node = { type: string, [string]: any };
|
|
||||||
|
|
||||||
type Definition = {
|
|
||||||
type: "ImportedBinding",
|
|
||||||
name: Node,
|
|
||||||
node: Node,
|
|
||||||
parent: Node,
|
|
||||||
};
|
|
||||||
|
|
||||||
type Variable = {
|
|
||||||
defs: Definition[],
|
|
||||||
};
|
|
||||||
|
|
||||||
type Scope = {
|
|
||||||
set: Map<string, Variable>,
|
|
||||||
upper: ?Scope,
|
|
||||||
};
|
|
||||||
|
|
||||||
type Context = {
|
|
||||||
report(options: {
|
|
||||||
node: Node,
|
|
||||||
message: string,
|
|
||||||
fix?: (fixer: Fixer) => ?Fixer,
|
|
||||||
}): void,
|
|
||||||
|
|
||||||
getScope(): Scope,
|
|
||||||
};
|
|
||||||
|
|
||||||
type Fixer = {
|
|
||||||
replaceText(node: Node, replacement: string): Fixer,
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
@ -1,166 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
module.exports = getReferenceOrigin;
|
|
||||||
|
|
||||||
/*::
|
|
||||||
type ReferenceOriginImport = { kind: "import", source: string, name: string };
|
|
||||||
type ReferenceOriginParam = {
|
|
||||||
kind: "export param",
|
|
||||||
exportName: string,
|
|
||||||
index: number,
|
|
||||||
};
|
|
||||||
|
|
||||||
type ReferenceOrigin =
|
|
||||||
| ReferenceOriginImport
|
|
||||||
| ReferenceOriginParam
|
|
||||||
| { kind: "import *", source: string }
|
|
||||||
| {
|
|
||||||
kind: "property",
|
|
||||||
base: ReferenceOriginImport | ReferenceOriginParam,
|
|
||||||
path: string,
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Given a node and a context, returns a description of where its value comes
|
|
||||||
// from.
|
|
||||||
// It resolves imports, parameters of exported functions and property accesses.
|
|
||||||
// See the ReferenceOrigin type for more informations.
|
|
||||||
function getReferenceOrigin(
|
|
||||||
node /*: Node */,
|
|
||||||
scope /*: Scope */
|
|
||||||
) /*: ?ReferenceOrigin */ {
|
|
||||||
if (node.type === "Identifier") {
|
|
||||||
const variable = getVariableDefinition(node.name, scope);
|
|
||||||
if (!variable) return null;
|
|
||||||
|
|
||||||
const definition = variable.definition;
|
|
||||||
const defNode = definition.node;
|
|
||||||
|
|
||||||
if (definition.type === "ImportBinding") {
|
|
||||||
if (defNode.type === "ImportSpecifier") {
|
|
||||||
return {
|
|
||||||
kind: "import",
|
|
||||||
source: definition.parent.source.value,
|
|
||||||
name: defNode.imported.name,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (defNode.type === "ImportNamespaceSpecifier") {
|
|
||||||
return {
|
|
||||||
kind: "import *",
|
|
||||||
source: definition.parent.source.value,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (definition.type === "Variable" && defNode.init) {
|
|
||||||
const origin = getReferenceOrigin(defNode.init, variable.scope);
|
|
||||||
return origin && patternToProperty(definition.name, origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (definition.type === "Parameter") {
|
|
||||||
const parent = defNode.parent;
|
|
||||||
let exportName /*: string */;
|
|
||||||
if (parent.type === "ExportDefaultDeclaration") {
|
|
||||||
exportName = "default";
|
|
||||||
} else if (parent.type === "ExportNamedDeclaration") {
|
|
||||||
exportName = defNode.id.name;
|
|
||||||
} else if (
|
|
||||||
parent.type === "AssignmentExpression" &&
|
|
||||||
parent.left.type === "MemberExpression" &&
|
|
||||||
parent.left.object.type === "Identifier" &&
|
|
||||||
parent.left.object.name === "module" &&
|
|
||||||
parent.left.property.type === "Identifier" &&
|
|
||||||
parent.left.property.name === "exports"
|
|
||||||
) {
|
|
||||||
exportName = "module.exports";
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return patternToProperty(definition.name, {
|
|
||||||
kind: "export param",
|
|
||||||
exportName,
|
|
||||||
index: definition.index,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.type === "MemberExpression" && !node.computed) {
|
|
||||||
const origin = getReferenceOrigin(node.object, scope);
|
|
||||||
return origin && addProperty(origin, node.property.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getVariableDefinition(name /*: string */, scope /*: Scope */) {
|
|
||||||
let currentScope = scope;
|
|
||||||
do {
|
|
||||||
const variable = currentScope.set.get(name);
|
|
||||||
if (variable && variable.defs[0]) {
|
|
||||||
return { scope: currentScope, definition: variable.defs[0] };
|
|
||||||
}
|
|
||||||
} while ((currentScope = currentScope.upper));
|
|
||||||
}
|
|
||||||
|
|
||||||
function patternToProperty(
|
|
||||||
id /*: Node */,
|
|
||||||
base /*: ReferenceOrigin */
|
|
||||||
) /*: ?ReferenceOrigin */ {
|
|
||||||
const path = getPatternPath(id);
|
|
||||||
return path && path.reduce(addProperty, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds a property to a given origin. If it was a namespace import it becomes
|
|
||||||
// a named import, so that `import * as x from "foo"; x.bar` and
|
|
||||||
// `import { bar } from "foo"` have the same origin.
|
|
||||||
function addProperty(
|
|
||||||
origin /*: ReferenceOrigin */,
|
|
||||||
name /*: string */
|
|
||||||
) /* ReferenceOrigin */ {
|
|
||||||
if (origin.kind === "import *") {
|
|
||||||
return {
|
|
||||||
kind: "import",
|
|
||||||
source: origin.source,
|
|
||||||
name,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (origin.kind === "property") {
|
|
||||||
return {
|
|
||||||
kind: "property",
|
|
||||||
base: origin.base,
|
|
||||||
path: origin.path + "." + name,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
kind: "property",
|
|
||||||
base: origin,
|
|
||||||
path: name,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// if "node" is c of { a: { b: c } }, the result is ["a","b"]
|
|
||||||
function getPatternPath(node /*: Node */) /*: ?string[] */ {
|
|
||||||
let current = node;
|
|
||||||
const path = [];
|
|
||||||
|
|
||||||
// Unshift keys to path while going up
|
|
||||||
do {
|
|
||||||
const property = current.parent;
|
|
||||||
if (
|
|
||||||
property.type === "ArrayPattern" ||
|
|
||||||
property.type === "AssignmentPattern" ||
|
|
||||||
property.computed
|
|
||||||
) {
|
|
||||||
// These nodes are not supported.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (property.type === "Property") {
|
|
||||||
path.unshift(property.key.name);
|
|
||||||
} else {
|
|
||||||
// The destructuring pattern is finished
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while ((current = current.parent.parent));
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
10
yarn.lock
10
yarn.lock
@ -53,6 +53,11 @@
|
|||||||
semver "^5.4.1"
|
semver "^5.4.1"
|
||||||
source-map "^0.5.0"
|
source-map "^0.5.0"
|
||||||
|
|
||||||
|
"@babel/eslint-plugin-development@^1.0.1":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/eslint-plugin-development/-/eslint-plugin-development-1.0.1.tgz#1f5206ae95795db09b65e7dbc2b158d66497a44c"
|
||||||
|
integrity sha512-ioEhN8HgKr4Yx8ef+XryNpKN4FimSFceb0qVVxvoUzpFn3xyq17MlY5AquEqtXObE7Nu7WKq7QL9INzjCrugyw==
|
||||||
|
|
||||||
"@babel/generator@7.0.0-beta.40":
|
"@babel/generator@7.0.0-beta.40":
|
||||||
version "7.0.0-beta.40"
|
version "7.0.0-beta.40"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.40.tgz#ab61f9556f4f71dbd1138949c795bb9a21e302ea"
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.40.tgz#ab61f9556f4f71dbd1138949c795bb9a21e302ea"
|
||||||
@ -3533,11 +3538,6 @@ eslint-plugin-flowtype@^3.2.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
lodash "^4.17.10"
|
lodash "^4.17.10"
|
||||||
|
|
||||||
eslint-plugin-local-rules@0.1.0:
|
|
||||||
version "0.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-local-rules/-/eslint-plugin-local-rules-0.1.0.tgz#6808bb4c1b9a432f6e54ff4dfb290073e1cdf700"
|
|
||||||
integrity sha1-aAi7TBuaQy9uVP9N+ykAc+HN9wA=
|
|
||||||
|
|
||||||
eslint-plugin-prettier@^3.0.0:
|
eslint-plugin-prettier@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.0.tgz#f6b823e065f8c36529918cdb766d7a0e975ec30c"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.0.tgz#f6b823e065f8c36529918cdb766d7a0e975ec30c"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user