build: update npm install command to use --legacy-peer-deps
This change modifies the build scripts to use --legacy-peer-deps flag when installing npm dependencies to resolve potential peer dependency conflicts during the build process. The change is applied to both bash (build.sh) and batch (build.bat) build scripts.
This commit is contained in:
+261
-345
@@ -17,378 +17,294 @@ const keywords = require("./utils/keywords");
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
deprecated: {
|
||||
message: "Formatting rules are being moved out of ESLint core.",
|
||||
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
|
||||
deprecatedSince: "8.53.0",
|
||||
availableUntil: "11.0.0",
|
||||
replacedBy: [
|
||||
{
|
||||
message:
|
||||
"ESLint Stylistic now maintains deprecated stylistic core rules.",
|
||||
url: "https://eslint.style/guide/migration",
|
||||
plugin: {
|
||||
name: "@stylistic/eslint-plugin",
|
||||
url: "https://eslint.style",
|
||||
},
|
||||
rule: {
|
||||
name: "quote-props",
|
||||
url: "https://eslint.style/rules/quote-props",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
type: "suggestion",
|
||||
meta: {
|
||||
deprecated: true,
|
||||
replacedBy: [],
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "Require quotes around object literal property names",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/quote-props",
|
||||
},
|
||||
docs: {
|
||||
description: "Require quotes around object literal property names",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/quote-props"
|
||||
},
|
||||
|
||||
schema: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "array",
|
||||
items: [
|
||||
{
|
||||
enum: [
|
||||
"always",
|
||||
"as-needed",
|
||||
"consistent",
|
||||
"consistent-as-needed",
|
||||
],
|
||||
},
|
||||
],
|
||||
minItems: 0,
|
||||
maxItems: 1,
|
||||
},
|
||||
{
|
||||
type: "array",
|
||||
items: [
|
||||
{
|
||||
enum: [
|
||||
"always",
|
||||
"as-needed",
|
||||
"consistent",
|
||||
"consistent-as-needed",
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
keywords: {
|
||||
type: "boolean",
|
||||
},
|
||||
unnecessary: {
|
||||
type: "boolean",
|
||||
},
|
||||
numbers: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
minItems: 0,
|
||||
maxItems: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
schema: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "array",
|
||||
items: [
|
||||
{
|
||||
enum: ["always", "as-needed", "consistent", "consistent-as-needed"]
|
||||
}
|
||||
],
|
||||
minItems: 0,
|
||||
maxItems: 1
|
||||
},
|
||||
{
|
||||
type: "array",
|
||||
items: [
|
||||
{
|
||||
enum: ["always", "as-needed", "consistent", "consistent-as-needed"]
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
keywords: {
|
||||
type: "boolean"
|
||||
},
|
||||
unnecessary: {
|
||||
type: "boolean"
|
||||
},
|
||||
numbers: {
|
||||
type: "boolean"
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}
|
||||
],
|
||||
minItems: 0,
|
||||
maxItems: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
fixable: "code",
|
||||
messages: {
|
||||
requireQuotesDueToReservedWord:
|
||||
"Properties should be quoted as '{{property}}' is a reserved word.",
|
||||
inconsistentlyQuotedProperty:
|
||||
"Inconsistently quoted property '{{key}}' found.",
|
||||
unnecessarilyQuotedProperty:
|
||||
"Unnecessarily quoted property '{{property}}' found.",
|
||||
unquotedReservedProperty:
|
||||
"Unquoted reserved word '{{property}}' used as key.",
|
||||
unquotedNumericProperty:
|
||||
"Unquoted number literal '{{property}}' used as key.",
|
||||
unquotedPropertyFound: "Unquoted property '{{property}}' found.",
|
||||
redundantQuoting:
|
||||
"Properties shouldn't be quoted as all quotes are redundant.",
|
||||
},
|
||||
},
|
||||
fixable: "code",
|
||||
messages: {
|
||||
requireQuotesDueToReservedWord: "Properties should be quoted as '{{property}}' is a reserved word.",
|
||||
inconsistentlyQuotedProperty: "Inconsistently quoted property '{{key}}' found.",
|
||||
unnecessarilyQuotedProperty: "Unnecessarily quoted property '{{property}}' found.",
|
||||
unquotedReservedProperty: "Unquoted reserved word '{{property}}' used as key.",
|
||||
unquotedNumericProperty: "Unquoted number literal '{{property}}' used as key.",
|
||||
unquotedPropertyFound: "Unquoted property '{{property}}' found.",
|
||||
redundantQuoting: "Properties shouldn't be quoted as all quotes are redundant."
|
||||
}
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const MODE = context.options[0],
|
||||
KEYWORDS = context.options[1] && context.options[1].keywords,
|
||||
CHECK_UNNECESSARY =
|
||||
!context.options[1] || context.options[1].unnecessary !== false,
|
||||
NUMBERS = context.options[1] && context.options[1].numbers,
|
||||
sourceCode = context.sourceCode;
|
||||
create(context) {
|
||||
|
||||
/**
|
||||
* Checks whether a certain string constitutes an ES3 token
|
||||
* @param {string} tokenStr The string to be checked.
|
||||
* @returns {boolean} `true` if it is an ES3 token.
|
||||
*/
|
||||
function isKeyword(tokenStr) {
|
||||
return keywords.includes(tokenStr);
|
||||
}
|
||||
const MODE = context.options[0],
|
||||
KEYWORDS = context.options[1] && context.options[1].keywords,
|
||||
CHECK_UNNECESSARY = !context.options[1] || context.options[1].unnecessary !== false,
|
||||
NUMBERS = context.options[1] && context.options[1].numbers,
|
||||
|
||||
/**
|
||||
* Checks if an espree-tokenized key has redundant quotes (i.e. whether quotes are unnecessary)
|
||||
* @param {string} rawKey The raw key value from the source
|
||||
* @param {espreeTokens} tokens The espree-tokenized node key
|
||||
* @param {boolean} [skipNumberLiterals=false] Indicates whether number literals should be checked
|
||||
* @returns {boolean} Whether or not a key has redundant quotes.
|
||||
* @private
|
||||
*/
|
||||
function areQuotesRedundant(rawKey, tokens, skipNumberLiterals) {
|
||||
return (
|
||||
tokens.length === 1 &&
|
||||
tokens[0].start === 0 &&
|
||||
tokens[0].end === rawKey.length &&
|
||||
(["Identifier", "Keyword", "Null", "Boolean"].includes(
|
||||
tokens[0].type,
|
||||
) ||
|
||||
(tokens[0].type === "Numeric" &&
|
||||
!skipNumberLiterals &&
|
||||
String(+tokens[0].value) === tokens[0].value))
|
||||
);
|
||||
}
|
||||
sourceCode = context.sourceCode;
|
||||
|
||||
/**
|
||||
* Returns a string representation of a property node with quotes removed
|
||||
* @param {ASTNode} key Key AST Node, which may or may not be quoted
|
||||
* @returns {string} A replacement string for this property
|
||||
*/
|
||||
function getUnquotedKey(key) {
|
||||
return key.type === "Identifier" ? key.name : key.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of a property node with quotes added
|
||||
* @param {ASTNode} key Key AST Node, which may or may not be quoted
|
||||
* @returns {string} A replacement string for this property
|
||||
*/
|
||||
function getQuotedKey(key) {
|
||||
if (key.type === "Literal" && typeof key.value === "string") {
|
||||
// If the key is already a string literal, don't replace the quotes with double quotes.
|
||||
return sourceCode.getText(key);
|
||||
}
|
||||
/**
|
||||
* Checks whether a certain string constitutes an ES3 token
|
||||
* @param {string} tokenStr The string to be checked.
|
||||
* @returns {boolean} `true` if it is an ES3 token.
|
||||
*/
|
||||
function isKeyword(tokenStr) {
|
||||
return keywords.includes(tokenStr);
|
||||
}
|
||||
|
||||
// Otherwise, the key is either an identifier or a number literal.
|
||||
return `"${key.type === "Identifier" ? key.name : key.value}"`;
|
||||
}
|
||||
/**
|
||||
* Checks if an espree-tokenized key has redundant quotes (i.e. whether quotes are unnecessary)
|
||||
* @param {string} rawKey The raw key value from the source
|
||||
* @param {espreeTokens} tokens The espree-tokenized node key
|
||||
* @param {boolean} [skipNumberLiterals=false] Indicates whether number literals should be checked
|
||||
* @returns {boolean} Whether or not a key has redundant quotes.
|
||||
* @private
|
||||
*/
|
||||
function areQuotesRedundant(rawKey, tokens, skipNumberLiterals) {
|
||||
return tokens.length === 1 && tokens[0].start === 0 && tokens[0].end === rawKey.length &&
|
||||
(["Identifier", "Keyword", "Null", "Boolean"].includes(tokens[0].type) ||
|
||||
(tokens[0].type === "Numeric" && !skipNumberLiterals && String(+tokens[0].value) === tokens[0].value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that a property's key is quoted only when necessary
|
||||
* @param {ASTNode} node Property AST node
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkUnnecessaryQuotes(node) {
|
||||
const key = node.key;
|
||||
/**
|
||||
* Returns a string representation of a property node with quotes removed
|
||||
* @param {ASTNode} key Key AST Node, which may or may not be quoted
|
||||
* @returns {string} A replacement string for this property
|
||||
*/
|
||||
function getUnquotedKey(key) {
|
||||
return key.type === "Identifier" ? key.name : key.value;
|
||||
}
|
||||
|
||||
if (node.method || node.computed || node.shorthand) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Returns a string representation of a property node with quotes added
|
||||
* @param {ASTNode} key Key AST Node, which may or may not be quoted
|
||||
* @returns {string} A replacement string for this property
|
||||
*/
|
||||
function getQuotedKey(key) {
|
||||
if (key.type === "Literal" && typeof key.value === "string") {
|
||||
|
||||
if (key.type === "Literal" && typeof key.value === "string") {
|
||||
let tokens;
|
||||
// If the key is already a string literal, don't replace the quotes with double quotes.
|
||||
return sourceCode.getText(key);
|
||||
}
|
||||
|
||||
try {
|
||||
tokens = espree.tokenize(key.value);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
// Otherwise, the key is either an identifier or a number literal.
|
||||
return `"${key.type === "Identifier" ? key.name : key.value}"`;
|
||||
}
|
||||
|
||||
if (tokens.length !== 1) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Ensures that a property's key is quoted only when necessary
|
||||
* @param {ASTNode} node Property AST node
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkUnnecessaryQuotes(node) {
|
||||
const key = node.key;
|
||||
|
||||
const isKeywordToken = isKeyword(tokens[0].value);
|
||||
if (node.method || node.computed || node.shorthand) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isKeywordToken && KEYWORDS) {
|
||||
return;
|
||||
}
|
||||
if (key.type === "Literal" && typeof key.value === "string") {
|
||||
let tokens;
|
||||
|
||||
if (
|
||||
CHECK_UNNECESSARY &&
|
||||
areQuotesRedundant(key.value, tokens, NUMBERS)
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unnecessarilyQuotedProperty",
|
||||
data: { property: key.value },
|
||||
fix: fixer =>
|
||||
fixer.replaceText(key, getUnquotedKey(key)),
|
||||
});
|
||||
}
|
||||
} else if (
|
||||
KEYWORDS &&
|
||||
key.type === "Identifier" &&
|
||||
isKeyword(key.name)
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unquotedReservedProperty",
|
||||
data: { property: key.name },
|
||||
fix: fixer => fixer.replaceText(key, getQuotedKey(key)),
|
||||
});
|
||||
} else if (
|
||||
NUMBERS &&
|
||||
key.type === "Literal" &&
|
||||
astUtils.isNumericLiteral(key)
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unquotedNumericProperty",
|
||||
data: { property: key.value },
|
||||
fix: fixer => fixer.replaceText(key, getQuotedKey(key)),
|
||||
});
|
||||
}
|
||||
}
|
||||
try {
|
||||
tokens = espree.tokenize(key.value);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that a property's key is quoted
|
||||
* @param {ASTNode} node Property AST node
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkOmittedQuotes(node) {
|
||||
const key = node.key;
|
||||
if (tokens.length !== 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!node.method &&
|
||||
!node.computed &&
|
||||
!node.shorthand &&
|
||||
!(key.type === "Literal" && typeof key.value === "string")
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unquotedPropertyFound",
|
||||
data: { property: key.name || key.value },
|
||||
fix: fixer => fixer.replaceText(key, getQuotedKey(key)),
|
||||
});
|
||||
}
|
||||
}
|
||||
const isKeywordToken = isKeyword(tokens[0].value);
|
||||
|
||||
/**
|
||||
* Ensures that an object's keys are consistently quoted, optionally checks for redundancy of quotes
|
||||
* @param {ASTNode} node Property AST node
|
||||
* @param {boolean} checkQuotesRedundancy Whether to check quotes' redundancy
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkConsistency(node, checkQuotesRedundancy) {
|
||||
const quotedProps = [],
|
||||
unquotedProps = [];
|
||||
let keywordKeyName = null,
|
||||
necessaryQuotes = false;
|
||||
if (isKeywordToken && KEYWORDS) {
|
||||
return;
|
||||
}
|
||||
|
||||
node.properties.forEach(property => {
|
||||
const key = property.key;
|
||||
if (CHECK_UNNECESSARY && areQuotesRedundant(key.value, tokens, NUMBERS)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unnecessarilyQuotedProperty",
|
||||
data: { property: key.value },
|
||||
fix: fixer => fixer.replaceText(key, getUnquotedKey(key))
|
||||
});
|
||||
}
|
||||
} else if (KEYWORDS && key.type === "Identifier" && isKeyword(key.name)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unquotedReservedProperty",
|
||||
data: { property: key.name },
|
||||
fix: fixer => fixer.replaceText(key, getQuotedKey(key))
|
||||
});
|
||||
} else if (NUMBERS && key.type === "Literal" && astUtils.isNumericLiteral(key)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unquotedNumericProperty",
|
||||
data: { property: key.value },
|
||||
fix: fixer => fixer.replaceText(key, getQuotedKey(key))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!key ||
|
||||
property.method ||
|
||||
property.computed ||
|
||||
property.shorthand
|
||||
) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Ensures that a property's key is quoted
|
||||
* @param {ASTNode} node Property AST node
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkOmittedQuotes(node) {
|
||||
const key = node.key;
|
||||
|
||||
if (key.type === "Literal" && typeof key.value === "string") {
|
||||
quotedProps.push(property);
|
||||
if (!node.method && !node.computed && !node.shorthand && !(key.type === "Literal" && typeof key.value === "string")) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unquotedPropertyFound",
|
||||
data: { property: key.name || key.value },
|
||||
fix: fixer => fixer.replaceText(key, getQuotedKey(key))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (checkQuotesRedundancy) {
|
||||
let tokens;
|
||||
/**
|
||||
* Ensures that an object's keys are consistently quoted, optionally checks for redundancy of quotes
|
||||
* @param {ASTNode} node Property AST node
|
||||
* @param {boolean} checkQuotesRedundancy Whether to check quotes' redundancy
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkConsistency(node, checkQuotesRedundancy) {
|
||||
const quotedProps = [],
|
||||
unquotedProps = [];
|
||||
let keywordKeyName = null,
|
||||
necessaryQuotes = false;
|
||||
|
||||
try {
|
||||
tokens = espree.tokenize(key.value);
|
||||
} catch {
|
||||
necessaryQuotes = true;
|
||||
return;
|
||||
}
|
||||
node.properties.forEach(property => {
|
||||
const key = property.key;
|
||||
|
||||
necessaryQuotes =
|
||||
necessaryQuotes ||
|
||||
!areQuotesRedundant(key.value, tokens) ||
|
||||
(KEYWORDS && isKeyword(tokens[0].value));
|
||||
}
|
||||
} else if (
|
||||
KEYWORDS &&
|
||||
checkQuotesRedundancy &&
|
||||
key.type === "Identifier" &&
|
||||
isKeyword(key.name)
|
||||
) {
|
||||
unquotedProps.push(property);
|
||||
necessaryQuotes = true;
|
||||
keywordKeyName = key.name;
|
||||
} else {
|
||||
unquotedProps.push(property);
|
||||
}
|
||||
});
|
||||
if (!key || property.method || property.computed || property.shorthand) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
checkQuotesRedundancy &&
|
||||
quotedProps.length &&
|
||||
!necessaryQuotes
|
||||
) {
|
||||
quotedProps.forEach(property => {
|
||||
context.report({
|
||||
node: property,
|
||||
messageId: "redundantQuoting",
|
||||
fix: fixer =>
|
||||
fixer.replaceText(
|
||||
property.key,
|
||||
getUnquotedKey(property.key),
|
||||
),
|
||||
});
|
||||
});
|
||||
} else if (unquotedProps.length && keywordKeyName) {
|
||||
unquotedProps.forEach(property => {
|
||||
context.report({
|
||||
node: property,
|
||||
messageId: "requireQuotesDueToReservedWord",
|
||||
data: { property: keywordKeyName },
|
||||
fix: fixer =>
|
||||
fixer.replaceText(
|
||||
property.key,
|
||||
getQuotedKey(property.key),
|
||||
),
|
||||
});
|
||||
});
|
||||
} else if (quotedProps.length && unquotedProps.length) {
|
||||
unquotedProps.forEach(property => {
|
||||
context.report({
|
||||
node: property,
|
||||
messageId: "inconsistentlyQuotedProperty",
|
||||
data: { key: property.key.name || property.key.value },
|
||||
fix: fixer =>
|
||||
fixer.replaceText(
|
||||
property.key,
|
||||
getQuotedKey(property.key),
|
||||
),
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
if (key.type === "Literal" && typeof key.value === "string") {
|
||||
|
||||
return {
|
||||
Property(node) {
|
||||
if (MODE === "always" || !MODE) {
|
||||
checkOmittedQuotes(node);
|
||||
}
|
||||
if (MODE === "as-needed") {
|
||||
checkUnnecessaryQuotes(node);
|
||||
}
|
||||
},
|
||||
ObjectExpression(node) {
|
||||
if (MODE === "consistent") {
|
||||
checkConsistency(node, false);
|
||||
}
|
||||
if (MODE === "consistent-as-needed") {
|
||||
checkConsistency(node, true);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
quotedProps.push(property);
|
||||
|
||||
if (checkQuotesRedundancy) {
|
||||
let tokens;
|
||||
|
||||
try {
|
||||
tokens = espree.tokenize(key.value);
|
||||
} catch {
|
||||
necessaryQuotes = true;
|
||||
return;
|
||||
}
|
||||
|
||||
necessaryQuotes = necessaryQuotes || !areQuotesRedundant(key.value, tokens) || KEYWORDS && isKeyword(tokens[0].value);
|
||||
}
|
||||
} else if (KEYWORDS && checkQuotesRedundancy && key.type === "Identifier" && isKeyword(key.name)) {
|
||||
unquotedProps.push(property);
|
||||
necessaryQuotes = true;
|
||||
keywordKeyName = key.name;
|
||||
} else {
|
||||
unquotedProps.push(property);
|
||||
}
|
||||
});
|
||||
|
||||
if (checkQuotesRedundancy && quotedProps.length && !necessaryQuotes) {
|
||||
quotedProps.forEach(property => {
|
||||
context.report({
|
||||
node: property,
|
||||
messageId: "redundantQuoting",
|
||||
fix: fixer => fixer.replaceText(property.key, getUnquotedKey(property.key))
|
||||
});
|
||||
});
|
||||
} else if (unquotedProps.length && keywordKeyName) {
|
||||
unquotedProps.forEach(property => {
|
||||
context.report({
|
||||
node: property,
|
||||
messageId: "requireQuotesDueToReservedWord",
|
||||
data: { property: keywordKeyName },
|
||||
fix: fixer => fixer.replaceText(property.key, getQuotedKey(property.key))
|
||||
});
|
||||
});
|
||||
} else if (quotedProps.length && unquotedProps.length) {
|
||||
unquotedProps.forEach(property => {
|
||||
context.report({
|
||||
node: property,
|
||||
messageId: "inconsistentlyQuotedProperty",
|
||||
data: { key: property.key.name || property.key.value },
|
||||
fix: fixer => fixer.replaceText(property.key, getQuotedKey(property.key))
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
Property(node) {
|
||||
if (MODE === "always" || !MODE) {
|
||||
checkOmittedQuotes(node);
|
||||
}
|
||||
if (MODE === "as-needed") {
|
||||
checkUnnecessaryQuotes(node);
|
||||
}
|
||||
},
|
||||
ObjectExpression(node) {
|
||||
if (MODE === "consistent") {
|
||||
checkConsistency(node, false);
|
||||
}
|
||||
if (MODE === "consistent-as-needed") {
|
||||
checkConsistency(node, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user