@huangjunsen/eslint-config 1.0.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.
Files changed (57) hide show
  1. package/.editorconfig +17 -0
  2. package/.eslintignore +17 -0
  3. package/.eslintrc.js +5 -0
  4. package/LICENSE +21 -0
  5. package/README.md +286 -0
  6. package/__tests__/fixtures/es5.js +4 -0
  7. package/__tests__/fixtures/index.js +3 -0
  8. package/__tests__/fixtures/node.js +24 -0
  9. package/__tests__/fixtures/react-display-name.js +7 -0
  10. package/__tests__/fixtures/react.jsx +132 -0
  11. package/__tests__/fixtures/ts-import-a.ts +3 -0
  12. package/__tests__/fixtures/ts-import-b.ts +3 -0
  13. package/__tests__/fixtures/ts-node.ts +20 -0
  14. package/__tests__/fixtures/ts-react.tsx +27 -0
  15. package/__tests__/fixtures/ts-vue.vue +36 -0
  16. package/__tests__/fixtures/ts.ts +17 -0
  17. package/__tests__/fixtures/tsconfig.json +8 -0
  18. package/__tests__/fixtures/use-babel-eslint.jsx +170 -0
  19. package/__tests__/fixtures/vue.vue +16 -0
  20. package/__tests__/use-babel-eslint.test.js +47 -0
  21. package/__tests__/validate-js-configs.test.js +259 -0
  22. package/__tests__/validate-ts-configs.test.js +263 -0
  23. package/es5.js +10 -0
  24. package/essential/es5.js +12 -0
  25. package/essential/index.js +12 -0
  26. package/essential/react.js +76 -0
  27. package/essential/rules/blacklist.js +48 -0
  28. package/essential/rules/es6-blacklist.js +62 -0
  29. package/essential/rules/set-style-to-warn.js +30 -0
  30. package/essential/rules/ts-blacklist.js +15 -0
  31. package/essential/typescript/index.js +7 -0
  32. package/essential/typescript/react.js +7 -0
  33. package/essential/typescript/vue.js +9 -0
  34. package/essential/vue.js +8 -0
  35. package/index.js +23 -0
  36. package/jsx-a11y.js +5 -0
  37. package/node.js +6 -0
  38. package/package.json +48 -0
  39. package/react.js +11 -0
  40. package/rules/base/best-practices.js +284 -0
  41. package/rules/base/es6.js +168 -0
  42. package/rules/base/possible-errors.js +126 -0
  43. package/rules/base/strict.js +6 -0
  44. package/rules/base/style.js +445 -0
  45. package/rules/base/variables.js +48 -0
  46. package/rules/es5.js +11 -0
  47. package/rules/imports.js +167 -0
  48. package/rules/jsx-a11y.js +23 -0
  49. package/rules/node.js +11 -0
  50. package/rules/react.js +354 -0
  51. package/rules/typescript.js +807 -0
  52. package/rules/vue.js +96 -0
  53. package/typescript/index.js +6 -0
  54. package/typescript/node.js +6 -0
  55. package/typescript/react.js +6 -0
  56. package/typescript/vue.js +10 -0
  57. package/vue.js +10 -0
@@ -0,0 +1,170 @@
1
+ import React, { Component } from "react";
2
+ import { connect } from "react-redux";
3
+ import { bindActionCreators } from "redux";
4
+ import {
5
+ Breadcrumb,
6
+ Button,
7
+ Search,
8
+ Select,
9
+ Dropdown,
10
+ Menu,
11
+ Notice,
12
+ } from "antd";
13
+ import Layout from "layout";
14
+ import { Translate } from "antd-i18n";
15
+ import * as actions from "../actions/index";
16
+
17
+ function scoreAudioCoverFile(imgFile) {
18
+ const fileName = path
19
+ .basename(imgFile.name, path.extname(imgFile.name))
20
+ .toLowerCase();
21
+ const relevanceScore = {
22
+ cover: 80,
23
+ folder: 80,
24
+ album: 80,
25
+ front: 80,
26
+ back: 20,
27
+ spectrogram: -80,
28
+ };
29
+
30
+ for (const keyword in relevanceScore) {
31
+ if (fileName === keyword) {
32
+ return relevanceScore[keyword];
33
+ }
34
+ if (fileName.indexOf(keyword) !== -1) {
35
+ return relevanceScore[keyword];
36
+ }
37
+ }
38
+ return 0;
39
+ }
40
+
41
+ const { Nav, Card, Section, Toolbar } = Layout;
42
+
43
+ const ButtonGroup = Button.Group;
44
+ const { Option } = Select;
45
+
46
+ class Root extends Component {
47
+ componentDidMount() {
48
+ this.props.getBreadcrumb();
49
+ }
50
+
51
+ onSearch = (searchParams) => {
52
+ const foo = import(`./${searchParams}`);
53
+ console.log(foo);
54
+ };
55
+
56
+ onSelectChange(value, data) {
57
+ console.log(value, data);
58
+ }
59
+
60
+ onMenuClick(selectedKeys, menuItem, meta) {
61
+ console.log(selectedKeys, menuItem, meta);
62
+ }
63
+
64
+ render() {
65
+ const { breadcrumb } = this.props;
66
+ const subNavData = {
67
+ navs: [
68
+ {
69
+ key: "home",
70
+ text: "导航操作区",
71
+ active: true,
72
+ link: "#",
73
+ },
74
+ {
75
+ key: "permit",
76
+ text: "权限",
77
+ link: "#",
78
+ },
79
+ {
80
+ key: "favorite",
81
+ text: "常用链接",
82
+ link: "#",
83
+ },
84
+ ],
85
+ };
86
+
87
+ return (
88
+ <Layout>
89
+ <Nav data={subNavData} />
90
+ <Section>
91
+ <Breadcrumb dataSource={breadcrumb} />
92
+ </Section>
93
+ <Section>
94
+ <Notice title="提示:" type="info">
95
+ 页面提示信息区(Notice组件)
96
+ </Notice>
97
+ </Section>
98
+ <Section>
99
+ <Toolbar>
100
+ <Toolbar.Left>
101
+ <Toolbar.Item>
102
+ <Button type="primary">页面操作区</Button>
103
+ </Toolbar.Item>
104
+ <Toolbar.Item>
105
+ <ButtonGroup>
106
+ <Dropdown
107
+ triggerButton={<Button type="normal">批量操作</Button>}
108
+ triggerType="click"
109
+ >
110
+ <Menu onClick={this.onMenuClick}>
111
+ <Menu.Item key="submit_cr">提交发布</Menu.Item>
112
+ <Menu.Item key="close_cr">关闭变更</Menu.Item>
113
+ </Menu>
114
+ </Dropdown>
115
+ <Dropdown
116
+ triggerButton={<Button type="normal">更多</Button>}
117
+ triggerType="click"
118
+ >
119
+ <Menu onClick={this.onMenuClick}>
120
+ <Menu.Item key="other_1">更多操作 1</Menu.Item>
121
+ <Menu.Item key="other_2">更多操作 2</Menu.Item>
122
+ <Menu.Item key="other_3">更多操作 3</Menu.Item>
123
+ </Menu>
124
+ </Dropdown>
125
+ </ButtonGroup>
126
+ </Toolbar.Item>
127
+ </Toolbar.Left>
128
+ <Toolbar.Right>
129
+ <Toolbar.Item>
130
+ <Select onChange={this.onSelectChange} defaultValue="default">
131
+ <Option value="default">默认排序</Option>
132
+ <Option value="gmt_create|DESC">按创建时间降序</Option>
133
+ <Option value="gmt_create|ASC">按创建时间升序</Option>
134
+ </Select>
135
+ </Toolbar.Item>
136
+ <Toolbar.Item>
137
+ <Search
138
+ placeholder="请输入关键词搜索"
139
+ onSearch={this.onSearch}
140
+ />
141
+ </Toolbar.Item>
142
+ </Toolbar.Right>
143
+ </Toolbar>
144
+ </Section>
145
+ <Section>
146
+ <Card
147
+ title="详细内容展示区(Card组件)"
148
+ extra={<a href="#">更多操作</a>}
149
+ >
150
+ <p>
151
+ <a href="#" target="_blank" rel="noreferrer noopener">
152
+ 点击查看设计规范
153
+ </a>
154
+ </p>
155
+ <p>
156
+ <Button type="primary" onClick={this.props.changeLang}>
157
+ <Translate value="buttonText" />
158
+ </Button>
159
+ </p>
160
+ </Card>
161
+ </Section>
162
+ </Layout>
163
+ );
164
+ }
165
+ }
166
+
167
+ export default connect(
168
+ ({ index, ...others }) => ({ ...index, ...others }),
169
+ (dispatch) => bindActionCreators(actions, dispatch)
170
+ )(Root);
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <div style="margin: 20px;">
3
+ <textarea>{{ value }}</textarea>
4
+ </div>
5
+ </template>
6
+
7
+ <script lang="js">
8
+ export default {
9
+ data() {
10
+ const bo = import('./foo');
11
+ return {
12
+ value: 'value',
13
+ };
14
+ },
15
+ };
16
+ </script>
@@ -0,0 +1,47 @@
1
+ const assert = require('assert');
2
+ const eslint = require('eslint');
3
+ const path = require('path');
4
+
5
+ describe('test/use-babel-eslint.test.js', () => {
6
+ it('babel-eslint parser run well for react', async () => {
7
+ const configPath = './react.js';
8
+ const filePath = path.join(__dirname, './fixtures/use-babel-eslint.jsx');
9
+
10
+ const cli = new eslint.ESLint({
11
+ overrideConfigFile: configPath,
12
+ useEslintrc: false,
13
+ ignore: false,
14
+ });
15
+
16
+ const results = await cli.lintFiles([filePath]);
17
+ const { messages, errorCount, fatalErrorCount, warningCount } = results[0];
18
+
19
+ assert.equal(fatalErrorCount, 0);
20
+ assert.equal(errorCount, 27);
21
+ assert.equal(warningCount, 7);
22
+
23
+ const errorReportedByReactPlugin = messages.filter((result) => {
24
+ return result.ruleId && result.ruleId.indexOf('react/') !== -1;
25
+ });
26
+
27
+ assert.notEqual(errorReportedByReactPlugin.length, 0);
28
+ });
29
+
30
+ it('babel-eslint parser run well for vue', async () => {
31
+ const configPath = './vue.js';
32
+ const filePath = path.join(__dirname, './fixtures/vue.vue');
33
+
34
+ const cli = new eslint.ESLint({
35
+ overrideConfigFile: configPath,
36
+ useEslintrc: false,
37
+ ignore: false,
38
+ });
39
+
40
+ const results = await cli.lintFiles([filePath]);
41
+ const { errorCount, fatalErrorCount, warningCount } = results[0];
42
+
43
+ assert.equal(fatalErrorCount, 0);
44
+ assert.equal(errorCount, 4);
45
+ assert.equal(warningCount, 0);
46
+ });
47
+ });
@@ -0,0 +1,259 @@
1
+ /**
2
+ * 验证 JS
3
+ */
4
+
5
+ const assert = require('assert');
6
+ const eslint = require('eslint');
7
+ const path = require('path');
8
+ const sumBy = require('lodash/sumBy');
9
+
10
+ function isObject(obj) {
11
+ return typeof obj === 'object' && obj !== null;
12
+ }
13
+
14
+ describe('Validate JS configs', () => {
15
+ it('Validate eslint-config-encode', async () => {
16
+ const configPath = './index.js';
17
+ const filePath = path.join(__dirname, './fixtures/index.js');
18
+
19
+ const cli = new eslint.ESLint({
20
+ overrideConfigFile: configPath,
21
+ useEslintrc: false, // 如果不关这个参数,会将目录下的 eslintrc 与 overrideConfigFile merge
22
+ ignore: false,
23
+ });
24
+
25
+ // 验证导出的 config 是否正常
26
+ const config = await cli.calculateConfigForFile(filePath);
27
+ assert.ok(isObject(config));
28
+
29
+ // 验证 lint 工作是否正常
30
+ const results = await cli.lintFiles([filePath]);
31
+ assert.equal(sumBy(results, 'fatalErrorCount'), 0);
32
+ assert.notEqual(sumBy(results, 'errorCount'), 0);
33
+ assert.notEqual(sumBy(results, 'warningCount'), 0);
34
+ });
35
+
36
+ it('Validate eslint-config-encode/es5', async () => {
37
+ const configPath = './es5.js';
38
+ const filePath = path.join(__dirname, './fixtures/es5.js');
39
+
40
+ const cli = new eslint.ESLint({
41
+ overrideConfigFile: configPath,
42
+ useEslintrc: false,
43
+ ignore: false,
44
+ });
45
+
46
+ // 验证导出的 config 是否正常
47
+ const config = await cli.calculateConfigForFile(filePath);
48
+ assert.ok(isObject(config));
49
+
50
+ // 验证 lint 工作是否正常
51
+ const results = await cli.lintFiles([filePath]);
52
+ assert.equal(sumBy(results, 'fatalErrorCount'), 0);
53
+ assert.notEqual(sumBy(results, 'errorCount'), 0);
54
+ assert.equal(sumBy(results, 'warningCount'), 0);
55
+
56
+ // 验证 es5 覆盖的规则是否正常,取 comma-dangle 进行测试
57
+ const { messages } = results[0];
58
+ const errorReportedByReactPlugin = messages.filter((result) => {
59
+ return result.ruleId === 'comma-dangle';
60
+ });
61
+ assert.notEqual(errorReportedByReactPlugin.length, 0);
62
+ });
63
+
64
+ it('Validate eslint-config-encode/vue', async () => {
65
+ const configPath = './vue.js';
66
+ const filePath = path.join(__dirname, './fixtures/vue.vue');
67
+
68
+ const cli = new eslint.ESLint({
69
+ overrideConfigFile: configPath,
70
+ useEslintrc: false,
71
+ ignore: false,
72
+ });
73
+
74
+ // 验证导出的 config 是否正常
75
+ const config = await cli.calculateConfigForFile(filePath);
76
+ assert.ok(isObject(config));
77
+
78
+ // 验证 lint 工作是否正常
79
+ const results = await cli.lintFiles([filePath]);
80
+ assert.equal(sumBy(results, 'fatalErrorCount'), 0);
81
+ assert.notEqual(sumBy(results, 'errorCount'), 0);
82
+ assert.equal(sumBy(results, 'warningCount'), 0);
83
+
84
+ // 验证 eslint-plugin-vue 工作是否正常
85
+ const { messages } = results[0];
86
+ const errorReportedByReactPlugin = messages.filter((result) => {
87
+ return result.ruleId && result.ruleId.indexOf('vue/') !== -1;
88
+ });
89
+ assert.notEqual(errorReportedByReactPlugin.length, 0);
90
+ });
91
+
92
+ it('Validate eslint-config-encode/essential', async () => {
93
+ const configPath = './essential/index.js';
94
+ const filePath = path.join(__dirname, './fixtures/index.js');
95
+
96
+ const cli = new eslint.ESLint({
97
+ overrideConfigFile: configPath,
98
+ useEslintrc: false,
99
+ ignore: false,
100
+ });
101
+
102
+ // 验证导出的 config 是否正常
103
+ const config = await cli.calculateConfigForFile(filePath);
104
+ assert.ok(isObject(config));
105
+
106
+ // 验证 lint 工作是否正常
107
+ const results = await cli.lintFiles([filePath]);
108
+ assert.equal(sumBy(results, 'fatalErrorCount'), 0);
109
+ assert.equal(sumBy(results, 'errorCount'), 0);
110
+ assert.notEqual(sumBy(results, 'warningCount'), 0);
111
+
112
+ // 验证黑名单中的规则已关闭
113
+ const { messages } = results[0];
114
+
115
+ // 验证 semi 被关闭
116
+ const semiErrors = messages.filter((result) => {
117
+ return result.ruleId === 'semi';
118
+ });
119
+ assert.equal(semiErrors.length, 0);
120
+
121
+ // 验证 comma-spacing 被降级
122
+ const commaSpacingErrors = messages.filter((result) => {
123
+ return result.ruleId === 'comma-spacing';
124
+ });
125
+ assert.equal(commaSpacingErrors[0].severity, 1);
126
+ });
127
+
128
+ it('Validate eslint-config-encode/essential/es5', async () => {
129
+ const configPath = './essential/es5.js';
130
+ const filePath = path.join(__dirname, './fixtures/es5.js');
131
+
132
+ const cli = new eslint.ESLint({
133
+ overrideConfigFile: configPath,
134
+ useEslintrc: false,
135
+ ignore: false,
136
+ });
137
+
138
+ // 验证导出的 config 是否正常
139
+ const config = await cli.calculateConfigForFile(filePath);
140
+ assert.ok(isObject(config));
141
+
142
+ // 验证 lint 工作是否正常
143
+ const results = await cli.lintFiles([filePath]);
144
+ assert.equal(sumBy(results, 'fatalErrorCount'), 0);
145
+ assert.notEqual(sumBy(results, 'errorCount'), 0);
146
+ assert.notEqual(sumBy(results, 'warningCount'), 0);
147
+ // 验证 es5 覆盖的规则是否正常,取 comma-dangle 进行测试
148
+ const { messages } = results[0];
149
+ const errorReportedByReactPlugin = messages.filter((result) => {
150
+ return result.ruleId === 'comma-dangle';
151
+ });
152
+ assert.notEqual(errorReportedByReactPlugin.length, 0);
153
+
154
+ // 验证黑名单中的规则已关闭,取 semi 进行测试
155
+ const errorReportedByReactPluginBlackList = messages.filter((result) => {
156
+ return result.ruleId === 'semi';
157
+ });
158
+ assert.equal(errorReportedByReactPluginBlackList.length, 0);
159
+ });
160
+
161
+ it('Validate eslint-config-encode/essential/react', async () => {
162
+ const configPath = './essential/react.js';
163
+ const filePath = path.join(__dirname, './fixtures/react.jsx');
164
+
165
+ const cli = new eslint.ESLint({
166
+ overrideConfigFile: configPath,
167
+ useEslintrc: false,
168
+ ignore: false,
169
+ });
170
+
171
+ // 验证导出的 config 是否正常
172
+ const config = await cli.calculateConfigForFile(filePath);
173
+ assert.ok(isObject(config));
174
+
175
+ // 验证 lint 工作是否正常
176
+ const results = await cli.lintFiles([filePath]);
177
+ assert.equal(sumBy(results, 'fatalErrorCount'), 0);
178
+ assert.notEqual(sumBy(results, 'errorCount'), 0);
179
+ assert.notEqual(sumBy(results, 'warningCount'), 0);
180
+ // 验证 react plugin 工作是否正常
181
+ const { messages } = results[0];
182
+ const errorReportedByReactPlugin = messages.filter((result) => {
183
+ return result.ruleId && result.ruleId.indexOf('react/') !== -1;
184
+ });
185
+ assert.notEqual(errorReportedByReactPlugin.length, 0);
186
+
187
+ // 验证黑名单中的规则已关闭,取 react/jsx-indent 进行测试
188
+ const errorReportedByReactPluginBlackList = messages.filter((result) => {
189
+ return result.ruleId === 'react/jsx-indent';
190
+ });
191
+ assert.equal(errorReportedByReactPluginBlackList.length, 0);
192
+ });
193
+
194
+ it('Validate eslint-config-encode/essential/vue', async () => {
195
+ const configPath = './essential/vue.js';
196
+ const filePath = path.join(__dirname, './fixtures/vue.vue');
197
+
198
+ const cli = new eslint.ESLint({
199
+ overrideConfigFile: configPath,
200
+ useEslintrc: false,
201
+ ignore: false,
202
+ });
203
+
204
+ // 验证导出的 config 是否正常
205
+ const config = await cli.calculateConfigForFile(filePath);
206
+ assert.ok(isObject(config));
207
+
208
+ // 验证 lint 工作是否正常
209
+ const results = await cli.lintFiles([filePath]);
210
+ assert.equal(sumBy(results, 'fatalErrorCount'), 0);
211
+ assert.notEqual(sumBy(results, 'errorCount'), 0);
212
+ assert.equal(sumBy(results, 'warningCount'), 0);
213
+
214
+ // 验证 vue plugin 工作是否正常
215
+ const { messages } = results[0];
216
+ const errorReportedByReactPlugin = messages.filter((result) => {
217
+ return result.ruleId && result.ruleId.indexOf('vue/') !== -1;
218
+ });
219
+ assert.notEqual(errorReportedByReactPlugin.length, 0);
220
+
221
+ // 验证黑名单中的规则已关闭
222
+ const errorReportedByReactPluginBlackList = messages.filter((result) => {
223
+ return result.ruleId === 'indent';
224
+ });
225
+ assert.equal(errorReportedByReactPluginBlackList.length, 0);
226
+ });
227
+
228
+ it('Validate eslint-config-encode/node', async () => {
229
+ const configPath = './node.js';
230
+ const filePath = path.join(__dirname, './fixtures/node.js');
231
+
232
+ const cli = new eslint.ESLint({
233
+ overrideConfigFile: configPath,
234
+ useEslintrc: false,
235
+ ignore: false,
236
+ });
237
+
238
+ // 验证导出的 config 是否正常
239
+ const config = await cli.calculateConfigForFile(filePath);
240
+ assert.ok(isObject(config));
241
+ assert.strictEqual(config.env.node, true);
242
+ assert.strictEqual(config.plugins.includes('node'), true);
243
+
244
+ // 验证已开启的 link 规则是否校验正常
245
+ const results = await cli.lintFiles([filePath]);
246
+ const { messages, errorCount, warningCount } = results[0];
247
+ const ruleIds = Array.from(messages.map((item) => item.ruleId));
248
+ assert.strictEqual(ruleIds.includes('node/prefer-promises/fs'), true);
249
+ assert.strictEqual(ruleIds.includes('no-unused-vars'), true);
250
+ assert.strictEqual(ruleIds.includes('node/no-new-require'), true);
251
+ assert.strictEqual(ruleIds.includes('semi'), true);
252
+ assert.strictEqual(ruleIds.includes('quotes'), true);
253
+ assert.strictEqual(errorCount, 7);
254
+ assert.strictEqual(warningCount, 4);
255
+
256
+ // 验证已关闭的 link 规则是否校验正常,以 node/exports-style 为例
257
+ assert.strictEqual(ruleIds.includes('node/exports-style'), false);
258
+ });
259
+ });