Skip to content

Commit

Permalink
[New] no-absolute-path: add fixer
Browse files Browse the repository at this point in the history
  • Loading branch information
adipascu authored and ljharb committed Dec 13, 2022
1 parent 5a37196 commit b96b499
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -18,6 +18,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
- [`consistent-type-specifier-style`]: add rule ([#2473], thanks [@bradzacher])
- Add [`no-empty-named-blocks`] rule ([#2568], thanks [@guilhermelimak])
- [`prefer-default-export`]: add "target" option ([#2602], thanks [@azyzz228])
- [`no-absolute-path`]: add fixer ([#2613], thanks [@adipascu])

### Fixed
- [`order`]: move nested imports closer to main import entry ([#2396], thanks [@pri1311])
Expand Down Expand Up @@ -1026,6 +1027,7 @@ for info on changes for earlier releases.

[`memo-parser`]: ./memo-parser/README.md

[#2613]: https://github.com/import-js/eslint-plugin-import/pull/2613
[#2608]: https://github.com/import-js/eslint-plugin-import/pull/2608
[#2605]: https://github.com/import-js/eslint-plugin-import/pull/2605
[#2602]: https://github.com/import-js/eslint-plugin-import/pull/2602
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -56,7 +56,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a
| [default](docs/rules/default.md) | Ensure a default export is present, given a default import. | ❗ ☑️ | | | | | |
| [named](docs/rules/named.md) | Ensure named imports correspond to a named export in the remote file. | ❗ ☑️ | | ⌨️ | | | |
| [namespace](docs/rules/namespace.md) | Ensure imported namespaces contain dereferenced properties as they are dereferenced. | ❗ ☑️ | | | | | |
| [no-absolute-path](docs/rules/no-absolute-path.md) | Forbid import of modules using absolute paths. | | | | | | |
| [no-absolute-path](docs/rules/no-absolute-path.md) | Forbid import of modules using absolute paths. | | | | 🔧 | | |
| [no-cycle](docs/rules/no-cycle.md) | Forbid a module from importing a module with a dependency path back to itself. | | | | | | |
| [no-dynamic-require](docs/rules/no-dynamic-require.md) | Forbid `require()` calls with expressions. | | | | | | |
| [no-internal-modules](docs/rules/no-internal-modules.md) | Forbid importing the submodules of other modules. | | | | | | |
Expand Down
2 changes: 2 additions & 0 deletions docs/rules/no-absolute-path.md
@@ -1,5 +1,7 @@
# import/no-absolute-path

🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).

<!-- end auto-generated rule header -->

Node.js allows the import of modules using an absolute path such as `/home/xyz/file.js`. That is a bad practice as it ties the code using it to your computer, and therefore makes it unusable in packages distributed on `npm` for instance.
Expand Down
16 changes: 15 additions & 1 deletion src/rules/no-absolute-path.js
@@ -1,3 +1,4 @@
import path from 'path';
import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor';
import { isAbsolute } from '../core/importType';
import docsUrl from '../docsUrl';
Expand All @@ -10,13 +11,26 @@ module.exports = {
description: 'Forbid import of modules using absolute paths.',
url: docsUrl('no-absolute-path'),
},
fixable: 'code',
schema: [ makeOptionsSchema() ],
},

create(context) {
function reportIfAbsolute(source) {
if (isAbsolute(source.value)) {
context.report(source, 'Do not import modules using an absolute path');
context.report({
node: source,
message: 'Do not import modules using an absolute path',
fix: fixer => {
const resolvedContext = context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename();
// node.js and web imports work with posix style paths ("/")
let relativePath = path.posix.relative(path.dirname(resolvedContext), source.value);
if (!relativePath.startsWith('.')) {
relativePath = './' + relativePath;
}
return fixer.replaceText(source, JSON.stringify(relativePath));
},
});
}
}

Expand Down
26 changes: 26 additions & 0 deletions tests/src/rules/no-absolute-path.js
Expand Up @@ -53,48 +53,74 @@ ruleTester.run('no-absolute-path', rule, {
invalid: [
test({
code: 'import f from "/foo"',
filename: '/foo/bar/index.js',
errors: [error],
output: 'import f from ".."',
}),
test({
code: 'import f from "/foo/bar/baz.js"',
filename: '/foo/bar/index.js',
errors: [error],
output: 'import f from "./baz.js"',
}),
test({
code: 'import f from "/foo/path"',
filename: '/foo/bar/index.js',
errors: [error],
output: 'import f from "../path"',
}),
test({
code: 'import f from "/some/path"',
filename: '/foo/bar/index.js',
errors: [error],
output: 'import f from "../../some/path"',
}),
test({
code: 'import f from "/some/path"',
filename: '/foo/bar/index.js',
options: [{ amd: true }],
errors: [error],
output: 'import f from "../../some/path"',
}),
test({
code: 'var f = require("/foo")',
filename: '/foo/bar/index.js',
errors: [error],
output: 'var f = require("..")',
}),
test({
code: 'var f = require("/foo/path")',
filename: '/foo/bar/index.js',
errors: [error],
output: 'var f = require("../path")',
}),
test({
code: 'var f = require("/some/path")',
filename: '/foo/bar/index.js',
errors: [error],
output: 'var f = require("../../some/path")',
}),
test({
code: 'var f = require("/some/path")',
filename: '/foo/bar/index.js',
options: [{ amd: true }],
errors: [error],
output: 'var f = require("../../some/path")',
}),
// validate amd
test({
code: 'require(["/some/path"], function (f) { /* ... */ })',
filename: '/foo/bar/index.js',
options: [{ amd: true }],
errors: [error],
output: 'require(["../../some/path"], function (f) { /* ... */ })',
}),
test({
code: 'define(["/some/path"], function (f) { /* ... */ })',
filename: '/foo/bar/index.js',
options: [{ amd: true }],
errors: [error],
output: 'define(["../../some/path"], function (f) { /* ... */ })',
}),
],
});

0 comments on commit b96b499

Please sign in to comment.