Skip to content

Commit 22b378d

Browse files
authored
fix(eslint-plugin): [no-output-native] handle getters and outputs metadata property (#567)
1 parent 8dcb33b commit 22b378d

File tree

5 files changed

+317
-199
lines changed

5 files changed

+317
-199
lines changed
Lines changed: 31 additions & 190 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import type { TSESTree } from '@typescript-eslint/experimental-utils';
22
import { createESLintRule } from '../utils/create-eslint-rule';
3-
import { OUTPUT_DECORATOR } from '../utils/selectors';
4-
import { toPattern } from '../utils/utils';
3+
import { getNativeEventNames } from '../utils/get-native-event-names';
4+
import {
5+
OUTPUTS_METADATA_PROPERTY,
6+
OUTPUT_ALIAS,
7+
OUTPUT_PROPERTY_OR_GETTER,
8+
} from '../utils/selectors';
9+
import { getRawText } from '../utils/utils';
510

611
type Options = [];
712
export type MessageIds = 'noOutputNative';
@@ -12,27 +17,44 @@ export default createESLintRule<Options, MessageIds>({
1217
meta: {
1318
type: 'suggestion',
1419
docs: {
15-
description: 'Disallows naming or aliasing outputs as standard DOM event',
20+
description:
21+
'Ensures that output bindings, including aliases, are not named as standard DOM events',
1622
category: 'Best Practices',
1723
recommended: 'error',
1824
},
1925
schema: [],
2026
messages: {
2127
noOutputNative:
22-
'Outputs should not be named or aliased as standard DOM event',
28+
'Output bindings, including aliases, should not be named as standard DOM events',
2329
},
2430
},
2531
defaultOptions: [],
2632
create(context) {
27-
const nativeEventNames = toPattern([...getNativeEventNames()]);
28-
const outputAliasSelector = `ClassProperty ${OUTPUT_DECORATOR} :matches(Literal[value=${nativeEventNames}], TemplateElement[value.raw=${nativeEventNames}])`;
29-
const outputPropertySelector = `ClassProperty[computed=false]:has(${OUTPUT_DECORATOR}) > :matches(Identifier[name=${nativeEventNames}], Literal[value=${nativeEventNames}])`;
30-
const selectors = [outputAliasSelector, outputPropertySelector].join(',');
33+
const nativeEventNames = getNativeEventNames();
34+
const selectors = [
35+
OUTPUTS_METADATA_PROPERTY,
36+
OUTPUT_ALIAS,
37+
OUTPUT_PROPERTY_OR_GETTER,
38+
].join(',');
3139

3240
return {
3341
[selectors](
34-
node: TSESTree.Identifier | TSESTree.Literal | TSESTree.TemplateElement,
42+
node:
43+
| TSESTree.Identifier
44+
| TSESTree.StringLiteral
45+
| TSESTree.TemplateElement,
3546
) {
47+
const [propertyName, aliasName] = getRawText(node)
48+
.replace(/\s/g, '')
49+
.split(':');
50+
51+
if (
52+
!nativeEventNames.has(propertyName) &&
53+
!nativeEventNames.has(aliasName)
54+
) {
55+
return;
56+
}
57+
3658
context.report({
3759
node,
3860
messageId: 'noOutputNative',
@@ -41,184 +63,3 @@ export default createESLintRule<Options, MessageIds>({
4163
};
4264
},
4365
});
44-
45-
let nativeEventNames: ReadonlySet<string> | null = null;
46-
function getNativeEventNames(): ReadonlySet<string> {
47-
return (
48-
nativeEventNames ||
49-
// Source: https://developer.mozilla.org/en-US/docs/Web/Events
50-
(nativeEventNames = new Set<string>([
51-
'abort',
52-
'afterprint',
53-
'animationend',
54-
'animationiteration',
55-
'animationstart',
56-
'appinstalled',
57-
'audioprocess',
58-
'audioend',
59-
'audiostart',
60-
'beforeprint',
61-
'beforeunload',
62-
'beginEvent',
63-
'blocked',
64-
'blur',
65-
'boundary',
66-
'cached',
67-
'canplay',
68-
'canplaythrough',
69-
'change',
70-
'chargingchange',
71-
'chargingtimechange',
72-
'checking',
73-
'click',
74-
'close',
75-
'complete',
76-
'compositionend',
77-
'compositionstart',
78-
'compositionupdate',
79-
'contextmenu',
80-
'copy',
81-
'cut',
82-
'dblclick',
83-
'devicechange',
84-
'devicelight',
85-
'devicemotion',
86-
'deviceorientation',
87-
'deviceproximity',
88-
'dischargingtimechange',
89-
'DOMAttributeNameChanged',
90-
'DOMAttrModified',
91-
'DOMCharacterDataModified',
92-
'DOMContentLoaded',
93-
'DOMElementNameChanged',
94-
'focus',
95-
'focusin',
96-
'focusout',
97-
'DOMNodeInserted',
98-
'DOMNodeInsertedIntoDocument',
99-
'DOMNodeRemoved',
100-
'DOMNodeRemovedFromDocument',
101-
'DOMSubtreeModified',
102-
'downloading',
103-
'drag',
104-
'dragend',
105-
'dragenter',
106-
'dragleave',
107-
'dragover',
108-
'dragstart',
109-
'drop',
110-
'durationchange',
111-
'emptied',
112-
'end',
113-
'ended',
114-
'endEvent',
115-
'error',
116-
'fullscreenchange',
117-
'fullscreenerror',
118-
'gamepadconnected',
119-
'gamepaddisconnected',
120-
'gotpointercapture',
121-
'hashchange',
122-
'lostpointercapture',
123-
'input',
124-
'invalid',
125-
'keydown',
126-
'keypress',
127-
'keyup',
128-
'languagechange',
129-
'levelchange',
130-
'load',
131-
'loadeddata',
132-
'loadedmetadata',
133-
'loadend',
134-
'loadstart',
135-
'mark',
136-
'message',
137-
'messageerror',
138-
'mousedown',
139-
'mouseenter',
140-
'mouseleave',
141-
'mousemove',
142-
'mouseout',
143-
'mouseover',
144-
'mouseup',
145-
'nomatch',
146-
'notificationclick',
147-
'noupdate',
148-
'obsolete',
149-
'offline',
150-
'online',
151-
'open',
152-
'orientationchange',
153-
'pagehide',
154-
'pageshow',
155-
'paste',
156-
'pause',
157-
'pointercancel',
158-
'pointerdown',
159-
'pointerenter',
160-
'pointerleave',
161-
'pointerlockchange',
162-
'pointerlockerror',
163-
'pointermove',
164-
'pointerout',
165-
'pointerover',
166-
'pointerup',
167-
'play',
168-
'playing',
169-
'popstate',
170-
'progress',
171-
'push',
172-
'pushsubscriptionchange',
173-
'ratechange',
174-
'readystatechange',
175-
'repeatEvent',
176-
'reset',
177-
'resize',
178-
'resourcetimingbufferfull',
179-
'result',
180-
'resume',
181-
'scroll',
182-
'seeked',
183-
'seeking',
184-
'select',
185-
'selectstart',
186-
'selectionchange',
187-
'show',
188-
'soundend',
189-
'soundstart',
190-
'speechend',
191-
'speechstart',
192-
'stalled',
193-
'start',
194-
'storage',
195-
'submit',
196-
'success',
197-
'suspend',
198-
'SVGAbort',
199-
'SVGError',
200-
'SVGLoad',
201-
'SVGResize',
202-
'SVGScroll',
203-
'SVGUnload',
204-
'SVGZoom',
205-
'timeout',
206-
'timeupdate',
207-
'touchcancel',
208-
'touchend',
209-
'touchmove',
210-
'touchstart',
211-
'transitionend',
212-
'unload',
213-
'updateready',
214-
'upgradeneeded',
215-
'userproximity',
216-
'voiceschanged',
217-
'versionchange',
218-
'visibilitychange',
219-
'volumechange',
220-
'waiting',
221-
'wheel',
222-
]))
223-
);
224-
}

0 commit comments

Comments
 (0)