tools: update ESLint to 6.3.0

Update ESLint to 6.3.0

PR-URL: https://github.com/nodejs/node/pull/29382
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
This commit is contained in:
cjihrig 2019-08-30 16:56:49 -04:00 committed by Daniel Bevenius
parent d18b6a7e40
commit d62d2b4560
20 changed files with 143 additions and 30 deletions

View File

@ -1,5 +1,6 @@
[![NPM version][npm-image]][npm-url] [![NPM version][npm-image]][npm-url]
[![Build Status](https://dev.azure.com/eslint/eslint/_apis/build/status/eslint.eslint?branchName=master)](https://dev.azure.com/eslint/eslint/_build/latest?definitionId=1&branchName=master) [![Build Status](https://dev.azure.com/eslint/eslint/_apis/build/status/eslint.eslint?branchName=master)](https://dev.azure.com/eslint/eslint/_build/latest?definitionId=1&branchName=master)
[![Build Status](https://github.com/eslint/eslint/workflows/CI/badge.svg)](https://github.com/eslint/eslint/actions)
[![Downloads][downloads-image]][downloads-url] [![Downloads][downloads-image]][downloads-url]
[![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=282608)](https://www.bountysource.com/trackers/282608-eslint?utm_source=282608&utm_medium=shield&utm_campaign=TRACKER_BADGE) [![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=282608)](https://www.bountysource.com/trackers/282608-eslint?utm_source=282608&utm_medium=shield&utm_campaign=TRACKER_BADGE)
[![Join the chat at https://gitter.im/eslint/eslint](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/eslint/eslint?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://gitter.im/eslint/eslint](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/eslint/eslint?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

View File

@ -21,6 +21,7 @@ const baseConfigProperties = {
rules: { type: "object" }, rules: { type: "object" },
settings: { type: "object" }, settings: { type: "object" },
noInlineConfig: { type: "boolean" }, noInlineConfig: { type: "boolean" },
reportUnusedDisableDirectives: { type: "boolean" },
ecmaFeatures: { type: "object" } // deprecated; logs a warning when used ecmaFeatures: { type: "object" } // deprecated; logs a warning when used
}; };

View File

@ -26,6 +26,6 @@ module.exports = {
cacheFile: ".eslintcache", cacheFile: ".eslintcache",
fix: false, fix: false,
allowInlineConfig: true, allowInlineConfig: true,
reportUnusedDisableDirectives: false, reportUnusedDisableDirectives: void 0,
globInputPaths: true globInputPaths: true
}; };

View File

@ -531,6 +531,7 @@ class ConfigArrayFactory {
parserOptions, parserOptions,
plugins: pluginList, plugins: pluginList,
processor, processor,
reportUnusedDisableDirectives,
root, root,
rules, rules,
settings, settings,
@ -573,6 +574,7 @@ class ConfigArrayFactory {
parserOptions, parserOptions,
plugins, plugins,
processor, processor,
reportUnusedDisableDirectives,
root, root,
rules, rules,
settings settings

View File

@ -59,6 +59,7 @@ const { ExtractedConfig } = require("./extracted-config");
* @property {Object|undefined} parserOptions The parser options. * @property {Object|undefined} parserOptions The parser options.
* @property {Record<string, DependentPlugin>|undefined} plugins The plugin loaders. * @property {Record<string, DependentPlugin>|undefined} plugins The plugin loaders.
* @property {string|undefined} processor The processor name to refer plugin's processor. * @property {string|undefined} processor The processor name to refer plugin's processor.
* @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.
* @property {boolean|undefined} root The flag to express root. * @property {boolean|undefined} root The flag to express root.
* @property {Record<string, RuleConf>|undefined} rules The rule settings * @property {Record<string, RuleConf>|undefined} rules The rule settings
* @property {Object|undefined} settings The shared settings. * @property {Object|undefined} settings The shared settings.
@ -257,6 +258,11 @@ function createConfig(instance, indices) {
config.configNameOfNoInlineConfig = element.name; config.configNameOfNoInlineConfig = element.name;
} }
// Adopt the reportUnusedDisableDirectives which was found at first.
if (config.reportUnusedDisableDirectives === void 0 && element.reportUnusedDisableDirectives !== void 0) {
config.reportUnusedDisableDirectives = element.reportUnusedDisableDirectives;
}
// Merge others. // Merge others.
mergeWithoutOverwrite(config.env, element.env); mergeWithoutOverwrite(config.env, element.env);
mergeWithoutOverwrite(config.globals, element.globals); mergeWithoutOverwrite(config.globals, element.globals);

View File

@ -77,6 +77,12 @@ class ExtractedConfig {
*/ */
this.processor = null; this.processor = null;
/**
* The flag that reports unused `eslint-disable` directive comments.
* @type {boolean|undefined}
*/
this.reportUnusedDisableDirectives = void 0;
/** /**
* Rule settings. * Rule settings.
* @type {Record<string, [SeverityConf, ...any[]]>} * @type {Record<string, [SeverityConf, ...any[]]>}

View File

@ -96,5 +96,6 @@ module.exports = function(results) {
} }
} }
return total > 0 ? output : ""; // Resets output color, for prevent change on top level
return total > 0 ? chalk.reset(output) : "";
}; };

View File

@ -120,6 +120,12 @@ function getModulesList(config, installESLint) {
} }
} }
const parser = config.parser || (config.parserOptions && config.parserOptions.parser);
if (parser) {
modules[parser] = "latest";
}
if (installESLint === false) { if (installESLint === false) {
delete modules.eslint; delete modules.eslint;
} else { } else {
@ -291,6 +297,20 @@ function processAnswers(answers) {
config.extends.push("plugin:vue/essential"); config.extends.push("plugin:vue/essential");
} }
if (answers.typescript) {
if (answers.framework === "vue") {
config.parserOptions.parser = "@typescript-eslint/parser";
} else {
config.parser = "@typescript-eslint/parser";
}
if (Array.isArray(config.plugins)) {
config.plugins.push("@typescript-eslint");
} else {
config.plugins = ["@typescript-eslint"];
}
}
// setup rules based on problems/style enforcement preferences // setup rules based on problems/style enforcement preferences
if (answers.purpose === "problems") { if (answers.purpose === "problems") {
config.extends.unshift("eslint:recommended"); config.extends.unshift("eslint:recommended");
@ -306,6 +326,9 @@ function processAnswers(answers) {
config = autoconfig.extendFromRecommended(config); config = autoconfig.extendFromRecommended(config);
} }
} }
if (answers.typescript && config.extends.includes("eslint:recommended")) {
config.extends.push("plugin:@typescript-eslint/eslint-recommended");
}
// normalize extends // normalize extends
if (config.extends.length === 0) { if (config.extends.length === 0) {
@ -465,6 +488,12 @@ function promptUser() {
{ name: "None of these", value: "none" } { name: "None of these", value: "none" }
] ]
}, },
{
type: "confirm",
name: "typescript",
message: "Does your project use TypeScript?",
default: false
},
{ {
type: "checkbox", type: "checkbox",
name: "env", name: "env",

View File

@ -98,7 +98,7 @@ function fetchPeerDependencies(packageName) {
* and values are booleans indicating installation. * and values are booleans indicating installation.
*/ */
function check(packages, opt) { function check(packages, opt) {
let deps = []; const deps = new Set();
const pkgJson = (opt) ? findPackageJson(opt.startDir) : findPackageJson(); const pkgJson = (opt) ? findPackageJson(opt.startDir) : findPackageJson();
let fileJson; let fileJson;
@ -119,14 +119,14 @@ function check(packages, opt) {
throw error; throw error;
} }
if (opt.devDependencies && typeof fileJson.devDependencies === "object") { ["dependencies", "devDependencies"].forEach(key => {
deps = deps.concat(Object.keys(fileJson.devDependencies)); if (opt[key] && typeof fileJson[key] === "object") {
} Object.keys(fileJson[key]).forEach(dep => deps.add(dep));
if (opt.dependencies && typeof fileJson.dependencies === "object") {
deps = deps.concat(Object.keys(fileJson.dependencies));
} }
});
return packages.reduce((status, pkg) => { return packages.reduce((status, pkg) => {
status[pkg] = deps.indexOf(pkg) !== -1; status[pkg] = deps.has(pkg);
return status; return status;
}, {}); }, {});
} }

View File

@ -93,7 +93,7 @@ function applyDirectives(options) {
: "Unused eslint-disable directive (no problems were reported).", : "Unused eslint-disable directive (no problems were reported).",
line: directive.unprocessedDirective.line, line: directive.unprocessedDirective.line,
column: directive.unprocessedDirective.column, column: directive.unprocessedDirective.column,
severity: 2, severity: options.reportUnusedDisableDirectives === "warn" ? 1 : 2,
nodeType: null nodeType: null
})); }));
@ -114,17 +114,17 @@ function applyDirectives(options) {
* comment for two different rules is represented as two directives). * comment for two different rules is represented as two directives).
* @param {{ruleId: (string|null), line: number, column: number}[]} options.problems * @param {{ruleId: (string|null), line: number, column: number}[]} options.problems
* A list of problems reported by rules, sorted by increasing location in the file, with one-based columns. * A list of problems reported by rules, sorted by increasing location in the file, with one-based columns.
* @param {boolean} options.reportUnusedDisableDirectives If `true`, adds additional problems for unused directives * @param {"off" | "warn" | "error"} options.reportUnusedDisableDirectives If `"warn"` or `"error"`, adds additional problems for unused directives
* @returns {{ruleId: (string|null), line: number, column: number}[]} * @returns {{ruleId: (string|null), line: number, column: number}[]}
* A list of reported problems that were not disabled by the directive comments. * A list of reported problems that were not disabled by the directive comments.
*/ */
module.exports = options => { module.exports = ({ directives, problems, reportUnusedDisableDirectives = "off" }) => {
const blockDirectives = options.directives const blockDirectives = directives
.filter(directive => directive.type === "disable" || directive.type === "enable") .filter(directive => directive.type === "disable" || directive.type === "enable")
.map(directive => Object.assign({}, directive, { unprocessedDirective: directive })) .map(directive => Object.assign({}, directive, { unprocessedDirective: directive }))
.sort(compareLocations); .sort(compareLocations);
const lineDirectives = lodash.flatMap(options.directives, directive => { const lineDirectives = lodash.flatMap(directives, directive => {
switch (directive.type) { switch (directive.type) {
case "disable": case "disable":
case "enable": case "enable":
@ -147,10 +147,18 @@ module.exports = options => {
} }
}).sort(compareLocations); }).sort(compareLocations);
const blockDirectivesResult = applyDirectives({ problems: options.problems, directives: blockDirectives }); const blockDirectivesResult = applyDirectives({
const lineDirectivesResult = applyDirectives({ problems: blockDirectivesResult.problems, directives: lineDirectives }); problems,
directives: blockDirectives,
reportUnusedDisableDirectives
});
const lineDirectivesResult = applyDirectives({
problems: blockDirectivesResult.problems,
directives: lineDirectives,
reportUnusedDisableDirectives
});
return options.reportUnusedDisableDirectives return reportUnusedDisableDirectives !== "off"
? lineDirectivesResult.problems ? lineDirectivesResult.problems
.concat(blockDirectivesResult.unusedDisableDirectives) .concat(blockDirectivesResult.unusedDisableDirectives)
.concat(lineDirectivesResult.unusedDisableDirectives) .concat(lineDirectivesResult.unusedDisableDirectives)

View File

@ -54,6 +54,11 @@ const DEFAULT_ERROR_LOC = { start: { line: 1, column: 0 }, end: { line: 1, colum
/** @typedef {import("../shared/types").Processor} Processor */ /** @typedef {import("../shared/types").Processor} Processor */
/** @typedef {import("../shared/types").Rule} Rule */ /** @typedef {import("../shared/types").Rule} Rule */
/**
* @template T
* @typedef {{ [P in keyof T]-?: T[P] }} Required
*/
/** /**
* @typedef {Object} DisableDirective * @typedef {Object} DisableDirective
* @property {("disable"|"enable"|"disable-line"|"disable-next-line")} type * @property {("disable"|"enable"|"disable-line"|"disable-next-line")} type
@ -79,7 +84,7 @@ const DEFAULT_ERROR_LOC = { start: { line: 1, column: 0 }, end: { line: 1, colum
* @property {boolean} [disableFixes] if `true` then the linter doesn't make `fix` * @property {boolean} [disableFixes] if `true` then the linter doesn't make `fix`
* properties into the lint result. * properties into the lint result.
* @property {string} [filename] the filename of the source code. * @property {string} [filename] the filename of the source code.
* @property {boolean} [reportUnusedDisableDirectives] Adds reported errors for * @property {boolean | "off" | "warn" | "error"} [reportUnusedDisableDirectives] Adds reported errors for
* unused `eslint-disable` directives. * unused `eslint-disable` directives.
*/ */
@ -103,6 +108,12 @@ const DEFAULT_ERROR_LOC = { start: { line: 1, column: 0 }, end: { line: 1, colum
* whether fixes should be applied. * whether fixes should be applied.
*/ */
/**
* @typedef {Object} InternalOptions
* @property {string | null} warnInlineConfig The config name what `noInlineConfig` setting came from. If `noInlineConfig` setting didn't exist, this is null. If this is a config name, then the linter warns directive comments.
* @property {"off" | "warn" | "error"} reportUnusedDisableDirectives (boolean values were normalized)
*/
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Helpers // Helpers
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -467,7 +478,7 @@ function normalizeFilename(filename) {
* consistent shape. * consistent shape.
* @param {VerifyOptions} providedOptions Options * @param {VerifyOptions} providedOptions Options
* @param {ConfigData} config Config. * @param {ConfigData} config Config.
* @returns {Required<VerifyOptions> & { warnInlineConfig: string|null }} Normalized options * @returns {Required<VerifyOptions> & InternalOptions} Normalized options
*/ */
function normalizeVerifyOptions(providedOptions, config) { function normalizeVerifyOptions(providedOptions, config) {
const disableInlineConfig = config.noInlineConfig === true; const disableInlineConfig = config.noInlineConfig === true;
@ -476,13 +487,22 @@ function normalizeVerifyOptions(providedOptions, config) {
? ` (${config.configNameOfNoInlineConfig})` ? ` (${config.configNameOfNoInlineConfig})`
: ""; : "";
let reportUnusedDisableDirectives = providedOptions.reportUnusedDisableDirectives;
if (typeof reportUnusedDisableDirectives === "boolean") {
reportUnusedDisableDirectives = reportUnusedDisableDirectives ? "error" : "off";
}
if (typeof reportUnusedDisableDirectives !== "string") {
reportUnusedDisableDirectives = config.reportUnusedDisableDirectives ? "warn" : "off";
}
return { return {
filename: normalizeFilename(providedOptions.filename || "<input>"), filename: normalizeFilename(providedOptions.filename || "<input>"),
allowInlineConfig: !ignoreInlineConfig, allowInlineConfig: !ignoreInlineConfig,
warnInlineConfig: disableInlineConfig && !ignoreInlineConfig warnInlineConfig: disableInlineConfig && !ignoreInlineConfig
? `your config${configNameOfNoInlineConfig}` ? `your config${configNameOfNoInlineConfig}`
: null, : null,
reportUnusedDisableDirectives: Boolean(providedOptions.reportUnusedDisableDirectives), reportUnusedDisableDirectives,
disableFixes: Boolean(providedOptions.disableFixes) disableFixes: Boolean(providedOptions.disableFixes)
}; };
} }

View File

@ -192,7 +192,7 @@ module.exports = optionator({
{ {
option: "report-unused-disable-directives", option: "report-unused-disable-directives",
type: "Boolean", type: "Boolean",
default: false, default: void 0,
description: "Adds reported errors for unused eslint-disable directives" description: "Adds reported errors for unused eslint-disable directives"
}, },
{ {

View File

@ -118,6 +118,7 @@ module.exports = {
return false; return false;
} }
return node.type === "CallExpression" && return node.type === "CallExpression" &&
node.callee.type === "MemberExpression" &&
node.callee.object.name === objName && node.callee.object.name === objName &&
node.callee.property.name === funcName; node.callee.property.name === funcName;
} }

View File

@ -51,8 +51,8 @@ module.exports = {
expectedBefore: "Expected newline before ')'.", expectedBefore: "Expected newline before ')'.",
expectedAfter: "Expected newline after '('.", expectedAfter: "Expected newline after '('.",
expectedBetween: "Expected newline between arguments/params.", expectedBetween: "Expected newline between arguments/params.",
unexpectedBefore: "Unexpected newline before '('.", unexpectedBefore: "Unexpected newline before ')'.",
unexpectedAfter: "Unexpected newline after ')'." unexpectedAfter: "Unexpected newline after '('."
} }
}, },

View File

@ -102,7 +102,17 @@ module.exports = {
if (hasCommentsInside(parent)) { if (hasCommentsInside(parent)) {
return null; return null;
} }
return fixer.replaceText(parent, sourceCode.getText(node.argument));
let prefix = "";
const tokenBefore = sourceCode.getTokenBefore(parent);
const firstReplacementToken = sourceCode.getFirstToken(node.argument);
if (tokenBefore && tokenBefore.range[1] === parent.range[0] &&
!astUtils.canTokensBeAdjacent(tokenBefore, firstReplacementToken)) {
prefix = " ";
}
return fixer.replaceText(parent, prefix + sourceCode.getText(node.argument));
} }
}); });
} }

View File

@ -49,7 +49,8 @@ module.exports = {
nestedBinaryExpressions: { type: "boolean" }, nestedBinaryExpressions: { type: "boolean" },
returnAssign: { type: "boolean" }, returnAssign: { type: "boolean" },
ignoreJSX: { enum: ["none", "all", "single-line", "multi-line"] }, ignoreJSX: { enum: ["none", "all", "single-line", "multi-line"] },
enforceForArrowConditionals: { type: "boolean" } enforceForArrowConditionals: { type: "boolean" },
enforceForSequenceExpressions: { type: "boolean" }
}, },
additionalProperties: false additionalProperties: false
} }
@ -77,6 +78,8 @@ module.exports = {
const IGNORE_JSX = ALL_NODES && context.options[1] && context.options[1].ignoreJSX; const IGNORE_JSX = ALL_NODES && context.options[1] && context.options[1].ignoreJSX;
const IGNORE_ARROW_CONDITIONALS = ALL_NODES && context.options[1] && const IGNORE_ARROW_CONDITIONALS = ALL_NODES && context.options[1] &&
context.options[1].enforceForArrowConditionals === false; context.options[1].enforceForArrowConditionals === false;
const IGNORE_SEQUENCE_EXPRESSIONS = ALL_NODES && context.options[1] &&
context.options[1].enforceForSequenceExpressions === false;
const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" }); const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" });
const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" }); const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" });
@ -115,6 +118,10 @@ module.exports = {
} }
} }
if (node.type === "SequenceExpression" && IGNORE_SEQUENCE_EXPRESSIONS) {
return false;
}
return ALL_NODES || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression"; return ALL_NODES || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
} }

View File

@ -94,9 +94,19 @@ function eachSelfAssignment(left, right, props, report) {
const end = Math.min(left.elements.length, right.elements.length); const end = Math.min(left.elements.length, right.elements.length);
for (let i = 0; i < end; ++i) { for (let i = 0; i < end; ++i) {
const leftElement = left.elements[i];
const rightElement = right.elements[i]; const rightElement = right.elements[i];
eachSelfAssignment(left.elements[i], rightElement, props, report); // Avoid cases such as [...a] = [...a, 1]
if (
leftElement &&
leftElement.type === "RestElement" &&
i < right.elements.length - 1
) {
break;
}
eachSelfAssignment(leftElement, rightElement, props, report);
// After a spread element, those indices are unknown. // After a spread element, those indices are unknown.
if (rightElement && rightElement.type === "SpreadElement") { if (rightElement && rightElement.type === "SpreadElement") {

View File

@ -274,13 +274,22 @@ module.exports = {
* @returns {string} A string representation of the node with the sides and operator flipped * @returns {string} A string representation of the node with the sides and operator flipped
*/ */
function getFlippedString(node) { function getFlippedString(node) {
const tokenBefore = sourceCode.getTokenBefore(node);
const operatorToken = sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator); const operatorToken = sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator);
const textBeforeOperator = sourceCode.getText().slice(sourceCode.getTokenBefore(operatorToken).range[1], operatorToken.range[0]); const textBeforeOperator = sourceCode.getText().slice(sourceCode.getTokenBefore(operatorToken).range[1], operatorToken.range[0]);
const textAfterOperator = sourceCode.getText().slice(operatorToken.range[1], sourceCode.getTokenAfter(operatorToken).range[0]); const textAfterOperator = sourceCode.getText().slice(operatorToken.range[1], sourceCode.getTokenAfter(operatorToken).range[0]);
const leftText = sourceCode.getText().slice(node.range[0], sourceCode.getTokenBefore(operatorToken).range[1]); const leftText = sourceCode.getText().slice(node.range[0], sourceCode.getTokenBefore(operatorToken).range[1]);
const rightText = sourceCode.getText().slice(sourceCode.getTokenAfter(operatorToken).range[0], node.range[1]); const firstRightToken = sourceCode.getTokenAfter(operatorToken);
const rightText = sourceCode.getText().slice(firstRightToken.range[0], node.range[1]);
return rightText + textBeforeOperator + OPERATOR_FLIP_MAP[operatorToken.value] + textAfterOperator + leftText; let prefix = "";
if (tokenBefore && tokenBefore.range[1] === node.range[0] &&
!astUtils.canTokensBeAdjacent(tokenBefore, firstRightToken)) {
prefix = " ";
}
return prefix + rightText + textBeforeOperator + OPERATOR_FLIP_MAP[operatorToken.value] + textAfterOperator + leftText;
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------

View File

@ -36,6 +36,7 @@ module.exports = {};
* @property {ParserOptions} [parserOptions] The parser options. * @property {ParserOptions} [parserOptions] The parser options.
* @property {string[]} [plugins] The plugin specifiers. * @property {string[]} [plugins] The plugin specifiers.
* @property {string} [processor] The processor specifier. * @property {string} [processor] The processor specifier.
* @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.
* @property {boolean} [root] The root flag. * @property {boolean} [root] The root flag.
* @property {Record<string, RuleConf>} [rules] The rule settings. * @property {Record<string, RuleConf>} [rules] The rule settings.
* @property {Object} [settings] The shared settings. * @property {Object} [settings] The shared settings.
@ -54,6 +55,7 @@ module.exports = {};
* @property {ParserOptions} [parserOptions] The parser options. * @property {ParserOptions} [parserOptions] The parser options.
* @property {string[]} [plugins] The plugin specifiers. * @property {string[]} [plugins] The plugin specifiers.
* @property {string} [processor] The processor specifier. * @property {string} [processor] The processor specifier.
* @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.
* @property {Record<string, RuleConf>} [rules] The rule settings. * @property {Record<string, RuleConf>} [rules] The rule settings.
* @property {Object} [settings] The shared settings. * @property {Object} [settings] The shared settings.
*/ */

View File

@ -149,5 +149,5 @@
"test": "node Makefile.js test", "test": "node Makefile.js test",
"webpack": "node Makefile.js webpack" "webpack": "node Makefile.js webpack"
}, },
"version": "6.2.2" "version": "6.3.0"
} }