1<p align="center">
2  <a href="https://travis-ci.org/evcohen/jsx-ast-utils">
3    <img src="https://api.travis-ci.org/evcohen/jsx-ast-utils.svg?branch=master"
4         alt="build status">
5  </a>
6  <a href="https://npmjs.org/package/jsx-ast-utils">
7    <img src="https://img.shields.io/npm/v/jsx-ast-utils.svg"
8         alt="npm version">
9  </a>
10  <a href="https://github.com/evcohen/jsx-ast-utils/blob/master/LICENSE.md">
11    <img src="https://img.shields.io/npm/l/jsx-ast-utils.svg"
12         alt="license">
13  </a>
14  <a href='https://coveralls.io/github/evcohen/jsx-ast-utils?branch=master'>
15    <img src='https://coveralls.io/repos/github/evcohen/jsx-ast-utils/badge.svg?branch=master' alt='Coverage Status' />
16  </a>
17  <a href='https://npmjs.org/package/jsx-ast-utils'>
18    <img src='https://img.shields.io/npm/dt/jsx-ast-utils.svg'
19    alt='Total npm downloads' />
20  </a>
21</p>
22
23# jsx-ast-utils
24
25AST utility module for statically analyzing JSX.
26
27## Installation
28```sh
29$ npm i jsx-ast-utils --save
30```
31
32## Usage
33This is a utility module to evaluate AST objects for JSX syntax. This can be super useful when writing linting rules for JSX code. It was originally in the code for [eslint-plugin-jsx-a11y](https://github.com/evcohen/eslint-plugin-jsx-a11y), however I thought it could be useful to be extracted and maintained separately so **you** could write new interesting rules to statically analyze JSX.
34
35### ESLint example
36```js
37import { hasProp } from 'jsx-ast-utils';
38// OR: var hasProp = require('jsx-ast-utils').hasProp;
39// OR: const hasProp = require('jsx-ast-utils/hasProp');
40// OR: import hasProp from 'jsx-ast-utils/hasProp';
41
42module.exports = context => ({
43  JSXOpeningElement: node => {
44    const onChange = hasProp(node.attributes, 'onChange');
45
46    if (onChange) {
47      context.report({
48        node,
49        message: `No onChange!`
50      });
51    }
52  }
53});
54```
55
56## API
57### AST Resources
581. [JSX spec](https://github.com/facebook/jsx/blob/master/AST.md)
592. [JS spec](https://github.com/estree/estree/blob/master/spec.md)
60
61### hasProp
62```js
63hasProp(props, prop, options);
64```
65Returns boolean indicating whether an prop exists as an attribute on a JSX element node.
66
67#### Props
68Object - The attributes on the visited node. (Usually `node.attributes`).
69#### Prop
70String - A string representation of the prop you want to check for existence.
71#### Options
72Object - An object representing options for existence checking
73  1. `ignoreCase` - automatically set to `true`.
74  2. `spreadStrict` - automatically set to `true`. This means if spread operator exists in
75     props, it will assume the prop you are looking for is not in the spread.
76     Example: `<div {...props} />` looking for specific prop here will return false if `spreadStrict` is `true`.
77
78<hr />
79
80### hasAnyProp
81
82```js
83hasAnyProp(props, prop, options);
84```
85Returns a boolean indicating if **any** of props in `prop` argument exist on the node.
86
87#### Props
88Object - The attributes on the visited node. (Usually `node.attributes`).
89#### Prop
90Array<String> - An array of strings representing the props you want to check for existence.
91#### Options
92Object - An object representing options for existence checking
93  1. `ignoreCase` - automatically set to `true`.
94  2. `spreadStrict` - automatically set to `true`. This means if spread operator exists in
95     props, it will assume the prop you are looking for is not in the spread.
96     Example: `<div {...props} />` looking for specific prop here will return false if `spreadStrict` is `true`.
97
98<hr />
99
100### hasEveryProp
101
102```js
103hasEveryProp(props, prop, options);
104```
105Returns a boolean indicating if **all** of props in `prop` argument exist on the node.
106
107#### Props
108Object - The attributes on the visited node. (Usually `node.attributes`).
109#### Prop
110Array<String> - An array of strings representing the props you want to check for existence.
111#### Options
112Object - An object representing options for existence checking
113 1. `ignoreCase` - automatically set to `true`.
114 2. `spreadStrict` - automatically set to `true`. This means if spread operator exists in
115    props, it will assume the prop you are looking for is not in the spread.
116    Example: `<div {...props} />` looking for specific prop here will return false if `spreadStrict` is `true`.
117
118<hr />
119
120### getProp
121
122```js
123getProp(props, prop, options);
124```
125Returns the JSXAttribute itself or undefined, indicating the prop is not present on the JSXOpeningElement.
126
127#### Props
128Object - The attributes on the visited node. (Usually `node.attributes`).
129#### Prop
130String - A string representation of the prop you want to check for existence.
131#### Options
132Object - An object representing options for existence checking
133  1. `ignoreCase` - automatically set to `true`.
134
135<hr />
136
137### elementType
138```js
139elementType(node)
140```
141Returns the tagName associated with a JSXElement.
142
143#### Node
144Object - The visited JSXElement node object.
145
146<hr />
147
148### getPropValue
149
150```js
151getPropValue(prop);
152```
153Returns the value of a given attribute. Different types of attributes have their associated values in different properties on the object.
154
155This function should return the most *closely* associated value with the intention of the JSX.
156
157#### Prop
158Object - The JSXAttribute collected by AST parser.
159
160<hr />
161
162### getLiteralPropValue
163
164```js
165getLiteralPropValue(prop);
166```
167Returns the value of a given attribute. Different types of attributes have their associated values in different properties on the object.
168
169This function should return a value only if we can extract a literal value from its attribute (i.e. values that have generic types in JavaScript - strings, numbers, booleans, etc.)
170
171#### Prop
172Object - The JSXAttribute collected by AST parser.
173
174<hr />
175
176### propName
177
178```js
179propName(prop);
180```
181Returns the name associated with a JSXAttribute. For example, given `<div foo="bar" />` and the JSXAttribute for `foo`, this will return the string `"foo"`.
182
183#### Prop
184Object - The JSXAttribute collected by AST parser.
185
186<hr />
187
188### eventHandlers
189
190```js
191console.log(eventHandlers);
192/*
193[
194  'onCopy',
195  'onCut',
196  'onPaste',
197  'onCompositionEnd',
198  'onCompositionStart',
199  'onCompositionUpdate',
200  'onKeyDown',
201  'onKeyPress',
202  'onKeyUp',
203  'onFocus',
204  'onBlur',
205  'onChange',
206  'onInput',
207  'onSubmit',
208  'onClick',
209  'onContextMenu',
210  'onDblClick',
211  'onDoubleClick',
212  'onDrag',
213  'onDragEnd',
214  'onDragEnter',
215  'onDragExit',
216  'onDragLeave',
217  'onDragOver',
218  'onDragStart',
219  'onDrop',
220  'onMouseDown',
221  'onMouseEnter',
222  'onMouseLeave',
223  'onMouseMove',
224  'onMouseOut',
225  'onMouseOver',
226  'onMouseUp',
227  'onSelect',
228  'onTouchCancel',
229  'onTouchEnd',
230  'onTouchMove',
231  'onTouchStart',
232  'onScroll',
233  'onWheel',
234  'onAbort',
235  'onCanPlay',
236  'onCanPlayThrough',
237  'onDurationChange',
238  'onEmptied',
239  'onEncrypted',
240  'onEnded',
241  'onError',
242  'onLoadedData',
243  'onLoadedMetadata',
244  'onLoadStart',
245  'onPause',
246  'onPlay',
247  'onPlaying',
248  'onProgress',
249  'onRateChange',
250  'onSeeked',
251  'onSeeking',
252  'onStalled',
253  'onSuspend',
254  'onTimeUpdate',
255  'onVolumeChange',
256  'onWaiting',
257  'onLoad',
258  'onError',
259  'onAnimationStart',
260  'onAnimationEnd',
261  'onAnimationIteration',
262  'onTransitionEnd',
263]
264*/
265```
266
267Contains a flat list of common event handler props used in JSX to attach behaviors
268to DOM events.
269
270#### eventHandlersByType
271
272The same list as `eventHandlers`, grouped into types.
273
274```js
275console.log(eventHandlersByType);
276/*
277{
278  clipboard: [ 'onCopy', 'onCut', 'onPaste' ],
279  composition: [ 'onCompositionEnd', 'onCompositionStart', 'onCompositionUpdate' ],
280  keyboard: [ 'onKeyDown', 'onKeyPress', 'onKeyUp' ],
281  focus: [ 'onFocus', 'onBlur' ],
282  form: [ 'onChange', 'onInput', 'onSubmit' ],
283  mouse: [ 'onClick', 'onContextMenu', 'onDblClick', 'onDoubleClick', 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragExit', 'onDragLeave', 'onDragOver', 'onDragStart', 'onDrop', 'onMouseDown', 'onMouseEnter', 'onMouseLeave', 'onMouseMove', 'onMouseOut', 'onMouseOver', 'onMouseUp' ],
284  selection: [ 'onSelect' ],
285  touch: [ 'onTouchCancel', 'onTouchEnd', 'onTouchMove', 'onTouchStart' ],
286  ui: [ 'onScroll' ],
287  wheel: [ 'onWheel' ],
288  media: [ 'onAbort', 'onCanPlay', 'onCanPlayThrough', 'onDurationChange', 'onEmptied', 'onEncrypted', 'onEnded', 'onError', 'onLoadedData', 'onLoadedMetadata', 'onLoadStart', 'onPause', 'onPlay', 'onPlaying', 'onProgress', 'onRateChange', 'onSeeked', 'onSeeking', 'onStalled', 'onSuspend', 'onTimeUpdate', 'onVolumeChange', 'onWaiting' ],
289  image: [ 'onLoad', 'onError' ],
290  animation: [ 'onAnimationStart', 'onAnimationEnd', 'onAnimationIteration' ],
291  transition: [ 'onTransitionEnd' ],
292}
293*/
294```
295