@angular-eslint/eslint-plugin 17.2.2-alpha.7 → 17.2.2-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/configs/all.json +1 -0
- package/dist/index.js +2 -0
- package/dist/rules/consistent-component-styles.js +96 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
| [`component-class-suffix`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/component-class-suffix.md) | Classes decorated with @Component must have suffix "Component" (or custom) in their name. See more at https://angular.io/styleguide#style-02-03 | :white_check_mark: | | |
|
|
44
44
|
| [`component-max-inline-declarations`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/component-max-inline-declarations.md) | Enforces a maximum number of lines in inline template, styles and animations. See more at https://angular.io/guide/styleguide#style-05-04 | | | |
|
|
45
45
|
| [`component-selector`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/component-selector.md) | Component selectors should follow given naming rules. See more at https://angular.io/guide/styleguide#style-02-07, https://angular.io/guide/styleguide#style-05-02 and https://angular.io/guide/styleguide#style-05-03. | | | |
|
|
46
|
+
| [`consistent-component-styles`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/consistent-component-styles.md) | Ensures component `styles`/`styleUrl` with `string` is used over `styles`/`styleUrls` when there is only a single string in the array | | :wrench: | |
|
|
46
47
|
| [`contextual-decorator`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/contextual-decorator.md) | Ensures that classes use contextual decorators in its body | | | |
|
|
47
48
|
| [`directive-class-suffix`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/directive-class-suffix.md) | Classes decorated with @Directive must have suffix "Directive" (or custom) in their name. See more at https://angular.io/styleguide#style-02-03 | :white_check_mark: | | |
|
|
48
49
|
| [`directive-selector`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/directive-selector.md) | Directive selectors should follow given naming rules. See more at https://angular.io/guide/styleguide#style-02-06 and https://angular.io/guide/styleguide#style-02-08. | | | |
|
package/dist/configs/all.json
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"@angular-eslint/component-class-suffix": "error",
|
|
6
6
|
"@angular-eslint/component-max-inline-declarations": "error",
|
|
7
7
|
"@angular-eslint/component-selector": "error",
|
|
8
|
+
"@angular-eslint/consistent-component-styles": "error",
|
|
8
9
|
"@angular-eslint/contextual-decorator": "error",
|
|
9
10
|
"@angular-eslint/contextual-lifecycle": "error",
|
|
10
11
|
"@angular-eslint/directive-class-suffix": "error",
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ const recommended_json_1 = __importDefault(require("./configs/recommended.json")
|
|
|
30
30
|
const component_class_suffix_1 = __importStar(require("./rules/component-class-suffix"));
|
|
31
31
|
const component_max_inline_declarations_1 = __importStar(require("./rules/component-max-inline-declarations"));
|
|
32
32
|
const component_selector_1 = __importStar(require("./rules/component-selector"));
|
|
33
|
+
const consistent_component_styles_1 = __importStar(require("./rules/consistent-component-styles"));
|
|
33
34
|
const contextual_decorator_1 = __importStar(require("./rules/contextual-decorator"));
|
|
34
35
|
const contextual_lifecycle_1 = __importStar(require("./rules/contextual-lifecycle"));
|
|
35
36
|
const directive_class_suffix_1 = __importStar(require("./rules/directive-class-suffix"));
|
|
@@ -72,6 +73,7 @@ module.exports = {
|
|
|
72
73
|
[component_class_suffix_1.RULE_NAME]: component_class_suffix_1.default,
|
|
73
74
|
[component_max_inline_declarations_1.RULE_NAME]: component_max_inline_declarations_1.default,
|
|
74
75
|
[component_selector_1.RULE_NAME]: component_selector_1.default,
|
|
76
|
+
[consistent_component_styles_1.RULE_NAME]: consistent_component_styles_1.default,
|
|
75
77
|
[contextual_decorator_1.RULE_NAME]: contextual_decorator_1.default,
|
|
76
78
|
[contextual_lifecycle_1.RULE_NAME]: contextual_lifecycle_1.default,
|
|
77
79
|
[directive_class_suffix_1.RULE_NAME]: directive_class_suffix_1.default,
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RULE_NAME = void 0;
|
|
4
|
+
const utils_1 = require("@angular-eslint/utils");
|
|
5
|
+
const create_eslint_rule_1 = require("../utils/create-eslint-rule");
|
|
6
|
+
exports.RULE_NAME = 'consistent-component-styles';
|
|
7
|
+
exports.default = (0, create_eslint_rule_1.createESLintRule)({
|
|
8
|
+
name: exports.RULE_NAME,
|
|
9
|
+
meta: {
|
|
10
|
+
type: 'suggestion',
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Ensures consistent usage of `styles`/`styleUrls`/`styleUrl` within Component metadata',
|
|
13
|
+
},
|
|
14
|
+
fixable: 'code',
|
|
15
|
+
schema: [
|
|
16
|
+
{
|
|
17
|
+
type: 'string',
|
|
18
|
+
enum: ['array', 'string'],
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
messages: {
|
|
22
|
+
useStyleUrl: 'Use `styleUrl` instead of `styleUrls` for a single stylesheet',
|
|
23
|
+
useStyleUrls: 'Use `styleUrls` instead of `styleUrl`',
|
|
24
|
+
useStylesArray: 'Use a `string[]` instead of a `string` for the `styles` property',
|
|
25
|
+
useStylesString: 'Use a `string` instead of a `string[]` for the `styles` property',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
defaultOptions: ['string'],
|
|
29
|
+
create(context, [mode]) {
|
|
30
|
+
const { COMPONENT_CLASS_DECORATOR, metadataProperty } = utils_1.Selectors;
|
|
31
|
+
const LITERAL_OR_TEMPLATE_LITERAL = ':matches(Literal, TemplateLiteral)';
|
|
32
|
+
if (mode === 'array') {
|
|
33
|
+
const stylesStringExpression = `${COMPONENT_CLASS_DECORATOR} ${metadataProperty('styles')} > ${LITERAL_OR_TEMPLATE_LITERAL}`;
|
|
34
|
+
const styleUrlProperty = `${COMPONENT_CLASS_DECORATOR} ${metadataProperty('styleUrl')}:has(:matches(Literal, TemplateElement))`;
|
|
35
|
+
return {
|
|
36
|
+
[stylesStringExpression](node) {
|
|
37
|
+
context.report({
|
|
38
|
+
node,
|
|
39
|
+
messageId: 'useStylesArray',
|
|
40
|
+
fix: (fixer) => {
|
|
41
|
+
return fixer.replaceText(node, utils_1.ASTUtils.isStringLiteral(node)
|
|
42
|
+
? `[${node.raw}]`
|
|
43
|
+
: `[${context.getSourceCode().getText(node)}]`);
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
[styleUrlProperty](node) {
|
|
48
|
+
context.report({
|
|
49
|
+
node,
|
|
50
|
+
messageId: 'useStyleUrls',
|
|
51
|
+
fix: (fixer) => {
|
|
52
|
+
return fixer.replaceText(node, utils_1.ASTUtils.isStringLiteral(node.value)
|
|
53
|
+
? `styleUrls: [${node.value.raw}]`
|
|
54
|
+
: `styleUrls: [${context
|
|
55
|
+
.getSourceCode()
|
|
56
|
+
.getText(node.value)}]`);
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
const singleArrayStringLiteral = `ArrayExpression:matches([elements.length=1]:has(${LITERAL_OR_TEMPLATE_LITERAL}))`;
|
|
64
|
+
const singleStylesArrayExpression = `${COMPONENT_CLASS_DECORATOR} ${metadataProperty('styles')} > ${singleArrayStringLiteral}`;
|
|
65
|
+
const singleStyleUrlsProperty = `${COMPONENT_CLASS_DECORATOR} ${metadataProperty('styleUrls')}:has(${singleArrayStringLiteral})`;
|
|
66
|
+
return {
|
|
67
|
+
[singleStylesArrayExpression](node) {
|
|
68
|
+
// The selector ensures the element is not null.
|
|
69
|
+
const el = node.elements[0];
|
|
70
|
+
context.report({
|
|
71
|
+
node,
|
|
72
|
+
messageId: 'useStylesString',
|
|
73
|
+
fix: (fixer) => {
|
|
74
|
+
return fixer.replaceText(node, utils_1.ASTUtils.isStringLiteral(el)
|
|
75
|
+
? el.raw
|
|
76
|
+
: context.getSourceCode().getText(el));
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
[singleStyleUrlsProperty](node) {
|
|
81
|
+
// The selector ensures the value is an array with a single non-null element.
|
|
82
|
+
const el = node.value.elements[0];
|
|
83
|
+
context.report({
|
|
84
|
+
node,
|
|
85
|
+
messageId: 'useStyleUrl',
|
|
86
|
+
fix: (fixer) => {
|
|
87
|
+
return fixer.replaceText(node, utils_1.ASTUtils.isStringLiteral(el)
|
|
88
|
+
? `styleUrl: ${el.raw}`
|
|
89
|
+
: `styleUrl: ${context.getSourceCode().getText(el)}`);
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-eslint/eslint-plugin",
|
|
3
|
-
"version": "17.2.2-alpha.
|
|
3
|
+
"version": "17.2.2-alpha.8",
|
|
4
4
|
"description": "ESLint plugin for Angular applications, following angular.io/styleguide",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"LICENSE"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@angular-eslint/utils": "17.2.2-alpha.
|
|
20
|
+
"@angular-eslint/utils": "17.2.2-alpha.8",
|
|
21
21
|
"@typescript-eslint/utils": "7.2.0"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|