eslint-plugin-stylistic-compat
Version:
Compatibility version of @stylistic/eslint-plugin for Node.js >= 12 and ESLint v8
325 lines (321 loc) • 16.6 kB
JavaScript
'use strict';
var _Object$assign = require('/runtime-corejs3/core-js/object/assign');
var _includesInstanceProperty = require('/runtime-corejs3/core-js/instance/includes');
var _trimInstanceProperty = require('/runtime-corejs3/core-js/instance/trim');
var _mapInstanceProperty = require('/runtime-corejs3/core-js/instance/map');
var _JSON$stringify = require('/runtime-corejs3/core-js/json/stringify');
var _reduceInstanceProperty = require('/runtime-corejs3/core-js/instance/reduce');
var _sliceInstanceProperty = require('/runtime-corejs3/core-js/instance/slice');
var _filterInstanceProperty = require('/runtime-corejs3/core-js/instance/filter');
var _someInstanceProperty = require('/runtime-corejs3/core-js/instance/some');
var utils = require('../utils.js');
require('/runtime-corejs3/core-js/object/from-entries');
require('/runtime-corejs3/core-js/object/entries');
require('/runtime-corejs3/core-js/set');
require('/runtime-corejs3/core-js/instance/flags');
require('/runtime-corejs3/core-js/instance/starts-with');
require('../vendor.js');
require('/runtime-corejs3/core-js/object/create');
require('/runtime-corejs3/core-js/object/freeze');
require('/runtime-corejs3/core-js/array/is-array');
require('/runtime-corejs3/core-js/instance/last-index-of');
require('/runtime-corejs3/core-js/object/define-properties');
require('/runtime-corejs3/core-js/object/keys');
require('/runtime-corejs3/core-js/instance/index-of');
require('/runtime-corejs3/core-js/instance/at');
require('/runtime-corejs3/core-js/symbol');
require('/runtime-corejs3/core-js/symbol/iterator');
require('/runtime-corejs3/core-js/parse-int');
require('/runtime-corejs3/core-js/parse-float');
require('/runtime-corejs3/core-js/weak-map');
require('/runtime-corejs3/core-js/object/define-property');
require('/runtime-corejs3/core-js/global-this');
require('/runtime-corejs3/core-js/instance/for-each');
require('/runtime-corejs3/core-js/array/from');
require('eslint/use-at-your-own-risk');
require('eslint');
require('/runtime-corejs3/core-js/object/get-own-property-descriptor');
require('/runtime-corejs3/core-js/map');
require('/runtime-corejs3/core-js/instance/find');
require('/runtime-corejs3/core-js/instance/every');
require('/runtime-corejs3/core-js/instance/sort');
require('/runtime-corejs3/core-js/array/of');
require('/runtime-corejs3/core-js/instance/concat');
require('/runtime-corejs3/core-js/instance/entries');
require('/runtime-corejs3/core-js/instance/find-index');
require('/runtime-corejs3/core-js/instance/flat');
require('/runtime-corejs3/core-js/instance/keys');
require('/runtime-corejs3/core-js/instance/values');
require('/runtime-corejs3/core-js/object/get-own-property-names');
require('/runtime-corejs3/core-js/number/is-finite');
require('/runtime-corejs3/core-js/number/is-nan');
require('/runtime-corejs3/core-js/number/parse-float');
require('/runtime-corejs3/core-js/number/parse-int');
require('/runtime-corejs3/core-js/object/is');
require('/runtime-corejs3/core-js/object/is-extensible');
require('/runtime-corejs3/core-js/object/is-frozen');
require('/runtime-corejs3/core-js/object/is-sealed');
require('/runtime-corejs3/core-js/object/values');
require('/runtime-corejs3/core-js/string/from-code-point');
require('/runtime-corejs3/core-js/string/raw');
require('/runtime-corejs3/core-js/instance/code-point-at');
require('/runtime-corejs3/core-js/instance/ends-with');
require('/runtime-corejs3/core-js/instance/pad-end');
require('/runtime-corejs3/core-js/instance/pad-start');
require('/runtime-corejs3/core-js/instance/trim-end');
require('/runtime-corejs3/core-js/instance/trim-left');
require('/runtime-corejs3/core-js/instance/trim-right');
require('/runtime-corejs3/core-js/instance/trim-start');
require('/runtime-corejs3/core-js/symbol/for');
require('/runtime-corejs3/core-js/symbol/key-for');
require('/runtime-corejs3/core-js/object/prevent-extensions');
require('/runtime-corejs3/core-js/object/seal');
require('/runtime-corejs3/core-js/object/get-prototype-of');
require('/runtime-corejs3/core-js/symbol/replace');
require('/runtime-corejs3/core-js/instance/bind');
require('/runtime-corejs3/core-js/instance/splice');
require('/runtime-corejs3/core-js/instance/repeat');
require('/runtime-corejs3/core-js/instance/reverse');
const OPTION_ALWAYS = "always";
const OPTION_NEVER = "never";
const OPTION_IGNORE = "ignore";
const OPTION_VALUES = [OPTION_ALWAYS, OPTION_NEVER, OPTION_IGNORE];
const DEFAULT_CONFIG = {
props: OPTION_NEVER,
children: OPTION_NEVER,
propElementValues: OPTION_IGNORE
};
const messages = {
unnecessaryCurly: "Curly braces are unnecessary here.",
missingCurly: "Need to wrap this literal in a JSX expression."
};
var jsxCurlyBracePresence = utils.createRule({
name: "jsx-curly-brace-presence",
package: "jsx",
meta: {
type: "layout",
docs: {
description: "Disallow unnecessary JSX expressions when literals alone are sufficient or enforce JSX expressions on literals in JSX children or attributes"
},
fixable: "code",
messages,
schema: [{
anyOf: [{
type: "object",
properties: {
props: {
type: "string",
enum: OPTION_VALUES
},
children: {
type: "string",
enum: OPTION_VALUES
},
propElementValues: {
type: "string",
enum: OPTION_VALUES
}
},
additionalProperties: false
}, {
type: "string",
enum: OPTION_VALUES
}]
}]
},
create(context) {
const HTML_ENTITY_REGEX = () => /&[A-Z\d#]+;/gi;
const ruleOptions = context.options[0];
const userConfig = typeof ruleOptions === "string" ? {
props: ruleOptions,
children: ruleOptions,
propElementValues: OPTION_IGNORE
} : _Object$assign({}, DEFAULT_CONFIG, ruleOptions);
function containsLineTerminators(rawStringValue) {
return /[\n\r\u2028\u2029]/.test(rawStringValue);
}
function containsBackslash(rawStringValue) {
return _includesInstanceProperty(rawStringValue).call(rawStringValue, "\\");
}
function containsHTMLEntity(rawStringValue) {
return HTML_ENTITY_REGEX().test(rawStringValue);
}
function containsOnlyHtmlEntities(rawStringValue) {
var _context;
return _trimInstanceProperty(_context = rawStringValue.replace(HTML_ENTITY_REGEX(), "")).call(_context) === "";
}
function containsDisallowedJSXTextChars(rawStringValue) {
return /[{<>}]/.test(rawStringValue);
}
function containsQuoteCharacters(value) {
return /['"]/.test(value);
}
function containsMultilineComment(value) {
return /\/\*/.test(value);
}
function escapeDoubleQuotes(rawStringValue) {
return rawStringValue.replace(/\\"/g, '"').replace(/"/g, '\\"');
}
function escapeBackslashes(rawStringValue) {
return rawStringValue.replace(/\\/g, "\\\\");
}
function needToEscapeCharacterForJSX(raw, node) {
return containsBackslash(raw) || containsHTMLEntity(raw) || node.parent.type !== "JSXAttribute" && containsDisallowedJSXTextChars(raw);
}
function containsWhitespaceExpression(child) {
if (child.type === "JSXExpressionContainer") {
const value = child.expression.value;
return value ? utils.isWhiteSpaces(value) : false;
}
return false;
}
function isLineBreak(text) {
return containsLineTerminators(text) && _trimInstanceProperty(text).call(text) === "";
}
function wrapNonHTMLEntities(text) {
var _context2;
const HTML_ENTITY = "<HTML_ENTITY>";
const withCurlyBraces = _mapInstanceProperty(_context2 = text.split(HTML_ENTITY_REGEX())).call(_context2, word => word === "" ? "" : `{${_JSON$stringify(word)}}`).join(HTML_ENTITY);
const htmlEntities = text.match(HTML_ENTITY_REGEX());
return _reduceInstanceProperty(htmlEntities).call(htmlEntities, (acc, htmlEntity) => acc.replace(HTML_ENTITY, htmlEntity), withCurlyBraces);
}
function wrapWithCurlyBraces(rawText) {
var _context3;
if (!containsLineTerminators(rawText)) return `{${_JSON$stringify(rawText)}}`;
return _mapInstanceProperty(_context3 = rawText.split("\n")).call(_context3, line => {
if (_trimInstanceProperty(line).call(line) === "") return line;
const firstCharIndex = line.search(/\S/);
const leftWhitespace = _sliceInstanceProperty(line).call(line, 0, firstCharIndex);
const text = _sliceInstanceProperty(line).call(line, firstCharIndex);
if (containsHTMLEntity(line)) return `${leftWhitespace}${wrapNonHTMLEntities(text)}`;
return `${leftWhitespace}{${_JSON$stringify(text)}}`;
}).join("\n");
}
function reportUnnecessaryCurly(JSXExpressionNode) {
context.report({
messageId: "unnecessaryCurly",
node: JSXExpressionNode,
fix(fixer) {
const expression = JSXExpressionNode.expression;
let textToReplace;
if (utils.isJSX(expression)) {
const sourceCode = context.sourceCode;
textToReplace = sourceCode.getText(expression);
} else {
const parentType = JSXExpressionNode.parent.type;
if (parentType === "JSXAttribute") {
var _context4;
textToReplace = `"${expression.type === "TemplateLiteral" ? expression.quasis[0].value.raw : _sliceInstanceProperty(_context4 = expression.raw).call(_context4, 1, -1)}"`;
} else if (utils.isJSX(expression)) {
const sourceCode = context.sourceCode;
textToReplace = sourceCode.getText(expression);
} else {
textToReplace = expression.type === "TemplateLiteral" ? expression.quasis[0].value.cooked : expression.value;
}
}
return fixer.replaceText(JSXExpressionNode, textToReplace);
}
});
}
function reportMissingCurly(literalNode) {
context.report({
messageId: "missingCurly",
node: literalNode,
fix(fixer) {
var _context5;
if (utils.isJSX(literalNode)) return fixer.replaceText(literalNode, `{${context.sourceCode.getText(literalNode)}}`);
if (containsOnlyHtmlEntities(literalNode.raw) || literalNode.parent.type === "JSXAttribute" && containsLineTerminators(literalNode.raw) || isLineBreak(literalNode.raw)) {
return null;
}
const expression = literalNode.parent.type === "JSXAttribute" ? `{"${escapeDoubleQuotes(escapeBackslashes(_sliceInstanceProperty(_context5 = literalNode.raw).call(_context5, 1, -1)))}"}` : wrapWithCurlyBraces(literalNode.raw);
return fixer.replaceText(literalNode, expression);
}
});
}
function isWhiteSpaceLiteral(node) {
return node.type && node.type === "Literal" && node.value && utils.isWhiteSpaces(node.value);
}
function isStringWithTrailingWhiteSpaces(value) {
return /^\s|\s$/.test(value);
}
function isLiteralWithTrailingWhiteSpaces(node) {
return node.type && node.type === "Literal" && node.value && isStringWithTrailingWhiteSpaces(node.value);
}
function lintUnnecessaryCurly(JSXExpressionNode) {
var _context6;
const expression = JSXExpressionNode.expression;
const expressionType = expression.type;
const sourceCode = context.sourceCode;
if (sourceCode.getCommentsInside && sourceCode.getCommentsInside(JSXExpressionNode).length > 0) return;
if ((expressionType === "Literal" || expressionType === "JSXText") && typeof expression.value === "string" && (JSXExpressionNode.parent.type === "JSXAttribute" && !isWhiteSpaceLiteral(expression) || !isLiteralWithTrailingWhiteSpaces(expression)) && !containsMultilineComment(expression.value) && !needToEscapeCharacterForJSX(expression.raw, JSXExpressionNode) && (utils.isJSX(JSXExpressionNode.parent) || !containsQuoteCharacters(expression.value))) {
reportUnnecessaryCurly(JSXExpressionNode);
} else if (expressionType === "TemplateLiteral" && expression.expressions.length === 0 && !_includesInstanceProperty(_context6 = expression.quasis[0].value.raw).call(_context6, "\n") && !isStringWithTrailingWhiteSpaces(expression.quasis[0].value.raw) && !needToEscapeCharacterForJSX(expression.quasis[0].value.raw, JSXExpressionNode) && !containsQuoteCharacters(expression.quasis[0].value.cooked)) {
reportUnnecessaryCurly(JSXExpressionNode);
} else if (utils.isJSX(expression)) {
reportUnnecessaryCurly(JSXExpressionNode);
}
}
function areRuleConditionsSatisfied(parent, config, ruleCondition) {
return parent.type === "JSXAttribute" && typeof config.props === "string" && config.props === ruleCondition || utils.isJSX(parent) && typeof config.children === "string" && config.children === ruleCondition;
}
function getAdjacentSiblings(node, children) {
for (let i = 1; i < children.length - 1; i++) {
const child = children[i];
if (node === child) return [children[i - 1], children[i + 1]];
}
if (node === children[0] && children[1]) return [children[1]];
if (node === children[children.length - 1] && children[children.length - 2]) return [children[children.length - 2]];
return [];
}
function hasAdjacentJsxExpressionContainers(node, children) {
if (!children) return false;
const childrenExcludingWhitespaceLiteral = _filterInstanceProperty(children).call(children, child => !isWhiteSpaceLiteral(child));
const adjSiblings = getAdjacentSiblings(node, childrenExcludingWhitespaceLiteral);
return _someInstanceProperty(adjSiblings).call(adjSiblings, x => x.type && x.type === "JSXExpressionContainer");
}
function hasAdjacentJsx(node, children) {
if (!children) return false;
const childrenExcludingWhitespaceLiteral = _filterInstanceProperty(children).call(children, child => !isWhiteSpaceLiteral(child));
const adjSiblings = getAdjacentSiblings(node, childrenExcludingWhitespaceLiteral);
return _someInstanceProperty(adjSiblings).call(adjSiblings, x => {
var _context7;
return x.type && _includesInstanceProperty(_context7 = ["JSXExpressionContainer", "JSXElement"]).call(_context7, x.type);
});
}
function shouldCheckForUnnecessaryCurly(node, config) {
const parent = node.parent;
if (parent.type && parent.type === "JSXAttribute" && node.expression && node.expression.type && node.expression.type !== "Literal" && node.expression.type !== "StringLiteral" && node.expression.type !== "TemplateLiteral") {
return false;
}
if (utils.isJSX(parent) && hasAdjacentJsxExpressionContainers(node, parent.children)) return false;
if (containsWhitespaceExpression(node) && hasAdjacentJsx(node, parent.children)) return false;
if (parent.children && parent.children.length === 1 && containsWhitespaceExpression(node)) {
return false;
}
return areRuleConditionsSatisfied(parent, config, OPTION_NEVER);
}
function shouldCheckForMissingCurly(node, config) {
if (utils.isJSX(node)) return config.propElementValues !== OPTION_IGNORE;
if (isLineBreak(node.raw) || containsOnlyHtmlEntities(node.raw)) {
return false;
}
const parent = node.parent;
if (parent.children && parent.children.length === 1 && containsWhitespaceExpression(parent.children[0])) {
return false;
}
return areRuleConditionsSatisfied(parent, config, OPTION_ALWAYS);
}
return {
"JSXAttribute > JSXExpressionContainer > JSXElement": function (node) {
if (userConfig.propElementValues === OPTION_NEVER) reportUnnecessaryCurly(node.parent);
},
JSXExpressionContainer(node) {
if (shouldCheckForUnnecessaryCurly(node, userConfig)) lintUnnecessaryCurly(node);
},
"JSXAttribute > JSXElement, Literal, JSXText": function (node) {
if (shouldCheckForMissingCurly(node, userConfig)) reportMissingCurly(node);
}
};
}
});
module.exports = jsxCurlyBracePresence;