UNPKG

eslint-plugin-canonical

Version:
119 lines (118 loc) 5.09 kB
"use strict"; /* eslint-disable unicorn/no-array-reduce */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); /** * @author Steven Sojka * @see https://github.com/steelsojka/eslint-import-alias */ const node_path_1 = __importDefault(require("node:path")); const posix_1 = require("node:path/posix"); const win32_1 = require("node:path/win32"); const utilities_1 = require("../utilities"); const RELATIVE_MATCHER = /^(?:(\.\/)|(\.\.\/))+/u; const CWD = process.cwd(); exports.default = (0, utilities_1.createRule)({ create: (context, [options]) => { var _a; const { aliases: temporaryAliases = [], baseDirectory = CWD } = options; const aliases = temporaryAliases.map((temporaryAlias) => { return Object.assign(Object.assign({}, temporaryAlias), { matchPath: new RegExp(temporaryAlias.matchPath, 'u') }); }); const filename = (_a = context.filename) !== null && _a !== void 0 ? _a : context.getFilename(); return { ImportDeclaration(node) { var _a; const importValue = node.source.value; const accessor = (_a = importValue.match(RELATIVE_MATCHER)) === null || _a === void 0 ? void 0 : _a[0]; if (!accessor) { return; } const parsedPath = node_path_1.default.parse(filename); // e.g. grandparentAccessor => '../../' => 2 const depth = accessor === './' ? 0 : accessor.length / 3; const parentPath = node_path_1.default.resolve(baseDirectory, node_path_1.default.resolve(parsedPath.dir, '../'.repeat(depth))); const importPath = node_path_1.default .relative(baseDirectory, node_path_1.default.resolve(parsedPath.dir, importValue)) .replaceAll(win32_1.sep, posix_1.sep); for (const item of aliases) { const { alias, matchPath, matchParent, maxRelativeDepth = -1 } = item; if (maxRelativeDepth < -1) { throw new Error('maxRelativeDepth cannot be less than -1'); } if (depth < maxRelativeDepth) { continue; } if (matchParent && matchParent !== parentPath) { continue; } const pathMatch = importPath.match(matchPath); if (!pathMatch) { continue; } context.report({ data: { maxRelativeDepth, }, fix: (fixer) => { const matchingString = pathMatch[pathMatch.length - 1]; const index = pathMatch[0].indexOf(matchingString); const newImportPath = importPath.slice(0, index) + alias + importPath.slice(index + matchingString.length); return fixer.replaceTextRange([node.source.range[0] + 1, node.source.range[1] - 1], newImportPath); }, messageId: maxRelativeDepth === -1 ? 'mustBeAlias' : 'mustBeAliasOrShallow', node, }); break; } }, }; }, defaultOptions: [ { aliases: [], baseDirectory: process.cwd(), }, ], meta: { docs: { description: 'Restrict imports to path aliases or relative imports limited by depth.', }, fixable: 'code', messages: { mustBeAlias: 'Import path mush be a path alias', mustBeAliasOrShallow: 'Import statement must be an alias or no more than {{maxRelativeDepth}} levels deep', }, schema: [ { properties: { aliases: { items: { properties: { alias: { type: 'string' }, matchParent: { type: 'string' }, matchPath: { type: 'string' }, maxRelativeDepth: { type: 'number', }, }, required: ['alias', 'matchPath'], type: 'object', }, type: 'array', }, cwd: { type: 'string', }, }, type: 'object', }, ], type: 'problem', }, name: 'prefer-import-alias', });