@angular-eslint/eslint-plugin
Version:
ESLint plugin for Angular applications, following https://angular.dev/style-guide
97 lines (96 loc) • 4.56 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RULE_NAME = void 0;
const utils_1 = require("@angular-eslint/utils");
const create_eslint_rule_1 = require("../utils/create-eslint-rule");
exports.RULE_NAME = 'consistent-component-styles';
exports.default = (0, create_eslint_rule_1.createESLintRule)({
name: exports.RULE_NAME,
meta: {
type: 'suggestion',
docs: {
description: 'Ensures consistent usage of `styles`/`styleUrls`/`styleUrl` within Component metadata',
},
fixable: 'code',
schema: [
{
type: 'string',
enum: ['array', 'string'],
},
],
messages: {
useStyleUrl: 'Use `styleUrl` instead of `styleUrls` for a single stylesheet',
useStyleUrls: 'Use `styleUrls` instead of `styleUrl`',
useStylesArray: 'Use a `string[]` instead of a `string` for the `styles` property',
useStylesString: 'Use a `string` instead of a `string[]` for the `styles` property',
},
},
defaultOptions: ['string'],
create(context, [mode]) {
const { COMPONENT_CLASS_DECORATOR, metadataProperty } = utils_1.Selectors;
const LITERAL_OR_TEMPLATE_LITERAL = ':matches(Literal, TemplateLiteral)';
if (mode === 'array') {
const stylesStringExpression = `${COMPONENT_CLASS_DECORATOR} ${metadataProperty('styles')} > ${LITERAL_OR_TEMPLATE_LITERAL}`;
const styleUrlProperty = `${COMPONENT_CLASS_DECORATOR} ${metadataProperty('styleUrl')}:has(:matches(Literal, TemplateElement))`;
return {
[stylesStringExpression](node) {
context.report({
node,
messageId: 'useStylesArray',
fix: (fixer) => {
return fixer.replaceText(node, utils_1.ASTUtils.isStringLiteral(node)
? `[${node.raw}]`
: `[${context.sourceCode.getText(node)}]`);
},
});
},
[styleUrlProperty](node) {
context.report({
node,
messageId: 'useStyleUrls',
fix: (fixer) => {
return fixer.replaceText(node, utils_1.ASTUtils.isStringLiteral(node.value)
? `styleUrls: [${node.value.raw}]`
: `styleUrls: [${context
.getSourceCode()
.getText(node.value)}]`);
},
});
},
};
}
else {
const singleArrayStringLiteral = `ArrayExpression:matches([elements.length=1]:has(${LITERAL_OR_TEMPLATE_LITERAL}))`;
const singleStylesArrayExpression = `${COMPONENT_CLASS_DECORATOR} ${metadataProperty('styles')} > ${singleArrayStringLiteral}`;
const singleStyleUrlsProperty = `${COMPONENT_CLASS_DECORATOR} ${metadataProperty('styleUrls')}:has(${singleArrayStringLiteral})`;
return {
[singleStylesArrayExpression](node) {
// The selector ensures the element is not null.
const el = node.elements[0];
context.report({
node,
messageId: 'useStylesString',
fix: (fixer) => {
return fixer.replaceText(node, utils_1.ASTUtils.isStringLiteral(el)
? el.raw
: context.sourceCode.getText(el));
},
});
},
[singleStyleUrlsProperty](node) {
// The selector ensures the value is an array with a single non-null element.
const el = node.value.elements[0];
context.report({
node,
messageId: 'useStyleUrl',
fix: (fixer) => {
return fixer.replaceText(node, utils_1.ASTUtils.isStringLiteral(el)
? `styleUrl: ${el.raw}`
: `styleUrl: ${context.sourceCode.getText(el)}`);
},
});
},
};
}
},
});