eslint-plugin-taro 3.3.20 → 4.1.3-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +154 -1
- package/constant/index.js +7 -1
- package/package.json +20 -17
- package/rules/class-naming.js +1 -45
- package/rules/custom-component-children.js +1 -40
- package/rules/duplicate-name-of-state-and-props.js +2 -2
- package/rules/function-naming.js +16 -14
- package/rules/if-statement-in-map-loop.js +4 -1
- package/rules/index.js +1 -0
- package/rules/manipulate-jsx-as-array.js +3 -39
- package/rules/max-ternary-depth.js +53 -0
- package/rules/no-anonymous-function-in-props.js +3 -1
- package/rules/no-jsx-in-class-method.js +6 -3
- package/rules/no-jsx-in-props.js +3 -1
- package/rules/no-spread-in-props.js +3 -1
- package/rules/no-stateless-component.js +4 -2
- package/rules/props-reserve-keyword.js +1 -41
- package/rules/render-props.js +5 -3
- package/rules/reserve-class-properties.js +15 -12
- package/rules/switch-jsx.js +3 -1
- package/utils/utils.js +1 -39
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2018
|
|
3
|
+
Copyright (c) 2018 O2Team
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -19,3 +19,156 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
========================================================================
|
|
24
|
+
|
|
25
|
+
MIT (react-devtools):
|
|
26
|
+
The following files embed [react-devtools](https://github.com/facebook/react) MIT:
|
|
27
|
+
`/packages/taro-plugin-react-devtools/src/backend/index.js`
|
|
28
|
+
See `/LICENSE` for details of the license.
|
|
29
|
+
|
|
30
|
+
==================
|
|
31
|
+
|
|
32
|
+
MIT (vue-devtools):
|
|
33
|
+
The following files embed [vue-devtools](https://github.com/vuejs/devtools) MIT:
|
|
34
|
+
`/packages/taro-plugin-vue-devtools/src/backend/*`
|
|
35
|
+
See `/LICENSE` for details of the license.
|
|
36
|
+
|
|
37
|
+
==================
|
|
38
|
+
|
|
39
|
+
MIT (vite):
|
|
40
|
+
The following files embed [vite](https://github.com/vitejs/vite) MIT:
|
|
41
|
+
`/packages/taro-webpack5-prebundle/src/prebundle/scanImport.ts`,
|
|
42
|
+
`/packages/taro-webpack5-prebundle/src/prebundle/bundle.ts`,
|
|
43
|
+
`/packages/taro-webpack5-prebundle/src/h5.ts`,
|
|
44
|
+
`/packages/taro-webpack5-prebundle/src/min.ts`
|
|
45
|
+
See `/LICENSE` for details of the license.
|
|
46
|
+
|
|
47
|
+
==================
|
|
48
|
+
|
|
49
|
+
MIT (webpack):
|
|
50
|
+
The following files embed [webpack](https://github.com/webpack/webpack) MIT:
|
|
51
|
+
`/packages/taro-webpack5-prebundle/src/webpack/TaroContainerEntryModule.ts`,
|
|
52
|
+
`/packages/taro-webpack5-prebundle/src/webpack/TaroContainerPlugin.ts`,
|
|
53
|
+
`/packages/taro-webpack5-prebundle/src/webpack/TaroContainerReferencePlugin.ts`,
|
|
54
|
+
`/packages/taro-webpack5-prebundle/src/webpack/TaroModuleFederationPlugin.ts`
|
|
55
|
+
See `/LICENSE` for details of the license.
|
|
56
|
+
|
|
57
|
+
==================
|
|
58
|
+
|
|
59
|
+
MIT (sizzle):
|
|
60
|
+
The following files embed [sizzle](https://github.com/jquery/sizzle) MIT:
|
|
61
|
+
`/packages/taro-extends/src/jquery/sizzle.js`
|
|
62
|
+
See `/LICENSE.txt` for details of the license.
|
|
63
|
+
|
|
64
|
+
==================
|
|
65
|
+
|
|
66
|
+
MIT (zepto):
|
|
67
|
+
The following files embed [zepto](https://github.com/madrobby/zepto) MIT:
|
|
68
|
+
`/packages/taro-extends/src/jquery/zepto.js`,
|
|
69
|
+
`/packages/taro-extends/src/jquery/event.js`
|
|
70
|
+
See `/MIT-LICENSE` for details of the license.
|
|
71
|
+
|
|
72
|
+
==================
|
|
73
|
+
|
|
74
|
+
MIT (css-to-react-native):
|
|
75
|
+
The following files embed [css-to-react-native](https://github.com/styled-components/css-to-react-native) MIT:
|
|
76
|
+
`/packages/css-to-react-native/src/css-to-react-native/*`
|
|
77
|
+
See `/LICENSE.md` for details of the license.
|
|
78
|
+
|
|
79
|
+
==================
|
|
80
|
+
|
|
81
|
+
MIT (reactify-wc):
|
|
82
|
+
The following files embed [reactify-wc](https://github.com/BBKolton/reactify-wc) MIT:
|
|
83
|
+
`/packages/taro-components-library-react/src/component-lib/reactify-wc.ts`
|
|
84
|
+
See `/LICENSE` for details of the license.
|
|
85
|
+
|
|
86
|
+
==================
|
|
87
|
+
|
|
88
|
+
MIT (ant-design-mobile-rn):
|
|
89
|
+
The following files embed [ant-design-mobile-rn](https://github.com/ant-design/ant-design-mobile-rn) MIT:
|
|
90
|
+
`/packages/taro-components-rn/src/components/Swiper/carousel.tsx`
|
|
91
|
+
See `/LICENSE` for details of the license.
|
|
92
|
+
|
|
93
|
+
==================
|
|
94
|
+
|
|
95
|
+
MIT (react-wx-images-viewer):
|
|
96
|
+
The following files embed [react-wx-images-viewer](https://github.com/react-ld/react-wx-images-viewer) MIT:
|
|
97
|
+
`/packages/taro-h5/src/api/media/image/previewImage.ts`
|
|
98
|
+
See `/LICENSE` for details of the license.
|
|
99
|
+
|
|
100
|
+
==================
|
|
101
|
+
|
|
102
|
+
MIT (webpack-contrib/css-loader):
|
|
103
|
+
The following files embed [webpack-contrib/css-loader](https://github.com/webpack-contrib/css-loader) MIT:
|
|
104
|
+
`/packages/taro-rn-style-transformer/src/utils/index.ts`
|
|
105
|
+
See `/LICENSE` for details of the license.
|
|
106
|
+
|
|
107
|
+
==================
|
|
108
|
+
|
|
109
|
+
MIT (react-native):
|
|
110
|
+
The following files embed [react-native](https://github.com/facebook/react-native) MIT:
|
|
111
|
+
`/packages/taro-rn-style-transformer/src/transforms/StyleSheet/*`
|
|
112
|
+
See `/LICENSE` for details of the license.
|
|
113
|
+
|
|
114
|
+
==================
|
|
115
|
+
|
|
116
|
+
MIT (myrne/performance-now):
|
|
117
|
+
The following files embed [myrne/performance-now](https://github.com/myrne/performance-now) MIT:
|
|
118
|
+
`/packages/taro-runtime/src/bom/raf.ts`
|
|
119
|
+
See `/LICENSE` for details of the license.
|
|
120
|
+
|
|
121
|
+
==================
|
|
122
|
+
|
|
123
|
+
Apache (chameleon-api):
|
|
124
|
+
The following files embed [chameleon-api](https://github.com/chameleon-team/chameleon-api) Apache:
|
|
125
|
+
`/packages/taro-h5/src/api/device/clipboard.ts`
|
|
126
|
+
|
|
127
|
+
==================
|
|
128
|
+
|
|
129
|
+
MIT (uni-app):
|
|
130
|
+
The following files embed [uni-app](https://github.com/dcloudio/uni-app) MIT:
|
|
131
|
+
`/packages/taro-components-rn/src/components/Video/index.tsx`
|
|
132
|
+
See `/LICENSE` for details of the license.
|
|
133
|
+
|
|
134
|
+
==================
|
|
135
|
+
|
|
136
|
+
MIT (miniprogram-render):
|
|
137
|
+
The following files embed [miniprogram-render](https://github.com/Tencent/kbone) MIT:
|
|
138
|
+
`/packages/taro-plugin-http/src/runtime/Cookie.ts`
|
|
139
|
+
See `/LICENSE` for details of the license.
|
|
140
|
+
|
|
141
|
+
==================
|
|
142
|
+
|
|
143
|
+
MIT (stencil-ds-output-targets):
|
|
144
|
+
The following files embed [stencil-ds-output-targets](https://github.com/ionic-team/stencil-ds-output-targets/) MIT:
|
|
145
|
+
`/packages/taro-components-library-react/src/react-component-lib/utils/attachProps.ts`
|
|
146
|
+
`/packages/taro-components-library-react/src/react-component-lib/utils/case.ts`
|
|
147
|
+
`/packages/taro-components-library-react/src/react-component-lib/utils/dev.ts`
|
|
148
|
+
`/packages/taro-components-library-react/src/react-component-lib/utils/index.tsx`
|
|
149
|
+
`/packages/taro-components-library-react/src/react-component-lib/createComponent.tsx`
|
|
150
|
+
`/packages/taro-components-library-react/src/react-component-lib/createOverlayComponent.tsx`
|
|
151
|
+
`/packages/taro-components-library-react/src/react-component-lib/interfaces.ts`
|
|
152
|
+
`/packages/taro-components-library-vue3/src/vue-component-lib/utils.ts`
|
|
153
|
+
See `/LICENSE` for details of the license.
|
|
154
|
+
|
|
155
|
+
==================
|
|
156
|
+
|
|
157
|
+
MIT (weui):
|
|
158
|
+
The following files embed [weui](https://github.com/Tencent/weui) MIT:
|
|
159
|
+
`/packages/taro-components/src/components/*.scss`
|
|
160
|
+
See `/LICENSE.txt` for details of the license.
|
|
161
|
+
|
|
162
|
+
==================
|
|
163
|
+
|
|
164
|
+
Apache-2.0 (intersection-observer):
|
|
165
|
+
The following files embed [intersection-observer](https://github.com/GoogleChromeLabs/intersection-observer) Apache-2.0:
|
|
166
|
+
`/packages/taro-api/src/polyfill/intersection-observer.ts`
|
|
167
|
+
See `/LICENSE.txt` for details of the license.
|
|
168
|
+
|
|
169
|
+
==================
|
|
170
|
+
|
|
171
|
+
MIT (babel-plugin-jsx-dom-expressions):
|
|
172
|
+
The following files embed [babel-plugin-jsx-dom-expressions](https://github.com/ryansolid/dom-expressions/blob/main/packages/babel-plugin-jsx-dom-expressions) MIT:
|
|
173
|
+
`/packages/babel-plugin-transform-solid-jsx/src/*`
|
|
174
|
+
See `/LICENSE` for details of the license.
|
package/constant/index.js
CHANGED
|
@@ -16,6 +16,7 @@ const DEFAULT_Components_SET = new Set([
|
|
|
16
16
|
'Label',
|
|
17
17
|
'Picker',
|
|
18
18
|
'PickerView',
|
|
19
|
+
'PickerViewColumn',
|
|
19
20
|
'Radio',
|
|
20
21
|
'RadioGroup',
|
|
21
22
|
'CheckboxGroup',
|
|
@@ -36,7 +37,12 @@ const DEFAULT_Components_SET = new Set([
|
|
|
36
37
|
'SwiperItem',
|
|
37
38
|
'Provider',
|
|
38
39
|
'MovableArea',
|
|
39
|
-
'MovableView'
|
|
40
|
+
'MovableView',
|
|
41
|
+
'FunctionalPageNavigator',
|
|
42
|
+
'Ad',
|
|
43
|
+
'Block',
|
|
44
|
+
'Import',
|
|
45
|
+
'OfficialAccount',
|
|
40
46
|
])
|
|
41
47
|
|
|
42
48
|
module.exports = {
|
package/package.json
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-taro",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.1.3-beta.0",
|
|
4
4
|
"description": "Taro specific linting plugin for ESLint",
|
|
5
|
+
"author": "O2Team",
|
|
6
|
+
"license": "MIT",
|
|
5
7
|
"main": "index.js",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"taro",
|
|
10
|
+
"react",
|
|
11
|
+
"jsx"
|
|
12
|
+
],
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": "^20 || ^22"
|
|
15
|
+
},
|
|
6
16
|
"files": [
|
|
7
17
|
"rules",
|
|
8
18
|
"utils",
|
|
@@ -10,26 +20,19 @@
|
|
|
10
20
|
"index.js",
|
|
11
21
|
"README.md"
|
|
12
22
|
],
|
|
13
|
-
"scripts": {
|
|
14
|
-
"//test": "mocha -R progress __tests__/*.js"
|
|
15
|
-
},
|
|
16
23
|
"repository": {
|
|
17
24
|
"type": "git",
|
|
18
25
|
"url": "git+https://github.com/NervJS/taro.git"
|
|
19
26
|
},
|
|
20
|
-
"keywords": [
|
|
21
|
-
"taro",
|
|
22
|
-
"react",
|
|
23
|
-
"jsx"
|
|
24
|
-
],
|
|
25
|
-
"peerDependencies": {
|
|
26
|
-
"babel-eslint": "*",
|
|
27
|
-
"eslint": "*"
|
|
28
|
-
},
|
|
29
|
-
"author": "O2Team",
|
|
30
|
-
"license": "MIT",
|
|
31
27
|
"dependencies": {
|
|
32
28
|
"has": "^1.0.1"
|
|
33
29
|
},
|
|
34
|
-
"
|
|
35
|
-
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@babel/eslint-parser": "^7.24.1",
|
|
32
|
+
"eslint": "^8"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"test": "jest",
|
|
36
|
+
"test:ci": "jest --ci -i --coverage --silent"
|
|
37
|
+
}
|
|
38
|
+
}
|
package/rules/class-naming.js
CHANGED
|
@@ -1,49 +1,5 @@
|
|
|
1
|
+
const { DEFAULT_Components_SET } = require('../constant')
|
|
1
2
|
const { buildDocsMeta, isTaroComponent } = require('../utils/utils')
|
|
2
|
-
// eslint-disable-next-line
|
|
3
|
-
const DEFAULT_Components_SET = new Set([
|
|
4
|
-
'View',
|
|
5
|
-
'ScrollView',
|
|
6
|
-
'Swiper',
|
|
7
|
-
'CoverView',
|
|
8
|
-
'CoverImage',
|
|
9
|
-
'Icon',
|
|
10
|
-
'Text',
|
|
11
|
-
'RichText',
|
|
12
|
-
'Progress',
|
|
13
|
-
'Button',
|
|
14
|
-
'Checkbox',
|
|
15
|
-
'Form',
|
|
16
|
-
'Input',
|
|
17
|
-
'Label',
|
|
18
|
-
'Picker',
|
|
19
|
-
'PickerView',
|
|
20
|
-
'PickerViewColumn',
|
|
21
|
-
'Radio',
|
|
22
|
-
'RadioGroup',
|
|
23
|
-
'CheckboxGroup',
|
|
24
|
-
'Slider',
|
|
25
|
-
'Switch',
|
|
26
|
-
'Textarea',
|
|
27
|
-
'Navigator',
|
|
28
|
-
'Audio',
|
|
29
|
-
'Image',
|
|
30
|
-
'Video',
|
|
31
|
-
'Camera',
|
|
32
|
-
'LivePlayer',
|
|
33
|
-
'LivePusher',
|
|
34
|
-
'Map',
|
|
35
|
-
'Canvas',
|
|
36
|
-
'OpenData',
|
|
37
|
-
'WebView',
|
|
38
|
-
'SwiperItem',
|
|
39
|
-
'MovableArea',
|
|
40
|
-
'MovableView',
|
|
41
|
-
'FunctionalPageNavigator',
|
|
42
|
-
'Ad',
|
|
43
|
-
'Block',
|
|
44
|
-
'Import',
|
|
45
|
-
'OfficialAccount'
|
|
46
|
-
])
|
|
47
3
|
|
|
48
4
|
const ERROR_MESSAGE = '组件名不得与小程序内置组件名重复'
|
|
49
5
|
|
|
@@ -1,44 +1,5 @@
|
|
|
1
|
+
const { DEFAULT_Components_SET } = require('../constant')
|
|
1
2
|
const { buildDocsMeta } = require('../utils/utils')
|
|
2
|
-
// eslint-disable-next-line
|
|
3
|
-
const DEFAULT_Components_SET = new Set([
|
|
4
|
-
'View',
|
|
5
|
-
'ScrollView',
|
|
6
|
-
'Swiper',
|
|
7
|
-
'CoverImage',
|
|
8
|
-
'CoverView',
|
|
9
|
-
'Icon',
|
|
10
|
-
'Text',
|
|
11
|
-
'RichText',
|
|
12
|
-
'Progress',
|
|
13
|
-
'Button',
|
|
14
|
-
'Checkbox',
|
|
15
|
-
'Form',
|
|
16
|
-
'Input',
|
|
17
|
-
'Label',
|
|
18
|
-
'Picker',
|
|
19
|
-
'PickerView',
|
|
20
|
-
'Radio',
|
|
21
|
-
'RadioGroup',
|
|
22
|
-
'CheckboxGroup',
|
|
23
|
-
'Slider',
|
|
24
|
-
'Switch',
|
|
25
|
-
'Textarea',
|
|
26
|
-
'Navigator',
|
|
27
|
-
'Audio',
|
|
28
|
-
'Image',
|
|
29
|
-
'Video',
|
|
30
|
-
'Camera',
|
|
31
|
-
'LivePlayer',
|
|
32
|
-
'LivePusher',
|
|
33
|
-
'Map',
|
|
34
|
-
'Canvas',
|
|
35
|
-
'OpenData',
|
|
36
|
-
'WebView',
|
|
37
|
-
'SwiperItem',
|
|
38
|
-
'Provider',
|
|
39
|
-
'MovableArea',
|
|
40
|
-
'MovableView'
|
|
41
|
-
])
|
|
42
3
|
|
|
43
4
|
const ERROR_MESSAGE = '不能在自定义组件中写 children'
|
|
44
5
|
|
|
@@ -19,7 +19,7 @@ module.exports = {
|
|
|
19
19
|
|
|
20
20
|
return {
|
|
21
21
|
ObjectExpression (node) {
|
|
22
|
-
if (node.parent.type !== 'ClassProperty') {
|
|
22
|
+
if (node.parent.type !== 'ClassProperty' && node.parent.type !== 'PropertyDefinition') {
|
|
23
23
|
return
|
|
24
24
|
}
|
|
25
25
|
if (!node.parent.key) {
|
|
@@ -83,7 +83,7 @@ module.exports = {
|
|
|
83
83
|
stateNameFields.forEach(node => {
|
|
84
84
|
const key = node.key
|
|
85
85
|
if (propsNameFields.has(key.name)) {
|
|
86
|
-
context.report(node, `this.state.${key.name} 与 this.props.${key.name}
|
|
86
|
+
context.report(node, `this.state.${key.name} 与 this.props.${key.name} 重复可能会导致渲染结果不如意料之中。`)
|
|
87
87
|
}
|
|
88
88
|
})
|
|
89
89
|
}
|
package/rules/function-naming.js
CHANGED
|
@@ -43,6 +43,20 @@ module.exports = {
|
|
|
43
43
|
})
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
+
function checkClassProperty(node) {
|
|
47
|
+
if (!isTaroComponent(context, node)) {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
const key = node.key
|
|
51
|
+
const value = node.value
|
|
52
|
+
if (
|
|
53
|
+
key.type === 'Identifier' &&
|
|
54
|
+
value &&
|
|
55
|
+
(value.type === 'ArrowFunctionExpression' || value.type === 'FunctionExpression')
|
|
56
|
+
) {
|
|
57
|
+
examine(key)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
46
60
|
|
|
47
61
|
return {
|
|
48
62
|
MethodDefinition (node) {
|
|
@@ -54,20 +68,8 @@ module.exports = {
|
|
|
54
68
|
examine(key)
|
|
55
69
|
}
|
|
56
70
|
},
|
|
57
|
-
ClassProperty
|
|
58
|
-
|
|
59
|
-
return
|
|
60
|
-
}
|
|
61
|
-
const key = node.key
|
|
62
|
-
const value = node.value
|
|
63
|
-
if (
|
|
64
|
-
key.type === 'Identifier' &&
|
|
65
|
-
value &&
|
|
66
|
-
(value.type === 'ArrowFunctionExpression' || value.type === 'FunctionExpression')
|
|
67
|
-
) {
|
|
68
|
-
examine(key)
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
+
ClassProperty: checkClassProperty,
|
|
72
|
+
PropertyDefinition: checkClassProperty,
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
}
|
|
@@ -16,6 +16,8 @@ module.exports = {
|
|
|
16
16
|
},
|
|
17
17
|
|
|
18
18
|
create (context) {
|
|
19
|
+
const sourceCode = context.getSourceCode()
|
|
20
|
+
|
|
19
21
|
function isArrayMapCall (s) {
|
|
20
22
|
return s && s.type === 'CallExpression' &&
|
|
21
23
|
s.callee.type === 'MemberExpression' &&
|
|
@@ -24,9 +26,10 @@ module.exports = {
|
|
|
24
26
|
s.arguments[0].body &&
|
|
25
27
|
s.arguments[0].body.type === 'BlockStatement'
|
|
26
28
|
}
|
|
29
|
+
|
|
27
30
|
return {
|
|
28
31
|
JSXElement (node) {
|
|
29
|
-
const parents =
|
|
32
|
+
const parents = sourceCode.getAncestors(node)
|
|
30
33
|
const callExpr = parents.find(isArrayMapCall)
|
|
31
34
|
if (!callExpr) {
|
|
32
35
|
return
|
package/rules/index.js
CHANGED
|
@@ -3,6 +3,7 @@ const has = require('has')
|
|
|
3
3
|
const allRules = {
|
|
4
4
|
// 'if-statement-in-map-loop': require('./if-statement-in-map-loop'),
|
|
5
5
|
'manipulate-jsx-as-array': require('./manipulate-jsx-as-array'),
|
|
6
|
+
'max-ternary-depth': require('./max-ternary-depth'),
|
|
6
7
|
// 'no-jsx-in-class-method': require('./no-jsx-in-class-method'),
|
|
7
8
|
'no-spread-in-props': require('./no-spread-in-props'),
|
|
8
9
|
// 'no-stateless-component': require('./no-stateless-component'),
|
|
@@ -1,44 +1,6 @@
|
|
|
1
1
|
const { buildDocsMeta } = require('../utils/utils')
|
|
2
2
|
|
|
3
3
|
const ERROR_MESSAGE = '不能使用 Array#map 之外的方法操作 JSX 数组'
|
|
4
|
-
|
|
5
|
-
// eslint-disable-next-line
|
|
6
|
-
const DEFAULT_Components_SET = new Set([
|
|
7
|
-
'View',
|
|
8
|
-
'ScrollView',
|
|
9
|
-
'Swiper',
|
|
10
|
-
'MovableView',
|
|
11
|
-
'CoverView',
|
|
12
|
-
'Icon',
|
|
13
|
-
'Text',
|
|
14
|
-
'RichText',
|
|
15
|
-
'Progress',
|
|
16
|
-
'Button',
|
|
17
|
-
'Checkbox',
|
|
18
|
-
'Form',
|
|
19
|
-
'Input',
|
|
20
|
-
'Label',
|
|
21
|
-
'Picker',
|
|
22
|
-
'PickerView',
|
|
23
|
-
'Radio',
|
|
24
|
-
'RadioGroup',
|
|
25
|
-
'CheckboxGroup',
|
|
26
|
-
'Slider',
|
|
27
|
-
'Switch',
|
|
28
|
-
'Textarea',
|
|
29
|
-
'Navigator',
|
|
30
|
-
'Audio',
|
|
31
|
-
'Image',
|
|
32
|
-
'Video',
|
|
33
|
-
'Camera',
|
|
34
|
-
'LivePlayer',
|
|
35
|
-
'LivePusher',
|
|
36
|
-
'Map',
|
|
37
|
-
'Canvas',
|
|
38
|
-
'OpenData',
|
|
39
|
-
'WebView',
|
|
40
|
-
'SwiperItem'
|
|
41
|
-
])
|
|
42
4
|
// 可以传值的数组方法
|
|
43
5
|
const ARRAY_METHODS_EXCEPT_MAP = new Set([
|
|
44
6
|
'concat',
|
|
@@ -65,9 +27,11 @@ module.exports = {
|
|
|
65
27
|
},
|
|
66
28
|
|
|
67
29
|
create (context) {
|
|
30
|
+
const sourceCode = context.getSourceCode()
|
|
31
|
+
|
|
68
32
|
return {
|
|
69
33
|
JSXElement (node) {
|
|
70
|
-
const parents =
|
|
34
|
+
const parents = sourceCode.getAncestors(node)
|
|
71
35
|
const callExpression = parents.find(p => p.type === 'CallExpression' && p.callee.type === 'MemberExpression')
|
|
72
36
|
if (callExpression && ARRAY_METHODS_EXCEPT_MAP.has(callExpression.callee.property.name)) {
|
|
73
37
|
context.report({
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
meta: {
|
|
3
|
+
type: 'problem',
|
|
4
|
+
docs: {
|
|
5
|
+
description: 'Limit the depth of nested ternary expressions',
|
|
6
|
+
category: 'Best Practices',
|
|
7
|
+
recommended: true
|
|
8
|
+
},
|
|
9
|
+
fixable: null,
|
|
10
|
+
schema: [
|
|
11
|
+
{
|
|
12
|
+
type: 'integer',
|
|
13
|
+
minimum: 1,
|
|
14
|
+
maximum: 10
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
messages: {
|
|
18
|
+
tooDeep: 'Ternary expression is nested {{depth}} levels deep (max: {{maxDepth}}). Consider refactoring to if-else statements.'
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
create(context) {
|
|
23
|
+
const maxDepth = context.options[0] || 2
|
|
24
|
+
|
|
25
|
+
function getTernaryDepth(node) {
|
|
26
|
+
if (node.type !== 'ConditionalExpression') {
|
|
27
|
+
return 0
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const consequentDepth = getTernaryDepth(node.consequent)
|
|
31
|
+
const alternateDepth = getTernaryDepth(node.alternate)
|
|
32
|
+
|
|
33
|
+
return 1 + Math.max(consequentDepth, alternateDepth)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
ConditionalExpression(node) {
|
|
38
|
+
const depth = getTernaryDepth(node)
|
|
39
|
+
|
|
40
|
+
if (depth > maxDepth) {
|
|
41
|
+
context.report({
|
|
42
|
+
node,
|
|
43
|
+
messageId: 'tooDeep',
|
|
44
|
+
data: {
|
|
45
|
+
depth,
|
|
46
|
+
maxDepth
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -7,6 +7,7 @@ function isArrayMapCall (s) {
|
|
|
7
7
|
s.callee.type === 'MemberExpression' &&
|
|
8
8
|
s.callee.property.name === 'map' &&
|
|
9
9
|
Array.isArray(s.arguments) &&
|
|
10
|
+
s.arguments.length > 0 &&
|
|
10
11
|
s.arguments[0].body &&
|
|
11
12
|
s.arguments[0].body.type === 'BlockStatement'
|
|
12
13
|
}
|
|
@@ -17,8 +18,9 @@ module.exports = {
|
|
|
17
18
|
},
|
|
18
19
|
|
|
19
20
|
create (context) {
|
|
21
|
+
const sourceCode = context.getSourceCode()
|
|
20
22
|
const parentIsJSXAttribute = (node) => {
|
|
21
|
-
const parents =
|
|
23
|
+
const parents = sourceCode.getAncestors(node)
|
|
22
24
|
const jsxAttr = parents.find(p => p.type === 'JSXAttribute')
|
|
23
25
|
if (jsxAttr && jsxAttr.name.name !== 'ref' && !isArrayMapCall(node.parent)) {
|
|
24
26
|
context.report({
|
|
@@ -8,16 +8,19 @@ module.exports = {
|
|
|
8
8
|
},
|
|
9
9
|
|
|
10
10
|
create (context) {
|
|
11
|
+
const sourceCode = context.getSourceCode()
|
|
12
|
+
|
|
11
13
|
return {
|
|
12
14
|
JSXElement (node) {
|
|
13
|
-
const parents =
|
|
15
|
+
const parents = sourceCode.getAncestors(node)
|
|
14
16
|
const classMethod = parents.find(p => (
|
|
15
17
|
p.type === 'ClassMethod' ||
|
|
16
18
|
p.type === 'ClassProperty' ||
|
|
19
|
+
p.type === 'PropertyDefinition' ||
|
|
17
20
|
p.type === 'MethodDefinition' ||
|
|
18
|
-
p._babelType === 'ClassMethod')
|
|
21
|
+
p._babelType === 'ClassMethod') && p.key.name !== 'render'
|
|
19
22
|
)
|
|
20
|
-
if (classMethod
|
|
23
|
+
if (classMethod) {
|
|
21
24
|
context.report({
|
|
22
25
|
message: ERROR_MESSAGE,
|
|
23
26
|
node: classMethod
|
package/rules/no-jsx-in-props.js
CHANGED
|
@@ -8,9 +8,11 @@ module.exports = {
|
|
|
8
8
|
},
|
|
9
9
|
|
|
10
10
|
create (context) {
|
|
11
|
+
const sourceCode = context.getSourceCode()
|
|
12
|
+
|
|
11
13
|
return {
|
|
12
14
|
JSXElement (node) {
|
|
13
|
-
const parents =
|
|
15
|
+
const parents = sourceCode.getAncestors(node)
|
|
14
16
|
const jsxAttr = parents.find(p => p.type === 'JSXAttribute')
|
|
15
17
|
if (jsxAttr) {
|
|
16
18
|
context.report({
|
|
@@ -10,9 +10,11 @@ module.exports = {
|
|
|
10
10
|
},
|
|
11
11
|
|
|
12
12
|
create (context) {
|
|
13
|
+
const sourceCode = context.getSourceCode()
|
|
14
|
+
|
|
13
15
|
return {
|
|
14
16
|
JSXSpreadAttribute (node) {
|
|
15
|
-
const parents =
|
|
17
|
+
const parents = sourceCode.getAncestors(node)
|
|
16
18
|
const jsx = parents.find(p => p.type === 'JSXOpeningElement')
|
|
17
19
|
if (jsx && jsx.name && jsx.name.name) {
|
|
18
20
|
const componentName = jsx.name.name
|
|
@@ -8,9 +8,11 @@ module.exports = {
|
|
|
8
8
|
},
|
|
9
9
|
|
|
10
10
|
create (context) {
|
|
11
|
+
const sourceCode = context.getSourceCode()
|
|
12
|
+
|
|
11
13
|
return {
|
|
12
14
|
JSXElement (node) {
|
|
13
|
-
const parents =
|
|
15
|
+
const parents = sourceCode.getAncestors(node)
|
|
14
16
|
const funcDecl = parents.find(p => p.type === 'FunctionDeclaration')
|
|
15
17
|
if (parents.some(p => p.type === 'JSXElement')) {
|
|
16
18
|
return
|
|
@@ -25,7 +27,7 @@ module.exports = {
|
|
|
25
27
|
const funcExpression = parents.find(p => p.type === 'ArrowFunctionExpression' || p.type === 'FunctionExpression')
|
|
26
28
|
|
|
27
29
|
if (funcExpression && funcExpression.parent.type !== 'MethodDefinition') {
|
|
28
|
-
const arrowFuncParents =
|
|
30
|
+
const arrowFuncParents = sourceCode.getAncestors(funcExpression)
|
|
29
31
|
const isMapCallExpr = arrowFuncParents.some(p =>
|
|
30
32
|
p.type === 'CallExpression' &&
|
|
31
33
|
p.callee.type === 'MemberExpression' &&
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { DEFAULT_Components_SET } = require('../constant')
|
|
1
2
|
const { buildDocsMeta } = require('../utils/utils')
|
|
2
3
|
|
|
3
4
|
const ERROR_MESSAGE = '在小程序是保留关键字,请使用其他 props 名'
|
|
@@ -7,47 +8,6 @@ const reserveKeyWords = new Set([
|
|
|
7
8
|
'id'
|
|
8
9
|
])
|
|
9
10
|
|
|
10
|
-
// eslint-disable-next-line
|
|
11
|
-
const DEFAULT_Components_SET = new Set([
|
|
12
|
-
'View',
|
|
13
|
-
'ScrollView',
|
|
14
|
-
'Swiper',
|
|
15
|
-
'CoverImage',
|
|
16
|
-
'CoverView',
|
|
17
|
-
'Icon',
|
|
18
|
-
'Text',
|
|
19
|
-
'RichText',
|
|
20
|
-
'Progress',
|
|
21
|
-
'Button',
|
|
22
|
-
'Checkbox',
|
|
23
|
-
'Form',
|
|
24
|
-
'Input',
|
|
25
|
-
'Label',
|
|
26
|
-
'Picker',
|
|
27
|
-
'PickerView',
|
|
28
|
-
'Radio',
|
|
29
|
-
'RadioGroup',
|
|
30
|
-
'CheckboxGroup',
|
|
31
|
-
'Slider',
|
|
32
|
-
'Switch',
|
|
33
|
-
'Textarea',
|
|
34
|
-
'Navigator',
|
|
35
|
-
'Audio',
|
|
36
|
-
'Image',
|
|
37
|
-
'Video',
|
|
38
|
-
'Camera',
|
|
39
|
-
'LivePlayer',
|
|
40
|
-
'LivePusher',
|
|
41
|
-
'Map',
|
|
42
|
-
'Canvas',
|
|
43
|
-
'OpenData',
|
|
44
|
-
'WebView',
|
|
45
|
-
'SwiperItem',
|
|
46
|
-
'Provider',
|
|
47
|
-
'MovableArea',
|
|
48
|
-
'MovableView'
|
|
49
|
-
])
|
|
50
|
-
|
|
51
11
|
module.exports = {
|
|
52
12
|
meta: {
|
|
53
13
|
docs: buildDocsMeta(ERROR_MESSAGE, 'props-reserve-keyword')
|
package/rules/render-props.js
CHANGED
|
@@ -10,9 +10,11 @@ module.exports = {
|
|
|
10
10
|
},
|
|
11
11
|
|
|
12
12
|
create (context) {
|
|
13
|
+
const sourceCode = context.getSourceCode()
|
|
14
|
+
|
|
13
15
|
return {
|
|
14
16
|
JSXElement (node) {
|
|
15
|
-
const parents =
|
|
17
|
+
const parents = sourceCode.getAncestors(node)
|
|
16
18
|
if (parents.some(p => p.type === 'JSXElement')) {
|
|
17
19
|
return
|
|
18
20
|
}
|
|
@@ -29,7 +31,7 @@ module.exports = {
|
|
|
29
31
|
},
|
|
30
32
|
JSXAttribute (node) {
|
|
31
33
|
if (renderRE.test(node.name.name)) {
|
|
32
|
-
if (node.value.type !== 'JSXExpressionContainer') {
|
|
34
|
+
if (node.value && node.value.type !== 'JSXExpressionContainer') {
|
|
33
35
|
context.report({
|
|
34
36
|
message: '以 render 开头命名的 props 只能传入单个 JSX 元素或箭头函数',
|
|
35
37
|
node
|
|
@@ -63,7 +65,7 @@ module.exports = {
|
|
|
63
65
|
}
|
|
64
66
|
if (property.name === 'children') {
|
|
65
67
|
context.report({
|
|
66
|
-
message:
|
|
68
|
+
message: `无法操作 this.props.children`,
|
|
67
69
|
node
|
|
68
70
|
})
|
|
69
71
|
}
|
|
@@ -34,6 +34,19 @@ module.exports = {
|
|
|
34
34
|
},
|
|
35
35
|
|
|
36
36
|
create (context) {
|
|
37
|
+
function checkClassProperty(node) {
|
|
38
|
+
if (!isTaroComponent(context, node)) {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
const name = node.key.name
|
|
42
|
+
if (RESERVE_PROPERIES.has(name)) {
|
|
43
|
+
context.report({
|
|
44
|
+
message: createErrorMsg(name, '属性'),
|
|
45
|
+
node
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
37
50
|
return {
|
|
38
51
|
MethodDefinition (node) {
|
|
39
52
|
if (!isTaroComponent(context, node)) {
|
|
@@ -47,18 +60,8 @@ module.exports = {
|
|
|
47
60
|
})
|
|
48
61
|
}
|
|
49
62
|
},
|
|
50
|
-
ClassProperty
|
|
51
|
-
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
const name = node.key.name
|
|
55
|
-
if (RESERVE_PROPERIES.has(name)) {
|
|
56
|
-
context.report({
|
|
57
|
-
message: createErrorMsg(name, '属性'),
|
|
58
|
-
node
|
|
59
|
-
})
|
|
60
|
-
}
|
|
61
|
-
}
|
|
63
|
+
ClassProperty: checkClassProperty,
|
|
64
|
+
PropertyDefinition: checkClassProperty,
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
67
|
}
|
package/rules/switch-jsx.js
CHANGED
|
@@ -8,9 +8,11 @@ module.exports = {
|
|
|
8
8
|
},
|
|
9
9
|
|
|
10
10
|
create (context) {
|
|
11
|
+
const sourceCode = context.getSourceCode()
|
|
12
|
+
|
|
11
13
|
return {
|
|
12
14
|
JSXElement (node) {
|
|
13
|
-
const parents =
|
|
15
|
+
const parents = sourceCode.getAncestors(node)
|
|
14
16
|
const jsxAttr = parents.find(p => p.type === 'SwitchCase' || p.type === 'SwitchStatement')
|
|
15
17
|
if (jsxAttr) {
|
|
16
18
|
context.report({
|
package/utils/utils.js
CHANGED
|
@@ -11,21 +11,12 @@ function buildDocsMeta (description, rule) {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const parserOptions = {
|
|
15
|
-
ecmaVersion: 2018,
|
|
16
|
-
sourceType: 'module',
|
|
17
|
-
ecmaFeatures: {
|
|
18
|
-
jsx: true,
|
|
19
|
-
experimentalObjectRestSpread: true
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
14
|
function isTaroComponent (context, node) {
|
|
24
15
|
let classDcl
|
|
25
16
|
if (node.type === 'ClassDeclaration') {
|
|
26
17
|
classDcl = node
|
|
27
18
|
} else {
|
|
28
|
-
const parents = context.getAncestors(node)
|
|
19
|
+
const parents = context.getSourceCode().getAncestors(node)
|
|
29
20
|
classDcl = parents.find(p => p.type === 'ClassDeclaration')
|
|
30
21
|
}
|
|
31
22
|
if (
|
|
@@ -42,37 +33,8 @@ function isTaroComponent (context, node) {
|
|
|
42
33
|
return false
|
|
43
34
|
}
|
|
44
35
|
|
|
45
|
-
function testComponent (code) {
|
|
46
|
-
return `
|
|
47
|
-
class App extends Component {
|
|
48
|
-
render () {
|
|
49
|
-
${code}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
`
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function testValid (tests) {
|
|
56
|
-
return tests.map(code => ({
|
|
57
|
-
code: testComponent(code),
|
|
58
|
-
parser: 'babel-eslint'
|
|
59
|
-
}))
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function testInvalid (message, tests) {
|
|
63
|
-
return tests.map(code => ({
|
|
64
|
-
code: testComponent(code),
|
|
65
|
-
errors: [{ message }],
|
|
66
|
-
parser: 'babel-eslint'
|
|
67
|
-
}))
|
|
68
|
-
}
|
|
69
|
-
|
|
70
36
|
module.exports = {
|
|
71
37
|
docsUrl,
|
|
72
38
|
buildDocsMeta,
|
|
73
|
-
parserOptions,
|
|
74
|
-
testComponent,
|
|
75
|
-
testValid,
|
|
76
|
-
testInvalid,
|
|
77
39
|
isTaroComponent
|
|
78
40
|
}
|