@huangjunsen/eslint-plugin 1.0.0 → 1.0.2

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/README.md CHANGED
@@ -1,39 +1,39 @@
1
- # eslint-plugin-encode
2
-
3
- ## 安装
4
-
5
- 除了本包,你需要同时安装 [ESlint](https://eslint.org/)
6
-
7
- ```shell
8
- $ npm install eslint-plugin-encode eslint --save-dev
9
- ```
10
-
11
- ## 使用
12
-
13
- ### 引入插件
14
-
15
- ```js
16
- // .eslintrc.js
17
- module.exports = {
18
- plugin: ['eslint-config-encode'],
19
- rules: {
20
- 'eslint-plugin-encode/no-secret-info': 'error',
21
- },
22
- };
23
- ```
24
-
25
- ### 使用 presets
26
-
27
- ```js
28
- // .eslintrc.js
29
- module.exports = {
30
- extends: 'plugin:eslint-plugin-encode/recommended',
31
- };
32
- ```
33
-
34
- ## 支持的规则
35
-
36
- - [`no-broad-semantic-versioning`](https://encode-studio-fe.github.io/fe-spec/plugin/no-broad-semantic-versioning.html) 不要指定宽泛的版本范围
37
- - [`no-http-url`](https://encode-studio-fe.github.io/fe-spec/plugin/no-http-url.html) 使用 HTTPS 协议头的 URL,而不是 HTTP
38
- - [`no-js-in-ts-project`](https://encode-studio-fe.github.io/fe-spec/plugin/no-js-in-ts-project.html) 不要在 TS 项目中使用 JS
39
- - [`no-secret-info`](https://encode-studio-fe.github.io/fe-spec/plugin/no-secret-info.html) 不要在代码中直接设置 `password` `token` and `secret` 信息
1
+ # eslint-plugin-encode
2
+
3
+ ## 安装
4
+
5
+ 除了本包,你需要同时安装 [ESlint](https://eslint.org/)
6
+
7
+ ```shell
8
+ $ npm install eslint-plugin-encode eslint --save-dev
9
+ ```
10
+
11
+ ## 使用
12
+
13
+ ### 引入插件
14
+
15
+ ```js
16
+ // .eslintrc.js
17
+ module.exports = {
18
+ plugin: ['eslint-config-encode'],
19
+ rules: {
20
+ 'eslint-plugin-encode/no-secret-info': 'error',
21
+ },
22
+ };
23
+ ```
24
+
25
+ ### 使用 presets
26
+
27
+ ```js
28
+ // .eslintrc.js
29
+ module.exports = {
30
+ extends: 'plugin:eslint-plugin-encode/recommended',
31
+ };
32
+ ```
33
+
34
+ ## 支持的规则
35
+
36
+ - [`no-broad-semantic-versioning`](https://encode-studio-fe.github.io/fe-spec/plugin/no-broad-semantic-versioning.html) 不要指定宽泛的版本范围
37
+ - [`no-http-url`](https://encode-studio-fe.github.io/fe-spec/plugin/no-http-url.html) 使用 HTTPS 协议头的 URL,而不是 HTTP
38
+ - [`no-js-in-ts-project`](https://encode-studio-fe.github.io/fe-spec/plugin/no-js-in-ts-project.html) 不要在 TS 项目中使用 JS
39
+ - [`no-secret-info`](https://encode-studio-fe.github.io/fe-spec/plugin/no-secret-info.html) 不要在代码中直接设置 `password` `token` and `secret` 信息
@@ -0,0 +1,22 @@
1
+ import type { ESLint, Rule } from 'eslint';
2
+ export declare const rules: Record<string, Rule.RuleModule>;
3
+ declare const plugin: ESLint.Plugin;
4
+ export declare const configs: {
5
+ recommended: {
6
+ plugins: {
7
+ '@huangjunsen': ESLint.Plugin;
8
+ };
9
+ rules: {
10
+ '@huangjunsen/no-http-url': string;
11
+ '@huangjunsen/no-secret-info': string;
12
+ };
13
+ };
14
+ 'legacy-recommended': {
15
+ plugins: string[];
16
+ rules: {
17
+ '@huangjunsen/no-http-url': string;
18
+ '@huangjunsen/no-secret-info': string;
19
+ };
20
+ };
21
+ };
22
+ export default plugin;
package/dist/index.js ADDED
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configs = exports.rules = void 0;
4
+ const no_http_url_1 = require("./rules/no-http-url");
5
+ const no_secret_info_1 = require("./rules/no-secret-info");
6
+ const no_broad_semantic_versioning_1 = require("./rules/no-broad-semantic-versioning");
7
+ const no_js_in_ts_project_1 = require("./rules/no-js-in-ts-project");
8
+ // 版本号由构建时注入,避免与 package.json 脱节
9
+ const { version } = require('../package.json');
10
+ exports.rules = {
11
+ 'no-http-url': no_http_url_1.noHttpUrl,
12
+ 'no-secret-info': no_secret_info_1.noSecretInfo,
13
+ 'no-broad-semantic-versioning': no_broad_semantic_versioning_1.noBroadSemanticVersioning,
14
+ 'no-js-in-ts-project': no_js_in_ts_project_1.noJsInTsProject,
15
+ };
16
+ // 兼容 Flat Config 插件对象
17
+ const plugin = {
18
+ meta: {
19
+ name: '@huangjunsen/eslint-plugin',
20
+ version,
21
+ },
22
+ rules: exports.rules,
23
+ };
24
+ exports.configs = {
25
+ // Flat Config recommended 预设
26
+ recommended: {
27
+ plugins: {
28
+ '@huangjunsen': plugin,
29
+ },
30
+ rules: {
31
+ '@huangjunsen/no-http-url': 'warn',
32
+ '@huangjunsen/no-secret-info': 'error',
33
+ },
34
+ },
35
+ // Legacy Config 兼容预设
36
+ 'legacy-recommended': {
37
+ plugins: ['@huangjunsen'],
38
+ rules: {
39
+ '@huangjunsen/no-http-url': 'warn',
40
+ '@huangjunsen/no-secret-info': 'error',
41
+ },
42
+ },
43
+ };
44
+ plugin.configs = exports.configs;
45
+ exports.default = plugin;
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const noBroadSemanticVersioning: Rule.RuleModule;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.noBroadSemanticVersioning = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ exports.noBroadSemanticVersioning = {
9
+ meta: {
10
+ type: 'problem',
11
+ docs: {
12
+ description: 'Disallow broad semantic versioning in package.json',
13
+ category: 'Best Practices',
14
+ recommended: true,
15
+ },
16
+ schema: [],
17
+ messages: {
18
+ noBroadSemanticVersioning: 'The "{{dependencyName}}" is not recommended to use "{{versioning}}"',
19
+ },
20
+ },
21
+ create(context) {
22
+ const filename = typeof context.filename === 'string' ? context.filename : context.getFilename?.();
23
+ if (filename && path_1.default.basename(filename) !== 'package.json') {
24
+ return {};
25
+ }
26
+ return {
27
+ Property(node) {
28
+ if (node.key &&
29
+ node.key.value &&
30
+ (node.key.value === 'dependencies' || node.key.value === 'devDependencies') &&
31
+ node.value &&
32
+ node.value.properties) {
33
+ node.value.properties.forEach((property) => {
34
+ if (property.key && property.key.value && property.value && property.value.value) {
35
+ const dependencyName = property.key.value;
36
+ const dependencyVersion = String(property.value.value);
37
+ if (dependencyVersion.indexOf('*') > -1 ||
38
+ dependencyVersion.indexOf('x') > -1 ||
39
+ dependencyVersion.indexOf('>') > -1) {
40
+ context.report({
41
+ loc: property.loc,
42
+ messageId: 'noBroadSemanticVersioning',
43
+ data: {
44
+ dependencyName,
45
+ versioning: dependencyVersion,
46
+ },
47
+ });
48
+ }
49
+ }
50
+ });
51
+ }
52
+ },
53
+ };
54
+ },
55
+ };
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const noHttpUrl: Rule.RuleModule;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.noHttpUrl = void 0;
4
+ exports.noHttpUrl = {
5
+ meta: {
6
+ type: 'suggestion',
7
+ docs: {
8
+ description: 'Disallow http urls, recommend https',
9
+ category: 'Possible Errors',
10
+ recommended: true,
11
+ },
12
+ schema: [],
13
+ messages: {
14
+ noHttpUrl: 'Recommended "{{url}}" switch to HTTPS',
15
+ },
16
+ },
17
+ create(context) {
18
+ return {
19
+ Literal(node) {
20
+ if (node.value && typeof node.value === 'string' && node.value.startsWith('http:')) {
21
+ context.report({
22
+ node,
23
+ messageId: 'noHttpUrl',
24
+ data: {
25
+ url: node.value,
26
+ },
27
+ });
28
+ }
29
+ },
30
+ };
31
+ },
32
+ };
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const noJsInTsProject: Rule.RuleModule;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.noJsInTsProject = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const JS_REG = /\.jsx?$/;
9
+ const DEFAULT_WHITE_LIST = [
10
+ 'commitlint.config.js',
11
+ 'eslintrc.js',
12
+ 'prettierrc.js',
13
+ 'stylelintrc.js',
14
+ ];
15
+ exports.noJsInTsProject = {
16
+ meta: {
17
+ type: 'suggestion',
18
+ docs: {
19
+ description: 'Disallow JS files in TypeScript projects',
20
+ category: 'Best Practices',
21
+ recommended: true,
22
+ },
23
+ schema: [
24
+ {
25
+ type: 'object',
26
+ properties: {
27
+ whiteList: {
28
+ type: 'array',
29
+ items: { type: 'string' },
30
+ },
31
+ autoMerge: {
32
+ type: 'boolean',
33
+ },
34
+ },
35
+ additionalProperties: false,
36
+ },
37
+ ],
38
+ messages: {
39
+ noJSInTSProject: 'The "{{fileName}}" is not recommended in TS project',
40
+ },
41
+ },
42
+ create(context) {
43
+ const fileName = typeof context.filename === 'string' ? context.filename : context.getFilename?.();
44
+ if (!fileName)
45
+ return {};
46
+ const extName = path_1.default.extname(fileName);
47
+ const ruleOptions = context.options[0] || {};
48
+ let { whiteList = [], autoMerge = true } = ruleOptions;
49
+ if (whiteList.length === 0) {
50
+ whiteList = DEFAULT_WHITE_LIST;
51
+ }
52
+ else if (autoMerge) {
53
+ whiteList = Array.from(new Set([...DEFAULT_WHITE_LIST, ...whiteList]));
54
+ }
55
+ const whiteListReg = new RegExp(`(${whiteList.join('|')})$`);
56
+ if (!whiteListReg.test(fileName) && JS_REG.test(extName)) {
57
+ context.report({
58
+ loc: {
59
+ start: { line: 1, column: 0 },
60
+ end: { line: 1, column: 0 },
61
+ },
62
+ messageId: 'noJSInTSProject',
63
+ data: {
64
+ fileName,
65
+ },
66
+ });
67
+ }
68
+ return {};
69
+ },
70
+ };
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const noSecretInfo: Rule.RuleModule;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.noSecretInfo = void 0;
4
+ const DEFAULT_DANGEROUS_KEYS = ['secret', 'token', 'password'];
5
+ exports.noSecretInfo = {
6
+ meta: {
7
+ type: 'problem',
8
+ docs: {
9
+ description: 'Disallow secret keys in code',
10
+ category: 'Security',
11
+ recommended: true,
12
+ },
13
+ schema: [
14
+ {
15
+ type: 'object',
16
+ properties: {
17
+ dangerousKeys: {
18
+ type: 'array',
19
+ items: { type: 'string' },
20
+ },
21
+ autoMerge: {
22
+ type: 'boolean',
23
+ },
24
+ },
25
+ additionalProperties: false,
26
+ },
27
+ ],
28
+ messages: {
29
+ noSecretInfo: 'Detect that the "{{secret}}" might be a secret token, Please check!',
30
+ },
31
+ },
32
+ create(context) {
33
+ const ruleOptions = context.options[0] || {};
34
+ let { dangerousKeys = [], autoMerge = true } = ruleOptions;
35
+ if (dangerousKeys.length === 0) {
36
+ dangerousKeys = DEFAULT_DANGEROUS_KEYS;
37
+ }
38
+ else if (autoMerge) {
39
+ dangerousKeys = Array.from(new Set([...DEFAULT_DANGEROUS_KEYS, ...dangerousKeys]));
40
+ }
41
+ const reg = new RegExp(dangerousKeys.join('|'), 'i');
42
+ return {
43
+ Literal(node) {
44
+ if (node.value &&
45
+ node.parent &&
46
+ ((node.parent.type === 'VariableDeclarator' &&
47
+ node.parent.id &&
48
+ node.parent.id.name &&
49
+ reg.test(node.parent.id.name.toLocaleLowerCase())) ||
50
+ (node.parent.type === 'Property' &&
51
+ node.parent.key &&
52
+ node.parent.key.name &&
53
+ reg.test(node.parent.key.name.toLocaleLowerCase())))) {
54
+ context.report({
55
+ node,
56
+ messageId: 'noSecretInfo',
57
+ data: {
58
+ secret: String(node.value),
59
+ },
60
+ });
61
+ }
62
+ },
63
+ };
64
+ },
65
+ };
package/package.json CHANGED
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "name": "@huangjunsen/eslint-plugin",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "自定义eslint插件",
5
5
  "files": [
6
- "configs/",
7
- "rules/",
6
+ "dist/",
8
7
  "README.md"
9
8
  ],
10
9
  "keywords": [
@@ -12,7 +11,11 @@
12
11
  "eslint",
13
12
  "eslint-plugin"
14
13
  ],
15
- "main": "src/index.js",
14
+ "main": "dist/index.js",
15
+ "types": "dist/index.d.ts",
16
+ "peerDependencies": {
17
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0"
18
+ },
16
19
  "author": "Huangjunsen <951434130@qq.com>",
17
20
  "homepage": "https://github.com/Huang-junsen/js-encode-fe-spec#readme",
18
21
  "license": "ISC",
@@ -23,15 +26,15 @@
23
26
  "bugs": {
24
27
  "url": "https://github.com/Huang-junsen/js-encode-fe-spec/issues"
25
28
  },
26
- "dependencies": {
27
- "fs-extra": "^9.0.1",
28
- "require-all": "^3.0.0"
29
- },
29
+ "dependencies": {},
30
30
  "devDependencies": {
31
- "eslint": "^8.7.0",
32
- "jest": "^26.6.3"
31
+ "eslint": "^8.57.0",
32
+ "jest": "^30.5.1",
33
+ "typescript": "^5.0.4",
34
+ "@types/node": "^20.12.7"
33
35
  },
34
36
  "scripts": {
35
- "test": "jest"
37
+ "build": "rm -rf dist && tsc",
38
+ "test": "npm run build && jest"
36
39
  }
37
40
  }
@@ -1,7 +0,0 @@
1
- module.exports = {
2
- plugins: ['eslint-plugin-encode'],
3
- rules: {
4
- 'eslint-plugin-encode/no-http-url': 'warn',
5
- 'eslint-plugin-encode/no-secret-info': 'error',
6
- },
7
- };
@@ -1,59 +0,0 @@
1
- const path = require('path');
2
-
3
- const RULE_NAME = 'no-broad-semantic-versioning';
4
-
5
- module.exports = {
6
- name: RULE_NAME,
7
- meta: {
8
- type: 'problem',
9
- fixable: null,
10
- messages: {
11
- noBroadSemanticVersioning:
12
- 'The "{{dependencyName}}" is not recommended to use "{{versioning}}"',
13
- },
14
- },
15
-
16
- create(context) {
17
- if (path.basename(context.getFilename()) !== 'package.json') {
18
- return {};
19
- }
20
-
21
- const cwd = context.getCwd();
22
-
23
- return {
24
- Property: function handleRequires(node) {
25
- if (
26
- node.key &&
27
- node.key.value &&
28
- (node.key.value === 'dependencies' || node.key.value === 'devDependencies') &&
29
- node.value &&
30
- node.value.properties
31
- ) {
32
- node.value.properties.forEach((property) => {
33
- if (property.key && property.key.value) {
34
- const dependencyName = property.key.value;
35
- const dependencyVersion = property.value.value;
36
- if (
37
- // *
38
- dependencyVersion.indexOf('*') > -1 ||
39
- // x.x
40
- dependencyVersion.indexOf('x') > -1 ||
41
- // > x
42
- dependencyVersion.indexOf('>') > -1
43
- ) {
44
- context.report({
45
- loc: property.loc,
46
- messageId: 'noBroadSemanticVersioning',
47
- data: {
48
- dependencyName,
49
- versioning: dependencyVersion,
50
- },
51
- });
52
- }
53
- }
54
- });
55
- }
56
- },
57
- };
58
- },
59
- };
@@ -1,28 +0,0 @@
1
- const RULE_NAME = 'no-http-url';
2
-
3
- module.exports = {
4
- name: RULE_NAME,
5
- meta: {
6
- type: 'suggestion',
7
- fixable: null,
8
- messages: {
9
- noHttpUrl: 'Recommended "{{url}}" switch to HTTPS',
10
- },
11
- },
12
- create(context) {
13
- return {
14
- Literal: function handleRequires(node) {
15
- console.log(node.value);
16
- if (node.value && typeof node.value === 'string' && node.value.startsWith('http:')) {
17
- context.report({
18
- node,
19
- messageId: 'noHttpUrl',
20
- data: {
21
- url: node.value,
22
- },
23
- });
24
- }
25
- },
26
- };
27
- },
28
- };
@@ -1,58 +0,0 @@
1
- const path = require('path');
2
-
3
- const RULE_NAME = 'no-js-in-ts-project';
4
-
5
- const JS_REG = /\.jsx?$/;
6
-
7
- const DEFAULT_WHITE_LIST = [
8
- 'commitlint.config.js',
9
- 'eslintrc.js',
10
- 'prettierrc.js',
11
- 'stylelintrc.js',
12
- ];
13
-
14
- module.exports = {
15
- name: RULE_NAME,
16
- meta: {
17
- type: 'suggestion',
18
- fixable: null,
19
- messages: {
20
- noJSInTSProject: 'The "{{fileName}}" is not recommended in TS project',
21
- },
22
- },
23
-
24
- create(context) {
25
- const fileName = context.getFilename();
26
- const extName = path.extname(fileName);
27
- const ruleOptions = context.options[0] || {};
28
- let { whiteList = [], autoMerge = true } = ruleOptions;
29
- if (whiteList.length === 0) {
30
- whiteList = DEFAULT_WHITE_LIST;
31
- } else if (autoMerge) {
32
- whiteList = [...new Set([...DEFAULT_WHITE_LIST, ...whiteList])];
33
- }
34
- const whiteListReg = new RegExp(`(${whiteList.join('|')})$`);
35
-
36
- if (!whiteListReg.test(fileName) && JS_REG.test(extName)) {
37
- context.report({
38
- loc: {
39
- start: {
40
- line: 0,
41
- column: 0,
42
- },
43
- end: {
44
- line: 0,
45
- column: 0,
46
- },
47
- },
48
- messageId: 'noJSInTSProject',
49
- data: {
50
- fileName,
51
- },
52
- });
53
- }
54
-
55
- // Necessary
56
- return {};
57
- },
58
- };
@@ -1,49 +0,0 @@
1
- const RULE_NAME = 'no-secret-info';
2
-
3
- const DEFAULT_DANGEROUS_KEYS = ['secret', 'token', 'password'];
4
-
5
- module.exports = {
6
- meta: {
7
- type: 'problem',
8
- fixable: null,
9
- messages: {
10
- noSecretInfo: 'Detect that the "{{secret}}" might be a secret token, Please check!',
11
- },
12
- },
13
-
14
- create(context) {
15
- const ruleOptions = context.options[0] || {};
16
- let { dangerousKeys = [], autoMerge = true } = ruleOptions;
17
- if (dangerousKeys.length === 0) {
18
- dangerousKeys = DEFAULT_DANGEROUS_KEYS;
19
- } else if (autoMerge) {
20
- dangerousKeys = [...new Set(...DEFAULT_DANGEROUS_KEYS, ...dangerousKeys)];
21
- }
22
- const reg = new RegExp(dangerousKeys.join('|'));
23
-
24
- return {
25
- Literal: function handleRequires(node) {
26
- if (
27
- node.value &&
28
- node.parent &&
29
- ((node.parent.type === 'VariableDeclarator' &&
30
- node.parent.id &&
31
- node.parent.id.name &&
32
- reg.test(node.parent.id.name.toLocaleLowerCase())) ||
33
- (node.parent.type === 'Property' &&
34
- node.parent.key &&
35
- node.parent.key.name &&
36
- reg.test(node.parent.key.name.toLocaleLowerCase())))
37
- ) {
38
- context.report({
39
- node,
40
- messageId: 'noSecretInfo',
41
- data: {
42
- secret: node.value,
43
- },
44
- });
45
- }
46
- },
47
- };
48
- },
49
- };