Ajout de promotion et de commande
This commit is contained in:
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"presets": ["env"],
|
||||
"plugins": [
|
||||
["transform-replace-object-assign", { "moduleSpecifier": "object.assign" }],
|
||||
"transform-object-rest-spread",
|
||||
// "@babel/plugin-proposal-nullish-coalescing-operator", // TODO: update to babel 7
|
||||
],
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
node_modules/
|
||||
reports/
|
||||
lib/
|
||||
coverage/
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "airbnb-base",
|
||||
|
||||
"parser": "@babel/eslint-parser",
|
||||
|
||||
"rules": {
|
||||
"no-use-before-define": ["error", { "functions": false }],
|
||||
},
|
||||
|
||||
"overrides": [
|
||||
{
|
||||
"files": "src/index.js",
|
||||
"rules": {
|
||||
"import/no-import-module-exports": 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [jsx-eslint, ljharb]
|
||||
open_collective: eslint-plugin-jsx-a11y
|
||||
tidelift: "npm/jsx-ast-utils"
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [v3.3.5](https://github.com/jsx-eslint/jsx-ast-utils/compare/v3.3.4...v3.3.5) - 2023-07-28
|
||||
|
||||
### Fixed
|
||||
|
||||
- [Fix] `extractProp`: support `JSXFragment` [`#132`](https://github.com/jsx-eslint/jsx-ast-utils/issues/132)
|
||||
|
||||
### Commits
|
||||
|
||||
- [Dev Deps] update `@babel/core`, `@babel/eslint-parser`, `@babel/parser`, `eslint` [`e5555d1`](https://github.com/jsx-eslint/jsx-ast-utils/commit/e5555d152dbe1e85324139756f637e65fe047976)
|
||||
- [Tests] fix a test [`bde3ba9`](https://github.com/jsx-eslint/jsx-ast-utils/commit/bde3ba9c9dc294d5472eefa0b3f31ab0e1aed739)
|
||||
|
||||
## [v3.3.4](https://github.com/jsx-eslint/jsx-ast-utils/compare/v3.3.3...v3.3.4) - 2023-06-28
|
||||
|
||||
### Commits
|
||||
|
||||
- [Refactor] use `array.prototype.flat` `object.values` over `.reduce` [`bad51d0`](https://github.com/jsx-eslint/jsx-ast-utils/commit/bad51d062000ffdc19d925723a6515458318cf92)
|
||||
- [meta] add `auto-changelog` [`af1de69`](https://github.com/jsx-eslint/jsx-ast-utils/commit/af1de693d1005144c13a75573631a670fa44547e)
|
||||
- [Tests] add test for `import.meta` [`1d39f58`](https://github.com/jsx-eslint/jsx-ast-utils/commit/1d39f58c7bc6a89aa936e666b76e355c9436e854)
|
||||
- [Dev Deps] update `@babel/core`, `@babel/eslint-parser`, `@babel/parser`, `aud`, `eslint`, `eslint-plugin-import` [`3baaf76`](https://github.com/jsx-eslint/jsx-ast-utils/commit/3baaf76c9c48ae85687ed23a3b9894c45927e081)
|
||||
- [Fix] `TSNonNullExpression`: Handle function calls [`26cc3c4`](https://github.com/jsx-eslint/jsx-ast-utils/commit/26cc3c48165518b9fcdc9c625d918accc3e00107)
|
||||
- [Dev Deps] update `eslint`, `@babel/core`, `@babel/parser`, `object.entries`, `object.fromentries` [`0e4f80c`](https://github.com/jsx-eslint/jsx-ast-utils/commit/0e4f80c2129c5b5ee50e4df2f25c5fb6728cbe8e)
|
||||
- [Dev Deps] update `@babel/core`, `@babel/eslint-parser`, `@babel/parser`, `aud` [`b5427a6`](https://github.com/jsx-eslint/jsx-ast-utils/commit/b5427a65fac33e2264461b072b3edb078242dc85)
|
||||
- [meta] run build in prepack, not prepublish [`a0f4f38`](https://github.com/jsx-eslint/jsx-ast-utils/commit/a0f4f383ddf82cd2914c7e594f356d9a78c80570)
|
||||
- [Deps] update `array-includes` [`c479841`](https://github.com/jsx-eslint/jsx-ast-utils/commit/c479841d0b65188a3223541e885fa6286756a2c6)
|
||||
- [Deps] update `object.assign` [`9685dce`](https://github.com/jsx-eslint/jsx-ast-utils/commit/9685dce823d71ac06fccd61d8aa8e13ba3d42f38)
|
||||
|
||||
<!-- auto-changelog-above -->
|
||||
|
||||
3.3.3 / 2022-08-08
|
||||
==================
|
||||
- [Fix] Mark ChainExpression as a noop (#109)
|
||||
- [Deps] update `object.assign`
|
||||
- [Dev Deps] update `@babel/core`, `@babel/eslint-parser`, `@babel/parser`, `eslint`
|
||||
|
||||
3.3.2 / 2022-07-06
|
||||
==================
|
||||
- [Fix] Handle `as` casts in TSNonNullExpression
|
||||
|
||||
3.3.1 / 2022-06-22
|
||||
==================
|
||||
- [Fix] `ArrayExpression`: handle sparse array (#117)
|
||||
- [Deps] update `array-includes`
|
||||
- [meta] move jest config to separate file
|
||||
- [meta] use `npmignore` to autogenerate an npmignore file
|
||||
- [Dev Deps] update `@babel/core`, `@babel/eslint-parser`, `@babel/parser`, `eslint`
|
||||
|
||||
3.3.0 / 2022-04-30
|
||||
==================
|
||||
- [New] add `JSXFragment`, `JSXText`; fix `JSXElement` to handle children
|
||||
- [Dev Deps] update `@babel/core`, `@babel/parser`, `eslint`, `eslint-plugin-import`
|
||||
|
||||
3.2.2 / 2022-03-31
|
||||
==================
|
||||
- [Fix] `TSNonNullExpression`: handle computed MemberExpressions (#109)
|
||||
- [Fix] avoid a crash in ChainExpressions in a TSAsExpression
|
||||
|
||||
3.2.1 / 2021-09-16
|
||||
==================
|
||||
- [patch] include project name in error logging (#113)
|
||||
- [readme] update badges, URLs
|
||||
- [Deps] update `array-includes`
|
||||
- [meta] don‘t lint coverage results
|
||||
- [meta] add GitHub org to FUNDING.yml
|
||||
- [meta] add OpenCollective to FUNDING.yml
|
||||
- [meta] run `aud` in `posttest`
|
||||
- [meta] add Automatic Rebase and Require Allow Edits workflows
|
||||
- [actions] use `node/install` instead of `node/run`; use `codecov` action
|
||||
- [Tests] unpin `caniuse-lite`, since breaking change is fixed
|
||||
- [Tests] pin `caniuse-lite`, due to breaking change in patch version
|
||||
- [Tests] fix linting errors
|
||||
- [Tests] migrate tests to Github Actions
|
||||
- [Tests] stop using coveralls
|
||||
- [Tests] skip failing fragment test in node 4
|
||||
- [Dev Deps] update `@babel/core`, `@babel/parser`, `aud`, `eslint`, `eslint-plugin-import`, `object.entries`, `object.fromentries`
|
||||
|
||||
3.2.0 / 2020-12-16
|
||||
==================
|
||||
- [New] add support for fragment syntax (`<>`) (#108)
|
||||
- [Fix] `TSNonNullExpression`: handle `ThisExpression`s (#108)
|
||||
- [Deps] update `array-includes`, `object.assign`
|
||||
- [Dev Deps] update `@babel/core`, `@babel/parser`, `eslint`, `eslint-config-airbnb-base`, `object.entries`, `object.fromentries`
|
||||
|
||||
3.1.0 / 2020-10-13
|
||||
==================
|
||||
- [New] add `TSNonNullExpression` (#105)
|
||||
- [New] add `AssignmentExpression` (#106)
|
||||
- [Dev Deps] update `eslint`
|
||||
|
||||
3.0.0 / 2020-10-06
|
||||
==================
|
||||
- [Breaking] Don't return node.start & node.end (#100)
|
||||
- [Breaking] add `ChainExpression`; `CallExpression` now includes arguments (#102)
|
||||
- [New] add `SequenceExpression` (#101)
|
||||
- [Deps] update `object.assign`
|
||||
- [Dev Deps] update `eslint`, `eslint-plugin-import`
|
||||
- [Dev Deps] update `@babel/core`, `@babel/parser`, `eslint`, `eslint-plugin-import`
|
||||
- [Tests] use proper `actual, expected` ordering for non-confusing failure messages
|
||||
|
||||
2.4.1 / 2020-06-11
|
||||
==================
|
||||
- [Fix] `expressions/TemplateLiteral`: use `.range[0]` instead of `.start`
|
||||
|
||||
2.4.0 / 2020-06-11
|
||||
==================
|
||||
- [New] Provide both range and start & end property on Node, support eslint v7 (#97)
|
||||
- [Dev Deps] update `@babel/core`, `@babel/parser`, `eslint`, `eslint-config-airbnb-base`, `eslint-plugin-import`, `flow-parser`
|
||||
- [meta] remove yarn registry from npmrc, so `npm publish` works
|
||||
|
||||
2.3.0 / 2020-05-24
|
||||
==================
|
||||
- [New] add nullish coalescing (#99)
|
||||
- [New] add OptionalCallExpression (#99)
|
||||
- [Deps] update `array-includes`
|
||||
- [meta] add `safe-publish-latest`
|
||||
- [Dev Deps] update `@babel/parser`, `babel-eslint`, `coveralls`, `eslint`, `eslint-config-airbnb-base`, `eslint-plugin-import`, `in-publish`, `object.entries`, `object.fromentries`, `rimraf`
|
||||
- [Tests] on `node` `v14`; test all branches
|
||||
|
||||
2.2.3 / 2019-10-24
|
||||
==================
|
||||
- (fix) Fix crash on spread (#94)
|
||||
|
||||
2.2.2 / 2019-10-24
|
||||
==================
|
||||
- (improvement) Add support for retrieving props from a spread with object expression (#93)
|
||||
|
||||
2.2.1 / 2019-06-30
|
||||
==================
|
||||
- (improvement) Account for TypeCastExpression in the utils
|
||||
|
||||
2.2.0 / 2019-06-25
|
||||
==================
|
||||
- (fix) Fix getLiteralPropValue for TS-specific node types.
|
||||
- (chore) upgrade dependencies.
|
||||
- (improvement) Stop throwing errors when unknown AST nodes are encountered.
|
||||
- (dev) CI changes.
|
||||
|
||||
2.1.0 / 2018-04-19
|
||||
==================
|
||||
- Fix undefined bug for template strings. #45
|
||||
- Adding support for `objectRestSpread` within props #60
|
||||
- Accommodate ExperimentalSpreadProperty in prop values #75
|
||||
- Account for SpreadElement AST Nodes #76
|
||||
- Support OptionalMemberExpression AST nodes #77
|
||||
- Add support to Typescript's node types #72
|
||||
|
||||
2.0.1 / 2017-08-31
|
||||
==================
|
||||
- [fix] Add support for BindExpression
|
||||
|
||||
|
||||
2.0.0 / 2017-07-07
|
||||
==================
|
||||
- [breaking] Remove undefined return from `propName` so it always returns a value.
|
||||
|
||||
|
||||
1.4.1 / 2017-04-19
|
||||
==================
|
||||
- [fix] - Fixing fatal throw in `getPropValue` for `ArrowFunctionExpression`
|
||||
|
||||
|
||||
1.4.0 / 2017-02-02
|
||||
==================
|
||||
- [new] Add eventHandlers and eventHandlersByType to API. These are the event names for DOM elements on JSX-using libraries such as React, inferno, and preact.
|
||||
|
||||
|
||||
1.3.5 / 2016-12-14
|
||||
==================
|
||||
- [fix] Normalize literals "true" and "false" before converting to boolean in Literal prop value extractor.
|
||||
|
||||
|
||||
1.3.4 / 2016-11-15
|
||||
==================
|
||||
- [fix] Recursively resolve JSXMemberExpression names for elementType. (i.e. `<Component.Render.Me />`). Fixes [#9](https://github.com/evcohen/jsx-ast-utils/issues/9)
|
||||
|
||||
|
||||
1.3.3 / 2016-10-28
|
||||
==================
|
||||
- [fix] Add support for `ArrayExpression`.
|
||||
|
||||
|
||||
1.3.2 / 2016-10-11
|
||||
==================
|
||||
- [fix] Add support for `UpdateExpression`.
|
||||
|
||||
|
||||
1.3.1 / 2016-07-13
|
||||
==================
|
||||
- [fix] Add `JSXElement` to expression types to handle recursively extracting prop value.
|
||||
|
||||
|
||||
1.3.0 / 2016-07-12
|
||||
==================
|
||||
- [new] Add support for `TaggedTemplateExpression`.
|
||||
|
||||
|
||||
1.2.1 / 2016-06-15
|
||||
==================
|
||||
- [fix] Point to `lib` instead of `src` for root exports.
|
||||
|
||||
|
||||
1.2.0 / 2016-06-15
|
||||
==================
|
||||
- [new] Export functions from root so they can be imported like the following: `require('jsx-ast-utils/{function}')`.
|
||||
|
||||
|
||||
1.1.1 / 2016-06-12
|
||||
==================
|
||||
- [fix] Better support for expressions in `TemplateLiteral` extraction.
|
||||
|
||||
|
||||
1.1.0 / 2016-06-10
|
||||
==================
|
||||
- [new] Support for namespaced element names.
|
||||
- [new] Add `propName` to API to get correct name for prop.
|
||||
|
||||
|
||||
1.0.1 / 2016-06-10
|
||||
==================
|
||||
- [fix] Return actual reserved words instead of string representations of them.
|
||||
|
||||
|
||||
1.0.0 / 2016-06-09
|
||||
==================
|
||||
- Initial stable release
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2016 Ethan Cohen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+298
@@ -0,0 +1,298 @@
|
||||
# jsx-ast-utils <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
|
||||
|
||||
[![github actions][actions-image]][actions-url]
|
||||
[![coverage][codecov-image]][codecov-url]
|
||||
[![dependency status][deps-svg]][deps-url]
|
||||
[![dev dependency status][dev-deps-svg]][dev-deps-url]
|
||||
[![License][license-image]][license-url]
|
||||
[![Downloads][downloads-image]][downloads-url]
|
||||
|
||||
[![npm badge][npm-badge-png]][package-url]
|
||||
|
||||
AST utility module for statically analyzing JSX.
|
||||
|
||||
## Installation
|
||||
```sh
|
||||
$ npm i jsx-ast-utils --save
|
||||
```
|
||||
|
||||
## Usage
|
||||
This 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/jsx-eslint/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.
|
||||
|
||||
### ESLint example
|
||||
```js
|
||||
import { hasProp } from 'jsx-ast-utils';
|
||||
// OR: var hasProp = require('jsx-ast-utils').hasProp;
|
||||
// OR: const hasProp = require('jsx-ast-utils/hasProp');
|
||||
// OR: import hasProp from 'jsx-ast-utils/hasProp';
|
||||
|
||||
module.exports = context => ({
|
||||
JSXOpeningElement: node => {
|
||||
const onChange = hasProp(node.attributes, 'onChange');
|
||||
|
||||
if (onChange) {
|
||||
context.report({
|
||||
node,
|
||||
message: `No onChange!`
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## API
|
||||
### AST Resources
|
||||
1. [JSX spec](https://github.com/facebook/jsx/blob/master/AST.md)
|
||||
2. [JS spec](https://github.com/estree/estree/blob/master/spec.md)
|
||||
|
||||
### hasProp
|
||||
```js
|
||||
hasProp(props, prop, options);
|
||||
```
|
||||
Returns boolean indicating whether an prop exists as an attribute on a JSX element node.
|
||||
|
||||
#### Props
|
||||
Object - The attributes on the visited node. (Usually `node.attributes`).
|
||||
#### Prop
|
||||
String - A string representation of the prop you want to check for existence.
|
||||
#### Options
|
||||
Object - An object representing options for existence checking
|
||||
1. `ignoreCase` - automatically set to `true`.
|
||||
2. `spreadStrict` - automatically set to `true`. This means if spread operator exists in
|
||||
props, it will assume the prop you are looking for is not in the spread.
|
||||
Example: `<div {...props} />` looking for specific prop here will return false if `spreadStrict` is `true`.
|
||||
|
||||
<hr />
|
||||
|
||||
### hasAnyProp
|
||||
|
||||
```js
|
||||
hasAnyProp(props, prop, options);
|
||||
```
|
||||
Returns a boolean indicating if **any** of props in `prop` argument exist on the node.
|
||||
|
||||
#### Props
|
||||
Object - The attributes on the visited node. (Usually `node.attributes`).
|
||||
#### Prop
|
||||
Array<String> - An array of strings representing the props you want to check for existence.
|
||||
#### Options
|
||||
Object - An object representing options for existence checking
|
||||
1. `ignoreCase` - automatically set to `true`.
|
||||
2. `spreadStrict` - automatically set to `true`. This means if spread operator exists in
|
||||
props, it will assume the prop you are looking for is not in the spread.
|
||||
Example: `<div {...props} />` looking for specific prop here will return false if `spreadStrict` is `true`.
|
||||
|
||||
<hr />
|
||||
|
||||
### hasEveryProp
|
||||
|
||||
```js
|
||||
hasEveryProp(props, prop, options);
|
||||
```
|
||||
Returns a boolean indicating if **all** of props in `prop` argument exist on the node.
|
||||
|
||||
#### Props
|
||||
Object - The attributes on the visited node. (Usually `node.attributes`).
|
||||
#### Prop
|
||||
Array<String> - An array of strings representing the props you want to check for existence.
|
||||
#### Options
|
||||
Object - An object representing options for existence checking
|
||||
1. `ignoreCase` - automatically set to `true`.
|
||||
2. `spreadStrict` - automatically set to `true`. This means if spread operator exists in
|
||||
props, it will assume the prop you are looking for is not in the spread.
|
||||
Example: `<div {...props} />` looking for specific prop here will return false if `spreadStrict` is `true`.
|
||||
|
||||
<hr />
|
||||
|
||||
### getProp
|
||||
|
||||
```js
|
||||
getProp(props, prop, options);
|
||||
```
|
||||
Returns the JSXAttribute itself or undefined, indicating the prop is not present on the JSXOpeningElement.
|
||||
|
||||
#### Props
|
||||
Object - The attributes on the visited node. (Usually `node.attributes`).
|
||||
#### Prop
|
||||
String - A string representation of the prop you want to check for existence.
|
||||
#### Options
|
||||
Object - An object representing options for existence checking
|
||||
1. `ignoreCase` - automatically set to `true`.
|
||||
|
||||
<hr />
|
||||
|
||||
### elementType
|
||||
```js
|
||||
elementType(node)
|
||||
```
|
||||
Returns the tagName associated with a JSXElement.
|
||||
|
||||
#### Node
|
||||
Object - The visited JSXElement node object.
|
||||
|
||||
<hr />
|
||||
|
||||
### getPropValue
|
||||
|
||||
```js
|
||||
getPropValue(prop);
|
||||
```
|
||||
Returns the value of a given attribute. Different types of attributes have their associated values in different properties on the object.
|
||||
|
||||
This function should return the most *closely* associated value with the intention of the JSX.
|
||||
|
||||
#### Prop
|
||||
Object - The JSXAttribute collected by AST parser.
|
||||
|
||||
<hr />
|
||||
|
||||
### getLiteralPropValue
|
||||
|
||||
```js
|
||||
getLiteralPropValue(prop);
|
||||
```
|
||||
Returns the value of a given attribute. Different types of attributes have their associated values in different properties on the object.
|
||||
|
||||
This 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.)
|
||||
|
||||
#### Prop
|
||||
Object - The JSXAttribute collected by AST parser.
|
||||
|
||||
<hr />
|
||||
|
||||
### propName
|
||||
|
||||
```js
|
||||
propName(prop);
|
||||
```
|
||||
Returns the name associated with a JSXAttribute. For example, given `<div foo="bar" />` and the JSXAttribute for `foo`, this will return the string `"foo"`.
|
||||
|
||||
#### Prop
|
||||
Object - The JSXAttribute collected by AST parser.
|
||||
|
||||
<hr />
|
||||
|
||||
### eventHandlers
|
||||
|
||||
```js
|
||||
console.log(eventHandlers);
|
||||
/*
|
||||
[
|
||||
'onCopy',
|
||||
'onCut',
|
||||
'onPaste',
|
||||
'onCompositionEnd',
|
||||
'onCompositionStart',
|
||||
'onCompositionUpdate',
|
||||
'onKeyDown',
|
||||
'onKeyPress',
|
||||
'onKeyUp',
|
||||
'onFocus',
|
||||
'onBlur',
|
||||
'onChange',
|
||||
'onInput',
|
||||
'onSubmit',
|
||||
'onClick',
|
||||
'onContextMenu',
|
||||
'onDblClick',
|
||||
'onDoubleClick',
|
||||
'onDrag',
|
||||
'onDragEnd',
|
||||
'onDragEnter',
|
||||
'onDragExit',
|
||||
'onDragLeave',
|
||||
'onDragOver',
|
||||
'onDragStart',
|
||||
'onDrop',
|
||||
'onMouseDown',
|
||||
'onMouseEnter',
|
||||
'onMouseLeave',
|
||||
'onMouseMove',
|
||||
'onMouseOut',
|
||||
'onMouseOver',
|
||||
'onMouseUp',
|
||||
'onSelect',
|
||||
'onTouchCancel',
|
||||
'onTouchEnd',
|
||||
'onTouchMove',
|
||||
'onTouchStart',
|
||||
'onScroll',
|
||||
'onWheel',
|
||||
'onAbort',
|
||||
'onCanPlay',
|
||||
'onCanPlayThrough',
|
||||
'onDurationChange',
|
||||
'onEmptied',
|
||||
'onEncrypted',
|
||||
'onEnded',
|
||||
'onError',
|
||||
'onLoadedData',
|
||||
'onLoadedMetadata',
|
||||
'onLoadStart',
|
||||
'onPause',
|
||||
'onPlay',
|
||||
'onPlaying',
|
||||
'onProgress',
|
||||
'onRateChange',
|
||||
'onSeeked',
|
||||
'onSeeking',
|
||||
'onStalled',
|
||||
'onSuspend',
|
||||
'onTimeUpdate',
|
||||
'onVolumeChange',
|
||||
'onWaiting',
|
||||
'onLoad',
|
||||
'onError',
|
||||
'onAnimationStart',
|
||||
'onAnimationEnd',
|
||||
'onAnimationIteration',
|
||||
'onTransitionEnd',
|
||||
]
|
||||
*/
|
||||
```
|
||||
|
||||
Contains a flat list of common event handler props used in JSX to attach behaviors
|
||||
to DOM events.
|
||||
|
||||
#### eventHandlersByType
|
||||
|
||||
The same list as `eventHandlers`, grouped into types.
|
||||
|
||||
```js
|
||||
console.log(eventHandlersByType);
|
||||
/*
|
||||
{
|
||||
clipboard: [ 'onCopy', 'onCut', 'onPaste' ],
|
||||
composition: [ 'onCompositionEnd', 'onCompositionStart', 'onCompositionUpdate' ],
|
||||
keyboard: [ 'onKeyDown', 'onKeyPress', 'onKeyUp' ],
|
||||
focus: [ 'onFocus', 'onBlur' ],
|
||||
form: [ 'onChange', 'onInput', 'onSubmit' ],
|
||||
mouse: [ 'onClick', 'onContextMenu', 'onDblClick', 'onDoubleClick', 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragExit', 'onDragLeave', 'onDragOver', 'onDragStart', 'onDrop', 'onMouseDown', 'onMouseEnter', 'onMouseLeave', 'onMouseMove', 'onMouseOut', 'onMouseOver', 'onMouseUp' ],
|
||||
selection: [ 'onSelect' ],
|
||||
touch: [ 'onTouchCancel', 'onTouchEnd', 'onTouchMove', 'onTouchStart' ],
|
||||
ui: [ 'onScroll' ],
|
||||
wheel: [ 'onWheel' ],
|
||||
media: [ 'onAbort', 'onCanPlay', 'onCanPlayThrough', 'onDurationChange', 'onEmptied', 'onEncrypted', 'onEnded', 'onError', 'onLoadedData', 'onLoadedMetadata', 'onLoadStart', 'onPause', 'onPlay', 'onPlaying', 'onProgress', 'onRateChange', 'onSeeked', 'onSeeking', 'onStalled', 'onSuspend', 'onTimeUpdate', 'onVolumeChange', 'onWaiting' ],
|
||||
image: [ 'onLoad', 'onError' ],
|
||||
animation: [ 'onAnimationStart', 'onAnimationEnd', 'onAnimationIteration' ],
|
||||
transition: [ 'onTransitionEnd' ],
|
||||
}
|
||||
*/
|
||||
```
|
||||
|
||||
|
||||
[1]: https://npmjs.org/package/jsx-ast-utils
|
||||
[2]: https://versionbadg.es/jsx-eslint/jsx-ast-utils.svg
|
||||
[5]: https://david-dm.org/jsx-eslint/jsx-ast-utils.svg
|
||||
[6]: https://david-dm.org/jsx-eslint/jsx-ast-utils
|
||||
[7]: https://david-dm.org/jsx-eslint/jsx-ast-utils/dev-status.svg
|
||||
[8]: https://david-dm.org/jsx-eslint/jsx-ast-utils#info=devDependencies
|
||||
[11]: https://nodei.co/npm/jsx-ast-utils.png?downloads=true&stars=true
|
||||
[license-image]: https://img.shields.io/npm/l/jsx-ast-utils.svg
|
||||
[license-url]: LICENSE
|
||||
[downloads-image]: https://img.shields.io/npm/dm/jsx-ast-utils.svg
|
||||
[downloads-url]: https://npm-stat.com/charts.html?package=jsx-ast-utils
|
||||
[codecov-image]: https://codecov.io/gh/jsx-eslint/jsx-ast-utils/branch/main/graphs/badge.svg
|
||||
[codecov-url]: https://app.codecov.io/gh/jsx-eslint/jsx-ast-utils/
|
||||
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/jsx-eslint/jsx-ast-utils
|
||||
[actions-url]: https://github.com/jsx-eslint/jsx-ast-utils/actions
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/* eslint-env jest */
|
||||
import getProp from '../src/getProp';
|
||||
|
||||
const nodeVersion = parseInt(process.version.match(/^v(\d+)\./)[1], 10);
|
||||
|
||||
export const fallbackToBabylon = nodeVersion < 6;
|
||||
|
||||
let parserName;
|
||||
const babelParser = fallbackToBabylon ? require('babylon') : require('@babel/parser');
|
||||
const flowParser = require('flow-parser');
|
||||
|
||||
const defaultPlugins = [
|
||||
'jsx',
|
||||
'functionBind',
|
||||
'estree',
|
||||
'objectRestSpread',
|
||||
'optionalChaining',
|
||||
// 'nullishCoalescing', // TODO: update to babel 7
|
||||
];
|
||||
let plugins = [...defaultPlugins];
|
||||
let isESM = false;
|
||||
|
||||
export function setParserName(name) {
|
||||
parserName = name;
|
||||
}
|
||||
|
||||
export function changePlugins(pluginOrFn) {
|
||||
if (Array.isArray(pluginOrFn)) {
|
||||
plugins = pluginOrFn;
|
||||
} else if (typeof pluginOrFn === 'function') {
|
||||
plugins = pluginOrFn(plugins);
|
||||
} else {
|
||||
throw new Error('changePlugins argument should be either an array or a function');
|
||||
}
|
||||
}
|
||||
|
||||
export function setIsESM() {
|
||||
isESM = true;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
plugins = [...defaultPlugins];
|
||||
isESM = false;
|
||||
});
|
||||
|
||||
function parse(code) {
|
||||
if (parserName === undefined) {
|
||||
throw new Error('No parser specified');
|
||||
}
|
||||
if (parserName === 'babel') {
|
||||
try {
|
||||
return babelParser.parse(code, { plugins, sourceFilename: 'test.js', ...(isESM && { sourceType: 'module' }) });
|
||||
} catch (_) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`Failed to parse with ${fallbackToBabylon ? 'babylon' : 'Babel'} parser.`);
|
||||
}
|
||||
}
|
||||
if (parserName === 'flow') {
|
||||
try {
|
||||
return flowParser.parse(code, { plugins });
|
||||
} catch (_) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('Failed to parse with the Flow parser');
|
||||
}
|
||||
}
|
||||
throw new Error(`The parser ${parserName} is not yet supported for testing.`);
|
||||
}
|
||||
|
||||
export function getOpeningElement(code) {
|
||||
const parsedCode = parse(code);
|
||||
let body;
|
||||
if (parsedCode.program) {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
body = parsedCode.program.body;
|
||||
} else {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
body = parsedCode.body;
|
||||
}
|
||||
if (Array.isArray(body) && body[0] != null) {
|
||||
const [{ expression }] = body;
|
||||
return expression.type === 'JSXFragment' ? expression.openingFragment : expression.openingElement;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function extractProp(code, prop = 'foo') {
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
return getProp(props, prop);
|
||||
}
|
||||
|
||||
export const describeIfNotBabylon = fallbackToBabylon ? describe.skip : describe;
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/* eslint-env mocha */
|
||||
import assert from 'assert';
|
||||
import { getOpeningElement, setParserName, describeIfNotBabylon } from '../helper';
|
||||
import elementType from '../../src/elementType';
|
||||
|
||||
describe('elementType tests', () => {
|
||||
beforeEach(() => {
|
||||
setParserName('babel');
|
||||
});
|
||||
it('should export a function', () => {
|
||||
const expected = 'function';
|
||||
const actual = typeof elementType;
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should throw an error if the argument is missing', () => {
|
||||
assert.throws(() => { elementType(); }, Error);
|
||||
});
|
||||
|
||||
it('should throw an error if the argument not a JSX node', () => {
|
||||
assert.throws(() => { elementType({ a: 'foo' }); }, Error);
|
||||
});
|
||||
|
||||
it('should return the correct type of the DOM element given its node object', () => {
|
||||
const code = '<div />';
|
||||
const node = getOpeningElement(code);
|
||||
|
||||
const expected = 'div';
|
||||
const actual = elementType(node);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return the correct type of the custom element given its node object', () => {
|
||||
const code = '<Slider />';
|
||||
const node = getOpeningElement(code);
|
||||
|
||||
const expected = 'Slider';
|
||||
const actual = elementType(node);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return the correct type of the custom object element given its node object', () => {
|
||||
const code = '<UX.Slider />';
|
||||
const node = getOpeningElement(code);
|
||||
|
||||
const expected = 'UX.Slider';
|
||||
const actual = elementType(node);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return the correct type of the namespaced element given its node object', () => {
|
||||
const code = '<UX:Slider />';
|
||||
const node = getOpeningElement(code);
|
||||
|
||||
const expected = 'UX:Slider';
|
||||
const actual = elementType(node);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return the correct type of the multiple custom object element given its node object', () => {
|
||||
const code = '<UX.Slider.Blue.Light />';
|
||||
const node = getOpeningElement(code);
|
||||
|
||||
const expected = 'UX.Slider.Blue.Light';
|
||||
const actual = elementType(node);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return this.Component when given its node object', () => {
|
||||
const code = '<this.Component />';
|
||||
const node = getOpeningElement(code);
|
||||
|
||||
const expected = 'this.Component';
|
||||
const actual = elementType(node);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
describeIfNotBabylon('fragments', () => {
|
||||
it('should work with fragments', () => {
|
||||
const code = '<>foo</>';
|
||||
const node = getOpeningElement(code);
|
||||
|
||||
const expected = '<>';
|
||||
const actual = elementType(node);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('works with nested fragments', () => {
|
||||
const code = `
|
||||
<Hello
|
||||
role="checkbox"
|
||||
frag={
|
||||
<>
|
||||
<div>Hello</div>
|
||||
<>
|
||||
<div>There</div>
|
||||
</>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
`;
|
||||
const node = getOpeningElement(code);
|
||||
|
||||
const expected = 'Hello';
|
||||
const actual = elementType(node);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/* eslint-env mocha */
|
||||
import assert from 'assert';
|
||||
import includes from 'array-includes';
|
||||
import eventHandlers, { eventHandlersByType } from '../../src/eventHandlers';
|
||||
|
||||
describe('eventHandlers', () => {
|
||||
it('should contain a list of common JSX event handlers', () => {
|
||||
assert([
|
||||
'onCopy',
|
||||
'onCut',
|
||||
'onPaste',
|
||||
'onCompositionEnd',
|
||||
'onCompositionStart',
|
||||
'onCompositionUpdate',
|
||||
'onKeyDown',
|
||||
'onKeyPress',
|
||||
'onKeyUp',
|
||||
'onFocus',
|
||||
'onBlur',
|
||||
'onChange',
|
||||
'onInput',
|
||||
'onSubmit',
|
||||
'onClick',
|
||||
'onContextMenu',
|
||||
'onDblClick',
|
||||
'onDoubleClick',
|
||||
'onDrag',
|
||||
'onDragEnd',
|
||||
'onDragEnter',
|
||||
'onDragExit',
|
||||
'onDragLeave',
|
||||
'onDragOver',
|
||||
'onDragStart',
|
||||
'onDrop',
|
||||
'onMouseDown',
|
||||
'onMouseEnter',
|
||||
'onMouseLeave',
|
||||
'onMouseMove',
|
||||
'onMouseOut',
|
||||
'onMouseOver',
|
||||
'onMouseUp',
|
||||
'onSelect',
|
||||
'onTouchCancel',
|
||||
'onTouchEnd',
|
||||
'onTouchMove',
|
||||
'onTouchStart',
|
||||
'onScroll',
|
||||
'onWheel',
|
||||
'onAbort',
|
||||
'onCanPlay',
|
||||
'onCanPlayThrough',
|
||||
'onDurationChange',
|
||||
'onEmptied',
|
||||
'onEncrypted',
|
||||
'onEnded',
|
||||
'onError',
|
||||
'onLoadedData',
|
||||
'onLoadedMetadata',
|
||||
'onLoadStart',
|
||||
'onPause',
|
||||
'onPlay',
|
||||
'onPlaying',
|
||||
'onProgress',
|
||||
'onRateChange',
|
||||
'onSeeked',
|
||||
'onSeeking',
|
||||
'onStalled',
|
||||
'onSuspend',
|
||||
'onTimeUpdate',
|
||||
'onVolumeChange',
|
||||
'onWaiting',
|
||||
'onLoad',
|
||||
'onError',
|
||||
'onAnimationStart',
|
||||
'onAnimationEnd',
|
||||
'onAnimationIteration',
|
||||
'onTransitionEnd',
|
||||
].every((handlerName) => includes(eventHandlers, handlerName)));
|
||||
});
|
||||
});
|
||||
|
||||
describe('eventHandlersByType', () => {
|
||||
it('should be keyed by type', () => {
|
||||
assert([
|
||||
'clipboard',
|
||||
'composition',
|
||||
'keyboard',
|
||||
'focus',
|
||||
'form',
|
||||
'mouse',
|
||||
'selection',
|
||||
'touch',
|
||||
'ui',
|
||||
'wheel',
|
||||
'media',
|
||||
'image',
|
||||
'animation',
|
||||
'transition',
|
||||
].every((type) => !!eventHandlersByType[type]));
|
||||
});
|
||||
});
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
/* eslint-env mocha */
|
||||
import assert from 'assert';
|
||||
import entries from 'object.entries';
|
||||
import fromEntries from 'object.fromentries';
|
||||
import { getOpeningElement, setParserName, fallbackToBabylon } from '../helper';
|
||||
import getProp from '../../src/getProp';
|
||||
|
||||
const literal = {
|
||||
source: '<div {...{ id: "foo" }} />',
|
||||
target: '<div id="foo" />',
|
||||
offset: { keyOffset: -6, valueOffset: -7 },
|
||||
};
|
||||
|
||||
const expression1 = {
|
||||
source: '<div {...{ id }} />',
|
||||
target: '<div id={id} />',
|
||||
offset: { keyOffset: -6, valueOffset: -2 },
|
||||
};
|
||||
|
||||
const expression2 = {
|
||||
source: '<div {...{ id: `foo${bar}baz` }} />', // eslint-disable-line no-template-curly-in-string
|
||||
target: '<div id={`foo${bar}baz`} />', // eslint-disable-line no-template-curly-in-string
|
||||
offset: { keyOffset: -6, valueOffset: -6 },
|
||||
};
|
||||
|
||||
describe('getProp', () => {
|
||||
it('should create the correct AST for literal with flow parser', () => {
|
||||
actualTest('flow', literal);
|
||||
});
|
||||
it('should create the correct AST for literal with babel parser', () => {
|
||||
actualTest('babel', literal);
|
||||
});
|
||||
it('should create the correct AST for expression with flow parser (1)', () => {
|
||||
actualTest('flow', expression1);
|
||||
});
|
||||
it('should create the correct AST for expression with babel parser (1)', () => {
|
||||
actualTest('babel', expression1);
|
||||
});
|
||||
it('should create the correct AST for expression with flow parser (2)', () => {
|
||||
actualTest('flow', expression2);
|
||||
});
|
||||
it('should create the correct AST for expression with babel parser (2)', () => {
|
||||
actualTest('babel', expression2);
|
||||
});
|
||||
});
|
||||
|
||||
function actualTest(parserName, test) {
|
||||
setParserName(parserName);
|
||||
const { source, target, offset } = test;
|
||||
const sourceProps = stripConstructors(getOpeningElement(source).attributes);
|
||||
const targetProps = stripConstructors(getOpeningElement(target).attributes);
|
||||
const prop = 'id';
|
||||
const sourceResult = getProp(sourceProps, prop);
|
||||
const targetResult = getProp(targetProps, prop);
|
||||
|
||||
if (fallbackToBabylon && parserName === 'babel' && test === literal) {
|
||||
// Babylon (node < 6) adds an `extra: null` prop to a literal if it is parsed from a
|
||||
// JSXAttribute, other literals don't get this.
|
||||
sourceResult.value.extra = null;
|
||||
}
|
||||
|
||||
assert.deepStrictEqual(
|
||||
adjustLocations(sourceResult, offset),
|
||||
adjustRange(targetResult),
|
||||
);
|
||||
}
|
||||
|
||||
function adjustRange({ name, value: { expression, ...value }, ...node }) {
|
||||
return {
|
||||
...adjustNodeRange(node),
|
||||
name: adjustNodeRange(name),
|
||||
value: {
|
||||
...adjustNodeRange(value),
|
||||
...(expression ? { expression: adjustNodeRangeRecursively(expression) } : {}),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function adjustNodeRange(node) {
|
||||
if (!node.loc) {
|
||||
return node;
|
||||
}
|
||||
|
||||
const [start, end] = node.range || [node.start, node.end];
|
||||
return {
|
||||
...node,
|
||||
end: undefined,
|
||||
range: [start, end],
|
||||
start: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
function adjustNodeRangeRecursively(node) {
|
||||
if (Array.isArray(node)) {
|
||||
return node.map(adjustNodeRangeRecursively);
|
||||
}
|
||||
|
||||
if (node && typeof node === 'object') {
|
||||
return adjustNodeRange(mapValues(node, adjustNodeRangeRecursively));
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function stripConstructors(value) {
|
||||
return JSON.parse(JSON.stringify(value));
|
||||
}
|
||||
|
||||
function adjustLocations(node, { keyOffset, valueOffset }) {
|
||||
const hasExpression = !!node.value.expression;
|
||||
return {
|
||||
...adjustNodeLocations(node, {
|
||||
startOffset: keyOffset,
|
||||
endOffset: valueOffset + (hasExpression ? 1 : 0),
|
||||
}),
|
||||
name: adjustNodeLocations(node.name, { startOffset: keyOffset, endOffset: keyOffset }),
|
||||
value: {
|
||||
...adjustNodeLocations(node.value, {
|
||||
startOffset: valueOffset - (hasExpression ? 1 : 0),
|
||||
endOffset: valueOffset + (hasExpression ? 1 : 0),
|
||||
}),
|
||||
...(hasExpression
|
||||
? {
|
||||
expression: adjustLocationsRecursively(
|
||||
node.value.expression,
|
||||
{ startOffset: valueOffset, endOffset: valueOffset },
|
||||
),
|
||||
}
|
||||
: {}
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function adjustNodeLocations(node, { startOffset, endOffset }) {
|
||||
if (!node.loc) {
|
||||
return node;
|
||||
}
|
||||
|
||||
const [start, end] = node.range || [];
|
||||
return {
|
||||
...node,
|
||||
end: undefined,
|
||||
loc: {
|
||||
...node.loc,
|
||||
start: {
|
||||
...node.loc.start,
|
||||
column: node.loc.start.column + startOffset,
|
||||
},
|
||||
end: {
|
||||
...node.loc.end,
|
||||
column: node.loc.end.column + endOffset,
|
||||
},
|
||||
},
|
||||
range: [start + startOffset, end + endOffset],
|
||||
start: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
function adjustLocationsRecursively(node, { startOffset, endOffset }) {
|
||||
if (Array.isArray(node)) {
|
||||
return node.map((x) => adjustLocationsRecursively(x, { startOffset, endOffset }));
|
||||
}
|
||||
if (node && typeof node === 'object') {
|
||||
return adjustNodeLocations(
|
||||
mapValues(node, (x) => adjustLocationsRecursively(x, { startOffset, endOffset })),
|
||||
{ startOffset, endOffset },
|
||||
);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function mapValues(o, f) {
|
||||
return fromEntries(entries(o).map(([k, v]) => [k, f(v)]));
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/* eslint-env mocha */
|
||||
import assert from 'assert';
|
||||
import { getOpeningElement, setParserName } from '../helper';
|
||||
import getProp from '../../src/getProp';
|
||||
|
||||
describe('getProp', () => {
|
||||
beforeEach(() => {
|
||||
setParserName('babel');
|
||||
});
|
||||
it('should export a function', () => {
|
||||
const expected = 'function';
|
||||
const actual = typeof getProp;
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return undefined if no arguments are provided', () => {
|
||||
const expected = undefined;
|
||||
const actual = getProp();
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return undefined if the attribute is absent', () => {
|
||||
const code = '<div />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
|
||||
const expected = undefined;
|
||||
const actual = getProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return the correct attribute if the attribute exists', () => {
|
||||
const code = '<div id="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
|
||||
const expected = 'id';
|
||||
const actual = getProp(props, prop).name.name;
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return the correct attribute if the attribute exists in spread', () => {
|
||||
const code = '<div {...{ id: "foo" }} />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'ID';
|
||||
|
||||
const expected = 'id';
|
||||
const actual = getProp(props, prop).name.name;
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return the correct attribute if the attribute exists in spread as an expression', () => {
|
||||
const code = '<div {...{ id }} />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
|
||||
const expected = 'id';
|
||||
const actual = getProp(props, prop);
|
||||
const actualName = actual.name.name;
|
||||
const actualValue = actual.value.expression.name;
|
||||
|
||||
assert.equal(actualName, expected);
|
||||
assert.equal(actualValue, expected);
|
||||
});
|
||||
|
||||
it('should return the correct attribute if the attribute exists in spread (case sensitive)', () => {
|
||||
const code = '<div {...{ id: "foo" }} />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
const options = { ignoreCase: false };
|
||||
|
||||
const expected = 'id';
|
||||
const actual = getProp(props, prop, options).name.name;
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return undefined if the attribute does not exist in spread (case sensitive)', () => {
|
||||
const code = '<div {...{ id: "foo" }} />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'ID';
|
||||
const options = { ignoreCase: false };
|
||||
|
||||
const expected = undefined;
|
||||
const actual = getProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return undefined for key in spread', () => {
|
||||
// https://github.com/reactjs/rfcs/pull/107
|
||||
const code = '<div {...{ key }} />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'key';
|
||||
|
||||
const expected = undefined;
|
||||
const actual = getProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return undefined if the attribute may exist in spread', () => {
|
||||
const code = '<div {...props} />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
|
||||
const expected = undefined;
|
||||
const actual = getProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should not crash if the spread contains a spread', () => {
|
||||
const code = '<div {...{ ...props }} />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
|
||||
getProp(props, prop);
|
||||
});
|
||||
|
||||
it('should return undefined if the attribute is considered absent in case-sensitive mode', () => {
|
||||
const code = '<div ID="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
const options = {
|
||||
ignoreCase: false,
|
||||
};
|
||||
|
||||
const expected = undefined;
|
||||
const actual = getProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
});
|
||||
+556
File diff suppressed because it is too large
Load Diff
+522
File diff suppressed because it is too large
Load Diff
+1277
File diff suppressed because it is too large
Load Diff
+963
File diff suppressed because it is too large
Load Diff
+412
@@ -0,0 +1,412 @@
|
||||
/* eslint-env mocha */
|
||||
import assert from 'assert';
|
||||
import { getOpeningElement, setParserName } from '../helper';
|
||||
import hasProp, { hasAnyProp, hasEveryProp } from '../../src/hasProp';
|
||||
|
||||
describe('hasProp', () => {
|
||||
beforeEach(() => {
|
||||
setParserName('babel');
|
||||
});
|
||||
it('should export a function', () => {
|
||||
const expected = 'function';
|
||||
const actual = typeof hasProp;
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if no arguments are provided', () => {
|
||||
const expected = false;
|
||||
const actual = hasProp();
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if the prop is absent', () => {
|
||||
const code = '<div />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
|
||||
const expected = false;
|
||||
const actual = hasProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if the prop exists', () => {
|
||||
const code = '<div id="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
|
||||
const expected = true;
|
||||
const actual = hasProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if the prop may exist in spread loose mode', () => {
|
||||
const code = '<div {...props} />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
const options = {
|
||||
spreadStrict: false,
|
||||
};
|
||||
|
||||
const expected = true;
|
||||
const actual = hasProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if the prop is considered absent in case-sensitive mode', () => {
|
||||
const code = '<div ID="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
const options = {
|
||||
ignoreCase: false,
|
||||
};
|
||||
|
||||
const expected = false;
|
||||
const actual = hasProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasAnyProp tests', () => {
|
||||
it('should export a function', () => {
|
||||
const expected = 'function';
|
||||
const actual = typeof hasAnyProp;
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if no arguments are provided', () => {
|
||||
const expected = false;
|
||||
const actual = hasAnyProp();
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if the prop is absent', () => {
|
||||
const code = '<div />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
|
||||
const expected = false;
|
||||
const actual = hasAnyProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if all props are absent in array', () => {
|
||||
const code = '<div />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const propsToCheck = ['id', 'className'];
|
||||
|
||||
const expected = false;
|
||||
const actual = hasAnyProp(props, propsToCheck);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if all props are absent in space delimited string', () => {
|
||||
const code = '<div />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const propsToCheck = 'id className';
|
||||
|
||||
const expected = false;
|
||||
const actual = hasAnyProp(props, propsToCheck);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if the prop exists', () => {
|
||||
const code = '<div id="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
|
||||
const expected = true;
|
||||
const actual = hasAnyProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if any prop exists in array', () => {
|
||||
const code = '<div id="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = ['className', 'id'];
|
||||
|
||||
const expected = true;
|
||||
const actual = hasAnyProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if any prop exists in space delimited string', () => {
|
||||
const code = '<div id="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'className id';
|
||||
|
||||
const expected = true;
|
||||
const actual = hasAnyProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if the prop may exist in spread loose mode', () => {
|
||||
const code = '<div {...props} />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
const options = {
|
||||
spreadStrict: false,
|
||||
};
|
||||
|
||||
const expected = true;
|
||||
const actual = hasAnyProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if any prop may exist in spread loose mode', () => {
|
||||
const code = '<div {...props} />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = ['id', 'className'];
|
||||
const options = {
|
||||
spreadStrict: false,
|
||||
};
|
||||
|
||||
const expected = true;
|
||||
const actual = hasAnyProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if the prop is considered absent in case-sensitive mode', () => {
|
||||
const code = '<div ID="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
const options = {
|
||||
ignoreCase: false,
|
||||
};
|
||||
|
||||
const expected = false;
|
||||
const actual = hasAnyProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if all props are considered absent in case-sensitive mode', () => {
|
||||
const code = '<div ID="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = ['id', 'iD', 'className'];
|
||||
const options = {
|
||||
ignoreCase: false,
|
||||
};
|
||||
|
||||
const expected = false;
|
||||
const actual = hasAnyProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasEveryProp tests', () => {
|
||||
it('should export a function', () => {
|
||||
const expected = 'function';
|
||||
const actual = typeof hasEveryProp;
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if no arguments are provided', () => {
|
||||
const expected = true;
|
||||
const actual = hasEveryProp();
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if the prop is absent', () => {
|
||||
const code = '<div />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
|
||||
const expected = false;
|
||||
const actual = hasEveryProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if any props are absent in array', () => {
|
||||
const code = '<div id="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const propsToCheck = ['id', 'className'];
|
||||
|
||||
const expected = false;
|
||||
const actual = hasEveryProp(props, propsToCheck);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if all props are absent in array', () => {
|
||||
const code = '<div />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const propsToCheck = ['id', 'className'];
|
||||
|
||||
const expected = false;
|
||||
const actual = hasEveryProp(props, propsToCheck);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if any props are absent in space delimited string', () => {
|
||||
const code = '<div id="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const propsToCheck = 'id className';
|
||||
|
||||
const expected = false;
|
||||
const actual = hasEveryProp(props, propsToCheck);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if all props are absent in space delimited string', () => {
|
||||
const code = '<div />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const propsToCheck = 'id className';
|
||||
|
||||
const expected = false;
|
||||
const actual = hasEveryProp(props, propsToCheck);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if the prop exists', () => {
|
||||
const code = '<div id="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
|
||||
const expected = true;
|
||||
const actual = hasEveryProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if all props exist in array', () => {
|
||||
const code = '<div id="foo" className="box" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = ['className', 'id'];
|
||||
|
||||
const expected = true;
|
||||
const actual = hasEveryProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if all props exist in space delimited string', () => {
|
||||
const code = '<div id="foo" className="box" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'className id';
|
||||
|
||||
const expected = true;
|
||||
const actual = hasEveryProp(props, prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if the props may exist in spread loose mode', () => {
|
||||
const code = '<div {...props} />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
const options = {
|
||||
spreadStrict: false,
|
||||
};
|
||||
|
||||
const expected = true;
|
||||
const actual = hasEveryProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if all props may exist in spread loose mode', () => {
|
||||
const code = '<div {...props} />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = ['id', 'className'];
|
||||
const options = {
|
||||
spreadStrict: false,
|
||||
};
|
||||
|
||||
const expected = true;
|
||||
const actual = hasEveryProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if the prop is considered absent in case-sensitive mode', () => {
|
||||
const code = '<div ID="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = 'id';
|
||||
const options = {
|
||||
ignoreCase: false,
|
||||
};
|
||||
|
||||
const expected = false;
|
||||
const actual = hasEveryProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return false if all props are considered absent in case-sensitive mode', () => {
|
||||
const code = '<div ID="foo" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = ['id', 'iD', 'className'];
|
||||
const options = {
|
||||
ignoreCase: false,
|
||||
};
|
||||
|
||||
const expected = false;
|
||||
const actual = hasEveryProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return true if all props are considered present in case-sensitive mode', () => {
|
||||
const code = '<div ID="foo" className="box" />';
|
||||
const node = getOpeningElement(code);
|
||||
const { attributes: props } = node;
|
||||
const prop = ['ID', 'className'];
|
||||
const options = {
|
||||
ignoreCase: false,
|
||||
};
|
||||
|
||||
const expected = true;
|
||||
const actual = hasEveryProp(props, prop, options);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
});
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/* eslint-env mocha */
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import assert from 'assert';
|
||||
import core from '../../src/index';
|
||||
|
||||
const src = fs.readdirSync(path.resolve(__dirname, '../../src'))
|
||||
.filter((f) => f.indexOf('.js') >= 0)
|
||||
.map((f) => path.basename(f, '.js'));
|
||||
|
||||
describe('main export', () => {
|
||||
it('should export an object', () => {
|
||||
const expected = 'object';
|
||||
const actual = typeof core;
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
src.filter((f) => f !== 'index').forEach((f) => {
|
||||
it(`should export ${f}`, () => {
|
||||
assert.equal(
|
||||
core[f],
|
||||
require(path.join('../../src/', f)).default // eslint-disable-line
|
||||
);
|
||||
});
|
||||
|
||||
it(`should export ${f} from root`, () => {
|
||||
const file = `${f}.js`;
|
||||
const expected = true;
|
||||
const actual = fs.statSync(path.join(path.resolve('.'), file)).isFile();
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/* eslint-env mocha */
|
||||
import assert from 'assert';
|
||||
import { extractProp, setParserName } from '../helper';
|
||||
import propName from '../../src/propName';
|
||||
|
||||
describe('propName', () => {
|
||||
beforeEach(() => {
|
||||
setParserName('babel');
|
||||
});
|
||||
it('should export a function', () => {
|
||||
const expected = 'function';
|
||||
const actual = typeof propName;
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should throw an error if the argument is missing', () => {
|
||||
assert.throws(() => { propName(); }, Error);
|
||||
});
|
||||
|
||||
it('should throw an error if the argument not a JSX node', () => {
|
||||
assert.throws(() => { propName({ a: 'foo' }); }, Error);
|
||||
});
|
||||
|
||||
it('should return correct name for normal prop', () => {
|
||||
const prop = extractProp('<div foo="bar" />');
|
||||
|
||||
const expected = 'foo';
|
||||
const actual = propName(prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
|
||||
it('should return correct name for namespaced prop', () => {
|
||||
const prop = extractProp('<div foo:bar="baz" />', 'foo:bar');
|
||||
|
||||
const expected = 'foo:bar';
|
||||
const actual = propName(prop);
|
||||
|
||||
assert.equal(actual, expected);
|
||||
});
|
||||
});
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib').elementType; // eslint-disable-line import/no-unresolved
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib').eventHandlers; // eslint-disable-line import/no-unresolved
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib').eventHandlersByType; // eslint-disable-line import/no-unresolved
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib').getLiteralPropValue; // eslint-disable-line import/no-unresolved
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib').getProp; // eslint-disable-line import/no-unresolved
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib').getPropValue; // eslint-disable-line import/no-unresolved
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib').hasAnyProp; // eslint-disable-line import/no-unresolved
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib').hasEveryProp; // eslint-disable-line import/no-unresolved
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib').hasProp; // eslint-disable-line import/no-unresolved
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = elementType;
|
||||
function resolveMemberExpressions() {
|
||||
var object = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||
var property = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||||
|
||||
if (object.type === 'JSXMemberExpression') {
|
||||
return resolveMemberExpressions(object.object, object.property) + '.' + property.name;
|
||||
}
|
||||
|
||||
return object.name + '.' + property.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tagName associated with a JSXElement.
|
||||
*/
|
||||
function elementType() {
|
||||
var node = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||
var name = node.name;
|
||||
|
||||
|
||||
if (node.type === 'JSXOpeningFragment') {
|
||||
return '<>';
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
throw new Error('The argument provided is not a JSXElement node.');
|
||||
}
|
||||
|
||||
if (name.type === 'JSXMemberExpression') {
|
||||
var _name$object = name.object,
|
||||
object = _name$object === undefined ? {} : _name$object,
|
||||
_name$property = name.property,
|
||||
property = _name$property === undefined ? {} : _name$property;
|
||||
|
||||
return resolveMemberExpressions(object, property);
|
||||
}
|
||||
|
||||
if (name.type === 'JSXNamespacedName') {
|
||||
return name.namespace.name + ':' + name.name.name;
|
||||
}
|
||||
|
||||
return node.name.name;
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.eventHandlersByType = undefined;
|
||||
|
||||
var _arrayPrototype = require('array.prototype.flat');
|
||||
|
||||
var _arrayPrototype2 = _interopRequireDefault(_arrayPrototype);
|
||||
|
||||
var _object = require('object.values');
|
||||
|
||||
var _object2 = _interopRequireDefault(_object);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/**
|
||||
* Common event handlers for JSX element event binding.
|
||||
*/
|
||||
|
||||
var eventHandlersByType = {
|
||||
clipboard: ['onCopy', 'onCut', 'onPaste'],
|
||||
composition: ['onCompositionEnd', 'onCompositionStart', 'onCompositionUpdate'],
|
||||
keyboard: ['onKeyDown', 'onKeyPress', 'onKeyUp'],
|
||||
focus: ['onFocus', 'onBlur'],
|
||||
form: ['onChange', 'onInput', 'onSubmit'],
|
||||
mouse: ['onClick', 'onContextMenu', 'onDblClick', 'onDoubleClick', 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragExit', 'onDragLeave', 'onDragOver', 'onDragStart', 'onDrop', 'onMouseDown', 'onMouseEnter', 'onMouseLeave', 'onMouseMove', 'onMouseOut', 'onMouseOver', 'onMouseUp'],
|
||||
selection: ['onSelect'],
|
||||
touch: ['onTouchCancel', 'onTouchEnd', 'onTouchMove', 'onTouchStart'],
|
||||
ui: ['onScroll'],
|
||||
wheel: ['onWheel'],
|
||||
media: ['onAbort', 'onCanPlay', 'onCanPlayThrough', 'onDurationChange', 'onEmptied', 'onEncrypted', 'onEnded', 'onError', 'onLoadedData', 'onLoadedMetadata', 'onLoadStart', 'onPause', 'onPlay', 'onPlaying', 'onProgress', 'onRateChange', 'onSeeked', 'onSeeking', 'onStalled', 'onSuspend', 'onTimeUpdate', 'onVolumeChange', 'onWaiting'],
|
||||
image: ['onLoad', 'onError'],
|
||||
animation: ['onAnimationStart', 'onAnimationEnd', 'onAnimationIteration'],
|
||||
transition: ['onTransitionEnd']
|
||||
};
|
||||
|
||||
exports.default = (0, _arrayPrototype2.default)((0, _object2.default)(eventHandlersByType));
|
||||
exports.eventHandlersByType = eventHandlersByType;
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
exports.default = getProp;
|
||||
|
||||
var _propName = require('./propName');
|
||||
|
||||
var _propName2 = _interopRequireDefault(_propName);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
|
||||
|
||||
var DEFAULT_OPTIONS = {
|
||||
ignoreCase: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the JSXAttribute itself or undefined, indicating the prop
|
||||
* is not present on the JSXOpeningElement.
|
||||
*
|
||||
*/
|
||||
function getProp() {
|
||||
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
||||
var prop = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
|
||||
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_OPTIONS;
|
||||
|
||||
function getName(name) {
|
||||
return options.ignoreCase ? name.toUpperCase() : name;
|
||||
}
|
||||
var propToFind = getName(prop);
|
||||
function isPropToFind(property) {
|
||||
return property.type === 'Property' && property.key.type === 'Identifier' && propToFind === getName(property.key.name);
|
||||
}
|
||||
|
||||
var foundAttribute = props.find(function (attribute) {
|
||||
// If the props contain a spread prop, try to find the property in the object expression.
|
||||
if (attribute.type === 'JSXSpreadAttribute') {
|
||||
return attribute.argument.type === 'ObjectExpression' && propToFind !== getName('key') // https://github.com/reactjs/rfcs/pull/107
|
||||
&& attribute.argument.properties.some(isPropToFind);
|
||||
}
|
||||
|
||||
return propToFind === getName((0, _propName2.default)(attribute));
|
||||
});
|
||||
|
||||
if (foundAttribute && foundAttribute.type === 'JSXSpreadAttribute') {
|
||||
return propertyToJSXAttribute(foundAttribute.argument.properties.find(isPropToFind));
|
||||
}
|
||||
|
||||
return foundAttribute;
|
||||
}
|
||||
|
||||
function propertyToJSXAttribute(node) {
|
||||
var key = node.key,
|
||||
value = node.value;
|
||||
|
||||
return _extends({
|
||||
type: 'JSXAttribute',
|
||||
name: _extends({ type: 'JSXIdentifier', name: key.name }, getBaseProps(key)),
|
||||
value: value.type === 'Literal' ? adjustRangeOfNode(value) : _extends({ type: 'JSXExpressionContainer', expression: adjustExpressionRange(value) }, getBaseProps(value))
|
||||
}, getBaseProps(node));
|
||||
}
|
||||
|
||||
function adjustRangeOfNode(node) {
|
||||
var _ref = node.range || [node.start, node.end],
|
||||
_ref2 = _slicedToArray(_ref, 2),
|
||||
start = _ref2[0],
|
||||
end = _ref2[1];
|
||||
|
||||
return _extends({}, node, {
|
||||
end: undefined,
|
||||
range: [start, end],
|
||||
start: undefined
|
||||
});
|
||||
}
|
||||
|
||||
function adjustExpressionRange(_ref3) {
|
||||
var expressions = _ref3.expressions,
|
||||
quasis = _ref3.quasis,
|
||||
expression = _objectWithoutProperties(_ref3, ['expressions', 'quasis']);
|
||||
|
||||
return _extends({}, adjustRangeOfNode(expression), expressions ? { expressions: expressions.map(adjustRangeOfNode) } : {}, quasis ? { quasis: quasis.map(adjustRangeOfNode) } : {});
|
||||
}
|
||||
|
||||
function getBaseProps(_ref4) {
|
||||
var loc = _ref4.loc,
|
||||
node = _objectWithoutProperties(_ref4, ['loc']);
|
||||
|
||||
var _adjustRangeOfNode = adjustRangeOfNode(node),
|
||||
range = _adjustRangeOfNode.range;
|
||||
|
||||
return {
|
||||
loc: getBaseLocation(loc),
|
||||
range: range
|
||||
};
|
||||
}
|
||||
|
||||
function getBaseLocation(_ref5) {
|
||||
var start = _ref5.start,
|
||||
end = _ref5.end,
|
||||
source = _ref5.source,
|
||||
filename = _ref5.filename;
|
||||
|
||||
return _extends({
|
||||
start: start,
|
||||
end: end
|
||||
}, source !== undefined ? { source: source } : {}, filename !== undefined ? { filename: filename } : {});
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = getPropValue;
|
||||
exports.getLiteralPropValue = getLiteralPropValue;
|
||||
|
||||
var _values = require('./values');
|
||||
|
||||
var _values2 = _interopRequireDefault(_values);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var extractValue = function extractValue(attribute, extractor) {
|
||||
if (attribute && attribute.type === 'JSXAttribute') {
|
||||
if (attribute.value === null) {
|
||||
// Null valued attributes imply truthiness.
|
||||
// For example: <div aria-hidden />
|
||||
// See: https://facebook.github.io/react/docs/jsx-in-depth.html#boolean-attributes
|
||||
return true;
|
||||
}
|
||||
|
||||
return extractor(attribute.value);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the value of a given attribute.
|
||||
* Different types of attributes have their associated
|
||||
* values in different properties on the object.
|
||||
*
|
||||
* This function should return the most *closely* associated
|
||||
* value with the intention of the JSX.
|
||||
*
|
||||
* @param attribute - The JSXAttribute collected by AST parser.
|
||||
*/
|
||||
function getPropValue(attribute) {
|
||||
return extractValue(attribute, _values2.default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a given attribute.
|
||||
* Different types of attributes have their associated
|
||||
* values in different properties on the object.
|
||||
*
|
||||
* This 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.)
|
||||
*
|
||||
* @param attribute - The JSXAttribute collected by AST parser.
|
||||
*/
|
||||
function getLiteralPropValue(attribute) {
|
||||
return extractValue(attribute, _values.getLiteralValue);
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = hasProp;
|
||||
exports.hasAnyProp = hasAnyProp;
|
||||
exports.hasEveryProp = hasEveryProp;
|
||||
|
||||
var _propName = require('./propName');
|
||||
|
||||
var _propName2 = _interopRequireDefault(_propName);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var DEFAULT_OPTIONS = {
|
||||
spreadStrict: true,
|
||||
ignoreCase: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns boolean indicating whether an prop exists on the props
|
||||
* property of a JSX element node.
|
||||
*/
|
||||
function hasProp() {
|
||||
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
||||
var prop = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
|
||||
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_OPTIONS;
|
||||
|
||||
var propToCheck = options.ignoreCase ? prop.toUpperCase() : prop;
|
||||
|
||||
return props.some(function (attribute) {
|
||||
// If the props contain a spread prop, then refer to strict param.
|
||||
if (attribute.type === 'JSXSpreadAttribute') {
|
||||
return !options.spreadStrict;
|
||||
}
|
||||
|
||||
var currentProp = options.ignoreCase ? (0, _propName2.default)(attribute).toUpperCase() : (0, _propName2.default)(attribute);
|
||||
|
||||
return propToCheck === currentProp;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the props on a node and a list of props to check, this returns a boolean
|
||||
* indicating if any of them exist on the node.
|
||||
*/
|
||||
function hasAnyProp() {
|
||||
var nodeProps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
||||
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
||||
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_OPTIONS;
|
||||
|
||||
var propsToCheck = typeof props === 'string' ? props.split(' ') : props;
|
||||
|
||||
return propsToCheck.some(function (prop) {
|
||||
return hasProp(nodeProps, prop, options);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the props on a node and a list of props to check, this returns a boolean
|
||||
* indicating if all of them exist on the node
|
||||
*/
|
||||
function hasEveryProp() {
|
||||
var nodeProps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
||||
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
||||
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_OPTIONS;
|
||||
|
||||
var propsToCheck = typeof props === 'string' ? props.split(' ') : props;
|
||||
|
||||
return propsToCheck.every(function (prop) {
|
||||
return hasProp(nodeProps, prop, options);
|
||||
});
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
var _hasProp = require('./hasProp');
|
||||
|
||||
var _hasProp2 = _interopRequireDefault(_hasProp);
|
||||
|
||||
var _elementType = require('./elementType');
|
||||
|
||||
var _elementType2 = _interopRequireDefault(_elementType);
|
||||
|
||||
var _eventHandlers = require('./eventHandlers');
|
||||
|
||||
var _eventHandlers2 = _interopRequireDefault(_eventHandlers);
|
||||
|
||||
var _getProp = require('./getProp');
|
||||
|
||||
var _getProp2 = _interopRequireDefault(_getProp);
|
||||
|
||||
var _getPropValue = require('./getPropValue');
|
||||
|
||||
var _getPropValue2 = _interopRequireDefault(_getPropValue);
|
||||
|
||||
var _propName = require('./propName');
|
||||
|
||||
var _propName2 = _interopRequireDefault(_propName);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
module.exports = {
|
||||
hasProp: _hasProp2.default,
|
||||
hasAnyProp: _hasProp.hasAnyProp,
|
||||
hasEveryProp: _hasProp.hasEveryProp,
|
||||
elementType: _elementType2.default,
|
||||
eventHandlers: _eventHandlers2.default,
|
||||
eventHandlersByType: _eventHandlers.eventHandlersByType,
|
||||
getProp: _getProp2.default,
|
||||
getPropValue: _getPropValue2.default,
|
||||
getLiteralPropValue: _getPropValue.getLiteralPropValue,
|
||||
propName: _propName2.default
|
||||
};
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = propName;
|
||||
/**
|
||||
* Returns the name of the prop given the JSXAttribute object.
|
||||
*/
|
||||
function propName() {
|
||||
var prop = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||
|
||||
if (!prop.type || prop.type !== 'JSXAttribute') {
|
||||
throw new Error('The prop must be a JSXAttribute collected by the AST parser.');
|
||||
}
|
||||
|
||||
if (prop.name.type === 'JSXNamespacedName') {
|
||||
return prop.name.namespace.name + ':' + prop.name.name.name;
|
||||
}
|
||||
|
||||
return prop.name.name;
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromJSXElement;
|
||||
/**
|
||||
* Extractor function for a JSXElement type value node.
|
||||
*
|
||||
* Returns self-closing element with correct name.
|
||||
*/
|
||||
function extractValueFromJSXElement(value) {
|
||||
// eslint-disable-next-line global-require
|
||||
var getValue = require('.').default;
|
||||
|
||||
var Tag = value.openingElement.name.name;
|
||||
if (value.openingElement.selfClosing) {
|
||||
return '<' + Tag + ' />';
|
||||
}
|
||||
return '<' + Tag + '>' + [].concat(value.children).map(function (x) {
|
||||
return getValue(x);
|
||||
}).join('') + '</' + Tag + '>';
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromJSXFragment;
|
||||
/**
|
||||
* Extractor function for a JSXFragment type value node.
|
||||
*
|
||||
* Returns self-closing element with correct name.
|
||||
*/
|
||||
function extractValueFromJSXFragment(value) {
|
||||
// eslint-disable-next-line global-require
|
||||
var getValue = require('.').default;
|
||||
|
||||
if (value.children.length === 0) {
|
||||
return '<></>';
|
||||
}
|
||||
return '<>' + [].concat(value.children).map(function (x) {
|
||||
return getValue(x);
|
||||
}).join('') + '</>';
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromJSXText;
|
||||
/**
|
||||
* Extractor function for a JSXText type value node.
|
||||
*
|
||||
* Returns self-closing element with correct name.
|
||||
*/
|
||||
function extractValueFromJSXText(value) {
|
||||
return value.raw;
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromLiteral;
|
||||
/**
|
||||
* Extractor function for a Literal type value node.
|
||||
*
|
||||
* @param - value - AST Value object with type `Literal`
|
||||
* @returns { String|Boolean } - The extracted value converted to correct type.
|
||||
*/
|
||||
function extractValueFromLiteral(value) {
|
||||
var extractedValue = value.value;
|
||||
|
||||
|
||||
var normalizedStringValue = typeof extractedValue === 'string' && extractedValue.toLowerCase();
|
||||
if (normalizedStringValue === 'true') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (normalizedStringValue === 'false') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return extractedValue;
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromArrayExpression;
|
||||
/**
|
||||
* Extractor function for an ArrayExpression type value node.
|
||||
* An array expression is an expression with [] syntax.
|
||||
*
|
||||
* @returns - An array of the extracted elements.
|
||||
*/
|
||||
function extractValueFromArrayExpression(value) {
|
||||
// eslint-disable-next-line global-require
|
||||
var getValue = require('.').default;
|
||||
return value.elements.map(function (element) {
|
||||
if (element === null) return undefined;
|
||||
return getValue(element);
|
||||
});
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromAssignmentExpression;
|
||||
/**
|
||||
* Extractor function for a AssignmentExpression type value node.
|
||||
* An assignment expression looks like `x = y` or `x += y` in expression position.
|
||||
* This will return the assignment as the value.
|
||||
*
|
||||
* @param - value - AST Value object with type `AssignmentExpression`
|
||||
* @returns - The extracted value converted to correct type.
|
||||
*/
|
||||
function extractValueFromAssignmentExpression(value) {
|
||||
// eslint-disable-next-line global-require
|
||||
var getValue = require('.').default;
|
||||
return getValue(value.left) + ' ' + value.operator + ' ' + getValue(value.right);
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromBinaryExpression;
|
||||
/**
|
||||
* Extractor function for a BinaryExpression type value node.
|
||||
* A binary expression has a left and right side separated by an operator
|
||||
* such as `a + b`.
|
||||
*
|
||||
* @param - value - AST Value object with type `BinaryExpression`
|
||||
* @returns - The extracted value converted to correct type.
|
||||
*/
|
||||
function extractValueFromBinaryExpression(value) {
|
||||
// eslint-disable-next-line global-require
|
||||
var getValue = require('.').default;
|
||||
var operator = value.operator,
|
||||
left = value.left,
|
||||
right = value.right;
|
||||
|
||||
var leftVal = getValue(left);
|
||||
var rightVal = getValue(right);
|
||||
|
||||
switch (operator) {
|
||||
case '==':
|
||||
return leftVal == rightVal; // eslint-disable-line
|
||||
case '!=':
|
||||
return leftVal != rightVal; // eslint-disable-line
|
||||
case '===':
|
||||
return leftVal === rightVal;
|
||||
case '!==':
|
||||
return leftVal !== rightVal;
|
||||
case '<':
|
||||
return leftVal < rightVal;
|
||||
case '<=':
|
||||
return leftVal <= rightVal;
|
||||
case '>':
|
||||
return leftVal > rightVal;
|
||||
case '>=':
|
||||
return leftVal >= rightVal;
|
||||
case '<<':
|
||||
return leftVal << rightVal; // eslint-disable-line no-bitwise
|
||||
case '>>':
|
||||
return leftVal >> rightVal; // eslint-disable-line no-bitwise
|
||||
case '>>>':
|
||||
return leftVal >>> rightVal; // eslint-disable-line no-bitwise
|
||||
case '+':
|
||||
return leftVal + rightVal;
|
||||
case '-':
|
||||
return leftVal - rightVal;
|
||||
case '*':
|
||||
return leftVal * rightVal;
|
||||
case '/':
|
||||
return leftVal / rightVal;
|
||||
case '%':
|
||||
return leftVal % rightVal;
|
||||
case '|':
|
||||
return leftVal | rightVal; // eslint-disable-line no-bitwise
|
||||
case '^':
|
||||
return leftVal ^ rightVal; // eslint-disable-line no-bitwise
|
||||
case '&':
|
||||
return leftVal & rightVal; // eslint-disable-line no-bitwise
|
||||
case 'in':
|
||||
try {
|
||||
return leftVal in rightVal;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
case 'instanceof':
|
||||
if (typeof rightVal !== 'function') {
|
||||
return false;
|
||||
}
|
||||
return leftVal instanceof rightVal;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromBindExpression;
|
||||
/**
|
||||
* Extractor function for a BindExpression type value node.
|
||||
* A bind expression looks like `::this.foo`
|
||||
* This will return `this.foo.bind(this)` as the value to indicate its existence,
|
||||
* since we can not execute the function this.foo.bind(this) in a static environment.
|
||||
*
|
||||
* @param - value - AST Value object with type `BindExpression`
|
||||
* @returns - The extracted value converted to correct type.
|
||||
*/
|
||||
function extractValueFromBindExpression(value) {
|
||||
// eslint-disable-next-line global-require
|
||||
var getValue = require('.').default;
|
||||
var callee = getValue(value.callee);
|
||||
|
||||
// If value.object === null, the callee must be a MemberExpression.
|
||||
// https://github.com/babel/babylon/blob/master/ast/spec.md#bindexpression
|
||||
var object = value.object === null ? getValue(value.callee.object) : getValue(value.object);
|
||||
|
||||
if (value.object && value.object.property) {
|
||||
return object + '.' + callee + '.bind(' + object + ')';
|
||||
}
|
||||
|
||||
return callee + '.bind(' + object + ')';
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromCallExpression;
|
||||
/**
|
||||
* Extractor function for a CallExpression type value node.
|
||||
* A call expression looks like `bar()`
|
||||
* This will return `bar` as the value to indicate its existence,
|
||||
* since we can not execute the function bar in a static environment.
|
||||
*
|
||||
* @param - value - AST Value object with type `CallExpression`
|
||||
* @returns - The extracted value converted to correct type.
|
||||
*/
|
||||
function extractValueFromCallExpression(value) {
|
||||
// eslint-disable-next-line global-require
|
||||
var getValue = require('.').default;
|
||||
var args = Array.isArray(value.arguments) ? value.arguments.map(function (x) {
|
||||
return getValue(x);
|
||||
}).join(', ') : '';
|
||||
return '' + getValue(value.callee) + (value.optional ? '?.' : '') + '(' + args + ')';
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromChainExpression;
|
||||
/**
|
||||
* Extractor function for a ChainExpression type value node.
|
||||
* A member expression is accessing a property on an object `obj.property`.
|
||||
*
|
||||
* @param - value - AST Value object with type `ChainExpression`
|
||||
* @returns - The extracted value converted to correct type
|
||||
* and maintaing `obj?.property` convention.
|
||||
*/
|
||||
function extractValueFromChainExpression(value) {
|
||||
// eslint-disable-next-line global-require
|
||||
var getValue = require('.').default;
|
||||
return getValue(value.expression || value);
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromConditionalExpression;
|
||||
/**
|
||||
* Extractor function for a ConditionalExpression type value node.
|
||||
*
|
||||
* @param - value - AST Value object with type `ConditionalExpression`
|
||||
* @returns - The extracted value converted to correct type.
|
||||
*/
|
||||
function extractValueFromConditionalExpression(value) {
|
||||
// eslint-disable-next-line global-require
|
||||
var getValue = require('.').default;
|
||||
var test = value.test,
|
||||
alternate = value.alternate,
|
||||
consequent = value.consequent;
|
||||
|
||||
|
||||
return getValue(test) ? getValue(consequent) : getValue(alternate);
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromFunctionExpression;
|
||||
/**
|
||||
* Extractor function for a FunctionExpression type value node.
|
||||
* Statically, we can't execute the given function, so just return a function
|
||||
* to indicate that the value is present.
|
||||
*
|
||||
* @param - value - AST Value object with type `FunctionExpression`
|
||||
* @returns - The extracted value converted to correct type.
|
||||
*/
|
||||
function extractValueFromFunctionExpression(value) {
|
||||
return function () {
|
||||
return value;
|
||||
};
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromIdentifier;
|
||||
var JS_RESERVED = {
|
||||
Array: Array,
|
||||
Date: Date,
|
||||
Infinity: Infinity,
|
||||
Math: Math,
|
||||
Number: Number,
|
||||
Object: Object,
|
||||
String: String,
|
||||
undefined: undefined
|
||||
};
|
||||
|
||||
/**
|
||||
* Extractor function for a Identifier type value node.
|
||||
* An Identifier is usually a reference to a variable.
|
||||
* Just return variable name to determine its existence.
|
||||
*
|
||||
* @param - value - AST Value object with type `Identifier`
|
||||
* @returns - The extracted value converted to correct type.
|
||||
*/
|
||||
function extractValueFromIdentifier(value) {
|
||||
var name = value.name;
|
||||
|
||||
|
||||
if (Object.hasOwnProperty.call(JS_RESERVED, name)) {
|
||||
return JS_RESERVED[name];
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromLogicalExpression;
|
||||
/**
|
||||
* Extractor function for a LogicalExpression type value node.
|
||||
* A logical expression is `a && b` or `a || b`, so we evaluate both sides
|
||||
* and return the extracted value of the expression.
|
||||
*
|
||||
* @param - value - AST Value object with type `LogicalExpression`
|
||||
* @returns - The extracted value converted to correct type.
|
||||
*/
|
||||
function extractValueFromLogicalExpression(value) {
|
||||
// eslint-disable-next-line global-require
|
||||
var getValue = require('.').default;
|
||||
var operator = value.operator,
|
||||
left = value.left,
|
||||
right = value.right;
|
||||
|
||||
var leftVal = getValue(left);
|
||||
var rightVal = getValue(right);
|
||||
|
||||
if (operator === '&&') {
|
||||
return leftVal && rightVal;
|
||||
}
|
||||
if (operator === '??') {
|
||||
// return leftVal ?? rightVal; // TODO: update to babel 7
|
||||
return leftVal === null || typeof leftVal === 'undefined' ? rightVal : leftVal;
|
||||
}
|
||||
return leftVal || rightVal;
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = extractValueFromMemberExpression;
|
||||
/**
|
||||
* Extractor function for a MemberExpression type value node.
|
||||
* A member expression is accessing a property on an object `obj.property`.
|
||||
*
|
||||
* @param - value - AST Value object with type `MemberExpression`
|
||||
* @returns - The extracted value converted to correct type
|
||||
* and maintaing `obj.property` convention.
|
||||
*/
|
||||
function extractValueFromMemberExpression(value) {
|
||||
// eslint-disable-next-line global-require
|
||||
var getValue = require('.').default;
|
||||
return '' + getValue(value.object) + (value.optional ? '?.' : '.') + getValue(value.property);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user