line_push/node_modules/eslint-plugin-unicorn/rules/string-content.js
2022-07-17 13:16:16 +08:00

186 lines
3.3 KiB
JavaScript

'use strict';
const getDocumentationUrl = require('./utils/get-documentation-url');
const quoteString = require('./utils/quote-string');
const replaceTemplateElement = require('./utils/replace-template-element');
const escapeTemplateElementRaw = require('./utils/escape-template-element-raw');
const ignoredIdentifier = new Set([
'gql',
'html',
'svg'
]);
const ignoredMemberExpressionObject = new Set([
'styled'
]);
const isIgnoredTag = node => {
if (!node.parent || !node.parent.parent || !node.parent.parent.tag) {
return false;
}
const {tag} = node.parent.parent;
if (tag.type === 'Identifier' && ignoredIdentifier.has(tag.name)) {
return true;
}
if (tag.type === 'MemberExpression') {
const {object} = tag;
if (
object.type === 'Identifier' &&
ignoredMemberExpressionObject.has(object.name)
) {
return true;
}
}
return false;
};
const defaultMessage = 'Prefer `{{suggest}}` over `{{match}}`.';
const SUGGESTION_MESSAGE_ID = 'replace';
function getReplacements(patterns) {
return Object.entries(patterns)
.map(([match, options]) => {
if (typeof options === 'string') {
options = {
suggest: options
};
}
return {
match,
regex: new RegExp(match, 'gu'),
fix: true,
...options
};
});
}
const create = context => {
const {patterns} = {
patterns: {},
...context.options[0]
};
const replacements = getReplacements(patterns);
if (replacements.length === 0) {
return {};
}
return {
'Literal, TemplateElement': node => {
const {type} = node;
let string;
if (type === 'Literal') {
string = node.value;
} else if (!isIgnoredTag(node)) {
string = node.value.raw;
}
if (!string || typeof string !== 'string') {
return;
}
const replacement = replacements.find(({regex}) => regex.test(string));
if (!replacement) {
return;
}
const {fix: autoFix, message = defaultMessage, match, suggest} = replacement;
const messageData = {
match,
suggest
};
const problem = {
node,
message,
data: messageData
};
const fixed = string.replace(replacement.regex, suggest);
const fix = type === 'Literal' ?
fixer => fixer.replaceText(
node,
quoteString(fixed, node.raw[0])
) :
fixer => replaceTemplateElement(
fixer,
node,
escapeTemplateElementRaw(fixed)
);
if (autoFix) {
problem.fix = fix;
} else {
problem.suggest = [
{
messageId: SUGGESTION_MESSAGE_ID,
data: messageData,
fix
}
];
}
context.report(problem);
}
};
};
const schema = [
{
type: 'object',
properties: {
patterns: {
type: 'object',
additionalProperties: {
anyOf: [
{
type: 'string'
},
{
type: 'object',
required: [
'suggest'
],
properties: {
suggest: {
type: 'string'
},
fix: {
type: 'boolean'
// Default: true
},
message: {
type: 'string'
// Default: ''
}
},
additionalProperties: false
}
]
}}
},
additionalProperties: false
}
];
module.exports = {
create,
meta: {
type: 'suggestion',
docs: {
url: getDocumentationUrl(__filename)
},
fixable: 'code',
schema,
messages: {
[SUGGESTION_MESSAGE_ID]: 'Replace `{{match}}` with `{{suggest}}`.'
}
}
};