-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* update to 2.0.0 * add bundler * add some error handling * normalize the source before splitting * handle absolute path and fix other issues * fix tests * update readme and change version * update to use vite 5 * fix error message when viteConfig is not object * remove unnecessary log
- Loading branch information
1 parent
6709967
commit e0c140b
Showing
8 changed files
with
2,165 additions
and
1,088 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 |
---|---|---|
@@ -1 +1,2 @@ | ||
node_modules/ | ||
dist/ |
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,7 @@ | ||
.editorconfig | ||
.gitignore | ||
index.js | ||
index.test.js | ||
jest.config.js | ||
Makefile | ||
vite.config.js |
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 |
---|---|---|
|
@@ -2,88 +2,45 @@ | |
|
||
Vite module resolution plugin for `eslint-plugin-import`. This plugin will resolve the `resolve.alias` option. | ||
|
||
> #### Version `2.0.0-beta.3` is available. See [what's changed](https://github.com/pzmosquito/eslint-import-resolver-vite/releases/tag/2.0.0-beta.1). | ||
> ```sh | ||
> npm install --save-dev [email protected] | ||
> ``` | ||
|
||
### Installation | ||
```sh | ||
npm install --save-dev eslint-import-resolver-vite | ||
# install vite-plugin-eslint if you don't already have it | ||
npm install --save-dev vite-plugin-eslint | ||
``` | ||
|
||
|
||
### Config Options | ||
- **viteConfig**: The Vite config object. | ||
- Required: Yes | ||
- Type: object | ||
|
||
|
||
### How to use | ||
```js | ||
/** | ||
* vite config file | ||
*/ | ||
import eslintPlugin from "vite-plugin-eslint"; | ||
|
||
export default { | ||
#### Vite config file | ||
```js | ||
export const viteConfigObj = { | ||
resolve: { | ||
alias: { | ||
_: path.resolve(__dirname, "src") | ||
} | ||
}, | ||
plugins: [ | ||
eslintPlugin() | ||
] | ||
}; | ||
``` | ||
|
||
/** | ||
* eslint config file | ||
*/ | ||
#### ESLint config file | ||
NOTE: | ||
- Since `eslint-plugin-import` doesn't support an async resolver, Vite's [ResolvedConfig API](https://vitejs.dev/guide/api-javascript.html#resolvedconfig) cannot be utilized. | ||
- This plugin accepts a Vite config object to accommodate various setups, e.g. CJS, ESM, or mixed. | ||
```js | ||
module.exports = { | ||
settings: { | ||
// This uses the default `vite.config.js` file and the Vite configuration is an object. | ||
"import/resolver": "vite", | ||
|
||
// OR use custom config (see Config Options below): | ||
"import/resolver": { | ||
vite: { | ||
configPath: "./app1/vite.confg.ts" | ||
viteConfig: require("./vite.config").viteConfigObj, | ||
} | ||
} | ||
} | ||
} | ||
|
||
``` | ||
|
||
### Config Options | ||
- **configPath**: vite config file path. | ||
- Required: No | ||
- Type: string | ||
- Default: "vite.config.js" | ||
- By default, the plugin assumes the vite config file and eslintrc file are in the same directory. | ||
- **namedExport**: named export of vite config object. | ||
- Required: No | ||
- Type: string | ||
- Default: [No Default] | ||
- **If you use a function as vite config, you must export a named vite config object. This is a result of the limitation of `eslint-plugin-import`.** | ||
```js | ||
/** | ||
* vite config file | ||
*/ | ||
export const viteConfig = {}; | ||
|
||
export default ({ command, mode }) => { | ||
// conditional config | ||
return viteConfig; | ||
} | ||
|
||
/** | ||
* eslintrc file | ||
*/ | ||
module.exports = { | ||
settings: { | ||
"import/resolver": { | ||
vite: { | ||
namedExport: "viteConfig" | ||
} | ||
} | ||
} | ||
} | ||
``` |
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 |
---|---|---|
@@ -1,107 +1,97 @@ | ||
const path = require("path"); | ||
const resolve = require("resolve"); | ||
const fs = require("fs"); | ||
const debug = require("debug"); | ||
|
||
const namespace = "eslint-plugin-import:resolver:vite"; | ||
|
||
const log = debug(namespace); | ||
|
||
const logError = (message) => { | ||
log(message); | ||
console.error(`[${namespace}] ${message}`); | ||
const processAlias = (alias, source) => { | ||
if (alias) { | ||
const pathParts = path.normalize(source).split(path.sep); | ||
if (Array.isArray(alias)) { | ||
for (let i = 0; i < pathParts.length; i++) { | ||
alias.forEach(({find, replacement}) => { | ||
if (pathParts[i] === find) { | ||
pathParts[i] = replacement; | ||
} | ||
}); | ||
} | ||
} | ||
else if (typeof alias === "object") { | ||
for (let i = 0; i < pathParts.length; i++) { | ||
if (alias.hasOwnProperty(pathParts[i])) { | ||
pathParts[i] = alias[pathParts[i]]; | ||
} | ||
} | ||
} | ||
else { | ||
throw new Error("The alias must be either an object, or an array of objects."); | ||
} | ||
return pathParts.join(path.sep); | ||
} | ||
return source; | ||
}; | ||
|
||
const resolveSync = (source, resolveOptions, label) => { | ||
log("resolving:\t", `(${label})`, source); | ||
const resolvedPath = resolve.sync(source, resolveOptions); | ||
log("resolved:\t", resolvedPath); | ||
return { found: true, path: resolvedPath }; | ||
}; | ||
|
||
exports.interfaceVersion = 2; | ||
|
||
exports.resolve = (source, file, config) => { | ||
log("resolving:", source); | ||
log("in file:", file); | ||
log("\nin file:\t", file); | ||
|
||
if (resolve.isCore(source)) { | ||
log("resolved:\t", source); | ||
return { found: true, path: null }; | ||
} | ||
|
||
try { | ||
// combine default config with user defined config | ||
const pluginConfig = { | ||
configPath: "vite.config.js", | ||
...(config ?? {}), | ||
}; | ||
|
||
// load vite config | ||
const viteConfigPath = path.resolve(pluginConfig.configPath); | ||
if (!fs.existsSync(viteConfigPath)) { | ||
throw new Error(`Vite config file doesn't exist at '${viteConfigPath}'`) | ||
} | ||
const viteConfigFile = require(viteConfigPath); | ||
|
||
let viteConfig; | ||
if (pluginConfig.namedExport) { | ||
viteConfig = viteConfigFile[pluginConfig.namedExport] | ||
} | ||
else { | ||
const viteConfigObj = viteConfigFile.default ?? viteConfigFile | ||
viteConfig = typeof viteConfigObj === "function" ? viteConfigObj() : viteConfigObj; | ||
} | ||
const { viteConfig } = config; | ||
if (!viteConfig) { | ||
throw new Error("'viteConfig' option must be a vite config object."); | ||
} | ||
|
||
const defaultExtensions = [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json"]; | ||
const { alias, extensions = defaultExtensions } = viteConfig.resolve ?? {}; | ||
const defaultExtensions = [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json"]; | ||
const { alias, extensions = defaultExtensions } = viteConfig.resolve ?? {}; | ||
const resolveOptions = { basedir: path.dirname(file), extensions }; | ||
|
||
let actualSource = path.normalize(source); | ||
// try to resolve the source as is | ||
try { | ||
return resolveSync(source, resolveOptions, "as is"); | ||
} | ||
catch {} | ||
|
||
// parse and replace alias | ||
if (alias) { | ||
const pathParts = actualSource.split(path.sep); | ||
if (Array.isArray(alias)) { | ||
for (let i = 0; i < pathParts.length; i++) { | ||
alias.forEach(({find, replacement}) => { | ||
if (pathParts[i] === find) { | ||
pathParts[i] = replacement; | ||
} | ||
}); | ||
} | ||
} | ||
else if (typeof alias === "object") { | ||
for (let i = 0; i < pathParts.length; i++) { | ||
if (alias.hasOwnProperty(pathParts[i])) { | ||
pathParts[i] = alias[pathParts[i]]; | ||
} | ||
} | ||
} | ||
else { | ||
throw new Error("The alias must be either an object, or an array of objects."); | ||
} | ||
actualSource = pathParts.join(path.sep); | ||
// try to resolve the source with alias | ||
const parsedSource = processAlias(alias, source); | ||
if (parsedSource !== source) { | ||
try { | ||
return resolveSync(parsedSource, resolveOptions, "with alias"); | ||
} | ||
catch {} | ||
} | ||
|
||
// resolve module | ||
let resolvedPath = ""; | ||
// try to resolve the source if it is an absolute path | ||
if (path.isAbsolute(parsedSource)) { | ||
const root = viteConfig.root ?? process.cwd(); | ||
const absoluteSource = path.join(path.resolve(root), parsedSource); | ||
try { | ||
resolvedPath = resolve.sync(actualSource, { | ||
basedir: path.dirname(file), | ||
extensions, | ||
}); | ||
} | ||
catch (err) { | ||
if (viteConfig.publicDir !== false) { | ||
const publicDir = viteConfig.publicDir ?? "public"; | ||
const publicActualSource = path.join(path.resolve(publicDir), actualSource); | ||
resolvedPath = resolve.sync(publicActualSource, { | ||
basedir: path.dirname(file), | ||
extensions, | ||
}); | ||
} | ||
else { | ||
throw new Error("source cannot be resolved in actual path nor in 'Public' path."); | ||
} | ||
return resolveSync(absoluteSource, resolveOptions, "absolute path"); | ||
} | ||
|
||
log("resolved to:", resolvedPath); | ||
return { found: true, path: resolvedPath }; | ||
catch {} | ||
} | ||
catch (err) { | ||
logError(err.message); | ||
return { found: false }; | ||
|
||
// try to resolve the source in public directory if all above failed | ||
if (viteConfig.publicDir !== false) { | ||
const publicDir = viteConfig.publicDir ?? "public"; | ||
const publicSource = path.join(path.resolve(publicDir), parsedSource); | ||
try { | ||
return resolveSync(publicSource, resolveOptions, "in public directory"); | ||
} | ||
catch {} | ||
} | ||
|
||
log("ERROR:\t", "Unable to resolve"); | ||
return { found: false }; | ||
}; |
Oops, something went wrong.