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.
311 lines
12 KiB
JavaScript
311 lines
12 KiB
JavaScript
/**
|
|
* @fileoverview Rule to flag non-quoted property names in object literals.
|
|
* @author Mathias Bynens <http://mathiasbynens.be/>
|
|
* @deprecated in ESLint v8.53.0
|
|
*/
|
|
"use strict";
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Requirements
|
|
//------------------------------------------------------------------------------
|
|
|
|
const espree = require("espree");
|
|
const astUtils = require("./utils/ast-utils");
|
|
const keywords = require("./utils/keywords");
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Rule Definition
|
|
//------------------------------------------------------------------------------
|
|
|
|
/** @type {import('../shared/types').Rule} */
|
|
module.exports = {
|
|
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"
|
|
},
|
|
|
|
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."
|
|
}
|
|
},
|
|
|
|
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;
|
|
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
|
|
/**
|
|
* 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));
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
|
|
// Otherwise, the key is either an identifier or a number literal.
|
|
return `"${key.type === "Identifier" ? key.name : key.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;
|
|
|
|
if (node.method || node.computed || node.shorthand) {
|
|
return;
|
|
}
|
|
|
|
if (key.type === "Literal" && typeof key.value === "string") {
|
|
let tokens;
|
|
|
|
try {
|
|
tokens = espree.tokenize(key.value);
|
|
} catch {
|
|
return;
|
|
}
|
|
|
|
if (tokens.length !== 1) {
|
|
return;
|
|
}
|
|
|
|
const isKeywordToken = isKeyword(tokens[0].value);
|
|
|
|
if (isKeywordToken && KEYWORDS) {
|
|
return;
|
|
}
|
|
|
|
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))
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ensures that a property's key is quoted
|
|
* @param {ASTNode} node Property AST node
|
|
* @returns {void}
|
|
*/
|
|
function checkOmittedQuotes(node) {
|
|
const key = node.key;
|
|
|
|
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))
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
|
|
node.properties.forEach(property => {
|
|
const key = property.key;
|
|
|
|
if (!key || property.method || property.computed || property.shorthand) {
|
|
return;
|
|
}
|
|
|
|
if (key.type === "Literal" && typeof key.value === "string") {
|
|
|
|
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);
|
|
}
|
|
}
|
|
};
|
|
|
|
}
|
|
};
|