eslint-plugin-esm 0.3.0 → 0.5.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/CHANGELOG.md +20 -0
- package/dist/common.d.ts +2 -2
- package/dist/common.d.ts.map +1 -1
- package/dist/common.js +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -5
- package/dist/rules/no-declaration-file-imports.d.ts +5 -0
- package/dist/rules/no-declaration-file-imports.d.ts.map +1 -0
- package/dist/rules/no-declaration-file-imports.js +11 -0
- package/dist/rules/no-directory-imports.js +1 -1
- package/dist/rules/no-dynamic-imports.js +1 -1
- package/dist/rules/no-empty-exports.js +1 -1
- package/dist/rules/no-git-ignored-imports.js +1 -1
- package/dist/rules/no-inexistent-relative-imports.d.ts +5 -0
- package/dist/rules/no-inexistent-relative-imports.d.ts.map +1 -0
- package/dist/rules/no-inexistent-relative-imports.js +64 -0
- package/dist/rules/no-phantom-dep-imports.js +1 -1
- package/dist/rules/no-relative-parent-imports.js +1 -1
- package/dist/rules/no-rename-exports.js +1 -1
- package/dist/rules/no-rename-imports.js +1 -1
- package/dist/rules/no-side-effect-imports.js +1 -1
- package/dist/rules/no-useless-path-segments.d.ts +5 -0
- package/dist/rules/no-useless-path-segments.d.ts.map +1 -0
- package/dist/rules/no-useless-path-segments.js +28 -0
- package/dist/rules/required-exports.js +1 -1
- package/doc/rules/{no-ts-file-imports.md → no-declaration-file-imports.md} +7 -7
- package/doc/rules/no-inexistent-relative-imports.md +28 -0
- package/doc/rules/no-phantom-dep-imports.md +1 -1
- package/doc/rules/{nearest-relative-path.md → no-useless-path-segments.md} +7 -1
- package/package.json +4 -6
- package/src/common.ts +5 -5
- package/src/index.ts +16 -14
- package/src/rules/{no-ts-file-imports.spec.ts → no-declaration-file-imports.spec.ts} +13 -10
- package/src/rules/no-declaration-file-imports.ts +12 -0
- package/src/rules/no-directory-imports.spec.ts +2 -2
- package/src/rules/no-directory-imports.ts +2 -2
- package/src/rules/no-dynamic-imports.spec.ts +2 -2
- package/src/rules/no-dynamic-imports.ts +1 -1
- package/src/rules/no-empty-exports.spec.ts +2 -2
- package/src/rules/no-empty-exports.ts +1 -1
- package/src/rules/no-git-ignored-imports.spec.ts +2 -2
- package/src/rules/no-git-ignored-imports.ts +2 -2
- package/src/rules/no-inexistent-relative-imports.spec.ts +27 -0
- package/src/rules/no-inexistent-relative-imports.ts +72 -0
- package/src/rules/no-phantom-dep-imports.spec.ts +3 -3
- package/src/rules/no-phantom-dep-imports.ts +1 -1
- package/src/rules/no-relative-parent-imports.spec.ts +2 -2
- package/src/rules/no-relative-parent-imports.ts +1 -1
- package/src/rules/no-rename-exports.spec.ts +2 -2
- package/src/rules/no-rename-exports.ts +1 -1
- package/src/rules/no-rename-imports.spec.ts +2 -2
- package/src/rules/no-rename-imports.ts +1 -1
- package/src/rules/no-side-effect-imports.spec.ts +2 -2
- package/src/rules/no-side-effect-imports.ts +1 -1
- package/src/rules/{nearest-relative-path.spec.ts → no-useless-path-segments.spec.ts} +11 -3
- package/src/rules/{nearest-relative-path.ts → no-useless-path-segments.ts} +6 -3
- package/src/rules/required-exports.spec.ts +2 -2
- package/src/rules/required-exports.ts +1 -1
- package/dist/rules/nearest-relative-path.d.ts +0 -5
- package/dist/rules/nearest-relative-path.d.ts.map +0 -1
- package/dist/rules/nearest-relative-path.js +0 -25
- package/dist/rules/no-ts-file-imports.d.ts +0 -5
- package/dist/rules/no-ts-file-imports.d.ts.map +0 -1
- package/dist/rules/no-ts-file-imports.js +0 -14
- package/src/rules/no-ts-file-imports.ts +0 -15
- package/src/test.spec.ts +0 -123
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!-- prettier-ignore-start -->
|
|
2
|
-
#
|
|
2
|
+
# no-useless-path-segments
|
|
3
3
|
|
|
4
4
|
The relative source path should be a nearest relative path.
|
|
5
5
|
|
|
@@ -27,6 +27,10 @@ import "./../foo" // filename: /a/b/c/d/e.js
|
|
|
27
27
|
import("./../foo") // filename: /a/b/c/d/e.js
|
|
28
28
|
export * from "./../foo" // filename: /a/b/c/d/e.js
|
|
29
29
|
export {a} from "./../foo" // filename: /a/b/c/d/e.js
|
|
30
|
+
import foo from "./" // filename: /a/b/c/d/e.js
|
|
31
|
+
import foo from '../' // filename: /a/b/c/d/e.js
|
|
32
|
+
import foo from '../../' // filename: /a/b/c/d/e.js
|
|
33
|
+
import foo from './..' // filename: /a/b/c/d/e.js
|
|
30
34
|
```
|
|
31
35
|
|
|
32
36
|
### Pass
|
|
@@ -44,5 +48,7 @@ export * from "./a" // filename: /a/b/c/d/e.js
|
|
|
44
48
|
export {a} from "a" // filename: /a/b/c/d/e.js
|
|
45
49
|
export {a} from "./a" // filename: /a/b/c/d/e.js
|
|
46
50
|
import foo from "." // filename: /a/b/c/d/e.js
|
|
51
|
+
import foo from '..' // filename: /a/b/c/d/e.js
|
|
52
|
+
import foo from '../..' // filename: /a/b/c/d/e.js
|
|
47
53
|
```
|
|
48
54
|
<!-- prettier-ignore-end -->
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-esm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "ESLint plugin for linting ESM (import/export syntax)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -28,11 +28,9 @@
|
|
|
28
28
|
"@types/eslint": "8.56.11",
|
|
29
29
|
"@types/estree": "1.0.6",
|
|
30
30
|
"@types/json-schema": "7.0.15",
|
|
31
|
-
"@types/node": "22.
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"outdent": "0.8.0",
|
|
35
|
-
"tsx": "4.19.2"
|
|
31
|
+
"@types/node": "22.10.5",
|
|
32
|
+
"tsx": "4.19.2",
|
|
33
|
+
"@fenge/dev-utils": "0.0.0"
|
|
36
34
|
},
|
|
37
35
|
"scripts": {
|
|
38
36
|
"build": "tsc",
|
package/src/common.ts
CHANGED
|
@@ -17,7 +17,7 @@ export function createRule({
|
|
|
17
17
|
schema,
|
|
18
18
|
fixable,
|
|
19
19
|
type = "suggestion",
|
|
20
|
-
create,
|
|
20
|
+
create: createFn,
|
|
21
21
|
}: {
|
|
22
22
|
name: string;
|
|
23
23
|
message: string;
|
|
@@ -39,7 +39,7 @@ export function createRule({
|
|
|
39
39
|
description: message,
|
|
40
40
|
},
|
|
41
41
|
},
|
|
42
|
-
create,
|
|
42
|
+
create: createFn,
|
|
43
43
|
};
|
|
44
44
|
return { name, rule };
|
|
45
45
|
}
|
|
@@ -61,10 +61,10 @@ export type ImportationNode =
|
|
|
61
61
|
* @param check the check logic
|
|
62
62
|
* @returns ESLint RuleListener
|
|
63
63
|
*/
|
|
64
|
-
export
|
|
64
|
+
export function create(
|
|
65
65
|
context: Rule.RuleContext,
|
|
66
66
|
check: (filename: string, source: string, node: ImportationNode) => boolean,
|
|
67
|
-
): Rule.RuleListener
|
|
67
|
+
): Rule.RuleListener {
|
|
68
68
|
const handle = (node: ImportationNode) => {
|
|
69
69
|
if (!node.source) return;
|
|
70
70
|
if (!("value" in node.source)) return;
|
|
@@ -78,7 +78,7 @@ export const create = (
|
|
|
78
78
|
ExportAllDeclaration: handle,
|
|
79
79
|
ExportNamedDeclaration: handle,
|
|
80
80
|
};
|
|
81
|
-
}
|
|
81
|
+
}
|
|
82
82
|
|
|
83
83
|
export function getSourceType(source: string) {
|
|
84
84
|
if (
|
package/src/index.ts
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { noDirectoryImports } from "./rules/no-directory-imports.
|
|
3
|
-
import { noDynamicImports } from "./rules/no-dynamic-imports.
|
|
4
|
-
import { noEmptyExports } from "./rules/no-empty-exports.
|
|
5
|
-
import { noGitIgnoredImports } from "./rules/no-git-ignored-imports.
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
1
|
+
import { noDeclarationFileImports } from "./rules/no-declaration-file-imports.ts";
|
|
2
|
+
import { noDirectoryImports } from "./rules/no-directory-imports.ts";
|
|
3
|
+
import { noDynamicImports } from "./rules/no-dynamic-imports.ts";
|
|
4
|
+
import { noEmptyExports } from "./rules/no-empty-exports.ts";
|
|
5
|
+
import { noGitIgnoredImports } from "./rules/no-git-ignored-imports.ts";
|
|
6
|
+
import { noInexistentRelativeImports } from "./rules/no-inexistent-relative-imports.ts";
|
|
7
|
+
import { noPhantomDepImports } from "./rules/no-phantom-dep-imports.ts";
|
|
8
|
+
import { noRelativeParentImports } from "./rules/no-relative-parent-imports.ts";
|
|
9
|
+
import { noRenameExports } from "./rules/no-rename-exports.ts";
|
|
10
|
+
import { noRenameImports } from "./rules/no-rename-imports.ts";
|
|
11
|
+
import { noSideEffectImports } from "./rules/no-side-effect-imports.ts";
|
|
12
|
+
import { noUselessPathSegments } from "./rules/no-useless-path-segments.ts";
|
|
13
|
+
import { requiredExports } from "./rules/required-exports.ts";
|
|
13
14
|
|
|
14
15
|
export const rules = {
|
|
15
|
-
[
|
|
16
|
+
[noDeclarationFileImports.name]: noDeclarationFileImports.rule,
|
|
16
17
|
[noDirectoryImports.name]: noDirectoryImports.rule,
|
|
17
18
|
[noDynamicImports.name]: noDynamicImports.rule,
|
|
18
19
|
[noEmptyExports.name]: noEmptyExports.rule,
|
|
19
20
|
[noGitIgnoredImports.name]: noGitIgnoredImports.rule,
|
|
21
|
+
[noInexistentRelativeImports.name]: noInexistentRelativeImports.rule,
|
|
20
22
|
[noPhantomDepImports.name]: noPhantomDepImports.rule,
|
|
21
23
|
[noRelativeParentImports.name]: noRelativeParentImports.rule,
|
|
22
24
|
[noRenameExports.name]: noRenameExports.rule,
|
|
23
25
|
[noRenameImports.name]: noRenameImports.rule,
|
|
24
26
|
[noSideEffectImports.name]: noSideEffectImports.rule,
|
|
25
|
-
[
|
|
27
|
+
[noUselessPathSegments.name]: noUselessPathSegments.rule,
|
|
26
28
|
[requiredExports.name]: requiredExports.rule,
|
|
27
29
|
};
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
import { test } from "
|
|
2
|
-
import {
|
|
1
|
+
import { test } from "@fenge/dev-utils";
|
|
2
|
+
import { noDeclarationFileImports } from "./no-declaration-file-imports.ts";
|
|
3
3
|
|
|
4
4
|
const invalid = [
|
|
5
|
-
"import foo from './foo.ts'",
|
|
6
|
-
"import foo from './foo.cts'",
|
|
7
|
-
"import foo from './foo.mts'",
|
|
8
|
-
"import foo from './foo.tsx'",
|
|
9
|
-
|
|
10
5
|
"import foo from 'foo.d.bar'",
|
|
11
6
|
"import foo from './foo.d.bar'",
|
|
12
7
|
"import foo from './foo/foo.d.bar'",
|
|
@@ -21,10 +16,18 @@ const invalid = [
|
|
|
21
16
|
"import foo from './foo.d.mjs'",
|
|
22
17
|
"import foo from './foo.d.jsx'",
|
|
23
18
|
|
|
24
|
-
"import foo from '/foo.ts'",
|
|
25
19
|
"import foo from '/foo.d.js'",
|
|
26
20
|
];
|
|
27
21
|
|
|
28
|
-
const valid = [
|
|
22
|
+
const valid = [
|
|
23
|
+
"import foo from 'foo'",
|
|
24
|
+
|
|
25
|
+
"import foo from './foo.ts'",
|
|
26
|
+
"import foo from './foo.cts'",
|
|
27
|
+
"import foo from './foo.mts'",
|
|
28
|
+
"import foo from './foo.tsx'",
|
|
29
|
+
|
|
30
|
+
"import foo from '/foo.ts'",
|
|
31
|
+
];
|
|
29
32
|
|
|
30
|
-
test({ valid, invalid, ...
|
|
33
|
+
test({ valid, invalid, ...noDeclarationFileImports });
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { create, createRule, getRuleName } from "../common.ts";
|
|
2
|
+
|
|
3
|
+
export const noDeclarationFileImports = createRule({
|
|
4
|
+
name: getRuleName(import.meta.url),
|
|
5
|
+
message: "Disallow importing from a declaration style file.",
|
|
6
|
+
create: (context) => create(context, check),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
function check(_filename: string, source: string) {
|
|
10
|
+
const file = source.split("/").at(-1);
|
|
11
|
+
return !file || file.includes(".d.");
|
|
12
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import process from "node:process";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
import { test } from "
|
|
4
|
-
import { noDirectoryImports } from "./no-directory-imports.
|
|
3
|
+
import { test } from "@fenge/dev-utils";
|
|
4
|
+
import { noDirectoryImports } from "./no-directory-imports.ts";
|
|
5
5
|
|
|
6
6
|
const valid = [
|
|
7
7
|
"import foo from 'foo'",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { create, createRule, getRuleName, getSourceType } from "../common.
|
|
4
|
-
import { memoize } from "../utils.
|
|
3
|
+
import { create, createRule, getRuleName, getSourceType } from "../common.ts";
|
|
4
|
+
import { memoize } from "../utils.ts";
|
|
5
5
|
|
|
6
6
|
export const noDirectoryImports = createRule({
|
|
7
7
|
name: getRuleName(import.meta.url),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Node } from "estree";
|
|
2
|
-
import { createRule, DEFAULT_MESSAGE_ID, getRuleName } from "../common.
|
|
2
|
+
import { createRule, DEFAULT_MESSAGE_ID, getRuleName } from "../common.ts";
|
|
3
3
|
|
|
4
4
|
export const noDynamicImports = createRule({
|
|
5
5
|
name: getRuleName(import.meta.url),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Node } from "estree";
|
|
2
|
-
import { createRule, DEFAULT_MESSAGE_ID, getRuleName } from "../common.
|
|
2
|
+
import { createRule, DEFAULT_MESSAGE_ID, getRuleName } from "../common.ts";
|
|
3
3
|
|
|
4
4
|
export const noEmptyExports = createRule({
|
|
5
5
|
name: getRuleName(import.meta.url),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import process from "node:process";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
import { test } from "
|
|
4
|
-
import { noGitIgnoredImports } from "./no-git-ignored-imports.
|
|
3
|
+
import { test } from "@fenge/dev-utils";
|
|
4
|
+
import { noGitIgnoredImports } from "./no-git-ignored-imports.ts";
|
|
5
5
|
|
|
6
6
|
const valid = [
|
|
7
7
|
"import foo from 'foo'",
|
|
@@ -2,8 +2,8 @@ import childProcess from "node:child_process";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { isNativeError } from "node:util/types";
|
|
5
|
-
import { create, createRule, getRuleName, getSourceType } from "../common.
|
|
6
|
-
import { memoize } from "../utils.
|
|
5
|
+
import { create, createRule, getRuleName, getSourceType } from "../common.ts";
|
|
6
|
+
import { memoize } from "../utils.ts";
|
|
7
7
|
|
|
8
8
|
export const noGitIgnoredImports = createRule({
|
|
9
9
|
name: getRuleName(import.meta.url),
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { test } from "@fenge/dev-utils";
|
|
3
|
+
import { noInexistentRelativeImports } from "./no-inexistent-relative-imports.ts";
|
|
4
|
+
|
|
5
|
+
const filename = fileURLToPath(import.meta.url);
|
|
6
|
+
|
|
7
|
+
const valid = [
|
|
8
|
+
"import foo from 'foo'",
|
|
9
|
+
|
|
10
|
+
// with ext
|
|
11
|
+
"import foo from './no-inexistent-relative-imports.spec.ts'",
|
|
12
|
+
// without ext
|
|
13
|
+
"import foo from './no-inexistent-relative-imports.spec'",
|
|
14
|
+
"import foo from '../rules'",
|
|
15
|
+
"import foo from '.'",
|
|
16
|
+
"import foo from './'",
|
|
17
|
+
"import foo from '..'",
|
|
18
|
+
"import foo from '../'",
|
|
19
|
+
].map((code) => ({ code, filename }));
|
|
20
|
+
|
|
21
|
+
const invalid = [
|
|
22
|
+
"import foo from './no-inexistent-relative-imports.spec.js'",
|
|
23
|
+
"import foo from './inexistent-file'",
|
|
24
|
+
"import foo from '../inexistent-file'",
|
|
25
|
+
].map((code) => ({ code, filename }));
|
|
26
|
+
|
|
27
|
+
test({ valid, invalid, ...noInexistentRelativeImports });
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { create, createRule, getRuleName, getSourceType } from "../common.ts";
|
|
4
|
+
import { memoize } from "../utils.ts";
|
|
5
|
+
|
|
6
|
+
export const noInexistentRelativeImports = createRule({
|
|
7
|
+
name: getRuleName(import.meta.url),
|
|
8
|
+
message: "Disallow importing from a relative file which is inexistent.",
|
|
9
|
+
create: (context) => create(context, check),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
function check(filename: string, source: string) {
|
|
13
|
+
if (getSourceType(source) !== "local") {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
return !isExisting(path.resolve(path.dirname(filename), source));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const isExisting = memoize((filepath: string): boolean =>
|
|
20
|
+
endsWithExtension(filepath)
|
|
21
|
+
? isFile(filepath)
|
|
22
|
+
: isDirectory(filepath) ||
|
|
23
|
+
isFile(`${filepath}.js`) ||
|
|
24
|
+
isFile(`${filepath}.cjs`) ||
|
|
25
|
+
isFile(`${filepath}.mjs`) ||
|
|
26
|
+
isFile(`${filepath}.jsx`) ||
|
|
27
|
+
isFile(`${filepath}.ts`) ||
|
|
28
|
+
isFile(`${filepath}.cts`) ||
|
|
29
|
+
isFile(`${filepath}.mts`) ||
|
|
30
|
+
isFile(`${filepath}.tsx`) ||
|
|
31
|
+
isFile(`${filepath}.json`) ||
|
|
32
|
+
isFile(`${filepath}.node`),
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
function isFile(filepath: string) {
|
|
36
|
+
try {
|
|
37
|
+
return fs.statSync(filepath).isFile();
|
|
38
|
+
} catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isDirectory(filepath: string) {
|
|
44
|
+
try {
|
|
45
|
+
return fs.statSync(filepath).isDirectory();
|
|
46
|
+
} catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function endsWithExtension(filepath: string) {
|
|
52
|
+
const extensions = [
|
|
53
|
+
"js",
|
|
54
|
+
"cjs",
|
|
55
|
+
"mjs",
|
|
56
|
+
"jsx",
|
|
57
|
+
|
|
58
|
+
"ts",
|
|
59
|
+
"cts",
|
|
60
|
+
"mts",
|
|
61
|
+
"tsx",
|
|
62
|
+
|
|
63
|
+
"json",
|
|
64
|
+
"node",
|
|
65
|
+
|
|
66
|
+
"css",
|
|
67
|
+
"scss",
|
|
68
|
+
"sass",
|
|
69
|
+
"less",
|
|
70
|
+
];
|
|
71
|
+
return extensions.some((ext) => filepath.endsWith(`.${ext}`));
|
|
72
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { test } from "
|
|
2
|
-
import { noPhantomDepImports } from "./no-phantom-dep-imports.
|
|
1
|
+
import { test } from "@fenge/dev-utils";
|
|
2
|
+
import { noPhantomDepImports } from "./no-phantom-dep-imports.ts";
|
|
3
3
|
|
|
4
4
|
const valid = [
|
|
5
5
|
{ code: "import foo from '/foo'" },
|
|
@@ -10,7 +10,7 @@ const valid = [
|
|
|
10
10
|
{ code: "import type Foo from 'estree'" },
|
|
11
11
|
{ code: "import type {Foo} from 'eslint'" },
|
|
12
12
|
{
|
|
13
|
-
code: "import
|
|
13
|
+
code: "import foo from '@fenge/dev-utils'",
|
|
14
14
|
options: [{ allowDevDependencies: true }],
|
|
15
15
|
},
|
|
16
16
|
];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
|
-
import { create, createRule, getRuleName, getSourceType } from "../common.
|
|
4
|
+
import { create, createRule, getRuleName, getSourceType } from "../common.ts";
|
|
5
5
|
|
|
6
6
|
function isObject(value: unknown) {
|
|
7
7
|
return value !== null && typeof value === "object";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { test } from "
|
|
2
|
-
import { noRelativeParentImports } from "./no-relative-parent-imports.
|
|
1
|
+
import { test } from "@fenge/dev-utils";
|
|
2
|
+
import { noRelativeParentImports } from "./no-relative-parent-imports.ts";
|
|
3
3
|
|
|
4
4
|
const valid = [
|
|
5
5
|
"import foo from 'foo'",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { test } from "
|
|
2
|
-
import { noSideEffectImports } from "./no-side-effect-imports.
|
|
1
|
+
import { test } from "@fenge/dev-utils";
|
|
2
|
+
import { noSideEffectImports } from "./no-side-effect-imports.ts";
|
|
3
3
|
|
|
4
4
|
const valid = [
|
|
5
5
|
"import 'reflect-metadata'",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { test } from "
|
|
2
|
-
import {
|
|
1
|
+
import { test } from "@fenge/dev-utils";
|
|
2
|
+
import { noUselessPathSegments } from "./no-useless-path-segments.ts";
|
|
3
3
|
|
|
4
4
|
const valid = [
|
|
5
5
|
'import xxx from "../a"',
|
|
@@ -13,7 +13,10 @@ const valid = [
|
|
|
13
13
|
'export * from "./a"',
|
|
14
14
|
'export {a} from "a"',
|
|
15
15
|
'export {a} from "./a"',
|
|
16
|
+
|
|
16
17
|
'import foo from "."',
|
|
18
|
+
"import foo from '..'",
|
|
19
|
+
"import foo from '../..'",
|
|
17
20
|
].map((code) => ({ code, filename: "/a/b/c/d/e.js" }));
|
|
18
21
|
|
|
19
22
|
const invalid = [
|
|
@@ -39,6 +42,11 @@ const invalid = [
|
|
|
39
42
|
'import("./../foo")',
|
|
40
43
|
'export * from "./../foo"',
|
|
41
44
|
'export {a} from "./../foo"',
|
|
45
|
+
|
|
46
|
+
'import foo from "./"',
|
|
47
|
+
"import foo from '../'",
|
|
48
|
+
"import foo from '../../'",
|
|
49
|
+
"import foo from './..'",
|
|
42
50
|
].map((code) => ({ code, filename: "/a/b/c/d/e.js" }));
|
|
43
51
|
|
|
44
|
-
test({ valid, invalid, ...
|
|
52
|
+
test({ valid, invalid, ...noUselessPathSegments });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { create, createRule, getRuleName, getSourceType } from "../common.
|
|
2
|
+
import { create, createRule, getRuleName, getSourceType } from "../common.ts";
|
|
3
3
|
|
|
4
|
-
export const
|
|
4
|
+
export const noUselessPathSegments = createRule({
|
|
5
5
|
name: getRuleName(import.meta.url),
|
|
6
6
|
message: "The relative source path should be a nearest relative path.",
|
|
7
7
|
create: (context) => create(context, check),
|
|
@@ -15,13 +15,16 @@ function check(filename: string, source: string) {
|
|
|
15
15
|
) {
|
|
16
16
|
return false;
|
|
17
17
|
}
|
|
18
|
+
if (source.endsWith("/")) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
18
21
|
const currentPath = path.dirname(filename);
|
|
19
22
|
const absoluteSource = path.resolve(currentPath, source);
|
|
20
23
|
// compatible with windows
|
|
21
24
|
let resultPath = path
|
|
22
25
|
.relative(currentPath, absoluteSource)
|
|
23
26
|
.replaceAll("\\", "/");
|
|
24
|
-
if (!resultPath.startsWith("./") && !resultPath.startsWith("
|
|
27
|
+
if (!resultPath.startsWith("./") && !resultPath.startsWith("..")) {
|
|
25
28
|
resultPath = `./${resultPath}`;
|
|
26
29
|
}
|
|
27
30
|
return resultPath !== source;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nearest-relative-path.d.ts","sourceRoot":"","sources":["../../src/rules/nearest-relative-path.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,mBAAmB;;;CAI9B,CAAC"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { create, createRule, getRuleName, getSourceType } from "../common.js";
|
|
3
|
-
export const nearestRelativePath = createRule({
|
|
4
|
-
name: getRuleName(import.meta.url),
|
|
5
|
-
message: "The relative source path should be a nearest relative path.",
|
|
6
|
-
create: (context) => create(context, check),
|
|
7
|
-
});
|
|
8
|
-
function check(filename, source) {
|
|
9
|
-
if (getSourceType(source) !== "local" ||
|
|
10
|
-
source.startsWith("/") ||
|
|
11
|
-
source === ".") {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
const currentPath = path.dirname(filename);
|
|
15
|
-
const absoluteSource = path.resolve(currentPath, source);
|
|
16
|
-
// compatible with windows
|
|
17
|
-
let resultPath = path
|
|
18
|
-
.relative(currentPath, absoluteSource)
|
|
19
|
-
.replaceAll("\\", "/");
|
|
20
|
-
if (!resultPath.startsWith("./") && !resultPath.startsWith("../")) {
|
|
21
|
-
resultPath = `./${resultPath}`;
|
|
22
|
-
}
|
|
23
|
-
return resultPath !== source;
|
|
24
|
-
}
|
|
25
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmVhcmVzdC1yZWxhdGl2ZS1wYXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bGVzL25lYXJlc3QtcmVsYXRpdmUtcGF0aC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLElBQUksTUFBTSxXQUFXLENBQUM7QUFDN0IsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUU5RSxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxVQUFVLENBQUM7SUFDNUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztJQUNsQyxPQUFPLEVBQUUsNkRBQTZEO0lBQ3RFLE1BQU0sRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUM7Q0FDNUMsQ0FBQyxDQUFDO0FBRUgsU0FBUyxLQUFLLENBQUMsUUFBZ0IsRUFBRSxNQUFjO0lBQzdDLElBQ0UsYUFBYSxDQUFDLE1BQU0sQ0FBQyxLQUFLLE9BQU87UUFDakMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUM7UUFDdEIsTUFBTSxLQUFLLEdBQUcsRUFDZCxDQUFDO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBQ0QsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMzQyxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUN6RCwwQkFBMEI7SUFDMUIsSUFBSSxVQUFVLEdBQUcsSUFBSTtTQUNsQixRQUFRLENBQUMsV0FBVyxFQUFFLGNBQWMsQ0FBQztTQUNyQyxVQUFVLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3pCLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ2xFLFVBQVUsR0FBRyxLQUFLLFVBQVUsRUFBRSxDQUFDO0lBQ2pDLENBQUM7SUFDRCxPQUFPLFVBQVUsS0FBSyxNQUFNLENBQUM7QUFDL0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IGNyZWF0ZSwgY3JlYXRlUnVsZSwgZ2V0UnVsZU5hbWUsIGdldFNvdXJjZVR5cGUgfSBmcm9tIFwiLi4vY29tbW9uLmpzXCI7XG5cbmV4cG9ydCBjb25zdCBuZWFyZXN0UmVsYXRpdmVQYXRoID0gY3JlYXRlUnVsZSh7XG4gIG5hbWU6IGdldFJ1bGVOYW1lKGltcG9ydC5tZXRhLnVybCksXG4gIG1lc3NhZ2U6IFwiVGhlIHJlbGF0aXZlIHNvdXJjZSBwYXRoIHNob3VsZCBiZSBhIG5lYXJlc3QgcmVsYXRpdmUgcGF0aC5cIixcbiAgY3JlYXRlOiAoY29udGV4dCkgPT4gY3JlYXRlKGNvbnRleHQsIGNoZWNrKSxcbn0pO1xuXG5mdW5jdGlvbiBjaGVjayhmaWxlbmFtZTogc3RyaW5nLCBzb3VyY2U6IHN0cmluZykge1xuICBpZiAoXG4gICAgZ2V0U291cmNlVHlwZShzb3VyY2UpICE9PSBcImxvY2FsXCIgfHxcbiAgICBzb3VyY2Uuc3RhcnRzV2l0aChcIi9cIikgfHxcbiAgICBzb3VyY2UgPT09IFwiLlwiXG4gICkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBjb25zdCBjdXJyZW50UGF0aCA9IHBhdGguZGlybmFtZShmaWxlbmFtZSk7XG4gIGNvbnN0IGFic29sdXRlU291cmNlID0gcGF0aC5yZXNvbHZlKGN1cnJlbnRQYXRoLCBzb3VyY2UpO1xuICAvLyBjb21wYXRpYmxlIHdpdGggd2luZG93c1xuICBsZXQgcmVzdWx0UGF0aCA9IHBhdGhcbiAgICAucmVsYXRpdmUoY3VycmVudFBhdGgsIGFic29sdXRlU291cmNlKVxuICAgIC5yZXBsYWNlQWxsKFwiXFxcXFwiLCBcIi9cIik7XG4gIGlmICghcmVzdWx0UGF0aC5zdGFydHNXaXRoKFwiLi9cIikgJiYgIXJlc3VsdFBhdGguc3RhcnRzV2l0aChcIi4uL1wiKSkge1xuICAgIHJlc3VsdFBhdGggPSBgLi8ke3Jlc3VsdFBhdGh9YDtcbiAgfVxuICByZXR1cm4gcmVzdWx0UGF0aCAhPT0gc291cmNlO1xufVxuIl19
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"no-ts-file-imports.d.ts","sourceRoot":"","sources":["../../src/rules/no-ts-file-imports.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe;;;CAI1B,CAAC"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { create, createRule, getRuleName } from "../common.js";
|
|
2
|
-
export const noTsFileImports = createRule({
|
|
3
|
-
name: getRuleName(import.meta.url),
|
|
4
|
-
message: "Disallow importing from a declaration style file or a ts file",
|
|
5
|
-
create: (context) => create(context, check),
|
|
6
|
-
});
|
|
7
|
-
function check(_filename, source) {
|
|
8
|
-
const file = source.split("/").at(-1);
|
|
9
|
-
if (!file || file.includes(".d.")) {
|
|
10
|
-
return true;
|
|
11
|
-
}
|
|
12
|
-
return [".ts", ".cts", ".mts", ".tsx"].some((ext) => file.endsWith(ext));
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm8tdHMtZmlsZS1pbXBvcnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bGVzL25vLXRzLWZpbGUtaW1wb3J0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFL0QsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLFVBQVUsQ0FBQztJQUN4QyxJQUFJLEVBQUUsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO0lBQ2xDLE9BQU8sRUFBRSwrREFBK0Q7SUFDeEUsTUFBTSxFQUFFLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQztDQUM1QyxDQUFDLENBQUM7QUFFSCxTQUFTLEtBQUssQ0FBQyxTQUFpQixFQUFFLE1BQWM7SUFDOUMsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0QyxJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNsQyxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFDRCxPQUFPLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFDM0UsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0ZSwgY3JlYXRlUnVsZSwgZ2V0UnVsZU5hbWUgfSBmcm9tIFwiLi4vY29tbW9uLmpzXCI7XG5cbmV4cG9ydCBjb25zdCBub1RzRmlsZUltcG9ydHMgPSBjcmVhdGVSdWxlKHtcbiAgbmFtZTogZ2V0UnVsZU5hbWUoaW1wb3J0Lm1ldGEudXJsKSxcbiAgbWVzc2FnZTogXCJEaXNhbGxvdyBpbXBvcnRpbmcgZnJvbSBhIGRlY2xhcmF0aW9uIHN0eWxlIGZpbGUgb3IgYSB0cyBmaWxlXCIsXG4gIGNyZWF0ZTogKGNvbnRleHQpID0+IGNyZWF0ZShjb250ZXh0LCBjaGVjayksXG59KTtcblxuZnVuY3Rpb24gY2hlY2soX2ZpbGVuYW1lOiBzdHJpbmcsIHNvdXJjZTogc3RyaW5nKSB7XG4gIGNvbnN0IGZpbGUgPSBzb3VyY2Uuc3BsaXQoXCIvXCIpLmF0KC0xKTtcbiAgaWYgKCFmaWxlIHx8IGZpbGUuaW5jbHVkZXMoXCIuZC5cIikpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gW1wiLnRzXCIsIFwiLmN0c1wiLCBcIi5tdHNcIiwgXCIudHN4XCJdLnNvbWUoKGV4dCkgPT4gZmlsZS5lbmRzV2l0aChleHQpKTtcbn1cbiJdfQ==
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { create, createRule, getRuleName } from "../common.js";
|
|
2
|
-
|
|
3
|
-
export const noTsFileImports = createRule({
|
|
4
|
-
name: getRuleName(import.meta.url),
|
|
5
|
-
message: "Disallow importing from a declaration style file or a ts file",
|
|
6
|
-
create: (context) => create(context, check),
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
function check(_filename: string, source: string) {
|
|
10
|
-
const file = source.split("/").at(-1);
|
|
11
|
-
if (!file || file.includes(".d.")) {
|
|
12
|
-
return true;
|
|
13
|
-
}
|
|
14
|
-
return [".ts", ".cts", ".mts", ".tsx"].some((ext) => file.endsWith(ext));
|
|
15
|
-
}
|