From 627803930019e3f362c7c493572c834609f9dac7 Mon Sep 17 00:00:00 2001 From: Chris Lloyd Date: Tue, 1 May 2018 21:09:20 -0700 Subject: [PATCH 01/10] No relative parent imports rule --- CHANGELOG.md | 1 + README.md | 2 + docs/rules/no-relative-parent-imports.md | 55 +++++++++++++++++++ src/index.js | 1 + src/rules/no-relative-parent-imports.js | 36 ++++++++++++ tests/src/rules/no-relative-parent-imports.js | 35 ++++++++++++ 6 files changed, 130 insertions(+) create mode 100644 docs/rules/no-relative-parent-imports.md create mode 100644 src/rules/no-relative-parent-imports.js create mode 100644 tests/src/rules/no-relative-parent-imports.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 01b1f61ab..ee80331cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel ### Added - Ignore type imports for [`named`] rule ([#931], thanks [@mattijsbliek]) - Add documentation for [`no-useless-path-segments`] rule ([#1068], thanks [@manovotny]) +- Add [`no-relative-parent-imports`] rule: disallow relative imports from parent directories. # [2.11.0] - 2018-04-09 diff --git a/README.md b/README.md index 541c58296..53b264062 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a * Forbid a module from importing itself ([`no-self-import`]) * Forbid a module from importing a module with a dependency path back to itself ([`no-cycle`]) * Prevent unnecessary path segments in import and require statements ([`no-useless-path-segments`]) +* Forbid importing modules from parent directories ([`no-relative-parent-imports`]) [`no-unresolved`]: ./docs/rules/no-unresolved.md [`named`]: ./docs/rules/named.md @@ -39,6 +40,7 @@ This plugin intends to support linting of ES2015+ (ES6+) import/export syntax, a [`no-self-import`]: ./docs/rules/no-self-import.md [`no-cycle`]: ./docs/rules/no-cycle.md [`no-useless-path-segments`]: ./docs/rules/no-useless-path-segments.md +[`no-relative-parent-imports`]: ./docs/rules/no-relative-parent-imports.md ### Helpful warnings diff --git a/docs/rules/no-relative-parent-imports.md b/docs/rules/no-relative-parent-imports.md new file mode 100644 index 000000000..f61aa35fc --- /dev/null +++ b/docs/rules/no-relative-parent-imports.md @@ -0,0 +1,55 @@ +# no-relative-parent-imports + +Use this rule to prevent imports to folds in relative parent paths. + +It's useful for large codebases codebases to enforce directed-acyclic-graph like folder structures. + + +### Examples + +Given the following folder structure: + +``` +my-project +├── lib +│ ├── a.js +│ └── b.js +└── main.js +``` + +And the .eslintrc file: +``` +{ + ... + "rules": { + "import/no-relative-parent-imports": "error" + } +} +``` + +The following patterns are considered problems: + +```js +/** + * in my-project/lib/a.js + */ + +import bar from '../main'; // Import parent file using a relative path +``` + +The following patterns are NOT considered problems: + +```js +/** + * in my-project/main.js + */ + +import foo from 'foo'; // Import package using module path +import a from './lib/a'; // Import child file using relative path + +/** + * in my-project/lib/a.js + */ + +import b from './b'; // Import sibling file using relative path +``` diff --git a/src/index.js b/src/index.js index 5b55527b2..7df67867f 100644 --- a/src/index.js +++ b/src/index.js @@ -10,6 +10,7 @@ export const rules = { 'no-restricted-paths': require('./rules/no-restricted-paths'), 'no-internal-modules': require('./rules/no-internal-modules'), 'group-exports': require('./rules/group-exports'), + 'no-relative-parent-imports': require('./rules/no-relative-parent-imports'), 'no-self-import': require('./rules/no-self-import'), 'no-cycle': require('./rules/no-cycle'), diff --git a/src/rules/no-relative-parent-imports.js b/src/rules/no-relative-parent-imports.js new file mode 100644 index 000000000..b545f9ad5 --- /dev/null +++ b/src/rules/no-relative-parent-imports.js @@ -0,0 +1,36 @@ +import docsUrl from '../docsUrl' + +import importType from '../core/importType' +import isStaticRequire from '../core/staticRequire' + +module.exports = { + meta: { + docs: { + url: docsUrl('no-relative-parent-imports'), + }, + }, + + create: function noRelativePackages(context) { + + function checkImportForRelativeParentPath(importPath, node) { + if (importType(importPath, context) === 'parent') { + context.report({ + node, + message: 'Relative imports from parent directories are not allowed. ', + }) + } + } + + return { + ImportDeclaration(node) { + checkImportForRelativeParentPath(node.source.value, node.source) + }, + CallExpression(node) { + if (isStaticRequire(node)) { + const [ firstArgument ] = node.arguments + checkImportForRelativeParentPath(firstArgument.value, firstArgument) + } + }, + } + }, +} diff --git a/tests/src/rules/no-relative-parent-imports.js b/tests/src/rules/no-relative-parent-imports.js new file mode 100644 index 000000000..089115576 --- /dev/null +++ b/tests/src/rules/no-relative-parent-imports.js @@ -0,0 +1,35 @@ +import { RuleTester } from 'eslint' +import rule from 'rules/no-relative-parent-imports' + +import { test, testFilePath } from '../utils' + +const ruleTester = new RuleTester() + +ruleTester.run('no-relative-parent-imports', rule, { + valid: [ + test({ + code: 'import foo from "./internal.js"', + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + }), + test({ + code: 'import foo from "./app/index.js"', + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + }), + test({ + code: 'import foo from "package"', + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + }), + ], + + invalid: [ + test({ + code: 'import foo from "../plugin.js"', + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + errors: [ { + message: 'Relative imports from parent directories are not allowed.', + line: 1, + column: 17, + } ], + }), + ], +}) From 37a24faa9efc930c24e66ea96d60cb15199d2da1 Mon Sep 17 00:00:00 2001 From: Chris Lloyd Date: Tue, 1 May 2018 21:18:17 -0700 Subject: [PATCH 02/10] Fix test --- src/rules/no-relative-parent-imports.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rules/no-relative-parent-imports.js b/src/rules/no-relative-parent-imports.js index b545f9ad5..347fe1193 100644 --- a/src/rules/no-relative-parent-imports.js +++ b/src/rules/no-relative-parent-imports.js @@ -16,7 +16,7 @@ module.exports = { if (importType(importPath, context) === 'parent') { context.report({ node, - message: 'Relative imports from parent directories are not allowed. ', + message: 'Relative imports from parent directories are not allowed.', }) } } From 5bc2ae4d15d68ba52ccb0f286cac1b5c025b373b Mon Sep 17 00:00:00 2001 From: Chris Lloyd Date: Tue, 1 May 2018 21:28:51 -0700 Subject: [PATCH 03/10] Add tests for require() --- tests/src/rules/no-relative-parent-imports.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/src/rules/no-relative-parent-imports.js b/tests/src/rules/no-relative-parent-imports.js index 089115576..e14be9dbd 100644 --- a/tests/src/rules/no-relative-parent-imports.js +++ b/tests/src/rules/no-relative-parent-imports.js @@ -19,6 +19,18 @@ ruleTester.run('no-relative-parent-imports', rule, { code: 'import foo from "package"', filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), }), + test({ + code: 'require("./internal.js")', + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + }), + test({ + code: 'require("./app/index.js")', + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + }), + test({ + code: 'require("package")', + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + }), ], invalid: [ @@ -31,5 +43,14 @@ ruleTester.run('no-relative-parent-imports', rule, { column: 17, } ], }), + test({ + code: 'require("../plugin.js")', + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + errors: [ { + message: 'Relative imports from parent directories are not allowed.', + line: 1, + column: 9, + } ], + }), ], }) From d4e896fb768cbd76ce750c2cb0d24942a99787a0 Mon Sep 17 00:00:00 2001 From: Chris Lloyd Date: Tue, 1 May 2018 21:57:39 -0700 Subject: [PATCH 04/10] Add support for dynamic imports --- src/core/staticImport.js | 8 +++++ src/rules/no-relative-parent-imports.js | 3 +- tests/src/rules/no-relative-parent-imports.js | 32 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/core/staticImport.js diff --git a/src/core/staticImport.js b/src/core/staticImport.js new file mode 100644 index 000000000..e8d6c3bea --- /dev/null +++ b/src/core/staticImport.js @@ -0,0 +1,8 @@ +export default function isStaticImport(node) { + return node && + node.callee && + node.callee.type === 'Import' && + node.arguments.length === 1 && + node.arguments[0].type === 'Literal' && + typeof node.arguments[0].value === 'string' +} diff --git a/src/rules/no-relative-parent-imports.js b/src/rules/no-relative-parent-imports.js index 347fe1193..d1877abcd 100644 --- a/src/rules/no-relative-parent-imports.js +++ b/src/rules/no-relative-parent-imports.js @@ -1,6 +1,7 @@ import docsUrl from '../docsUrl' import importType from '../core/importType' +import isStaticImport from '../core/staticImport' import isStaticRequire from '../core/staticRequire' module.exports = { @@ -26,7 +27,7 @@ module.exports = { checkImportForRelativeParentPath(node.source.value, node.source) }, CallExpression(node) { - if (isStaticRequire(node)) { + if (isStaticRequire(node) || isStaticImport(node)) { const [ firstArgument ] = node.arguments checkImportForRelativeParentPath(firstArgument.value, firstArgument) } diff --git a/tests/src/rules/no-relative-parent-imports.js b/tests/src/rules/no-relative-parent-imports.js index e14be9dbd..fd85348f6 100644 --- a/tests/src/rules/no-relative-parent-imports.js +++ b/tests/src/rules/no-relative-parent-imports.js @@ -5,6 +5,9 @@ import { test, testFilePath } from '../utils' const ruleTester = new RuleTester() +const options = [{ importFunctions: ['dynamicImport'] }] +const parser = 'babel-eslint' + ruleTester.run('no-relative-parent-imports', rule, { valid: [ test({ @@ -31,6 +34,24 @@ ruleTester.run('no-relative-parent-imports', rule, { code: 'require("package")', filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), }), + test({ + code: 'import("./internal.js")', + options, + parser, + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + }), + test({ + code: 'import("./app/index.js")', + options, + parser, + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + }), + test({ + code: 'import("package")', + options, + parser, + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + }), ], invalid: [ @@ -52,5 +73,16 @@ ruleTester.run('no-relative-parent-imports', rule, { column: 9, } ], }), + test({ + code: 'import("../plugin.js")', + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + errors: [ { + message: 'Relative imports from parent directories are not allowed.', + line: 1, + column: 8, + } ], + options, + parser, + }), ], }) From 2305d32c42062bea7cb8ef0db8c7c4780450a651 Mon Sep 17 00:00:00 2001 From: Chris Lloyd Date: Thu, 3 May 2018 09:54:01 -0700 Subject: [PATCH 05/10] Typo --- docs/rules/no-relative-parent-imports.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/no-relative-parent-imports.md b/docs/rules/no-relative-parent-imports.md index f61aa35fc..6b8636bdb 100644 --- a/docs/rules/no-relative-parent-imports.md +++ b/docs/rules/no-relative-parent-imports.md @@ -1,6 +1,6 @@ # no-relative-parent-imports -Use this rule to prevent imports to folds in relative parent paths. +Use this rule to prevent imports to folders in relative parent paths. It's useful for large codebases codebases to enforce directed-acyclic-graph like folder structures. From 8fb588f99c8f8807cbcf7a853d24dabaff8065dd Mon Sep 17 00:00:00 2001 From: Chris Lloyd Date: Sat, 5 May 2018 12:22:50 -0700 Subject: [PATCH 06/10] Removes `src/core/staticImport` and adds support for dynamic imports to `utils/moduleVisitor` instead. --- src/core/staticImport.js | 8 ----- src/rules/no-relative-parent-imports.js | 24 +++++--------- tests/src/rules/no-relative-parent-imports.js | 33 +++++-------------- utils/moduleVisitor.js | 13 ++++++++ 4 files changed, 30 insertions(+), 48 deletions(-) delete mode 100644 src/core/staticImport.js diff --git a/src/core/staticImport.js b/src/core/staticImport.js deleted file mode 100644 index e8d6c3bea..000000000 --- a/src/core/staticImport.js +++ /dev/null @@ -1,8 +0,0 @@ -export default function isStaticImport(node) { - return node && - node.callee && - node.callee.type === 'Import' && - node.arguments.length === 1 && - node.arguments[0].type === 'Literal' && - typeof node.arguments[0].value === 'string' -} diff --git a/src/rules/no-relative-parent-imports.js b/src/rules/no-relative-parent-imports.js index d1877abcd..b32af3f43 100644 --- a/src/rules/no-relative-parent-imports.js +++ b/src/rules/no-relative-parent-imports.js @@ -1,37 +1,29 @@ +import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor' import docsUrl from '../docsUrl' import importType from '../core/importType' -import isStaticImport from '../core/staticImport' -import isStaticRequire from '../core/staticRequire' module.exports = { meta: { docs: { url: docsUrl('no-relative-parent-imports'), }, + schema: [makeOptionsSchema()], }, create: function noRelativePackages(context) { + const myPath = context.getFilename() + if (myPath === '') return {} // can't cycle-check a non-file - function checkImportForRelativeParentPath(importPath, node) { - if (importType(importPath, context) === 'parent') { + function checkSourceValue(sourceNode) { + if (importType(sourceNode.value, context) === 'parent') { context.report({ - node, + node: sourceNode, message: 'Relative imports from parent directories are not allowed.', }) } } - return { - ImportDeclaration(node) { - checkImportForRelativeParentPath(node.source.value, node.source) - }, - CallExpression(node) { - if (isStaticRequire(node) || isStaticImport(node)) { - const [ firstArgument ] = node.arguments - checkImportForRelativeParentPath(firstArgument.value, firstArgument) - } - }, - } + return moduleVisitor(checkSourceValue, context.options[0]) }, } diff --git a/tests/src/rules/no-relative-parent-imports.js b/tests/src/rules/no-relative-parent-imports.js index fd85348f6..35497d4e1 100644 --- a/tests/src/rules/no-relative-parent-imports.js +++ b/tests/src/rules/no-relative-parent-imports.js @@ -1,63 +1,51 @@ import { RuleTester } from 'eslint' import rule from 'rules/no-relative-parent-imports' +import { test as _test, testFilePath } from '../utils' -import { test, testFilePath } from '../utils' +const test = def => _test(Object.assign(def, { + filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + parser: 'babel-eslint', +})) const ruleTester = new RuleTester() -const options = [{ importFunctions: ['dynamicImport'] }] -const parser = 'babel-eslint' - ruleTester.run('no-relative-parent-imports', rule, { valid: [ test({ code: 'import foo from "./internal.js"', - filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), }), test({ code: 'import foo from "./app/index.js"', - filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), }), test({ code: 'import foo from "package"', - filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), }), test({ code: 'require("./internal.js")', - filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + options: [{ commonjs: true }], }), test({ code: 'require("./app/index.js")', - filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + options: [{ commonjs: true }], }), test({ code: 'require("package")', - filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + options: [{ commonjs: true }], }), test({ code: 'import("./internal.js")', - options, - parser, - filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), }), test({ code: 'import("./app/index.js")', - options, - parser, - filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), }), test({ code: 'import("package")', - options, - parser, - filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), }), ], invalid: [ test({ code: 'import foo from "../plugin.js"', - filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), errors: [ { message: 'Relative imports from parent directories are not allowed.', line: 1, @@ -66,7 +54,7 @@ ruleTester.run('no-relative-parent-imports', rule, { }), test({ code: 'require("../plugin.js")', - filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), + options: [{ commonjs: true }], errors: [ { message: 'Relative imports from parent directories are not allowed.', line: 1, @@ -75,14 +63,11 @@ ruleTester.run('no-relative-parent-imports', rule, { }), test({ code: 'import("../plugin.js")', - filename: testFilePath('./internal-modules/plugins/plugin2/index.js'), errors: [ { message: 'Relative imports from parent directories are not allowed.', line: 1, column: 8, } ], - options, - parser, }), ], }) diff --git a/utils/moduleVisitor.js b/utils/moduleVisitor.js index 7bb980e45..2e736242e 100644 --- a/utils/moduleVisitor.js +++ b/utils/moduleVisitor.js @@ -34,6 +34,18 @@ exports.default = function visitModules(visitor, options) { checkSourceValue(node.source, node) } + // for esmodule dynamic `import()` calls + function checkImportCall(node) { + if (node.callee.type !== 'Import') return + if (node.arguments.length !== 1) return + + const modulePath = node.arguments[0] + if (modulePath.type !== 'Literal') return + if (typeof modulePath.value !== 'string') return + + checkSourceValue(modulePath, node) + } + // for CommonJS `require` calls // adapted from @mctep: http://git.io/v4rAu function checkCommon(call) { @@ -74,6 +86,7 @@ exports.default = function visitModules(visitor, options) { 'ImportDeclaration': checkSource, 'ExportNamedDeclaration': checkSource, 'ExportAllDeclaration': checkSource, + 'CallExpression': checkImportCall, }) } From df6540f1a4ad91cad2b3c16d5da0848a58b0bed6 Mon Sep 17 00:00:00 2001 From: Chris Lloyd Date: Sat, 5 May 2018 13:04:50 -0700 Subject: [PATCH 07/10] Make the error messages more actionable. --- src/rules/no-relative-parent-imports.js | 9 +++++++-- tests/src/rules/no-relative-parent-imports.js | 6 +++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/rules/no-relative-parent-imports.js b/src/rules/no-relative-parent-imports.js index b32af3f43..3153eeb78 100644 --- a/src/rules/no-relative-parent-imports.js +++ b/src/rules/no-relative-parent-imports.js @@ -1,5 +1,6 @@ import moduleVisitor, { makeOptionsSchema } from 'eslint-module-utils/moduleVisitor' import docsUrl from '../docsUrl' +import { basename } from 'path' import importType from '../core/importType' @@ -16,10 +17,14 @@ module.exports = { if (myPath === '') return {} // can't cycle-check a non-file function checkSourceValue(sourceNode) { - if (importType(sourceNode.value, context) === 'parent') { + const depPath = sourceNode.value + if (importType(depPath, context) === 'parent') { context.report({ node: sourceNode, - message: 'Relative imports from parent directories are not allowed.', + message: 'Relative imports from parent directories are not allowed. ' + + `Please either pass what you're importing through at runtime ` + + `(dependency injection), move \`${basename(myPath)}\` to same ` + + `directory as \`${depPath}\` or consider making \`${depPath}\` a package.`, }) } } diff --git a/tests/src/rules/no-relative-parent-imports.js b/tests/src/rules/no-relative-parent-imports.js index 35497d4e1..6d7a2c2fa 100644 --- a/tests/src/rules/no-relative-parent-imports.js +++ b/tests/src/rules/no-relative-parent-imports.js @@ -47,7 +47,7 @@ ruleTester.run('no-relative-parent-imports', rule, { test({ code: 'import foo from "../plugin.js"', errors: [ { - message: 'Relative imports from parent directories are not allowed.', + message: 'Relative imports from parent directories are not allowed. Please either pass what you\'re importing through at runtime (dependency injection), move `index.js` to same directory as `../plugin.js` or consider making `../plugin.js` a package.', line: 1, column: 17, } ], @@ -56,7 +56,7 @@ ruleTester.run('no-relative-parent-imports', rule, { code: 'require("../plugin.js")', options: [{ commonjs: true }], errors: [ { - message: 'Relative imports from parent directories are not allowed.', + message: 'Relative imports from parent directories are not allowed. Please either pass what you\'re importing through at runtime (dependency injection), move `index.js` to same directory as `../plugin.js` or consider making `../plugin.js` a package.', line: 1, column: 9, } ], @@ -64,7 +64,7 @@ ruleTester.run('no-relative-parent-imports', rule, { test({ code: 'import("../plugin.js")', errors: [ { - message: 'Relative imports from parent directories are not allowed.', + message: 'Relative imports from parent directories are not allowed. Please either pass what you\'re importing through at runtime (dependency injection), move `index.js` to same directory as `../plugin.js` or consider making `../plugin.js` a package.', line: 1, column: 8, } ], From 07f3707fd02b5163584d5c669aff2d76c864135a Mon Sep 17 00:00:00 2001 From: Chris Lloyd Date: Sat, 5 May 2018 14:26:33 -0700 Subject: [PATCH 08/10] Add a lot more detail around how to fix errors in the docs. --- docs/rules/no-relative-parent-imports.md | 67 +++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/docs/rules/no-relative-parent-imports.md b/docs/rules/no-relative-parent-imports.md index 6b8636bdb..99dc43208 100644 --- a/docs/rules/no-relative-parent-imports.md +++ b/docs/rules/no-relative-parent-imports.md @@ -2,8 +2,73 @@ Use this rule to prevent imports to folders in relative parent paths. -It's useful for large codebases codebases to enforce directed-acyclic-graph like folder structures. +It's useful for enforcing tree-like folder structures instead of complex graph-like folder structures. While this might be a departure from Node's default resolution style, it can lead large codebases to be easier to maintain codebases over time. +To fix violations of this rule there are three general strategies. Given this example: + +``` +numbers +└── three.js +add.js +``` + +```js +// ./add.js +export default function (numbers) { + return numbers.reduce((sum, n) => sum + n, 0); +} + +// ./numbers/three.js +import add from '../add'; + +export default function three() { + return add([1, 2]); +} +``` + +You can, + +1. Move the file to be in a sibling folder (or higher) of the dependency. + +`three.js` could be be in the same folder as `../add.js`: + +``` +three.js +add.js +``` + +or because `add` doesn't have any imports, it could be in it's own namespace: + +``` +math +└── add.js +three.js +``` + +2. Pass the dependency as an argument at runtime (dependency injection) + +```js +// three.js +export default function three(add) { + return add([1, 2]); +} + +// somewhere else when you use `./three.js`: +import add from './add'; +import three from './numbers/three'; +console.log(three(add)); +``` + +3. Make the dependency a package so it's available to all files: + +```js +import add from 'add'; // from https://www.npmjs.com/package/add +export default function three() { + return add([1,2]); +} +``` + +These are (respectively) static, dynamic & global solutions to graph-like dependency resolution. ### Examples From 4b3bbca0ec14ecc10d85da746a8f9d93d0324aa1 Mon Sep 17 00:00:00 2001 From: Chris Lloyd Date: Sat, 5 May 2018 14:29:02 -0700 Subject: [PATCH 09/10] docs grammar --- docs/rules/no-relative-parent-imports.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/no-relative-parent-imports.md b/docs/rules/no-relative-parent-imports.md index 99dc43208..9a870e6d7 100644 --- a/docs/rules/no-relative-parent-imports.md +++ b/docs/rules/no-relative-parent-imports.md @@ -2,7 +2,7 @@ Use this rule to prevent imports to folders in relative parent paths. -It's useful for enforcing tree-like folder structures instead of complex graph-like folder structures. While this might be a departure from Node's default resolution style, it can lead large codebases to be easier to maintain codebases over time. +This rule is useful for enforcing tree-like folder structures instead of complex graph-like folder structures. While this restriction might be a departure from Node's default resolution style, it can lead large, complex codebases to be easier to maintain. If you've ever had debates over "where to put files" this rule is for you. To fix violations of this rule there are three general strategies. Given this example: From dd0520e1cf50c1402b2dc02ad27a9ef25573a30e Mon Sep 17 00:00:00 2001 From: Chris Lloyd Date: Sat, 5 May 2018 14:32:07 -0700 Subject: [PATCH 10/10] docs grammar --- docs/rules/no-relative-parent-imports.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/rules/no-relative-parent-imports.md b/docs/rules/no-relative-parent-imports.md index 9a870e6d7..84913b540 100644 --- a/docs/rules/no-relative-parent-imports.md +++ b/docs/rules/no-relative-parent-imports.md @@ -19,7 +19,7 @@ export default function (numbers) { } // ./numbers/three.js -import add from '../add'; +import add from '../add'; // violates import/no-relative-parent-imports export default function three() { return add([1, 2]); @@ -30,14 +30,14 @@ You can, 1. Move the file to be in a sibling folder (or higher) of the dependency. -`three.js` could be be in the same folder as `../add.js`: +`three.js` could be be in the same folder as `add.js`: ``` three.js add.js ``` -or because `add` doesn't have any imports, it could be in it's own namespace: +or since `add` doesn't have any imports, it could be in it's own directory (namespace): ``` math @@ -53,13 +53,13 @@ export default function three(add) { return add([1, 2]); } -// somewhere else when you use `./three.js`: +// somewhere else when you use `three.js`: import add from './add'; import three from './numbers/three'; console.log(three(add)); ``` -3. Make the dependency a package so it's available to all files: +3. Make the dependency a package so it's globally available to all files in your project: ```js import add from 'add'; // from https://www.npmjs.com/package/add