This repository has been archived by the owner on Aug 18, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
184 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Prevent directly importing image files and instead force usage of an index file | ||
|
||
Image files should live in a directory (e.g. `icons`, `illustrations` or `images`) that must contain a dedicated index file that reexports all the images in that folder. | ||
|
||
Files that consume images must import from that index file instead of importing images directly. | ||
|
||
## Rule Details | ||
|
||
Example of **incorrect** code for this rule: | ||
|
||
|
||
```js | ||
// components/Foo/Foo.js | ||
import icon1 from './icons/icon1.svg'; | ||
``` | ||
|
||
|
||
Example of **correct** code for this rule: | ||
|
||
```js | ||
// components/Foo/icons/index.js | ||
export {default as icon1} from './icon1.svg'; | ||
|
||
// components/Foo/Foo.js | ||
import {icon1} from './icons'; | ||
``` | ||
|
||
## When Not To Use It | ||
|
||
If you do not wish to enforce imports locations for images, then you can safely disable this rule. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
const {basename, dirname, extname} = require('path'); | ||
const resolve = require('eslint-module-utils/resolve').default; | ||
const {docsUrl} = require('../utilities'); | ||
|
||
function isImageImport(resolvedSource) { | ||
return /\.(svg|png|jpg)$/.test(resolvedSource); | ||
} | ||
|
||
function isImportFromCurrentFolderIndex(contextFilename, resolvedSource) { | ||
const isIndex = | ||
basename(contextFilename, extname(contextFilename)) === 'index'; | ||
|
||
return isIndex && dirname(resolvedSource) === dirname(contextFilename); | ||
} | ||
|
||
module.exports = { | ||
meta: { | ||
docs: { | ||
description: | ||
"Prefer that imports of image files go through an index file within the image's directory instead of directly referencing images within a component.", | ||
category: 'Best Practices', | ||
recommended: false, | ||
uri: docsUrl('images-no-direct-imports'), | ||
}, | ||
fixable: null, | ||
}, | ||
create(context) { | ||
function checkNode(node) { | ||
const resolvedSource = resolve(node.source.value, context); | ||
|
||
if ( | ||
resolvedSource && | ||
isImageImport(resolvedSource) && | ||
!isImportFromCurrentFolderIndex(context.getFilename(), resolvedSource) | ||
) { | ||
context.report({ | ||
node, | ||
message: | ||
'Do not import image files directly, instead import from the index folder that the icon is contained within', | ||
}); | ||
} | ||
} | ||
return { | ||
ImportDeclaration: checkNode, | ||
ExportNamedDeclaration: checkNode, | ||
ExportAllDeclaration: checkNode, | ||
}; | ||
}, | ||
}; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
const {RuleTester} = require('eslint'); | ||
const {fixtureFile} = require('../../utilities'); | ||
const rule = require('../../../lib/rules/images-no-direct-imports'); | ||
|
||
const ruleTester = new RuleTester({ | ||
parserOptions: { | ||
ecmaVersion: 6, | ||
sourceType: 'module', | ||
}, | ||
}); | ||
|
||
function errors(type) { | ||
return [ | ||
{ | ||
type, | ||
message: | ||
'Do not import image files directly, instead import from the index folder that the icon is contained within', | ||
}, | ||
]; | ||
} | ||
|
||
ruleTester.run('no-ancestor-directory-import', rule, { | ||
valid: [ | ||
// Importing / Exporting svg files from the folder index is valid | ||
{ | ||
code: "import icon1 from './icon1.svg'", | ||
filename: fixtureFile('basic-app/app/components/Foo/icons/index.js'), | ||
}, | ||
{ | ||
code: "import * as icon1 from './icon1.svg'", | ||
filename: fixtureFile('basic-app/app/components/Foo/icons/index.js'), | ||
}, | ||
{ | ||
code: "export {default as icon1} from './icon1.svg'", | ||
filename: fixtureFile('basic-app/app/components/Foo/icons/index.js'), | ||
}, | ||
{ | ||
code: "export * from './icon1.svg'", | ||
filename: fixtureFile('basic-app/app/components/Foo/icons/index.js'), | ||
}, | ||
// Importing / Exporting icon index file contents from a component is valid | ||
{ | ||
code: "import {icon1} from './icons'", | ||
filename: fixtureFile('basic-app/app/components/Foo/Foo.js'), | ||
}, | ||
{ | ||
code: "import * as icon1 from './icons'", | ||
filename: fixtureFile('basic-app/app/components/Foo/Foo.js'), | ||
}, | ||
{ | ||
code: "export {default as icon1} from './icons'", | ||
filename: fixtureFile('basic-app/app/components/Foo/Foo.js'), | ||
}, | ||
{ | ||
code: "export * from './icons'", | ||
filename: fixtureFile('basic-app/app/components/Foo/Foo.js'), | ||
}, | ||
], | ||
|
||
invalid: [ | ||
// Importing / Exporting an icon directly from component file is invalid | ||
{ | ||
code: "import icon1 from './icons/icon1.svg'", | ||
errors: errors('ImportDeclaration'), | ||
filename: fixtureFile('basic-app/app/components/Foo/Foo.js'), | ||
}, | ||
{ | ||
code: "import * as icon1 from './icons/icon1.svg'", | ||
errors: errors('ImportDeclaration'), | ||
filename: fixtureFile('basic-app/app/components/Foo/index.js'), | ||
}, | ||
{ | ||
code: "export {default as icon1} from './icons/icon1.svg'", | ||
errors: errors('ExportNamedDeclaration'), | ||
filename: fixtureFile('basic-app/app/components/Foo/Foo.js'), | ||
}, | ||
{ | ||
code: "export * from './icons/icon1.svg'", | ||
errors: errors('ExportAllDeclaration'), | ||
filename: fixtureFile('basic-app/app/components/Foo/Foo.js'), | ||
}, | ||
// Importing / Exporting an icon directly from some other index file | ||
{ | ||
code: "import icon1 from './icons/icon1.svg'", | ||
errors: errors('ImportDeclaration'), | ||
filename: fixtureFile('basic-app/app/components/Foo/index.js'), | ||
}, | ||
{ | ||
code: "import * as icon1 from './icons/icon1.svg'", | ||
errors: errors('ImportDeclaration'), | ||
filename: fixtureFile('basic-app/app/components/Foo/index.js'), | ||
}, | ||
{ | ||
code: "export {default as icon1} from './icons/icon1.svg'", | ||
errors: errors('ExportNamedDeclaration'), | ||
filename: fixtureFile('basic-app/app/components/Foo/index.js'), | ||
}, | ||
{ | ||
code: "export * from './icons/icon1.svg'", | ||
errors: errors('ExportAllDeclaration'), | ||
filename: fixtureFile('basic-app/app/components/Foo/index.js'), | ||
}, | ||
], | ||
}); |