eslint-plugin-esm 0.8.1 → 0.8.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.
Files changed (73) hide show
  1. package/dist/common.d.ts +8 -3
  2. package/dist/common.d.ts.map +1 -1
  3. package/dist/common.js +1 -1
  4. package/dist/index.d.ts +4 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +5 -1
  7. package/dist/rules/no-circular-imports.d.ts +8 -0
  8. package/dist/rules/no-circular-imports.d.ts.map +1 -0
  9. package/dist/rules/no-circular-imports.js +56 -0
  10. package/dist/rules/no-dynamic-imports.d.ts +2 -1
  11. package/dist/rules/no-dynamic-imports.d.ts.map +1 -1
  12. package/dist/rules/no-dynamic-imports.js +1 -1
  13. package/dist/rules/no-empty-exports.d.ts +2 -1
  14. package/dist/rules/no-empty-exports.d.ts.map +1 -1
  15. package/dist/rules/no-empty-exports.js +1 -1
  16. package/dist/rules/no-query-suffixes.d.ts +5 -0
  17. package/dist/rules/no-query-suffixes.d.ts.map +1 -0
  18. package/dist/rules/no-query-suffixes.js +10 -0
  19. package/dist/rules/no-side-effect-imports.d.ts.map +1 -1
  20. package/dist/rules/no-side-effect-imports.js +1 -1
  21. package/dist/rules/top-side-effect-imports.d.ts.map +1 -1
  22. package/dist/rules/top-side-effect-imports.js +1 -1
  23. package/dist/utils.d.ts +2 -0
  24. package/dist/utils.d.ts.map +1 -1
  25. package/dist/utils.js +1 -1
  26. package/package.json +5 -4
  27. package/CHANGELOG.md +0 -96
  28. package/doc/rules/existing-file-imports.md +0 -28
  29. package/doc/rules/no-declaration-file-imports.md +0 -35
  30. package/doc/rules/no-directory-imports.md +0 -30
  31. package/doc/rules/no-dynamic-imports.md +0 -30
  32. package/doc/rules/no-empty-exports.md +0 -29
  33. package/doc/rules/no-git-ignored-imports.md +0 -36
  34. package/doc/rules/no-phantom-dep-imports.md +0 -31
  35. package/doc/rules/no-relative-parent-imports.md +0 -33
  36. package/doc/rules/no-rename-exports.md +0 -29
  37. package/doc/rules/no-rename-imports.md +0 -28
  38. package/doc/rules/no-side-effect-imports.md +0 -30
  39. package/doc/rules/no-useless-path-segments.md +0 -54
  40. package/doc/rules/required-exports.md +0 -31
  41. package/doc/rules/top-side-effect-imports.md +0 -31
  42. package/src/common.ts +0 -97
  43. package/src/index.ts +0 -31
  44. package/src/rules/existing-file-imports.test.ts +0 -28
  45. package/src/rules/existing-file-imports.ts +0 -25
  46. package/src/rules/no-declaration-file-imports.test.ts +0 -33
  47. package/src/rules/no-declaration-file-imports.ts +0 -12
  48. package/src/rules/no-directory-imports.test.ts +0 -31
  49. package/src/rules/no-directory-imports.ts +0 -34
  50. package/src/rules/no-dynamic-imports.test.ts +0 -27
  51. package/src/rules/no-dynamic-imports.ts +0 -15
  52. package/src/rules/no-empty-exports.test.ts +0 -22
  53. package/src/rules/no-empty-exports.ts +0 -14
  54. package/src/rules/no-git-ignored-imports.test.ts +0 -40
  55. package/src/rules/no-git-ignored-imports.ts +0 -58
  56. package/src/rules/no-phantom-dep-imports.test.ts +0 -35
  57. package/src/rules/no-phantom-dep-imports.ts +0 -124
  58. package/src/rules/no-relative-parent-imports.test.ts +0 -28
  59. package/src/rules/no-relative-parent-imports.ts +0 -13
  60. package/src/rules/no-rename-exports.test.ts +0 -22
  61. package/src/rules/no-rename-exports.ts +0 -17
  62. package/src/rules/no-rename-imports.test.ts +0 -22
  63. package/src/rules/no-rename-imports.ts +0 -16
  64. package/src/rules/no-side-effect-imports.test.ts +0 -24
  65. package/src/rules/no-side-effect-imports.ts +0 -39
  66. package/src/rules/no-useless-path-segments.test.ts +0 -52
  67. package/src/rules/no-useless-path-segments.ts +0 -31
  68. package/src/rules/required-exports.test.ts +0 -24
  69. package/src/rules/required-exports.ts +0 -22
  70. package/src/rules/top-side-effect-imports.test.ts +0 -24
  71. package/src/rules/top-side-effect-imports.ts +0 -22
  72. package/src/utils.ts +0 -18
  73. package/tsconfig.json +0 -5
@@ -1,27 +0,0 @@
1
- import { test } from "@fenge/dev-utils";
2
- import { noDynamicImports } from "./no-dynamic-imports.ts";
3
-
4
- const valid = [
5
- "import('foo')",
6
- 'import("foo")',
7
- 'import("./foo")',
8
- 'await import("foo")',
9
- 'const foo = await import("foo")',
10
- ];
11
-
12
- const invalid = [
13
- // 'import()',
14
- // 'await import()',
15
- "import(false)",
16
- "import(123)",
17
- "await import(123)",
18
- "import(`foo`)",
19
- "import(foo)",
20
- "import({})",
21
- "import([])",
22
- "const foo = await import(foo)",
23
- // "import(foo, {})", // only ts support it, not ecmascript
24
- // 'import("foo", {})', // only ts support it, not ecmascript
25
- ];
26
-
27
- test({ valid, invalid, ...noDynamicImports });
@@ -1,15 +0,0 @@
1
- import type { Node } from "estree";
2
- import { createRule, DEFAULT_MESSAGE_ID, getRuleName } from "../common.ts";
3
-
4
- export const noDynamicImports = createRule({
5
- name: getRuleName(import.meta.url),
6
- message: "`import()` should be called with string literal.",
7
- create: (context) => ({
8
- "ImportExpression > :not(Literal)": (node: Node) => {
9
- context.report({ node, messageId: DEFAULT_MESSAGE_ID });
10
- },
11
- "ImportExpression > Literal[raw=/^[^'\"].*[^'\"]$/]": (node: Node) => {
12
- context.report({ node, messageId: DEFAULT_MESSAGE_ID });
13
- },
14
- }),
15
- });
@@ -1,22 +0,0 @@
1
- import { test } from "@fenge/dev-utils";
2
- import { noEmptyExports } from "./no-empty-exports.ts";
3
-
4
- const valid = [
5
- "var name = 123; export {name as age};",
6
- "const name = {}; export {name};",
7
- "export const name = {};",
8
- "export default {};",
9
- "var foo = 213; export {foo as default};",
10
- "export {default} from 'foo';",
11
- "export * as foo from 'foo';",
12
- ];
13
-
14
- const invalid = [
15
- "export {};",
16
- "console.log(123); export {};",
17
- "export default {}; export {};",
18
- "export {} from 'foo';",
19
- "export {} from './foo';",
20
- ];
21
-
22
- test({ valid, invalid, ...noEmptyExports });
@@ -1,14 +0,0 @@
1
- import type { Node } from "estree";
2
- import { createRule, DEFAULT_MESSAGE_ID, getRuleName } from "../common.ts";
3
-
4
- export const noEmptyExports = createRule({
5
- name: getRuleName(import.meta.url),
6
- message: "Disallow `export {}`.",
7
- create: (context) => ({
8
- "ExportNamedDeclaration[specifiers.length=0][declaration=null]": (
9
- node: Node,
10
- ) => {
11
- context.report({ node, messageId: DEFAULT_MESSAGE_ID });
12
- },
13
- }),
14
- });
@@ -1,40 +0,0 @@
1
- import process from "node:process";
2
- import { fileURLToPath } from "node:url";
3
- import { test } from "@fenge/dev-utils";
4
- import { noGitIgnoredImports } from "./no-git-ignored-imports.ts";
5
-
6
- const valid = [
7
- "import foo from 'foo'",
8
- "import 'foo'",
9
- "require('foo')",
10
- "import('foo')",
11
- "export * from 'foo'",
12
- "export {name} from 'foo'",
13
-
14
- "import foo from '.foo'",
15
- "import foo from '../../../../for-test'",
16
- ].map((code) => ({
17
- code,
18
- filename: fileURLToPath(import.meta.url),
19
- }));
20
-
21
- const invalid = [
22
- "import foo from './dist/foo'",
23
- "import './dist/foo'",
24
- "import('./dist/foo')",
25
- "export * from './dist/foo'",
26
- "export {name} from './dist/foo'",
27
-
28
- "import foo from '../dist/index.js'",
29
- "import foo from '../../node_modules/foo/bar.js'",
30
-
31
- "import foo from '/foo/tmp'",
32
- `import foo from '${process.cwd()}/tmp'`,
33
- "import foo from '../../test/for-test'",
34
- "import foo from '../../../../../for-test'",
35
- ].map((code) => ({
36
- code,
37
- filename: fileURLToPath(import.meta.url),
38
- }));
39
-
40
- test({ valid, invalid, ...noGitIgnoredImports });
@@ -1,58 +0,0 @@
1
- import childProcess from "node:child_process";
2
- import path from "node:path";
3
- import process from "node:process";
4
- import { isNativeError } from "node:util/types";
5
- import { create, createRule, getRuleName, getSourceType } from "../common.ts";
6
- import { memoize } from "../utils.ts";
7
-
8
- export const noGitIgnoredImports = createRule({
9
- name: getRuleName(import.meta.url),
10
- message: "Disallow to import module from a git-ignored path.",
11
- create: (context) => create(context, checkIgnored),
12
- });
13
-
14
- function checkIgnored(filename: string, source: string) {
15
- // from node_modules
16
- if (getSourceType(source) !== "local") {
17
- return false;
18
- }
19
- // out side of project root
20
- if (source.startsWith("/") && !source.startsWith(process.cwd())) {
21
- return true;
22
- }
23
- // This file of absolutePath may be a symbolic link
24
- const absolutePath = path.resolve(path.dirname(filename), source);
25
- if (!absolutePath.startsWith("/")) {
26
- throw new Error(
27
- `ESLint plugin internal error. Absolute path incorrect: ${absolutePath}.`,
28
- );
29
- }
30
- return isIgnored(absolutePath);
31
- }
32
-
33
- const isIgnored = memoize((filePath: string) => {
34
- try {
35
- return (
36
- childProcess
37
- // Adding `stdio: 'pipe'` to depress unexpected error messages in console.
38
- // For example, `git check-ignore /absolute/path/to/file` (even wrapped with try-catch) will print something unnecessary.
39
- .execSync(`git check-ignore ${filePath}`, {
40
- encoding: "utf8",
41
- stdio: "pipe",
42
- })
43
- .trim() === filePath
44
- );
45
- } catch (e) {
46
- if (
47
- isNativeError(e) &&
48
- "stdout" in e &&
49
- e.stdout === "" &&
50
- "stderr" in e &&
51
- e.stderr === ""
52
- ) {
53
- return false;
54
- }
55
- // We cannot throw an error here. So we have to return true to report the filePath is bad.
56
- return true;
57
- }
58
- });
@@ -1,35 +0,0 @@
1
- import { test } from "@fenge/dev-utils";
2
- import { noPhantomDepImports } from "./no-phantom-dep-imports.ts";
3
-
4
- const valid = [
5
- { code: "import foo from '/foo'" },
6
- { code: "import foo from './foo'" },
7
- { code: "import foo from '../foo'" },
8
- { code: "import foo from 'node:foo'" },
9
-
10
- { code: "import type Foo from 'estree'" },
11
- { code: "import type {Foo} from 'eslint'" },
12
- {
13
- code: "import foo from '@fenge/dev-utils'",
14
- options: [{ allowDevDependencies: true }],
15
- },
16
- ];
17
-
18
- const invalid = [
19
- {
20
- code: "import type foo from 'foo'",
21
- options: [{ allowDevDependencies: true }],
22
- },
23
- {
24
- code: "import type foo from 'foo'",
25
- options: [{ allowDevDependencies: false }],
26
- },
27
- { code: "import {type Foo} from 'foo'" },
28
- { code: "import foo from 'foo'" },
29
-
30
- { code: "import {type Foo} from 'eslint'" },
31
- { code: "import {Foo} from 'eslint'" },
32
- { code: "import eslint from 'eslint'" },
33
- ];
34
-
35
- test({ valid, invalid, ...noPhantomDepImports });
@@ -1,124 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import process from "node:process";
4
- import { create, createRule, getRuleName, getSourceType } from "../common.ts";
5
-
6
- function isObject(value: unknown) {
7
- return value !== null && typeof value === "object";
8
- }
9
-
10
- function isFile(filePath: string) {
11
- try {
12
- return fs.statSync(filePath).isFile();
13
- } catch {
14
- return false;
15
- }
16
- }
17
-
18
- const cache = new Map<string, { path: string; content: object } | undefined>(); // key is dir, value is package.json
19
- function getPkgJson(
20
- dir: string,
21
- ): { path: string; content: object } | undefined {
22
- if (cache.has(dir)) {
23
- return cache.get(dir);
24
- }
25
- const pkgJsonPath = path.join(dir, "package.json");
26
- if (isFile(pkgJsonPath)) {
27
- const content: unknown = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
28
- const result = isObject(content)
29
- ? { path: pkgJsonPath, content }
30
- : undefined;
31
- cache.set(dir, result);
32
- return result;
33
- }
34
-
35
- // if it is a directory
36
- if (dir === process.cwd() || dir === "/") {
37
- // stop here
38
- cache.set(dir, undefined);
39
- return undefined;
40
- }
41
-
42
- return getPkgJson(path.join(dir, ".."));
43
- }
44
-
45
- export const noPhantomDepImports = createRule({
46
- name: getRuleName(import.meta.url),
47
- message:
48
- "Disallow importing from a module which the nearest `package.json` doesn't include it.",
49
- schema: [
50
- {
51
- type: "object",
52
- properties: {
53
- allowDevDependencies: { type: "boolean" },
54
- },
55
- additionalProperties: false,
56
- },
57
- ],
58
- create: (context) =>
59
- create(context, (filename, source, node) => {
60
- const option = context.options[0];
61
- // default false
62
- const allowDevDependencies: boolean =
63
- (typeof option === "object" &&
64
- option &&
65
- "allowDevDependencies" in option &&
66
- typeof option.allowDevDependencies === "boolean" &&
67
- option.allowDevDependencies) ??
68
- false;
69
-
70
- // ignore `import {foo} from './'`
71
- // check `import {foo} from 'node:foo'` and `import {foo} from 'foo'`
72
- if (getSourceType(source) === "local") {
73
- return false;
74
- }
75
- const pkgJson = getPkgJson(path.dirname(filename));
76
- // cannot find package.json file
77
- if (!pkgJson) {
78
- return true;
79
- }
80
- const dep =
81
- "dependencies" in pkgJson.content &&
82
- isObject(pkgJson.content.dependencies)
83
- ? pkgJson.content.dependencies
84
- : {};
85
- const peerDep =
86
- "peerDependencies" in pkgJson.content &&
87
- isObject(pkgJson.content.peerDependencies)
88
- ? pkgJson.content.peerDependencies
89
- : {};
90
- const devDep =
91
- "devDependencies" in pkgJson.content &&
92
- isObject(pkgJson.content.devDependencies)
93
- ? pkgJson.content.devDependencies
94
- : {};
95
-
96
- // TODO: Optimize the error message which is reported on `import foo from 'node:foo'`
97
- // 1. check `import foo from 'node:foo'`
98
- if (source.startsWith("node:")) {
99
- return !("@types/node" in devDep || "@types/node" in dep);
100
- }
101
-
102
- // 2. check `import foo from 'foo'`
103
- const moduleName = source
104
- .split("/")
105
- .slice(0, source.startsWith("@") ? 2 : 1)
106
- .join("/");
107
-
108
- const isInDep = moduleName in dep || moduleName in peerDep;
109
- const isInDev = moduleName in devDep;
110
- if ("importKind" in node && node.importKind === "type") {
111
- const typeDepName = moduleName.startsWith("@")
112
- ? `@types/${moduleName.slice(1).replace("/", "__")}`
113
- : `@types/${moduleName}`;
114
- return !(
115
- isInDep ||
116
- isInDev ||
117
- typeDepName in dep ||
118
- typeDepName in devDep
119
- );
120
- } else {
121
- return allowDevDependencies ? !(isInDep || isInDev) : !isInDep;
122
- }
123
- }),
124
- });
@@ -1,28 +0,0 @@
1
- import { test } from "@fenge/dev-utils";
2
- import { noRelativeParentImports } from "./no-relative-parent-imports.ts";
3
-
4
- const valid = [
5
- "import foo from 'foo'",
6
- "import 'foo'",
7
- "require('foo')",
8
- "import('foo')",
9
- "export * from 'foo'",
10
- "export {name} from 'foo'",
11
-
12
- "import foo from '.foo'",
13
- "import foo from './foo'",
14
- "import foo from '../foo'",
15
- "import foo from '../../foo'",
16
- ];
17
-
18
- const invalid = [
19
- "import foo from '../../../foo'",
20
- "import '../../../foo'",
21
- "import('../../../foo')",
22
- "export * from '../../../foo'",
23
- "export {name} from '../../../foo'",
24
-
25
- "import foo from '../../../../foo'",
26
- ];
27
-
28
- test({ valid, invalid, ...noRelativeParentImports });
@@ -1,13 +0,0 @@
1
- import { create, createRule, getRuleName } from "../common.ts";
2
-
3
- const depth = 3;
4
-
5
- export const noRelativeParentImports = createRule({
6
- name: getRuleName(import.meta.url),
7
- message: "Disallow importing module from a relative parent path too deeply.",
8
- create: (context) => create(context, checkDepth),
9
- });
10
-
11
- function checkDepth(_filename: string, source: string) {
12
- return new RegExp(`^(\\.\\./){${depth.toString()},}`).test(source);
13
- }
@@ -1,22 +0,0 @@
1
- import { test } from "@fenge/dev-utils";
2
- import { noRenameExports } from "./no-rename-exports.ts";
3
-
4
- const valid = [
5
- "let foo=1; export {foo}",
6
- "export let foo",
7
- "export const foo = bar",
8
- "export default foo",
9
- "export default {}",
10
- "export {}",
11
- ];
12
- const invalid = [
13
- "let foo=1; export {foo as bar}",
14
- "let foo=1; export {foo as default}",
15
- "export {foo as bar} from './foo'",
16
- "export {default as foo} from './foo'",
17
- // ts
18
- "export {type Foo as Bar}",
19
- "export type {Foo as Bar}",
20
- ];
21
-
22
- test({ valid, invalid, ...noRenameExports });
@@ -1,17 +0,0 @@
1
- import { createRule, DEFAULT_MESSAGE_ID, getRuleName } from "../common.ts";
2
-
3
- export const noRenameExports = createRule({
4
- name: getRuleName(import.meta.url),
5
- message: "Disallow renaming the named-exports.",
6
- create: (context) => ({
7
- ExportSpecifier: (node) => {
8
- if (
9
- node.exported.type !== "Identifier" ||
10
- node.local.type !== "Identifier" ||
11
- node.exported.name !== node.local.name
12
- ) {
13
- context.report({ node, messageId: DEFAULT_MESSAGE_ID });
14
- }
15
- },
16
- }),
17
- });
@@ -1,22 +0,0 @@
1
- import { test } from "@fenge/dev-utils";
2
- import { noRenameImports } from "./no-rename-imports.ts";
3
-
4
- const valid = [
5
- "import Foo from 'foo'",
6
- "import {foo, bar} from 'foo'",
7
- // ts
8
- "import {type foo} from 'foo'",
9
- "import type {foo} from 'foo'",
10
- "import type Foo from 'foo'",
11
- ];
12
- const invalid = [
13
- "import {foo as bar} from 'foo'",
14
- "import {default as foo} from 'foo'",
15
- // ts
16
- "import type {foo as bar} from 'foo'",
17
- "import {type foo as bar} from 'foo'",
18
- "import type {default as foo} from 'foo'",
19
- "import {type default as foo} from 'foo'",
20
- ];
21
-
22
- test({ valid, invalid, ...noRenameImports });
@@ -1,16 +0,0 @@
1
- import { createRule, DEFAULT_MESSAGE_ID, getRuleName } from "../common.ts";
2
-
3
- export const noRenameImports = createRule({
4
- name: getRuleName(import.meta.url),
5
- message: "Disallow renaming the named-imports.",
6
- create: (context) => ({
7
- ImportSpecifier: (node) => {
8
- if (
9
- node.imported.type !== "Identifier" ||
10
- node.imported.name !== node.local.name
11
- ) {
12
- context.report({ node, messageId: DEFAULT_MESSAGE_ID });
13
- }
14
- },
15
- }),
16
- });
@@ -1,24 +0,0 @@
1
- import { test } from "@fenge/dev-utils";
2
- import { noSideEffectImports } from "./no-side-effect-imports.ts";
3
-
4
- const valid = [
5
- "import 'reflect-metadata'",
6
- "import {} from 'reflect-metadata'",
7
- "import {foo} from 'foo'",
8
- ];
9
-
10
- const invalid = [
11
- "import 'foo'",
12
- "import './foo'",
13
- "import {} from 'foo'",
14
- "import {} from './foo'",
15
- "import './reflect-metadata'",
16
- "import './foo.module.css'",
17
- "import 'foo.module.css'",
18
-
19
- "import 'foo.css'",
20
- "import './foo.css'",
21
- "import 'module.css'",
22
- ];
23
-
24
- test({ valid, invalid, ...noSideEffectImports });
@@ -1,39 +0,0 @@
1
- import type { ImportDeclaration } from "estree";
2
- import { createRule, DEFAULT_MESSAGE_ID, getRuleName } from "../common.ts";
3
-
4
- const ignores = [
5
- "^reflect-metadata$",
6
- // https://github.com/vitejs/vite/blob/main/packages/vite/client.d.ts
7
- // "(?<!\\.module)\\.css$",
8
- // "(?<!\\.module)\\.scss$",
9
- // "(?<!\\.module)\\.sass$",
10
- // "(?<!\\.module)\\.less$",
11
- // "(?<!\\.module)\\.styl$",
12
- // "(?<!\\.module)\\.stylus$",
13
- // "(?<!\\.module)\\.pcss$",
14
- // "(?<!\\.module)\\.sss$",
15
- ];
16
-
17
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
18
- export const noSideEffectImports = createRule({
19
- name: getRuleName(import.meta.url),
20
- message:
21
- "Side effect import is often used for polyfills and css. It's unsafe to use it.",
22
- create: (context) => {
23
- const ignoreExps = ignores.map((ignore) => new RegExp(ignore));
24
- return {
25
- "ImportDeclaration[specifiers.length=0]": (node: ImportDeclaration) => {
26
- if (
27
- ignoreExps.some(
28
- (exp) =>
29
- typeof node.source.value === "string" &&
30
- exp.test(node.source.value),
31
- )
32
- ) {
33
- return;
34
- }
35
- context.report({ node, messageId: DEFAULT_MESSAGE_ID });
36
- },
37
- };
38
- },
39
- });
@@ -1,52 +0,0 @@
1
- import { test } from "@fenge/dev-utils";
2
- import { noUselessPathSegments } from "./no-useless-path-segments.ts";
3
-
4
- const valid = [
5
- 'import xxx from "../a"',
6
- 'import "../a"',
7
- 'import("../a")',
8
- 'require("../a")',
9
- 'import xxx from "./a"',
10
- 'import xxx from "a"',
11
- 'import xxx from ".a"',
12
- 'export * from "a"',
13
- 'export * from "./a"',
14
- 'export {a} from "a"',
15
- 'export {a} from "./a"',
16
-
17
- 'import foo from "."',
18
- "import foo from '..'",
19
- "import foo from '../..'",
20
- ].map((code) => ({ code, filename: "/a/b/c/d/e.js" }));
21
-
22
- const invalid = [
23
- 'import xxx from ".././../a"',
24
- 'import ".././../a"',
25
- 'import(".././../a")',
26
- 'export * from ".././../a"',
27
- 'export {a} from ".././../a"',
28
-
29
- 'import xxx from "./../a"',
30
- 'import "./../a"',
31
- 'import("./../a")',
32
- 'export * from "./../a"',
33
- 'export {a} from "./../a"',
34
-
35
- 'import "././foo"',
36
- 'import "./../.././foo"',
37
- 'import("./../.././foo")',
38
- 'export * from "./../.././foo"',
39
- 'export {a} from "./../.././foo"',
40
-
41
- 'import "./../foo"',
42
- 'import("./../foo")',
43
- 'export * from "./../foo"',
44
- 'export {a} from "./../foo"',
45
-
46
- 'import foo from "./"',
47
- "import foo from '../'",
48
- "import foo from '../../'",
49
- "import foo from './..'",
50
- ].map((code) => ({ code, filename: "/a/b/c/d/e.js" }));
51
-
52
- test({ valid, invalid, ...noUselessPathSegments });
@@ -1,31 +0,0 @@
1
- import path from "node:path";
2
- import { create, createRule, getRuleName, getSourceType } from "../common.ts";
3
-
4
- export const noUselessPathSegments = createRule({
5
- name: getRuleName(import.meta.url),
6
- message: "The relative source path should be a nearest relative path.",
7
- create: (context) => create(context, check),
8
- });
9
-
10
- function check(filename: string, source: string) {
11
- if (
12
- getSourceType(source) !== "local" ||
13
- source.startsWith("/") ||
14
- source === "."
15
- ) {
16
- return false;
17
- }
18
- if (source.endsWith("/")) {
19
- return true;
20
- }
21
- const currentPath = path.dirname(filename);
22
- const absoluteSource = path.resolve(currentPath, source);
23
- // compatible with windows
24
- let resultPath = path
25
- .relative(currentPath, absoluteSource)
26
- .replaceAll("\\", "/");
27
- if (!resultPath.startsWith("./") && !resultPath.startsWith("..")) {
28
- resultPath = `./${resultPath}`;
29
- }
30
- return resultPath !== source;
31
- }
@@ -1,24 +0,0 @@
1
- import { test } from "@fenge/dev-utils";
2
- import { requiredExports } from "./required-exports.ts";
3
-
4
- const valid = [
5
- "export {}",
6
- "const foo = 'foo'; export {foo}",
7
- "export const foo = {}",
8
- "export default {}",
9
- "export {foo} from 'foo'",
10
- "export {} from 'foo'",
11
- "export * as foo from 'foo'",
12
- "export {}; let foo = ''",
13
- ];
14
-
15
- const invalid = [
16
- "// This rule will also report on empty files",
17
- "",
18
- "console.log()",
19
- "import foo from 'foo'",
20
- "exports.foo = {}",
21
- "module.exports = {}",
22
- ];
23
-
24
- test({ valid, invalid, ...requiredExports });
@@ -1,22 +0,0 @@
1
- import { createRule, DEFAULT_MESSAGE_ID, getRuleName } from "../common.ts";
2
-
3
- export const requiredExports = createRule({
4
- name: getRuleName(import.meta.url),
5
- message: "It's required at least one `export` statement in a file.",
6
- create: (context) => {
7
- let existExport = false;
8
- const hasExport = () => {
9
- existExport = true;
10
- };
11
- return {
12
- ExportAllDeclaration: () => hasExport(),
13
- ExportDefaultDeclaration: () => hasExport(),
14
- ExportNamedDeclaration: () => hasExport(),
15
- "Program:exit": (node) => {
16
- if (!existExport) {
17
- context.report({ node, messageId: DEFAULT_MESSAGE_ID });
18
- }
19
- },
20
- };
21
- },
22
- });