@yoo-digital/eslint-plugin-angular 1.0.0 → 1.1.0

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
@@ -8,28 +8,106 @@ Here should live all custom Angular lint rules that eslint does not already prov
8
8
 
9
9
  Wrong code is yellow underlined in VScode, it can also be raises running : `npm run lint`
10
10
 
11
- ## Rule 1 : boolean input conversion
11
+ ## Rule 1 : boolean input conversion (prefer-boolean-attribute-shorthand)
12
12
 
13
13
  `booleanAttribute @angular/core`
14
14
 
15
15
  `BooleanInput @angular/cdk/coercion`
16
16
 
17
+ ### ⚠️ Important Limitations
18
+
19
+ **Current Implementation:** This rule enforces shorthand syntax (`<x a />` instead of `<x [a]="true" />`) but **cannot automatically verify**:
20
+ - Whether an input has `transform: booleanAttribute`
21
+ - What the default value of an input is
22
+
23
+ This is a technical limitation of Angular ESLint - template rules cannot access the component's TypeScript code.
24
+
25
+ ### Recommended Usage
26
+
27
+ This rule works best when:
28
+ 1. **All boolean inputs** in your project use `booleanAttribute` transform
29
+ 2. **Most boolean inputs** have `default = false` or no default
30
+ 3. You treat this as a **style guide enforcer** rather than a safety checker
31
+
32
+ ### Configuration
33
+
34
+ By default, the rule only flags `[attr]="true"` bindings (safe default):
35
+
36
+ ```json
37
+ {
38
+ "rules": {
39
+ "@yoo-digital/eslint-plugin-angular/prefer-boolean-attribute-shorthand": "error"
40
+ }
41
+ }
42
+ ```
43
+
44
+ To also enforce removal of `[attr]="false"` bindings:
45
+
46
+ ```json
47
+ {
48
+ "rules": {
49
+ "@yoo-digital/eslint-plugin-angular/prefer-boolean-attribute-shorthand": [
50
+ "error",
51
+ { "allowFalseLiteral": false }
52
+ ]
53
+ }
54
+ }
55
+ ```
56
+
17
57
  ### Examples
18
58
 
19
- `<myComp [myBoolInput]="true" ` must be `<myComp myBoolInput`
59
+ #### Recommended Pattern (Default false or no default)
60
+
61
+ ```typescript
62
+ // Component
63
+ @Input({ transform: booleanAttribute }) disabled: boolean = false;
64
+ // OR
65
+ disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });
66
+ ```
67
+
68
+ **Template:**
69
+ - ❌ `<button [disabled]="true">` → Should be `<button disabled>`
70
+ - ✅ `<button disabled>` (shorthand for true)
71
+ - ✅ `<button>` (omit for false)
72
+ - ✅ `<button [disabled]="isLoading">` (expressions are allowed)
73
+
74
+ #### ⚠️ Special Case: Default true (Disable rule if needed)
75
+
76
+ ```typescript
77
+ // Component
78
+ @Input({ transform: booleanAttribute }) enabled: boolean = true;
79
+ ```
80
+
81
+ **Template:**
82
+ ```html
83
+ <!-- eslint-disable-next-line @yoo-digital/eslint-plugin-angular/prefer-boolean-attribute-shorthand -->
84
+ <button [enabled]="false">Explicitly disabled</button>
85
+ ```
86
+
87
+ When default is `true`, you may need explicit `[attr]="true"` or `[attr]="false"` bindings.
88
+
89
+ #### ❌ Without booleanAttribute (Won't work!)
20
90
 
21
- `<myComp [myBoolInput]="false"` must be `<myComp `
91
+ ```typescript
92
+ // Component - Missing transform!
93
+ @Input() checked: boolean = false;
94
+ ```
22
95
 
23
- `<myComp [myBoolInput]="2+2===4"` is accepted
96
+ **Template:**
97
+ - ❌ `<input checked>` → Will pass `""` (empty string), NOT boolean!
98
+ - ✅ `<input [checked]="true">` (must use property binding)
24
99
 
25
- ### Decorator
100
+ ### Decorator Syntax
26
101
 
27
- `@Input({ transform: booleanAttribute }) myInput: boolean = true;`
102
+ `@Input({ transform: booleanAttribute }) myInput: boolean = false;`
28
103
 
29
- ### Signal
104
+ ### Signal Input Syntax
30
105
 
31
- `myInput = input<boolean, BooleanInput>(true, {transform: booleanAttribute,});`
106
+ `myInput = input<boolean, BooleanInput>(false, { transform: booleanAttribute });`
32
107
 
33
- ### Exception
108
+ ### Summary
34
109
 
35
- If a **required** boolean input needs to be false, no choice, `[myRequiredInput]="false"` must be written. Therefore boolean input should never be required.
110
+ - **Rule enforces**: `[attr]="true"` `attr` shorthand
111
+ - **Rule assumes**: Inputs have `booleanAttribute` and `default ≠ true`
112
+ - **Manual override**: Use eslint-disable comments for special cases
113
+ - **Best practice**: Ensure all boolean inputs use `booleanAttribute`
@@ -4,5 +4,34 @@ interface Options {
4
4
  }
5
5
  type MessageIds = 'preferTrue' | 'preferFalse' | 'suggestTrue' | 'suggestRemove';
6
6
  export declare const RULE_NAME = "prefer-boolean-attribute-shorthand";
7
+ /**
8
+ * IMPORTANT LIMITATIONS:
9
+ *
10
+ * Angular ESLint template rules cannot directly access the TypeScript component class
11
+ * to check for booleanAttribute transforms or default values. This would require:
12
+ * 1. Access to the TypeScript program (not available in template parser services)
13
+ * 2. Cross-file analysis (template -> component.ts)
14
+ * 3. Complex AST traversal and decorator/signal input analysis
15
+ *
16
+ * The current implementation enforces shorthand syntax for [attr]="true" bindings
17
+ * but cannot verify:
18
+ * - Whether the input has `transform: booleanAttribute`
19
+ * - What the default value of the input is
20
+ *
21
+ * RECOMMENDATIONS FOR USERS:
22
+ * 1. Only use this rule in projects where ALL boolean inputs have booleanAttribute
23
+ * 2. If an input has default=true, manually disable the rule for that binding
24
+ * 3. Consider the rule as a style guide enforcer, not a safety checker
25
+ *
26
+ * FUTURE ENHANCEMENTS:
27
+ * To implement the full feature set requested would require creating a SEPARATE
28
+ * TypeScript ESLint rule that:
29
+ * - Runs on .ts component files (not templates)
30
+ * - Analyzes @Component decorators to find template references
31
+ * - Parses templates and cross-references with component inputs
32
+ * - Reports errors in both .ts and template files
33
+ *
34
+ * This would be a significantly more complex multi-file analysis rule.
35
+ */
7
36
  export declare const preferBooleanAttributeShorthandRule: TSESLint.RuleModule<MessageIds, Options[]>;
8
37
  export {};
@@ -3,11 +3,40 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.preferBooleanAttributeShorthandRule = exports.RULE_NAME = void 0;
4
4
  const utils_1 = require("@angular-eslint/utils");
5
5
  exports.RULE_NAME = 'prefer-boolean-attribute-shorthand';
6
+ /**
7
+ * IMPORTANT LIMITATIONS:
8
+ *
9
+ * Angular ESLint template rules cannot directly access the TypeScript component class
10
+ * to check for booleanAttribute transforms or default values. This would require:
11
+ * 1. Access to the TypeScript program (not available in template parser services)
12
+ * 2. Cross-file analysis (template -> component.ts)
13
+ * 3. Complex AST traversal and decorator/signal input analysis
14
+ *
15
+ * The current implementation enforces shorthand syntax for [attr]="true" bindings
16
+ * but cannot verify:
17
+ * - Whether the input has `transform: booleanAttribute`
18
+ * - What the default value of the input is
19
+ *
20
+ * RECOMMENDATIONS FOR USERS:
21
+ * 1. Only use this rule in projects where ALL boolean inputs have booleanAttribute
22
+ * 2. If an input has default=true, manually disable the rule for that binding
23
+ * 3. Consider the rule as a style guide enforcer, not a safety checker
24
+ *
25
+ * FUTURE ENHANCEMENTS:
26
+ * To implement the full feature set requested would require creating a SEPARATE
27
+ * TypeScript ESLint rule that:
28
+ * - Runs on .ts component files (not templates)
29
+ * - Analyzes @Component decorators to find template references
30
+ * - Parses templates and cross-references with component inputs
31
+ * - Reports errors in both .ts and template files
32
+ *
33
+ * This would be a significantly more complex multi-file analysis rule.
34
+ */
6
35
  exports.preferBooleanAttributeShorthandRule = {
7
36
  meta: {
8
37
  type: 'suggestion',
9
38
  docs: {
10
- description: 'Prefer boolean input attribute shorthand instead of binding to literal true/false.',
39
+ description: 'Prefer boolean input attribute shorthand instead of binding to literal true/false. NOTE: This rule assumes inputs have booleanAttribute transform and does not have default=true.',
11
40
  },
12
41
  hasSuggestions: true,
13
42
  schema: [
@@ -20,22 +49,22 @@ exports.preferBooleanAttributeShorthandRule = {
20
49
  },
21
50
  ],
22
51
  messages: {
23
- preferTrue: 'Use attribute shorthand "{{attr}}" instead of [{{attr}}]="true".',
24
- preferFalse: 'Avoid binding [{{attr}}]="false"; remove the binding or ensure default is false.',
52
+ preferTrue: 'Use attribute shorthand "{{attr}}" instead of [{{attr}}]="true". WARNING: Only works if input has booleanAttribute transform.',
53
+ preferFalse: 'Avoid binding [{{attr}}]="false"; remove the binding if default is false.',
25
54
  suggestTrue: 'Replace with attribute shorthand {{attr}}',
26
55
  suggestRemove: 'Remove the false binding',
27
56
  },
28
57
  },
29
58
  defaultOptions: [
30
59
  {
31
- allowFalseLiteral: false,
60
+ allowFalseLiteral: true, // Changed default to true for safety
32
61
  },
33
62
  ],
34
63
  create(context) {
35
64
  // Robust to missing options: default to [{}] if undefined
36
65
  const optionsArr = context.options ?? [{}];
37
66
  const options = optionsArr[0] ?? {};
38
- const allowFalseLiteral = options.allowFalseLiteral ?? false;
67
+ const allowFalseLiteral = options.allowFalseLiteral ?? true; // Default to true for safety
39
68
  const parserServices = (0, utils_1.getTemplateParserServices)(context);
40
69
  return {
41
70
  BoundAttribute(node) {
@@ -49,6 +78,8 @@ exports.preferBooleanAttributeShorthandRule = {
49
78
  const start = node.sourceSpan.start.offset;
50
79
  const end = node.sourceSpan.end.offset;
51
80
  if (ast.value === true) {
81
+ // Enforce shorthand for true bindings
82
+ // NOTE: This assumes the input has booleanAttribute and default != true
52
83
  context.report({
53
84
  loc,
54
85
  messageId: 'preferTrue',
@@ -63,6 +94,7 @@ exports.preferBooleanAttributeShorthandRule = {
63
94
  });
64
95
  }
65
96
  else if (ast.value === false && !allowFalseLiteral) {
97
+ // Only flag false bindings if explicitly configured
66
98
  context.report({
67
99
  loc,
68
100
  messageId: 'preferFalse',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yoo-digital/eslint-plugin-angular",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Yoo Digital custom Angular ESLint plugin providing prefer-boolean-attribute-shorthand rule.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/index.js",