@yoo-digital/eslint-plugin-angular 2.0.0 → 2.0.3
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.
|
@@ -29,7 +29,6 @@ exports.preferBooleanAttributeShorthandRule = {
|
|
|
29
29
|
docs: {
|
|
30
30
|
description: 'Prefer boolean input attribute shorthand when binding to true (e.g., use "disabled" instead of [disabled]="true").',
|
|
31
31
|
},
|
|
32
|
-
fixable: 'code',
|
|
33
32
|
schema: [],
|
|
34
33
|
messages: {
|
|
35
34
|
preferTrue: 'Use attribute shorthand "{{attr}}" instead of [{{attr}}]="true".',
|
|
@@ -51,13 +50,10 @@ exports.preferBooleanAttributeShorthandRule = {
|
|
|
51
50
|
if (ast.value === true) {
|
|
52
51
|
const attrName = node.name;
|
|
53
52
|
const loc = parserServices.convertNodeSourceSpanToLoc(node.sourceSpan);
|
|
54
|
-
const start = node.sourceSpan.start.offset;
|
|
55
|
-
const end = node.sourceSpan.end.offset;
|
|
56
53
|
context.report({
|
|
57
54
|
loc,
|
|
58
55
|
messageId: 'preferTrue',
|
|
59
56
|
data: { attr: attrName },
|
|
60
|
-
fix: (fixer) => fixer.replaceTextRange([start, end], attrName),
|
|
61
57
|
});
|
|
62
58
|
}
|
|
63
59
|
// [attr]="false" is explicitly ignored - no warning
|
|
@@ -19,7 +19,6 @@ exports.requireBooleanAttributeTransformRule = {
|
|
|
19
19
|
docs: {
|
|
20
20
|
description: 'Require booleanAttribute transform on boolean @Input() properties and input() signals.',
|
|
21
21
|
},
|
|
22
|
-
fixable: 'code',
|
|
23
22
|
schema: [],
|
|
24
23
|
messages: {
|
|
25
24
|
requireTransformDecorator: 'Boolean @Input() "{{name}}" must use transform: booleanAttribute',
|
|
@@ -28,7 +27,6 @@ exports.requireBooleanAttributeTransformRule = {
|
|
|
28
27
|
},
|
|
29
28
|
defaultOptions: [],
|
|
30
29
|
create(context) {
|
|
31
|
-
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
32
30
|
return {
|
|
33
31
|
// Handle @Input() decorator syntax
|
|
34
32
|
PropertyDefinition(node) {
|
|
@@ -65,36 +63,6 @@ exports.requireBooleanAttributeTransformRule = {
|
|
|
65
63
|
node: node.key,
|
|
66
64
|
messageId: 'requireTransformDecorator',
|
|
67
65
|
data: { name: propertyName },
|
|
68
|
-
fix(fixer) {
|
|
69
|
-
const decoratorNode = inputDecorator?.expression;
|
|
70
|
-
if (!decoratorNode || decoratorNode.type !== 'CallExpression') {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
const decoratorStart = decoratorNode.range[0];
|
|
74
|
-
const decoratorEnd = decoratorNode.range[1];
|
|
75
|
-
const decoratorText = sourceCode.getText(decoratorNode);
|
|
76
|
-
// Generate the fixed decorator
|
|
77
|
-
let newDecorator;
|
|
78
|
-
if (decoratorNode.arguments.length === 0) {
|
|
79
|
-
// @Input() → @Input({ transform: booleanAttribute })
|
|
80
|
-
newDecorator = '@Input({ transform: booleanAttribute })';
|
|
81
|
-
}
|
|
82
|
-
else if (decoratorNode.arguments[0].type === 'ObjectExpression') {
|
|
83
|
-
// @Input({ ... }) → @Input({ ..., transform: booleanAttribute })
|
|
84
|
-
const objExpr = decoratorNode.arguments[0];
|
|
85
|
-
const objText = sourceCode.getText(objExpr);
|
|
86
|
-
const closingBrace = objText.lastIndexOf('}');
|
|
87
|
-
const existingProps = objText.substring(1, closingBrace).trim();
|
|
88
|
-
const separator = existingProps ? ', ' : '';
|
|
89
|
-
newDecorator = `@Input({ ${existingProps}${separator}transform: booleanAttribute })`;
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
// @Input('alias') → @Input({ alias: 'alias', transform: booleanAttribute })
|
|
93
|
-
const aliasArg = sourceCode.getText(decoratorNode.arguments[0]);
|
|
94
|
-
newDecorator = `@Input({ alias: ${aliasArg}, transform: booleanAttribute })`;
|
|
95
|
-
}
|
|
96
|
-
return fixer.replaceTextRange([decoratorStart, decoratorEnd], newDecorator);
|
|
97
|
-
},
|
|
98
66
|
});
|
|
99
67
|
},
|
|
100
68
|
// Handle input() signal syntax
|
|
@@ -105,19 +73,22 @@ exports.requireBooleanAttributeTransformRule = {
|
|
|
105
73
|
return;
|
|
106
74
|
}
|
|
107
75
|
const callExpr = node.init;
|
|
108
|
-
// Check if it's a boolean input
|
|
109
|
-
|
|
110
|
-
|
|
76
|
+
// Check if it's a boolean input (with or without type arguments)
|
|
77
|
+
let isBooleanInput = false;
|
|
78
|
+
if (callExpr.typeArguments && callExpr.typeArguments.params.length > 0) {
|
|
79
|
+
const firstTypeParam = callExpr.typeArguments.params[0];
|
|
80
|
+
isBooleanInput = firstTypeParam.type === 'TSBooleanKeyword';
|
|
111
81
|
}
|
|
112
|
-
|
|
113
|
-
if (firstTypeParam.type !== 'TSBooleanKeyword') {
|
|
82
|
+
if (!isBooleanInput) {
|
|
114
83
|
return;
|
|
115
84
|
}
|
|
85
|
+
// At this point, we know typeArguments exists and has at least one boolean param
|
|
86
|
+
const typeArgs = callExpr.typeArguments;
|
|
116
87
|
// Check if it already has BooleanInput as second type parameter
|
|
117
|
-
const hasBooleanInput =
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
88
|
+
const hasBooleanInput = typeArgs.params.length > 1 &&
|
|
89
|
+
typeArgs.params[1].type === 'TSTypeReference' &&
|
|
90
|
+
typeArgs.params[1].typeName.type === 'Identifier' &&
|
|
91
|
+
typeArgs.params[1].typeName.name === 'BooleanInput';
|
|
121
92
|
// Check if it already has transform in options
|
|
122
93
|
const hasTransformOption = callExpr.arguments.length > 1 &&
|
|
123
94
|
callExpr.arguments[1].type === 'ObjectExpression' &&
|
|
@@ -126,6 +97,7 @@ exports.requireBooleanAttributeTransformRule = {
|
|
|
126
97
|
prop.key.name === 'transform' &&
|
|
127
98
|
prop.value.type === 'Identifier' &&
|
|
128
99
|
prop.value.name === 'booleanAttribute');
|
|
100
|
+
// Both BooleanInput type and transform option are required
|
|
129
101
|
if (hasBooleanInput && hasTransformOption) {
|
|
130
102
|
return; // Already correctly configured
|
|
131
103
|
}
|
|
@@ -135,15 +107,6 @@ exports.requireBooleanAttributeTransformRule = {
|
|
|
135
107
|
node: node.id,
|
|
136
108
|
messageId: 'requireTransformSignal',
|
|
137
109
|
data: { name: propertyName },
|
|
138
|
-
fix(fixer) {
|
|
139
|
-
const callStart = callExpr.range[0];
|
|
140
|
-
const callEnd = callExpr.range[1];
|
|
141
|
-
// Get the default value argument
|
|
142
|
-
const defaultValue = callExpr.arguments[0] ? sourceCode.getText(callExpr.arguments[0]) : 'false';
|
|
143
|
-
// Build the new call expression
|
|
144
|
-
const newCall = `input<boolean, BooleanInput>(${defaultValue}, {\n transform: booleanAttribute,\n })`;
|
|
145
|
-
return fixer.replaceTextRange([callStart, callEnd], newCall);
|
|
146
|
-
},
|
|
147
110
|
});
|
|
148
111
|
},
|
|
149
112
|
};
|
package/package.json
CHANGED