@raycast/eslint-plugin
Version:
ESLint plugin designed to help Raycast's extensions authors follow best practices
113 lines (112 loc) • 6.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const utils_2 = require("../utils");
const title_case_1 = require("../title-case");
exports.default = (0, utils_2.createRule)({
create: (context) => {
return {
JSXOpeningElement: (node) => {
if ((0, utils_2.isActionComponent)(node.name)) {
const titleAttribute = node.attributes.find((attribute) => {
return (attribute.type === "JSXAttribute" &&
attribute.name.name === "title");
});
if (titleAttribute) {
const value = titleAttribute.type === "JSXAttribute" && titleAttribute.value;
if (value) {
if (value.type === utils_1.AST_NODE_TYPES.Literal &&
typeof value.value === "string") {
const originalTitle = value.value;
const formattedTitle = (0, title_case_1.titleCase)(originalTitle);
if (originalTitle !== formattedTitle) {
context.report({
node: value,
messageId: "isNotTitleCased",
fix: (fixer) => fixer.replaceText(value, `"${formattedTitle}"`),
});
}
}
if (value.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer) {
const expression = value.expression;
if (expression.type === utils_1.AST_NODE_TYPES.Literal &&
expression.value &&
typeof expression.value === "string") {
const formattedTitle = (0, title_case_1.titleCase)(expression.value);
if (expression.value !== formattedTitle) {
context.report({
node: expression,
messageId: "isNotTitleCased",
fix: (fixer) => fixer.replaceText(expression, `"${formattedTitle}"`),
});
}
}
if (expression.type === utils_1.AST_NODE_TYPES.ConditionalExpression) {
const consequent = expression.consequent;
const alternate = expression.alternate;
if (consequent.type === utils_1.AST_NODE_TYPES.Literal &&
consequent.value &&
typeof consequent.value === "string") {
const formattedTitle = (0, title_case_1.titleCase)(consequent.value);
if (consequent.value !== formattedTitle) {
context.report({
node: consequent,
messageId: "isNotTitleCased",
fix: (fixer) => fixer.replaceText(consequent, `"${formattedTitle}"`),
});
}
}
if (alternate.type === utils_1.AST_NODE_TYPES.Literal &&
alternate.value &&
typeof alternate.value === "string") {
const formattedTitle = (0, title_case_1.titleCase)(alternate.value);
if (alternate.value !== formattedTitle) {
context.report({
node: alternate,
messageId: "isNotTitleCased",
fix: (fixer) => fixer.replaceText(alternate, `"${formattedTitle}"`),
});
}
}
}
if (expression.type === utils_1.AST_NODE_TYPES.TemplateLiteral) {
const quasis = expression.quasis;
var hasQuasiWithoutTitleCase = false;
quasis.forEach((quasi) => {
if (quasi.type === utils_1.AST_NODE_TYPES.TemplateElement &&
quasi.value &&
typeof quasi.value.raw === "string") {
const formattedTitle = (0, title_case_1.titleCase)(quasi.value.raw);
if (quasi.value.raw !== formattedTitle) {
hasQuasiWithoutTitleCase = true;
}
}
});
if (hasQuasiWithoutTitleCase) {
return context.report({
node: expression,
messageId: "isNotTitleCased",
});
}
}
}
}
}
}
},
};
},
name: "prefer-title-case",
meta: {
fixable: "code",
messages: {
isNotTitleCased: "Prefer Title Case naming convention for action titles (e.g Copy to Clipboard).",
},
type: "suggestion",
docs: {
description: "Prefer Title Case",
},
schema: [],
},
defaultOptions: [],
});