eslint-plugin-light 0.0.18 → 1.0.3

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/CHANGELOG.md CHANGED
@@ -1,6 +1,32 @@
1
- # Changelog
1
+ ## [1.0.0](https://git.woa.com/pmd-mobile/support/eslint-plugin-pmd/compare/v0.0.16...v1.0.0) (2023-07-12)
2
2
 
3
- All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
3
+
4
+ ### ✨ Features | 新功能
5
+
6
+ * 添加规则不能使用this.tip_uid,但是没有开启 ([d913d2b](https://git.woa.com/pmd-mobile/support/eslint-plugin-pmd/commit/d913d2be33aaa44dbb6615f2d4ac98d4a7acebb0))
7
+ * 新增no-import-vant ([c5b8722](https://git.woa.com/pmd-mobile/support/eslint-plugin-pmd/commit/c5b87222db44111338cd1d9d4356695efa20cb93))
8
+ * 优化插件 ([505f17f](https://git.woa.com/pmd-mobile/support/eslint-plugin-pmd/commit/505f17f2191fdd6a9f32c67d64420ae115909af2))
9
+
10
+
11
+ ### ♻️ Code Refactoring | 代码重构
12
+
13
+ * 插件重命名为light ([21c1dd9](https://git.woa.com/pmd-mobile/support/eslint-plugin-pmd/commit/21c1dd93dcd5e31265767cf53121a718826abaad))
14
+
15
+
16
+ ### ✏️ Documentation | 文档
17
+
18
+ * 文档更新 ([4f33c36](https://git.woa.com/pmd-mobile/support/eslint-plugin-pmd/commit/4f33c36f40bd8c872c586d05cd6ffbd0d21b5f62))
19
+ * 优化readme ([f0183d0](https://git.woa.com/pmd-mobile/support/eslint-plugin-pmd/commit/f0183d0b7cd66af9c47d3e389ccc11c572e1f54a))
20
+
21
+
22
+ ### ✅ Tests | 测试
23
+
24
+ * 测试用例修正 ([70e9f36](https://git.woa.com/pmd-mobile/support/eslint-plugin-pmd/commit/70e9f36fdad34b72d94b85c2590bbb06489fd6aa))
25
+
26
+
27
+ ### 🚀 Chore | 构建/工程依赖/工具
28
+
29
+ * 删除无效注释 ([96d5e9d](https://git.woa.com/pmd-mobile/support/eslint-plugin-pmd/commit/96d5e9d158c10df93c6f714805eaf8d670d39eeb))
4
30
 
5
31
  ### [0.0.16](https://git.woa.com/pmd-mobile/support/eslint-plugin-pmd/compare/v0.0.15...v0.0.16) (2022-07-26)
6
32
 
package/README.md CHANGED
@@ -1,30 +1,30 @@
1
- # eslint-plugin-pmd
1
+ ## Eslint Plugin Light
2
2
 
3
- eslint插件
3
+ Simple Eslint plugin.
4
4
 
5
5
 
6
- ## 1. Installation
6
+ ### 1. Installation
7
7
 
8
- You'll first need to install [ESLint](https://eslint.org/):
8
+ You need to install [ESLint](https://eslint.org/) first.
9
9
 
10
10
  ```sh
11
- npm i eslint --save-dev
11
+ npm i eslint -D
12
12
  ```
13
13
 
14
- Next, install `eslint-plugin-pmd`:
14
+ Next, install `eslint-plugin-light`.
15
15
 
16
16
  ```sh
17
- npm install @tencent/eslint-plugin-pmd --save-dev
17
+ npm i eslint-plugin-light -D
18
18
  ```
19
19
 
20
- ## 2. Usage
20
+ ### 2. Usage
21
21
 
22
- Add `pmd` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:
22
+ Add `light` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:
23
23
 
24
24
  ```json
25
25
  {
26
26
  "plugins": [
27
- "pmd"
27
+ "light"
28
28
  ]
29
29
  }
30
30
  ```
@@ -35,7 +35,7 @@ Then configure the rules you want to use under the rules section.
35
35
  ```json
36
36
  {
37
37
  "rules": {
38
- "pmd/rule-name": 2
38
+ "light/rule-name": 2
39
39
  }
40
40
  }
41
41
  ```
@@ -44,21 +44,21 @@ or use extends:
44
44
 
45
45
  ```json
46
46
  {
47
- extends: ['plugin:pmd/recommended'],
47
+ "extends": ["plugin:light/recommended"],
48
48
  }
49
49
  ```
50
50
 
51
51
 
52
- ## 3. Supported Rules
52
+ ### 3. Supported Rules
53
53
 
54
- ### 3.1. pmd/valid-vue-comp-import
54
+ #### 3.1. light/valid-vue-comp-import
55
55
 
56
- 禁止从js文件中加载Vue组件
56
+ 禁止从`js`文件中加载`Vue`组件
57
57
 
58
58
  比如,
59
59
 
60
60
 
61
- 1. 导入地址是js/ts文件
61
+ 1. 导入地址是`js/ts`文件
62
62
 
63
63
  ```js
64
64
  import SomeComp from 'src/local-component/ui/pages/user/account-manage/index.js';
@@ -67,7 +67,7 @@ import SomeComp from 'src/local-component/ui/pages/user/account-manage/index.js'
67
67
  import SomeComp from 'src/local-component/ui/pages/user/account-manage/index';
68
68
  ```
69
69
 
70
- 如果加了--fix,会被转换为:
70
+ 如果加了 `--fix`,会被转换为:
71
71
 
72
72
  ```js
73
73
  import SomeComp from 'src/local-component/ui/pages/user/account-manage/xxx.vue';
@@ -77,7 +77,7 @@ import SomeComp from 'src/local-component/ui/pages/user/account-manage/xxx.vue';
77
77
 
78
78
 
79
79
 
80
- 2. 导入一个目录,但目录存在index.js,这时候不管存不存在index.vue,uniapp转换都会失败
80
+ 2. 导入一个目录,但目录存在`index.js`,这时候不管存不存在`index.vue`,`uni-app`转换都会失败
81
81
 
82
82
  ```js
83
83
  import SomeComp from 'src/local-component/ui/pages/user/account-manage';
@@ -109,9 +109,9 @@ import CComp from 'src/local-component/module/tip-match/tip-match-schedule-tree-
109
109
  import DComp from 'src/local-component/module/tip-match/tip-match-schedule-tree-new/comp/d.vue';
110
110
  ```
111
111
 
112
- ### 3.2. pmd/no-plus-turn-number
112
+ #### 3.2. light/no-plus-turn-number
113
113
 
114
- 禁止在vuetemplate中用+号转换字符串为数字
114
+ 禁止在`vue`的`template`中用`+`号转换字符串为数字
115
115
 
116
116
  比如:
117
117
 
@@ -121,7 +121,7 @@ import DComp from 'src/local-component/module/tip-match/tip-match-schedule-tree-
121
121
  />
122
122
  ```
123
123
 
124
- 如果加了--fix,会被转化成:
124
+ 如果加了`--fix`,会被转化成:
125
125
 
126
126
  ```html
127
127
  <ScheduleItem
@@ -129,22 +129,25 @@ import DComp from 'src/local-component/module/tip-match/tip-match-schedule-tree-
129
129
  />
130
130
  ```
131
131
 
132
- ### 3.3 no-complex-key
132
+ #### 3.3 no-complex-key
133
133
 
134
- 不要在vue模板中使用复杂的key。包括:
134
+ 不要在`vue`模板中使用复杂的`key`。包括:
135
135
 
136
136
  1. 字符串拼接,如:
137
137
 
138
- ```
138
+ ```vue
139
139
  :key="`hold` + index"`
140
140
  ```
141
+
141
142
  2. 模板字符串,如:
142
- ```
143
+
144
+ ```vue
143
145
  :key="`hold-${index}`"
144
146
  ```
145
- 3. 将key提到一个函数中,如:
146
147
 
147
- ```
148
+ 3. 将`key`提到一个函数中,如:
149
+
150
+ ```vue
148
151
  :key="getHoldKey(index)"
149
152
 
150
153
  getHoldKey(index) {
@@ -152,7 +155,7 @@ getHoldKey(index) {
152
155
  }
153
156
  ```
154
157
 
155
- 最佳方式其实是提前处理好数据,这样性能会更好,也避免了key重复。
158
+ 最佳方式其实是提前处理好数据,这样性能会更好,也避免了`key`重复。
156
159
 
157
160
  ```ts
158
161
  getData() {
@@ -163,5 +166,31 @@ getData() {
163
166
  }
164
167
  ```
165
168
 
169
+ `uni-app`中,`key`重复的话,会造成挂载在组件上面的事件参数为`undefined`,从而不成功。
170
+
171
+
172
+ #### 3.4 json-parse-try-catch
173
+
174
+ `JSON.parse` 应该加 `try catch`。
175
+
176
+ 默认配置会排除下面情况:
177
+
178
+ ```ts
179
+ JSON.parse(JSON.stringify(abc));
180
+ ```
181
+
182
+ 可以配置 `strict` 参数为 `true`,开启检查。
166
183
 
167
- uniapp中,key重复的话,会造成挂载在组件上面的事件参数为undefined,从而不成功。
184
+
185
+ ```js
186
+ // .eslintrc.js
187
+
188
+ module.exports = {
189
+ plugins: [
190
+ 'light',
191
+ ],
192
+ rules: {
193
+ 'light/json-parse-try-catch': [2, { strict: true }],
194
+ },
195
+ }
196
+ ```
package/package.json CHANGED
@@ -1,30 +1,27 @@
1
1
  {
2
2
  "name": "eslint-plugin-light",
3
- "version": "0.0.18",
4
- "description": "eslint插件",
3
+ "version": "1.0.3",
4
+ "description": "Light Eslint Plugin",
5
5
  "keywords": [
6
6
  "eslint",
7
7
  "eslint plugin",
8
8
  "eslint-plugin",
9
- "eslint-plugin-uni"
9
+ "eslint-plugin-light"
10
10
  ],
11
11
  "files": [
12
12
  "lib/",
13
13
  "README.md",
14
14
  "CHANGELOG.md"
15
15
  ],
16
- "author": "GuoWangYang",
17
16
  "main": "lib/index.js",
18
- "scripts": {
19
- "lint": "eslint --ext .js,.vue .",
20
- "lint:fix": "eslint --fix --ext .js,.vue .",
21
- "test": "mocha tests --recursive",
22
- "create:mr": "node ./script/create-mr.js",
23
- "release": "npm run release-patch && npm publish",
24
- "release:first": "standard-version --first-release",
25
- "release-major": "standard-version --release-as major",
26
- "release-minor": "standard-version --release-as minor",
27
- "release-patch": "standard-version --release-as patch"
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/novlan1/plugin-light"
20
+ },
21
+ "author": "guowangyang",
22
+ "homepage": "https://novlan1.github.io/plugin-light/",
23
+ "bugs": {
24
+ "url": "https://github.com/novlan1/plugin-light/issues"
28
25
  },
29
26
  "dependencies": {
30
27
  "requireindex": "^1.2.0"
@@ -36,9 +33,9 @@
36
33
  "devDependencies": {
37
34
  "@babel/core": "^7.18.9",
38
35
  "@babel/eslint-parser": "^7.18.9",
39
- "@tencent/eslint-config-light": "^1.4.6",
40
36
  "axios": "^0.27.2",
41
37
  "eslint": "^8.0.1",
38
+ "eslint-config-light": "^1.4.7",
42
39
  "eslint-plugin-eslint-plugin": "^4.0.1",
43
40
  "eslint-plugin-node": "^11.1.0",
44
41
  "mocha": "^9.1.3",
@@ -47,5 +44,10 @@
47
44
  "engines": {
48
45
  "node": "12.x || 14.x || >= 16"
49
46
  },
50
- "license": "ISC"
47
+ "scripts": {
48
+ "build": "echo 0",
49
+ "changelog": "node ../../script/monorepo/changelog $PWD",
50
+ "bump": "node ../../script/monorepo/version-simple $PWD",
51
+ "release": "node ../../script/monorepo/release $PWD"
52
+ }
51
53
  }
@@ -1,16 +0,0 @@
1
- module.exports = {
2
- plugins: ['@tencent/eslint-plugin-pmd', 'vue'],
3
- parser: require.resolve('vue-eslint-parser'),
4
- parserOptions: {
5
- ecmaVersion: 2020,
6
- sourceType: 'module',
7
- },
8
- env: {
9
- browser: true,
10
- es6: true,
11
- },
12
- rules: {
13
- '@tencent/pmd/valid-vue-comp-import': 2,
14
- '@tencent/pmd/no-plus-turn-number': 2,
15
- },
16
- };
@@ -1,5 +0,0 @@
1
- module.exports = {
2
- extends: require.resolve('./base'),
3
- rules: {
4
- },
5
- };
@@ -1,7 +0,0 @@
1
- module.exports = {
2
- extends: require.resolve('./base'),
3
- rules: {
4
- '@tencent/pmd/no-complex-key': 1,
5
- '@tencent/pmd/no-import-vant': 2,
6
- },
7
- };
package/lib/index.js DELETED
@@ -1,28 +0,0 @@
1
- /**
2
- * @fileoverview test
3
- * @author
4
- */
5
- 'use strict';
6
-
7
- // ------------------------------------------------------------------------------
8
- // Requirements
9
- // ------------------------------------------------------------------------------
10
-
11
- const requireIndex = require('requireindex');
12
-
13
- // ------------------------------------------------------------------------------
14
- // Plugin Definition
15
- // ------------------------------------------------------------------------------
16
-
17
-
18
- // import all rules in lib/rules
19
- module.exports = {
20
- rules: requireIndex(`${__dirname}/rules`),
21
- configs: {
22
- base: require('./configs/base'),
23
- essential: require('./configs/essential'),
24
- recommended: require('./configs/recommended'),
25
- },
26
- };
27
-
28
-
@@ -1,62 +0,0 @@
1
- module.exports = {
2
- meta: {
3
- type: 'problem',
4
- schema: [],
5
- docs: {
6
- description: 'vue模板中不要使用复杂的key',
7
- },
8
- messages: {
9
- error: 'Do not use complex key',
10
- funcError: 'Do not use function as key',
11
- stringError: 'Do not use string concatenation as key',
12
- tplError: 'Do not use template string as key',
13
- },
14
- },
15
-
16
- create(context) {
17
- const fileName = context.getFilename();
18
- if (!fileName.endsWith('.vue')) {
19
- return {};
20
- }
21
- if (!context.parserServices?.defineTemplateBodyVisitor) {
22
- return {
23
- };
24
- }
25
-
26
- return context.parserServices.defineTemplateBodyVisitor({
27
- VAttribute(node) {
28
- if (!node.key
29
- || node.key.type !== 'VDirectiveKey'
30
- || node.key?.argument?.type !== 'VIdentifier'
31
- || node.key?.argument?.name !== 'key'
32
- ) {
33
- return;
34
- }
35
-
36
- if (node?.value?.type === 'VExpressionContainer') {
37
- if (node.value.expression?.type === 'CallExpression') {
38
- // :key="getHoldKey(item)"
39
- context.report({
40
- node,
41
- messageId: 'funcError',
42
- });
43
- } else if (node.value.expression?.type === 'BinaryExpression') {
44
- // :key="index + 'hold'"
45
- context.report({
46
- node,
47
- messageId: 'stringError',
48
- });
49
- } else if (node.value.expression?.type === 'TemplateLiteral') {
50
- // :key="`${index}hold`"
51
- context.report({
52
- node,
53
- messageId: 'tplError',
54
- });
55
- }
56
-
57
- // 合法的是MemberExpression,比如item.key
58
- }
59
- },
60
- });
61
- },
62
- };
@@ -1,70 +0,0 @@
1
- module.exports = {
2
- meta: {
3
- type: 'problem',
4
- schema: [],
5
- docs: {
6
- description: '不要直接引用vant',
7
- },
8
- fixable: 'code',
9
- messages: {
10
- error: 'Do not import vant',
11
- },
12
- },
13
-
14
- create(context) {
15
- const fileName = context.getFilename();
16
- if (!fileName.endsWith('.vue')) {
17
- return {};
18
- }
19
- return {
20
- ImportDeclaration: (node) => {
21
- if (node.source.value === 'vant') {
22
- context.report({
23
- node,
24
- messageId: 'error',
25
- });
26
- }
27
- },
28
- };
29
- // if (!context.parserServices?.defineTemplateBodyVisitor) {
30
- // return {
31
- // };
32
- // }
33
-
34
- // return context.parserServices.defineTemplateBodyVisitor({
35
- // VAttribute(node) {
36
- // if (!node.key
37
- // || node.key.type !== 'VDirectiveKey'
38
- // || node.key?.argument?.type !== 'VIdentifier'
39
- // || node.key?.argument?.name !== 'key'
40
- // ) {
41
- // return;
42
- // }
43
-
44
- // if (node?.value?.type === 'VExpressionContainer') {
45
- // if (node.value.expression?.type === 'CallExpression') {
46
- // // :key="getHoldKey(item)"
47
- // context.report({
48
- // node,
49
- // messageId: 'funcError',
50
- // });
51
- // } else if (node.value.expression?.type === 'BinaryExpression') {
52
- // // :key="index + 'hold'"
53
- // context.report({
54
- // node,
55
- // messageId: 'stringError',
56
- // });
57
- // } else if (node.value.expression?.type === 'TemplateLiteral') {
58
- // // :key="`${index}hold`"
59
- // context.report({
60
- // node,
61
- // messageId: 'tplError',
62
- // });
63
- // }
64
-
65
- // // 合法的是MemberExpression,比如item.key
66
- // }
67
- // },
68
- // });
69
- },
70
- };
@@ -1,47 +0,0 @@
1
- module.exports = {
2
- meta: {
3
- type: 'problem',
4
- schema: [],
5
- docs: {
6
- description: 'vue模板中不能使用+号转换字符串',
7
- },
8
- fixable: 'code',
9
- messages: {
10
- error: 'Do not use plus symbol to transfer string',
11
- },
12
- },
13
-
14
- create(context) {
15
- const fileName = context.getFilename();
16
- if (!fileName.endsWith('.vue')) {
17
- return {};
18
- }
19
- if (!context.parserServices?.defineTemplateBodyVisitor) {
20
- return {
21
- };
22
- }
23
-
24
- return context.parserServices.defineTemplateBodyVisitor({
25
- VAttribute(node) {
26
- if (node.value && node.value.type === 'VExpressionContainer' && node.value.expression) {
27
- const { operator } = node.value.expression;
28
- const { argument } = node.value.expression;
29
-
30
- // console.log('operator',operator)
31
- // console.log('argument',argument && argument.type)
32
-
33
- if (operator === '+' && argument && argument.type === 'Identifier') {
34
- const { name } = node.value.expression.argument;
35
- context.report({
36
- node,
37
- messageId: 'error',
38
- fix(fixer) {
39
- return fixer.replaceTextRange(node.value.expression.range, `parseInt(${name},10)`);
40
- },
41
- });
42
- }
43
- }
44
- },
45
- });
46
- },
47
- };
@@ -1,40 +0,0 @@
1
- /**
2
- * @fileoverview no use this.tip_uid
3
- * @author junshao
4
- */
5
- 'use strict';
6
-
7
- // ------------------------------------------------------------------------------
8
- // Rule Definition
9
- // ------------------------------------------------------------------------------
10
-
11
- /** @type {import('eslint').Rule.RuleModule} */
12
- module.exports = {
13
- meta: {
14
- type: 'problem',
15
- schema: [],
16
- docs: {
17
- description: '不能使用this.tip_uid',
18
- },
19
- fixable: null, // Or `code` or `whitespace`,
20
- messages: {
21
- noUseTipUidId: '不能使用this.tip_uid',
22
- },
23
- },
24
-
25
- create(context) {
26
- return {
27
- MemberExpression: (node) => {
28
- if (node.object.type === 'ThisExpression'
29
- && node.property.type === 'Identifier'
30
- && node.property.name === 'tip_uid') {
31
- context.report({
32
- node,
33
- messageId: 'noUseTipUidId',
34
- });
35
- }
36
- },
37
- // visitor functions for different types of nodes
38
- };
39
- },
40
- };
@@ -1,281 +0,0 @@
1
- const path = require('path');
2
- const fs = require('fs');
3
- const jsParser = require('@babel/eslint-parser');
4
-
5
- const ROOT_PATH = process.cwd();
6
-
7
- const VALID_FILES = ['js', 'ts', 'vue'];
8
-
9
- /**
10
- * 获取引入文件的真实位置,如果是目录,返回目录,如果是文件,返回带后缀的文件
11
- */
12
- function findCompDir(source = '', dirname = '') {
13
- let compFile;
14
- if (source.startsWith('.')) {
15
- compFile = path.resolve(dirname, source);
16
- } else if (source.startsWith('src')) {
17
- compFile = path.resolve(process.cwd(), source);
18
- }
19
-
20
- if (fs.existsSync(compFile)) {
21
- return compFile;
22
- }
23
-
24
- for (let i = 0; i < VALID_FILES.length; i++) {
25
- const postfix = VALID_FILES[i];
26
- const wholeFileName = `${compFile}.${postfix}`;
27
- if (fs.existsSync(wholeFileName)) {
28
- return wholeFileName;
29
- }
30
- }
31
- console.log('\x1B[31m%s\x1B[0m', '未找到引入文件');
32
- return compFile;
33
- }
34
-
35
- function getSourceAST(sourceFile) {
36
- const jsData = fs.readFileSync(sourceFile, {
37
- encoding: 'utf-8',
38
- });
39
-
40
- let scriptAST = undefined;
41
-
42
- const opts = {
43
- sourceType: 'module',
44
- requireConfigFile: false,
45
- babelOptions: {
46
- configFile: false,
47
- },
48
- };
49
-
50
- try {
51
- scriptAST = jsParser.parse(jsData, opts);
52
- delete scriptAST.tokens;
53
- } catch (e) {
54
- console.log('出错了:', e);
55
- }
56
- return scriptAST;
57
- }
58
-
59
-
60
- function getDefaultExportComp(ast) {
61
- if (!ast) return '';
62
-
63
-
64
- const namedDeclarationNodes = ast.body.filter(item => item.type === 'ExportNamedDeclaration');
65
-
66
- const namedObj = {};
67
- // console.log('namedDeclarationNodes',namedDeclarationNodes.length)
68
- for (let i = 0;i < namedDeclarationNodes.length;i++) {
69
- const node = namedDeclarationNodes[i];
70
- // console.log('node',node)
71
- if (!node.specifiers || !node.specifiers.length) {
72
- continue;
73
- }
74
- // console.log('i',node)
75
- const { value } = node.source;
76
- const { name } = node.specifiers[0].exported;
77
- namedObj[name] = value;
78
- }
79
-
80
- // console.log('namedObj', namedObj);
81
-
82
- if (namedObj.default) {
83
- return namedObj;
84
- }
85
-
86
- const nodes = ast.body.filter(item => item.type === 'ExportDefaultDeclaration') || [];
87
- if (nodes[0] && nodes[0].declaration.type === 'Identifier') {
88
- // 是一个变量,代表从上面导入的
89
- const { name } = nodes[0].declaration;
90
- const importAst = ast.body.filter(item => item.type === 'ImportDeclaration' && !!item.specifiers.find(it => it.local.name === name));
91
- // console.log('importAst', importAst)
92
- namedObj.default = importAst[0].source.value;
93
- }
94
-
95
- return namedObj;
96
- }
97
-
98
- function getRelativePath(originPath = '') {
99
- return originPath.replace(`${path.resolve(ROOT_PATH)}/`, '');
100
- }
101
-
102
- function getDefaultExportPathFromSouceFile(sourceFile) {
103
- const scriptAST = getSourceAST(sourceFile);
104
- // console.log('scriptAST', scriptAST)
105
-
106
- const defaultExportComp = getDefaultExportComp(scriptAST);
107
- // console.log('defaultExportComp',defaultExportComp)
108
- if (!defaultExportComp) return;
109
-
110
- const obj = {};
111
- const keys = Object.keys(defaultExportComp);
112
- for (let i = 0;i < keys.length;i++) {
113
- const name = keys[i];
114
- const value = defaultExportComp[name];
115
- const defaultFilePath = findCompDir(value, path.dirname(sourceFile));
116
- const relativePath = getRelativePath(defaultFilePath);
117
- obj[name] = relativePath;
118
- }
119
- // console.log('defaultFilePath',defaultFilePath)
120
-
121
- // console.log('relativePath',relativePath)
122
- return obj;
123
- }
124
-
125
-
126
- function handleError({
127
- specifiers,
128
- sourceFile,
129
- context,
130
- node: one,
131
- }) {
132
- if (!specifiers || !specifiers.length) return;
133
- const componentList = [];
134
- let statementString = '\n';
135
- const relativePath = getDefaultExportPathFromSouceFile(sourceFile);
136
-
137
- const isJSError = sourceFile.endsWith('.js');
138
-
139
- for (let i = 0;i < specifiers.length;i++) {
140
- const specifier = specifiers[i];
141
- const componentName = specifier.local.name;
142
- // console.log('componentName', componentName);
143
- componentList.push(componentName);
144
- if (relativePath[componentName]) {
145
- statementString += `import ${componentName} from '${relativePath[componentName]}';\n`;
146
- }
147
- }
148
-
149
- // console.log('relativePath', relativePath);
150
- context.report({
151
- node: one,
152
- messageId: isJSError ? 'jsError' : 'tsError',
153
- fix(fixer) {
154
- /**
155
- * 默认导入,比如:
156
- *
157
- * import BottomTipBarComp from 'xxx';
158
- *
159
- */
160
- const defaultCompStr = relativePath.default;
161
- if (defaultCompStr && specifiers.length === 1 && specifiers[0].type === 'ImportDefaultSpecifier') {
162
- return fixer.replaceTextRange(one.source.range, `'${defaultCompStr}'`);
163
- }
164
-
165
- /**
166
- * 具名导入,比如:
167
- * import { xx, yy } from 'xxx';
168
- */
169
- return [
170
- fixer.insertTextBeforeRange(one.range, statementString),
171
- fixer.removeRange(one.range),
172
- ];
173
- },
174
- });
175
- }
176
-
177
- module.exports = {
178
- meta: {
179
- type: 'problem',
180
- schema: [],
181
- docs: {
182
- description: '不能从js/ts文件中引入组件',
183
- },
184
- fixable: 'code',
185
- messages: {
186
- jsError: 'Do not import component from JS file',
187
- tsError: 'Do not import component from TS file',
188
- },
189
- },
190
-
191
- create(context) {
192
- // const sourceCode = context.getSourceCode();
193
- // const cwd = context.getCwd();
194
- const fileName = context.getFilename();
195
-
196
- // console.log('cwd', cwd)
197
- // console.log('fileName', fileName)
198
- const dirname = path.dirname(fileName);
199
- // console.log('dirname', dirname);
200
- if (!fileName.endsWith('.vue')) {
201
- return {};
202
- }
203
-
204
- return {
205
- Program: (node) => {
206
- const exportAst = node.body.find(item => item.type === 'ExportDefaultDeclaration');
207
- if (!exportAst || !exportAst.declaration) return;
208
-
209
- const properties = exportAst.declaration.properties || [];
210
- const componentsNode = properties.find(item => item.key && item.key.name === 'components');
211
-
212
- // console.log('componentsNode',componentsNode)
213
- if (!componentsNode || !componentsNode.value
214
- || !componentsNode.value.properties
215
- || !componentsNode.value.properties.length
216
- ) return;
217
- const components = componentsNode.value.properties.map(item => ((item.value && item.value.name) || ''));
218
-
219
- // console.log('components', components);
220
-
221
- if (!components || !components.length) return;
222
-
223
- const importAst = node.body.filter(item => item.type === 'ImportDeclaration');
224
- const realImport = importAst.filter(item => !!item.specifiers.find((it) => {
225
- const name = (it.imported && it.imported.name) || (it.local && it.local.name);
226
- return components.includes(name);
227
- }));
228
- // console.log('realImport',realImport, realImport.length)
229
-
230
- for (let i = 0;i < realImport.length;i++) {
231
- const one = realImport[i];
232
- const { specifiers } = one;
233
- const source = one.source.value;
234
-
235
- if (source.endsWith('.vue')) {
236
- continue;
237
- }
238
-
239
- if (source.endsWith('.js') || source.endsWith('.ts')) {
240
- const compFile = findCompDir(source, dirname);
241
-
242
- handleError({
243
- specifiers,
244
- sourceFile: compFile,
245
- node: one,
246
- context,
247
- });
248
- continue;
249
- }
250
-
251
- const compFile = findCompDir(source, dirname);
252
-
253
- if (fs.existsSync(compFile)) {
254
- const stat = fs.lstatSync(compFile);
255
- if (stat.isDirectory()) {
256
- const indexJs = path.resolve(compFile, 'index.js');
257
- const indexTs = path.resolve(compFile, 'index.ts');
258
- if (fs.existsSync(indexJs)) {
259
- handleError({
260
- specifiers,
261
- sourceFile: indexJs,
262
- node: one,
263
- context,
264
- });
265
- continue;
266
- }
267
- if (fs.existsSync(indexTs)) {
268
- handleError({
269
- specifiers,
270
- sourceFile: indexTs,
271
- node: one,
272
- context,
273
- });
274
- }
275
- }
276
- }
277
- }
278
- },
279
- };
280
- },
281
- };