Skip to content

Commit

Permalink
feat: add support to allow relative import overrides
Browse files Browse the repository at this point in the history
Closes #7

The feature request was to support allowing some level
of relative imports. Although I don't personally believe
the benefit of a short import outweighs that of absolute
imports, that is not my call to make for every project using
the plugin, so support was added here.
  • Loading branch information
Limegrass committed Sep 11, 2023
1 parent 404a1b8 commit 54f95cd
Show file tree
Hide file tree
Showing 2 changed files with 910 additions and 2 deletions.
89 changes: 89 additions & 0 deletions src/rules/import-alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,25 @@ import type { JSONSchema4 } from "json-schema";
import { dirname, join as joinPath, resolve, sep as pathSep } from "path";
import slash from "slash";

function isPermittedRelativeImport(
importModuleName: string,
relativeImportOverrides: RelativeImportConfig[],
fileAbsoluteDir: string
) {
const configOfPath = relativeImportOverrides.find((config) =>
fileAbsoluteDir.includes(resolve(config.path))
);
if (!configOfPath) {
return false;
}

const importParts = importModuleName.split("/");
const relativeDepth = importParts.filter(
(moduleNamePart) => moduleNamePart === ".."
).length;
return configOfPath.depth >= relativeDepth;
}

function getAliasSuggestion(
importModuleName: string,
aliasConfigs: AliasConfig[],
Expand Down Expand Up @@ -72,10 +91,49 @@ function getBestAliasConfig(
: currentBest;
}, currentAlias);
}

interface RelativeImportConfig {
/**
* The starting path from which a relative depth is accepted.
*
* @example
* With a configuration like `{ path: "src/foo", depth: 0 }`
* 1. Relative paths can be used in `./src/foo`.
* 2. Relative paths can be used in `./src/foo/bar`.
* 3. Relative paths can NOT be used in `./src`.
*
* @example
* With a configuration like `{ path: "src/*", depth: 0 }`
* 1. Relative paths can be used in `./src/foo`.
* 2. Relative paths can be used in `./src/bar/baz`.
* 3. Relative paths can NOT be used in `./src`.
*
* @example
* With a configuration like `{ path: "src", depth: 0 }`
* 1. Relative paths can be used in `./src/foo`.
* 2. Relative paths can be used in `./src/bar/baz`.
* 3. Relative paths can be used in `./src`.
*/
path: string;
/**
* A positive number which represents the relative depth
* that is acceptable for the associated path.
*
* @example
* In `./src/foo` with `path: "src"`
* 1. `import "./bar"` for `./src/bar` when `depth` \>= `0`.
* 2. `import "./bar/baz"` when `depth` \>= `0`.
* 3. `import "../bar"` when `depth` \>= `1`.
*/
depth: number;
}

type ImportAliasOptions = {
aliasConfigPath?: string;
// TODO: A fuller solution might need a property for the position, but not sure if needed
aliasImportFunctions: string[];
/** An array defining which paths can be allowed to used relative imports within it to defined depths. */
relativeImportOverrides?: RelativeImportConfig[];
};

/**
Expand All @@ -97,6 +155,26 @@ const schemaProperties: Record<keyof ImportAliasOptions, JSONSchema4> = {
},
default: ["require", "mock"],
},
relativeImportOverrides: {
type: "array",
default: [],
items: {
type: "object",
properties: {
path: {
type: "string",
description:
"The starting path from which a relative depth is accepted.",
},
depth: {
type: "number",
description:
"A positive number which represents the" +
" relative depth that is acceptable for the associated path.",
},
},
},
},
};

const importAliasRule: Rule.RuleModule = {
Expand Down Expand Up @@ -125,6 +203,7 @@ const importAliasRule: Rule.RuleModule = {
aliasConfigPath,
aliasImportFunctions = schemaProperties.aliasImportFunctions
.default as string[],
relativeImportOverrides = [],
}: ImportAliasOptions = context.options[0] || {}; // No idea what the other array values are

const aliasesResult = loadAliasConfigs(cwd, aliasConfigPath);
Expand Down Expand Up @@ -160,6 +239,16 @@ const importAliasRule: Rule.RuleModule = {
// preserve user quote style
const quotelessRange: AST.Range = [moduleStart + 1, moduleEnd - 1];

if (
isPermittedRelativeImport(
importModuleName,
relativeImportOverrides,
absoluteDir
)
) {
return undefined;
}

const aliasSuggestion = getAliasSuggestion(
importModuleName,
aliasesResult,
Expand Down
Loading

0 comments on commit 54f95cd

Please sign in to comment.