@angular-eslint/eslint-plugin 17.2.2-alpha.7 → 17.2.2-alpha.9

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 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. | | | |
@@ -63,7 +64,7 @@
63
64
  | [`pipe-prefix`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/pipe-prefix.md) | Enforce consistent prefix for pipes. | | | |
64
65
  | [`prefer-on-push-component-change-detection`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-on-push-component-change-detection.md) | Ensures component's `changeDetection` is set to `ChangeDetectionStrategy.OnPush` | | | :bulb: |
65
66
  | [`prefer-output-readonly`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-output-readonly.md) | Prefer to declare `@Output` as `readonly` since they are not supposed to be reassigned | | | :bulb: |
66
- | [`prefer-standalone-component`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-standalone-component.md) | Ensures component `standalone` property is set to `true` in the component decorator | | :wrench: | |
67
+ | [`prefer-standalone`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-standalone.md) | Ensures component, directive and pipe `standalone` property is set to `true` in the component decorator | | :wrench: | |
67
68
  | [`relative-url-prefix`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/relative-url-prefix.md) | The ./ and ../ prefix is standard syntax for relative URLs; don't depend on Angular's current ability to do without that prefix. See more at https://angular.io/styleguide#style-05-04 | | | |
68
69
  | [`require-localize-metadata`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/require-localize-metadata.md) | Ensures that $localize tagged messages contain helpful metadata to aid with translations. | | | |
69
70
  | [`sort-ngmodule-metadata-arrays`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/sort-ngmodule-metadata-arrays.md) | Ensures ASC alphabetical order for `NgModule` metadata arrays for easy visual scanning | | :wrench: | |
@@ -82,4 +83,12 @@
82
83
 
83
84
  <!-- begin deprecated rule list -->
84
85
 
86
+ ### Deprecated
87
+
88
+ <!-- prettier-ignore-start -->
89
+ | Rule | Replaced by |
90
+ | --- | --- |
91
+ | [`prefer-standalone-component`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-standalone-component.md) | [`prefer-standalone`](https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/prefer-standalone-component.md) |
92
+ <!-- prettier-ignore-end -->
93
+
85
94
  <!-- end deprecated rule list -->
@@ -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",
@@ -28,6 +29,7 @@
28
29
  "@angular-eslint/pipe-prefix": "error",
29
30
  "@angular-eslint/prefer-on-push-component-change-detection": "error",
30
31
  "@angular-eslint/prefer-output-readonly": "error",
32
+ "@angular-eslint/prefer-standalone": "error",
31
33
  "@angular-eslint/prefer-standalone-component": "error",
32
34
  "@angular-eslint/relative-url-prefix": "error",
33
35
  "@angular-eslint/require-localize-metadata": "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"));
@@ -53,6 +54,7 @@ const no_queries_metadata_property_1 = __importStar(require("./rules/no-queries-
53
54
  const pipe_prefix_1 = __importStar(require("./rules/pipe-prefix"));
54
55
  const prefer_on_push_component_change_detection_1 = __importStar(require("./rules/prefer-on-push-component-change-detection"));
55
56
  const prefer_output_readonly_1 = __importStar(require("./rules/prefer-output-readonly"));
57
+ const prefer_standalone_1 = __importStar(require("./rules/prefer-standalone"));
56
58
  const prefer_standalone_component_1 = __importStar(require("./rules/prefer-standalone-component"));
57
59
  const relative_url_prefix_1 = __importStar(require("./rules/relative-url-prefix"));
58
60
  const require_localize_metadata_1 = __importStar(require("./rules/require-localize-metadata"));
@@ -72,6 +74,7 @@ module.exports = {
72
74
  [component_class_suffix_1.RULE_NAME]: component_class_suffix_1.default,
73
75
  [component_max_inline_declarations_1.RULE_NAME]: component_max_inline_declarations_1.default,
74
76
  [component_selector_1.RULE_NAME]: component_selector_1.default,
77
+ [consistent_component_styles_1.RULE_NAME]: consistent_component_styles_1.default,
75
78
  [contextual_decorator_1.RULE_NAME]: contextual_decorator_1.default,
76
79
  [contextual_lifecycle_1.RULE_NAME]: contextual_lifecycle_1.default,
77
80
  [directive_class_suffix_1.RULE_NAME]: directive_class_suffix_1.default,
@@ -94,6 +97,7 @@ module.exports = {
94
97
  [no_queries_metadata_property_1.RULE_NAME]: no_queries_metadata_property_1.default,
95
98
  [pipe_prefix_1.RULE_NAME]: pipe_prefix_1.default,
96
99
  [prefer_on_push_component_change_detection_1.RULE_NAME]: prefer_on_push_component_change_detection_1.default,
100
+ [prefer_standalone_1.RULE_NAME]: prefer_standalone_1.default,
97
101
  [prefer_standalone_component_1.RULE_NAME]: prefer_standalone_component_1.default,
98
102
  [prefer_output_readonly_1.RULE_NAME]: prefer_output_readonly_1.default,
99
103
  [relative_url_prefix_1.RULE_NAME]: relative_url_prefix_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
+ });
@@ -13,6 +13,8 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
13
13
  docs: {
14
14
  description: `Ensures component \`${METADATA_PROPERTY_NAME}\` property is set to \`${IS_STANDALONE}\` in the component decorator`,
15
15
  },
16
+ deprecated: true,
17
+ replacedBy: ['prefer-standalone'],
16
18
  fixable: 'code',
17
19
  schema: [],
18
20
  messages: {
@@ -0,0 +1,61 @@
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 = 'prefer-standalone';
7
+ const METADATA_PROPERTY_NAME = 'standalone';
8
+ const IS_STANDALONE = 'true';
9
+ exports.default = (0, create_eslint_rule_1.createESLintRule)({
10
+ name: exports.RULE_NAME,
11
+ meta: {
12
+ type: 'suggestion',
13
+ docs: {
14
+ description: `Ensures component, directive and pipe \`${METADATA_PROPERTY_NAME}\` property is set to \`${IS_STANDALONE}\` in the component decorator`,
15
+ },
16
+ fixable: 'code',
17
+ schema: [],
18
+ messages: {
19
+ preferStandalone: `The {{type}} \`${METADATA_PROPERTY_NAME}\` property should be set to \`${IS_STANDALONE}\``,
20
+ },
21
+ },
22
+ defaultOptions: [],
23
+ create(context) {
24
+ const standaloneRuleFactory = (type) => (node) => {
25
+ const standalone = utils_1.ASTUtils.getDecoratorPropertyValue(node, METADATA_PROPERTY_NAME);
26
+ if (standalone &&
27
+ utils_1.ASTUtils.isLiteral(standalone) &&
28
+ standalone.value === true) {
29
+ return;
30
+ }
31
+ context.report({
32
+ node: nodeToReport(node),
33
+ messageId: 'preferStandalone',
34
+ data: { type },
35
+ fix: (fixer) => {
36
+ if (standalone &&
37
+ utils_1.ASTUtils.isLiteral(standalone) &&
38
+ standalone.value !== true) {
39
+ return [fixer.replaceText(standalone, IS_STANDALONE)].filter(utils_1.isNotNullOrUndefined);
40
+ }
41
+ return [
42
+ utils_1.RuleFixes.getDecoratorPropertyAddFix(node, fixer, `${METADATA_PROPERTY_NAME}: ${IS_STANDALONE}`),
43
+ ].filter(utils_1.isNotNullOrUndefined);
44
+ },
45
+ });
46
+ };
47
+ return {
48
+ [utils_1.Selectors.COMPONENT_CLASS_DECORATOR]: standaloneRuleFactory('component'),
49
+ [utils_1.Selectors.DIRECTIVE_CLASS_DECORATOR]: standaloneRuleFactory('directive'),
50
+ [utils_1.Selectors.PIPE_CLASS_DECORATOR]: standaloneRuleFactory('pipe'),
51
+ };
52
+ },
53
+ });
54
+ function nodeToReport(node) {
55
+ if (!utils_1.ASTUtils.isProperty(node)) {
56
+ return node;
57
+ }
58
+ return utils_1.ASTUtils.isMemberExpression(node.value)
59
+ ? node.value.property
60
+ : node.value;
61
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular-eslint/eslint-plugin",
3
- "version": "17.2.2-alpha.7",
3
+ "version": "17.2.2-alpha.9",
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.7",
20
+ "@angular-eslint/utils": "17.2.2-alpha.9",
21
21
  "@typescript-eslint/utils": "7.2.0"
22
22
  },
23
23
  "peerDependencies": {