@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 +1 -1
- package/dist/rules/click-events-have-key-events.d.ts +6 -2
- package/dist/rules/click-events-have-key-events.d.ts.map +1 -1
- package/dist/rules/click-events-have-key-events.js +44 -5
- package/dist/rules/interactive-supports-focus.js +1 -1
- package/dist/rules/label-has-associated-control.d.ts.map +1 -1
- package/dist/rules/label-has-associated-control.js +6 -4
- package/dist/rules/prefer-template-literal.d.ts.map +1 -1
- package/dist/rules/prefer-template-literal.js +89 -46
- package/dist/utils/is-interactive-element/index.d.ts +1 -1
- package/dist/utils/is-interactive-element/index.d.ts.map +1 -1
- package/dist/utils/is-interactive-element/index.js +2 -2
- package/dist/utils/literal-primitive.d.ts +2 -1
- package/dist/utils/literal-primitive.d.ts.map +1 -1
- package/package.json +6 -6
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",
|
|
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",
|
|
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":"
|
|
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 ((
|
|
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.
|
|
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.
|
|
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,
|
|
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
|
|
74
|
-
|
|
75
|
-
|
|
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":"
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
return leftValue;
|
|
43
|
+
if (parentIsTemplateLiteral) {
|
|
44
|
+
return '';
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
if (
|
|
48
|
-
return
|
|
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
|
-
|
|
63
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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 [
|
|
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],
|
|
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.
|
|
120
|
-
fixer.removeRange([innerEnd - 1,
|
|
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],
|
|
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],
|
|
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 [
|
|
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],
|
|
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.
|
|
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],
|
|
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],
|
|
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
|
|
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,
|
|
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.
|
|
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
|
|
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:
|
|
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,
|
|
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.
|
|
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.
|
|
24
|
-
"@angular-eslint/utils": "20.0.0-alpha.
|
|
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/
|
|
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
|
}
|