UNPKG

@rushstack/eslint-plugin

Version:

An ESLint plugin providing supplementary rules for use with the @rushstack/eslint-config package

66 lines 3.39 kB
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. import * as path from 'node:path'; import { getFilePathFromContext, parseImportSpecifierFromExpression, serializeImportSpecifier } from './LintUtilities'; export const MESSAGE_ID = 'error-normalized-imports'; export const normalizedImportsRule = { defaultOptions: [], meta: { type: 'suggestion', messages: { [MESSAGE_ID]: 'The specified import target path was not provided in a normalized form.' }, schema: [], docs: { description: 'Prevents and normalizes references to relative imports using paths that make unnecessary ' + 'traversals (ex. "../blah/module" in directory "blah" -> "./module")', url: 'https://www.npmjs.com/package/@rushstack/eslint-plugin' }, fixable: 'code' }, create: (context) => { const checkImportExpression = (importExpression) => { if (!importExpression) { // Can't validate, return return; } // Determine the target file path and find the most direct relative path from the source file const importSpecifier = parseImportSpecifierFromExpression(importExpression); if (!importSpecifier || !importSpecifier.importTarget.startsWith('.')) { // Can't validate, return return; } const { importTarget } = importSpecifier; const parentDirectory = path.dirname(getFilePathFromContext(context)); const absoluteImportPath = path.resolve(parentDirectory, importTarget); const relativeImportPath = path.relative(parentDirectory, absoluteImportPath); // Reconstruct the import target using posix separators and manually re-add the leading './' if needed let normalizedImportPath = path.sep !== '/' ? relativeImportPath.replace(/\\/g, '/') : relativeImportPath; if (!normalizedImportPath.startsWith('.')) { normalizedImportPath = `.${normalizedImportPath ? '/' : ''}${normalizedImportPath}`; } // If they don't match, suggest the normalized path as a fix if (importTarget !== normalizedImportPath) { context.report({ node: importExpression, messageId: MESSAGE_ID, fix: (fixer) => { // Re-include stripped loader and query strings, if provided const normalizedSpecifier = serializeImportSpecifier({ ...importSpecifier, importTarget: normalizedImportPath }); return fixer.replaceText(importExpression, `'${normalizedSpecifier}'`); } }); } }; return { ImportDeclaration: (node) => checkImportExpression(node.source), ImportExpression: (node) => checkImportExpression(node.source), ExportAllDeclaration: (node) => checkImportExpression(node.source), ExportNamedDeclaration: (node) => checkImportExpression(node.source) }; } }; //# sourceMappingURL=normalized-imports.js.map