@angular-eslint/eslint-plugin-template 20.0.0-alpha.1 → 20.0.0-alpha.2

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/dist/index.d.ts CHANGED
@@ -91,7 +91,7 @@ declare const _default: {
91
91
  "attributes-order": import("@typescript-eslint/utils/ts-eslint").RuleModule<"attributesOrder", import("./rules/attributes-order").Options, import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
92
92
  "banana-in-box": import("@typescript-eslint/utils/ts-eslint").RuleModule<"bananaInBox", [], import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
93
93
  "button-has-type": import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./rules/button-has-type").MessageIds, import("./rules/button-has-type").Options, import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
94
- "click-events-have-key-events": import("@typescript-eslint/utils/ts-eslint").RuleModule<"clickEventsHaveKeyEvents", [], import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
94
+ "click-events-have-key-events": import("@typescript-eslint/utils/ts-eslint").RuleModule<"clickEventsHaveKeyEvents", import("./rules/click-events-have-key-events").Options, import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
95
95
  "conditional-complexity": import("@typescript-eslint/utils/ts-eslint").RuleModule<"conditionalComplexity", import("./rules/conditional-complexity").Options, import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
96
96
  "cyclomatic-complexity": import("@typescript-eslint/utils/ts-eslint").RuleModule<"cyclomaticComplexity", import("./rules/cyclomatic-complexity").Options, import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
97
97
  "elements-content": import("@typescript-eslint/utils/ts-eslint").RuleModule<"elementsContent", import("./rules/elements-content").Options, import("./utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
@@ -1,6 +1,10 @@
1
- export type Options = [];
1
+ export type Options = [
2
+ {
3
+ readonly ignoreWithDirectives?: string[];
4
+ }
5
+ ];
2
6
  export type MessageIds = 'clickEventsHaveKeyEvents';
3
7
  export declare const RULE_NAME = "click-events-have-key-events";
4
- declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"clickEventsHaveKeyEvents", [], import("../utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
8
+ declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"clickEventsHaveKeyEvents", Options, import("../utils/create-eslint-rule").RuleDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
5
9
  export default _default;
6
10
  //# sourceMappingURL=click-events-have-key-events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"click-events-have-key-events.d.ts","sourceRoot":"","sources":["../../src/rules/click-events-have-key-events.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAAG,0BAA0B,CAAC;AACpD,eAAO,MAAM,SAAS,iCAAiC,CAAC;;AAExD,wBAwDG"}
1
+ {"version":3,"file":"click-events-have-key-events.d.ts","sourceRoot":"","sources":["../../src/rules/click-events-have-key-events.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,OAAO,GAAG;IACpB;QACE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC1C;CACF,CAAC;AACF,MAAM,MAAM,UAAU,GAAG,0BAA0B,CAAC;AACpD,eAAO,MAAM,SAAS,iCAAiC,CAAC;;AAKxD,wBA+EG"}
@@ -7,7 +7,11 @@ const get_dom_elements_1 = require("../utils/get-dom-elements");
7
7
  const is_hidden_from_screen_reader_1 = require("../utils/is-hidden-from-screen-reader");
8
8
  const is_interactive_element_1 = require("../utils/is-interactive-element");
9
9
  const is_presentation_role_1 = require("../utils/is-presentation-role");
10
+ const get_attribute_value_1 = require("../utils/get-attribute-value");
10
11
  exports.RULE_NAME = 'click-events-have-key-events';
12
+ const DEFAULT_OPTIONS = {
13
+ ignoreWithDirectives: [],
14
+ };
11
15
  exports.default = (0, create_eslint_rule_1.createESLintRule)({
12
16
  name: exports.RULE_NAME,
13
17
  meta: {
@@ -15,21 +19,41 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
15
19
  docs: {
16
20
  description: '[Accessibility] Ensures that the click event is accompanied with at least one key event keyup, keydown or keypress.',
17
21
  },
18
- schema: [],
22
+ schema: [
23
+ {
24
+ type: 'object',
25
+ properties: {
26
+ ignoreWithDirectives: {
27
+ type: 'array',
28
+ items: { type: 'string' },
29
+ uniqueItems: true,
30
+ default: DEFAULT_OPTIONS.ignoreWithDirectives,
31
+ },
32
+ },
33
+ additionalProperties: false,
34
+ },
35
+ ],
19
36
  messages: {
20
37
  clickEventsHaveKeyEvents: 'click must be accompanied by either keyup, keydown or keypress event for accessibility.',
21
38
  },
22
39
  },
23
- defaultOptions: [],
24
- create(context) {
40
+ defaultOptions: [DEFAULT_OPTIONS],
41
+ create(context, [{ ignoreWithDirectives }]) {
25
42
  return {
26
43
  Element(node) {
27
44
  if (!(0, get_dom_elements_1.getDomElements)().has(node.name)) {
28
45
  return;
29
46
  }
30
- if ((0, is_presentation_role_1.isPresentationRole)(node) ||
47
+ if (isIgnored(ignoreWithDirectives, node) ||
48
+ (0, is_presentation_role_1.isPresentationRole)(node) ||
31
49
  (0, is_hidden_from_screen_reader_1.isHiddenFromScreenReader)(node) ||
32
- (0, is_interactive_element_1.isInteractiveElement)(node)) {
50
+ (0, is_interactive_element_1.isInherentlyInteractiveElement)(node)) {
51
+ return;
52
+ }
53
+ // The final case that should be ignored is element which is not inherently interactive, but which has an interactive role.
54
+ // TODO: extend utils with this check (and make it include all interactive roles)
55
+ const role = (0, get_attribute_value_1.getAttributeValue)(node, 'role');
56
+ if (role === 'button') {
33
57
  return;
34
58
  }
35
59
  let hasClick = false, hasKeyEvent = false;
@@ -54,3 +78,18 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
54
78
  };
55
79
  },
56
80
  });
81
+ function isIgnored(ignoreWithDirectives, { inputs, attributes }) {
82
+ if (ignoreWithDirectives && ignoreWithDirectives.length > 0) {
83
+ for (const input of inputs) {
84
+ if (ignoreWithDirectives.includes(input.name)) {
85
+ return true;
86
+ }
87
+ }
88
+ for (const attribute of attributes) {
89
+ if (ignoreWithDirectives.includes(attribute.name)) {
90
+ return true;
91
+ }
92
+ }
93
+ }
94
+ return false;
95
+ }
@@ -61,7 +61,7 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
61
61
  const tabIndex = [...node.attributes, ...node.inputs].find((attr) => attr.name === 'tabindex');
62
62
  if (interactiveOutput &&
63
63
  !tabIndex &&
64
- !(0, is_interactive_element_1.isInteractiveElement)(node) &&
64
+ !(0, is_interactive_element_1.isInherentlyInteractiveElement)(node) &&
65
65
  !(0, is_interactive_element_1.isNonInteractiveRole)(node) &&
66
66
  !(0, is_content_editable_1.isContentEditable)(node)) {
67
67
  const parserServices = (0, utils_1.getTemplateParserServices)(context);
@@ -1 +1 @@
1
- {"version":3,"file":"label-has-associated-control.d.ts","sourceRoot":"","sources":["../../src/rules/label-has-associated-control.ts"],"names":[],"mappings":"AAQA,KAAK,cAAc,GAAG;IACpB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AACF,MAAM,MAAM,OAAO,GAAG;IACpB;QACE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAC/C,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;QACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;KAC7B;CACF,CAAC;AACF,MAAM,MAAM,UAAU,GAAG,2BAA2B,CAAC;AACrD,eAAO,MAAM,SAAS,iCAAiC,CAAC;;AAkBxD,wBA8GG"}
1
+ {"version":3,"file":"label-has-associated-control.d.ts","sourceRoot":"","sources":["../../src/rules/label-has-associated-control.ts"],"names":[],"mappings":"AAQA,KAAK,cAAc,GAAG;IACpB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AACF,MAAM,MAAM,OAAO,GAAG;IACpB;QACE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAC/C,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;QACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;KAC7B;CACF,CAAC;AACF,MAAM,MAAM,UAAU,GAAG,2BAA2B,CAAC;AACrD,eAAO,MAAM,SAAS,iCAAiC,CAAC;;AAkBxD,wBAoHG"}
@@ -70,10 +70,12 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
70
70
  ...DEFAULT_CONTROL_COMPONENTS,
71
71
  ...(controlComponents ?? []),
72
72
  ]);
73
- const allLabelComponents = [
74
- ...DEFAULT_LABEL_COMPONENTS,
75
- ...(labelComponents ?? []),
76
- ];
73
+ const labelMap = new Map(DEFAULT_LABEL_COMPONENTS.map((comp) => [comp.selector, comp]));
74
+ // Add custom components, overriding defaults with same selector
75
+ if (labelComponents) {
76
+ labelComponents.forEach((comp) => labelMap.set(comp.selector, comp));
77
+ }
78
+ const allLabelComponents = Array.from(labelMap.values());
77
79
  let inputItems = [];
78
80
  let labelItems = [];
79
81
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-template-literal.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-template-literal.ts"],"names":[],"mappings":"AAiBA,QAAA,MAAM,SAAS,0BAA0B,CAAC;AAE1C,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAAG,OAAO,SAAS,CAAC;AAC1C,eAAO,MAAM,SAAS,4BAA4B,CAAC;;AAEnD,wBA+GG"}
1
+ {"version":3,"file":"prefer-template-literal.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-template-literal.ts"],"names":[],"mappings":"AAkBA,QAAA,MAAM,SAAS,0BAA0B,CAAC;AAE1C,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAAG,OAAO,SAAS,CAAC;AAC1C,eAAO,MAAM,SAAS,4BAA4B,CAAC;;AAEnD,wBAsKG"}
@@ -38,14 +38,25 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
38
38
  return;
39
39
  }
40
40
  const { sourceSpan: { start, end }, } = node;
41
+ const parentIsTemplateLiteral = 'parent' in node && node.parent instanceof bundled_angular_compiler_1.TemplateLiteral;
41
42
  function getQuote() {
42
- const leftValue = sourceCode.text.at(left.sourceSpan.start);
43
- if (leftValue === "'" || leftValue === '"') {
44
- return leftValue;
43
+ if (parentIsTemplateLiteral) {
44
+ return '';
45
45
  }
46
- const rightValue = sourceCode.text.at(right.sourceSpan.start);
47
- if (rightValue === "'" || rightValue === '"') {
48
- return rightValue;
46
+ // If either side is not a literal primitive, we need to use backticks for interpolation
47
+ if (!(0, literal_primitive_1.isLiteralPrimitive)(left) || !(0, literal_primitive_1.isLiteralPrimitive)(right)) {
48
+ return '`';
49
+ }
50
+ if (left instanceof bundled_angular_compiler_1.LiteralPrimitive &&
51
+ right instanceof bundled_angular_compiler_1.LiteralPrimitive) {
52
+ const leftValue = sourceCode.text.at(left.sourceSpan.start);
53
+ if (leftValue === "'" || leftValue === '"') {
54
+ return leftValue;
55
+ }
56
+ const rightValue = sourceCode.text.at(right.sourceSpan.start);
57
+ if (rightValue === "'" || rightValue === '"') {
58
+ return rightValue;
59
+ }
49
60
  }
50
61
  return '`';
51
62
  }
@@ -56,32 +67,52 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
56
67
  },
57
68
  messageId,
58
69
  fix: (fixer) => {
70
+ const quote = getQuote();
71
+ const fixes = Array();
72
+ // If the parent is a template literal, remove the `${` sign
73
+ if (parentIsTemplateLiteral) {
74
+ const templateInterpolationStartIndex = sourceCode.text.lastIndexOf('${', node.sourceSpan.start);
75
+ fixes.push(fixer.removeRange([
76
+ templateInterpolationStartIndex,
77
+ node.sourceSpan.start,
78
+ ]));
79
+ }
59
80
  // If both sides are literals, we remove the `+` sign, escape if necessary and concatenate them
60
81
  if (left instanceof bundled_angular_compiler_1.LiteralPrimitive &&
61
82
  right instanceof bundled_angular_compiler_1.LiteralPrimitive) {
62
- const quote = getQuote();
63
- return fixer.replaceTextRange([start, end], `${quote}${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(left, quote)}${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(right, quote)}${quote}`);
64
- }
65
- const fixes = Array();
66
- // Fix the left side - handle parenthesized expressions specially
67
- if (originalLeft instanceof bundled_angular_compiler_1.ParenthesizedExpression) {
68
- fixes.push(...getLeftSideFixesForParenthesized(fixer, left, originalLeft));
83
+ fixes.push(fixer.replaceTextRange([start, end], parentIsTemplateLiteral
84
+ ? `${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(left, '`')}${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(right, '`')}`
85
+ : `${quote}${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(left, quote)}${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(right, quote)}${quote}`));
69
86
  }
70
87
  else {
71
- fixes.push(...getLeftSideFixes(fixer, left));
88
+ // Fix the left side - handle parenthesized expressions specially
89
+ if (originalLeft instanceof bundled_angular_compiler_1.ParenthesizedExpression) {
90
+ fixes.push(...getLeftSideFixesForParenthesized(fixer, left, originalLeft, quote));
91
+ }
92
+ else {
93
+ fixes.push(...getLeftSideFixes(fixer, left, quote));
94
+ }
95
+ // Remove the `+` sign (including surrounding whitespace)
96
+ fixes.push(fixer.removeRange([
97
+ originalLeft.sourceSpan.end,
98
+ originalRight.sourceSpan.start,
99
+ ]));
100
+ // Fix the right side - handle parenthesized expressions specially
101
+ if (originalRight instanceof bundled_angular_compiler_1.ParenthesizedExpression) {
102
+ // For parenthesized expressions, we want to replace the whole thing including parens
103
+ fixes.push(...getRightSideFixesForParenthesized(fixer, right, originalRight, quote));
104
+ }
105
+ else {
106
+ fixes.push(...getRightSideFixes(fixer, right, quote));
107
+ }
72
108
  }
73
- // Remove the `+` sign (including surrounding whitespace)
74
- fixes.push(fixer.removeRange([
75
- originalLeft.sourceSpan.end,
76
- originalRight.sourceSpan.start,
77
- ]));
78
- // Fix the right side - handle parenthesized expressions specially
79
- if (originalRight instanceof bundled_angular_compiler_1.ParenthesizedExpression) {
80
- // For parenthesized expressions, we want to replace the whole thing including parens
81
- fixes.push(...getRightSideFixesForParenthesized(fixer, right, originalRight));
82
- }
83
- else {
84
- fixes.push(...getRightSideFixes(fixer, right));
109
+ // If the parent is a template literal, remove the `}` sign
110
+ if (parentIsTemplateLiteral) {
111
+ const templateInterpolationEndIndex = sourceCode.text.indexOf('}', node.sourceSpan.end);
112
+ fixes.push(fixer.removeRange([
113
+ node.sourceSpan.end,
114
+ templateInterpolationEndIndex + 1,
115
+ ]));
85
116
  }
86
117
  return fixes;
87
118
  },
@@ -90,25 +121,30 @@ exports.default = (0, create_eslint_rule_1.createESLintRule)({
90
121
  };
91
122
  },
92
123
  });
93
- function getLeftSideFixes(fixer, left) {
124
+ function getLeftSideFixes(fixer, left, quote) {
94
125
  const { start, end } = left.sourceSpan;
95
126
  if (left instanceof bundled_angular_compiler_1.TemplateLiteral) {
96
127
  // Remove the end ` sign from the left side
97
- return [fixer.removeRange([end - 1, end])];
128
+ return [
129
+ fixer.replaceTextRange([start, start + 1], quote),
130
+ fixer.removeRange([end - 1, end]),
131
+ ];
98
132
  }
99
133
  if ((0, literal_primitive_1.isLiteralPrimitive)(left)) {
100
134
  // Transform left side to template literal
101
135
  return [
102
- fixer.replaceTextRange([start, end], `\`${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(left, '`')}`),
136
+ fixer.replaceTextRange([start, end], quote === ''
137
+ ? `${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(left, '`')}`
138
+ : `${quote}${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(left, quote)}`),
103
139
  ];
104
140
  }
105
141
  // Transform left side to template literal
106
142
  return [
107
- fixer.insertTextBeforeRange([start, end], '`${'),
143
+ fixer.insertTextBeforeRange([start, end], `${quote}\${`),
108
144
  fixer.insertTextAfterRange([start, end], '}'),
109
145
  ];
110
146
  }
111
- function getLeftSideFixesForParenthesized(fixer, innerExpression, parenthesizedExpression) {
147
+ function getLeftSideFixesForParenthesized(fixer, innerExpression, parenthesizedExpression, quote) {
112
148
  const parenthesizedStart = parenthesizedExpression.sourceSpan.start;
113
149
  const parenthesizedEnd = parenthesizedExpression.sourceSpan.end;
114
150
  const innerStart = innerExpression.sourceSpan.start;
@@ -116,42 +152,48 @@ function getLeftSideFixesForParenthesized(fixer, innerExpression, parenthesizedE
116
152
  if (innerExpression instanceof bundled_angular_compiler_1.TemplateLiteral) {
117
153
  // Remove the end ` sign from the inner expression and remove the parentheses
118
154
  return [
119
- fixer.removeRange([parenthesizedStart, innerStart]), // Remove opening paren
120
- fixer.removeRange([innerEnd - 1, innerEnd]), // Remove closing backtick
121
- fixer.removeRange([innerEnd, parenthesizedEnd]), // Remove closing paren
155
+ fixer.replaceTextRange([parenthesizedStart, innerStart + 1], quote), // Replace opening paren and backtick with quote
156
+ fixer.removeRange([innerEnd - 1, parenthesizedEnd]), // Remove closing backtick and paren
122
157
  ];
123
158
  }
124
159
  if ((0, literal_primitive_1.isLiteralPrimitive)(innerExpression)) {
125
160
  // Transform to template literal and remove parentheses
126
161
  return [
127
- fixer.replaceTextRange([parenthesizedStart, parenthesizedEnd], `\`${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(innerExpression, '`')}`),
162
+ fixer.replaceTextRange([parenthesizedStart, parenthesizedEnd], quote === ''
163
+ ? `${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(innerExpression, '`')}`
164
+ : `${quote}${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(innerExpression, quote)}`),
128
165
  ];
129
166
  }
130
167
  // Transform parenthesized expression to template literal by removing parens and wrapping in ${}
131
168
  return [
132
- fixer.replaceTextRange([parenthesizedStart, innerStart], '`${'), // Replace opening paren with `${
169
+ fixer.replaceTextRange([parenthesizedStart, innerStart], `${quote}\${`), // Replace opening paren with quote${
133
170
  fixer.replaceTextRange([innerEnd, parenthesizedEnd], '}'), // Replace closing paren with }
134
171
  ];
135
172
  }
136
- function getRightSideFixes(fixer, right) {
173
+ function getRightSideFixes(fixer, right, quote) {
137
174
  const { start, end } = right.sourceSpan;
138
175
  if (right instanceof bundled_angular_compiler_1.TemplateLiteral) {
139
176
  // Remove the start ` sign from the right side
140
- return [fixer.removeRange([start, start + 1])];
177
+ return [
178
+ fixer.removeRange([start, start + 1]),
179
+ fixer.replaceTextRange([end - 1, end], quote),
180
+ ];
141
181
  }
142
182
  if ((0, literal_primitive_1.isLiteralPrimitive)(right)) {
143
183
  // Transform right side to template literal if it's a string
144
184
  return [
145
- fixer.replaceTextRange([start, end], `${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(right, '`')}\``),
185
+ fixer.replaceTextRange([start, end], quote === ''
186
+ ? `${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(right, '`')}`
187
+ : `${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(right, quote)}${quote}`),
146
188
  ];
147
189
  }
148
190
  // Transform right side to template literal
149
191
  return [
150
192
  fixer.insertTextBeforeRange([start, end], '${'),
151
- fixer.insertTextAfterRange([start, end], '}`'),
193
+ fixer.insertTextAfterRange([start, end], `}${quote}`),
152
194
  ];
153
195
  }
154
- function getRightSideFixesForParenthesized(fixer, innerExpression, parenthesizedExpression) {
196
+ function getRightSideFixesForParenthesized(fixer, innerExpression, parenthesizedExpression, quote) {
155
197
  const parenthesizedStart = parenthesizedExpression.sourceSpan.start;
156
198
  const parenthesizedEnd = parenthesizedExpression.sourceSpan.end;
157
199
  const innerStart = innerExpression.sourceSpan.start;
@@ -159,20 +201,21 @@ function getRightSideFixesForParenthesized(fixer, innerExpression, parenthesized
159
201
  if (innerExpression instanceof bundled_angular_compiler_1.TemplateLiteral) {
160
202
  // Remove the start ` sign from the inner expression and remove the parentheses
161
203
  return [
162
- fixer.removeRange([parenthesizedStart, innerStart]), // Remove opening paren
163
- fixer.removeRange([innerStart, innerStart + 1]), // Remove opening backtick
164
- fixer.removeRange([innerEnd, parenthesizedEnd]), // Remove closing paren
204
+ fixer.removeRange([parenthesizedStart, innerStart + 1]), // Remove opening paren and backtick
205
+ fixer.replaceTextRange([innerEnd - 1, parenthesizedEnd], quote), // Replace closing backtick and paren with quote
165
206
  ];
166
207
  }
167
208
  if ((0, literal_primitive_1.isLiteralPrimitive)(innerExpression)) {
168
209
  // Transform to template literal and remove parentheses
169
210
  return [
170
- fixer.replaceTextRange([parenthesizedStart, parenthesizedEnd], `${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(innerExpression, '`')}\``),
211
+ fixer.replaceTextRange([parenthesizedStart, parenthesizedEnd], quote === ''
212
+ ? `${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(innerExpression, '`')}`
213
+ : `${(0, literal_primitive_1.getLiteralPrimitiveStringValue)(innerExpression, quote)}${quote}`),
171
214
  ];
172
215
  }
173
216
  // Transform parenthesized expression to template literal by removing parens and wrapping in ${}
174
217
  return [
175
218
  fixer.replaceTextRange([parenthesizedStart, innerStart], '${'), // Replace opening paren with ${
176
- fixer.replaceTextRange([innerEnd, parenthesizedEnd], '}`'), // Replace closing paren with }`
219
+ fixer.replaceTextRange([innerEnd, parenthesizedEnd], `}${quote}`), // Replace closing paren with }quote
177
220
  ];
178
221
  }
@@ -5,6 +5,6 @@ import type { TmplAstElement } from '@angular-eslint/bundled-angular-compiler';
5
5
  * has a dynamic handler on it and we need to discern whether or not
6
6
  * it's intention is to be interacted with on the DOM.
7
7
  */
8
- export declare function isInteractiveElement(node: TmplAstElement): boolean;
8
+ export declare function isInherentlyInteractiveElement(node: TmplAstElement): boolean;
9
9
  export declare function isNonInteractiveRole(node: TmplAstElement): boolean;
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/is-interactive-element/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAwC/E;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAElE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAElE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/is-interactive-element/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAwC/E;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAE5E;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAElE"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isInteractiveElement = isInteractiveElement;
3
+ exports.isInherentlyInteractiveElement = isInherentlyInteractiveElement;
4
4
  exports.isNonInteractiveRole = isNonInteractiveRole;
5
5
  const attributes_comparator_1 = require("../attributes-comparator");
6
6
  const get_attribute_value_1 = require("../get-attribute-value");
@@ -36,7 +36,7 @@ function checkIsNonInteractiveRole(node) {
36
36
  * has a dynamic handler on it and we need to discern whether or not
37
37
  * it's intention is to be interacted with on the DOM.
38
38
  */
39
- function isInteractiveElement(node) {
39
+ function isInherentlyInteractiveElement(node) {
40
40
  return (0, get_dom_elements_1.getDomElements)().has(node.name) && checkIsInteractiveElement(node);
41
41
  }
42
42
  function isNonInteractiveRole(node) {
@@ -1,7 +1,8 @@
1
1
  import { AST, LiteralPrimitive } from '@angular-eslint/bundled-angular-compiler';
2
+ export type Quote = "'" | '"' | '`';
2
3
  export declare function isLiteralPrimitive(node: AST): node is LiteralPrimitive;
3
4
  export declare function isStringLiteralPrimitive(node: AST): node is Omit<LiteralPrimitive, 'value'> & {
4
5
  value: string;
5
6
  };
6
- export declare function getLiteralPrimitiveStringValue(node: LiteralPrimitive, quote: "'" | '"' | '`'): string;
7
+ export declare function getLiteralPrimitiveStringValue(node: LiteralPrimitive, quote: Quote): string;
7
8
  //# sourceMappingURL=literal-primitive.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"literal-primitive.d.ts","sourceRoot":"","sources":["../../src/utils/literal-primitive.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EACH,gBAAgB,EACjB,MAAM,0CAA0C,CAAC;AAElD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,IAAI,gBAAgB,CAEtE;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,GAAG,GACR,IAAI,IAAI,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAE7D;AAED,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GACrB,MAAM,CAIR"}
1
+ {"version":3,"file":"literal-primitive.d.ts","sourceRoot":"","sources":["../../src/utils/literal-primitive.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EACH,gBAAgB,EACjB,MAAM,0CAA0C,CAAC;AAElD,MAAM,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEpC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,IAAI,gBAAgB,CAEtE;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,GAAG,GACR,IAAI,IAAI,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAE7D;AAED,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,KAAK,GACX,MAAM,CAIR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular-eslint/eslint-plugin-template",
3
- "version": "20.0.0-alpha.1",
3
+ "version": "20.0.0-alpha.2",
4
4
  "description": "ESLint plugin for Angular Templates",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -20,19 +20,19 @@
20
20
  "dependencies": {
21
21
  "aria-query": "5.3.2",
22
22
  "axobject-query": "4.1.0",
23
- "@angular-eslint/bundled-angular-compiler": "20.0.0-alpha.1",
24
- "@angular-eslint/utils": "20.0.0-alpha.1"
23
+ "@angular-eslint/bundled-angular-compiler": "20.0.0-alpha.2",
24
+ "@angular-eslint/utils": "20.0.0-alpha.2"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/aria-query": "5.0.4",
28
- "@angular-eslint/template-parser": "20.0.0-alpha.1",
29
- "@angular-eslint/test-utils": "20.0.0-alpha.1"
28
+ "@angular-eslint/test-utils": "20.0.0-alpha.2"
30
29
  },
31
30
  "peerDependencies": {
32
31
  "@typescript-eslint/types": "^7.11.0 || ^8.0.0",
33
32
  "@typescript-eslint/utils": "^7.11.0 || ^8.0.0",
34
33
  "eslint": "^8.57.0 || ^9.0.0",
35
- "typescript": "*"
34
+ "typescript": "*",
35
+ "@angular-eslint/template-parser": "20.0.0-alpha.2"
36
36
  },
37
37
  "gitHead": "e2006e5e9c99e5a943d1a999e0efa5247d29ec24"
38
38
  }