UNPKG

eslint-plugin-import-sorting

Version:

ESLint plugin to group and sort imports by module, à la Python isort

110 lines (109 loc) 3.69 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const node_module = require("node:module"); const utils = require("@typescript-eslint/utils"); const order = require("../rules/order.cjs"); const useGroups = require("./use-groups.cjs"); function computeGroup(node, settings, sourceCode) { let { getGroup, defineGroup } = useGroups.useGroups(order.IMPORT_GROUPS); if (node.type === utils.AST_NODE_TYPES.ImportDeclaration || node.type === utils.AST_NODE_TYPES.VariableDeclaration) { let value; let frameworkPatterns = validateSetting(settings, "import-sorting/framework-patterns"); let internalPatterns = validateSetting(settings, "import-sorting/internal-patterns"); if (node.type === utils.AST_NODE_TYPES.ImportDeclaration) { value = node.source.value; } else { let decl = node.declarations[0].init; let declValue = decl.arguments[0].value; value = declValue.toString(); } if (isSideEffectImport(node, sourceCode)) defineGroup("unassigned"); if (isBuiltin(value)) defineGroup("builtin"); if (isStyle(value)) defineGroup("style"); if (frameworkPatterns && isFramework(value, frameworkPatterns)) defineGroup("framework"); if (internalPatterns && isInternal(value, internalPatterns)) defineGroup("internal"); if (isExternal(value)) defineGroup("external"); if (isLocal(value)) defineGroup("local"); } return getGroup(); } function isSideEffectImport(node, sourceCode) { return node.type === utils.AST_NODE_TYPES.ImportDeclaration && node.specifiers.length === 0 && /* Avoid matching on named imports without specifiers. */ !/}\s*from\s+/.test(sourceCode.getText(node)); } function isBuiltin(name) { let bunModules = [ "bun", "bun:ffi", "bun:jsc", "bun:sqlite", "bun:test", "bun:wrap", "detect-libc", "undici", "ws" ]; let builtinPrefixOnlyModules = ["sea", "sqlite", "test"]; return node_module.builtinModules.includes(name.startsWith("node:") ? name.split("node:")[1] : name) || builtinPrefixOnlyModules.some((module2) => `node:${module2}` === name) || bunModules.includes(name); } const moduleRegExp = /^\w/; function isModule(name) { return moduleRegExp.test(name); } const scopedRegExp = /^@[^/]+\/?[^/]+/; function isScoped(name) { return scopedRegExp.test(name); } function isFramework(name, pattern) { if (Array.isArray(pattern)) { return pattern.some((item) => new RegExp(item).test(name)); } return new RegExp(pattern).test(name); } function isExternal(name) { return isModule(name) || isScoped(name); } function isInternal(name, pattern) { if (Array.isArray(pattern)) { return pattern.some((item) => new RegExp(item).test(name)); } return new RegExp(pattern).test(name); } function isLocal(name) { return name.startsWith("."); } function isStyle(name) { return [".less", ".scss", ".sass", ".styl", ".pcss", ".css", ".sss"].some( (extension) => name.endsWith(extension) ); } function assertString(value, setting) { if (typeof value !== "string") throw new Error( // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `Invalid value for '${setting}': '${value}'. Expected 'string', got '${typeof value}' instead.` ); } function validateSetting(settings, setting) { let value = settings[setting]; if (!value) return void 0; if (Array.isArray(value)) { for (let item of value) { assertString(item, setting); } return value; } assertString(value, setting); return value; } exports.computeGroup = computeGroup; exports.isSideEffectImport = isSideEffectImport;