UNPKG

eslint-plugin-export-scope

Version:

Don't leak LOCAL utils, states, components into the global scope

173 lines 6.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isSubPath = exports.getPathContext = exports.PathContextType = exports.generateAncestorPaths = exports.validateExceptionPath = exports.validateScopePath = exports.isAncestorPath = exports.getFullScopePath = exports.getRootDir = exports.getPathOfTheNearestConfig = exports.toPosix = exports.sameOrSubPath = void 0; const fs_1 = require("fs"); const path_1 = require("path"); // Platform-aware path operations const isWin = process.platform === "win32"; const fold = (s) => (isWin ? s.toLowerCase() : s); /** child is same as base or inside base (logical tree only). */ const sameOrSubPath = (base, child) => { const a = fold((0, path_1.resolve)(base)); const b = fold((0, path_1.resolve)(child)); if (a === b) return true; const rel = (0, path_1.relative)(a, b); return rel !== "" && !rel.startsWith("..") && !(0, path_1.isAbsolute)(rel); }; exports.sameOrSubPath = sameOrSubPath; exports.isSubPath = exports.sameOrSubPath; const toPosix = (p) => p.replace(/\\/g, "/"); exports.toPosix = toPosix; // Config and root directory utilities const nearestConfigMap = new Map(); const getPathOfTheNearestConfig = (originPath, configFileName) => { const configFileNames = Array.isArray(configFileName) ? configFileName : [configFileName]; const key = [originPath, configFileNames.join("_")].join("_"); if (nearestConfigMap.has(key)) { return nearestConfigMap.get(key); } const cacheResult = (result) => { nearestConfigMap.set(key, result); // clear cache after 1 second setTimeout(() => nearestConfigMap.delete(key), 1000); return result; }; let currentDir = originPath; while (currentDir !== "/") { const fileNames = (0, fs_1.readdirSync)(currentDir); const fileName = fileNames.find((x) => configFileNames.includes(x)); if (fileName) { return cacheResult((0, path_1.resolve)(currentDir, fileName)); } if (fileNames.includes("package.json")) { return cacheResult(null); } currentDir = (0, path_1.dirname)(currentDir); } return cacheResult(null); }; exports.getPathOfTheNearestConfig = getPathOfTheNearestConfig; const getRootDir = (originPath) => { const configPath = (0, exports.getPathOfTheNearestConfig)(originPath, "package.json"); return configPath ? (0, path_1.dirname)(configPath) : null; }; exports.getRootDir = getRootDir; const getFullScopePath = (exportDir, scope) => { if (scope.startsWith(".")) { return (0, path_1.resolve)(exportDir, scope); } const rootDir = (0, exports.getRootDir)(exportDir); if (!rootDir) return null; return (0, path_1.resolve)(rootDir, scope); }; exports.getFullScopePath = getFullScopePath; /** * Check if a path is an ancestor of the current directory (or is the current directory) */ const isAncestorPath = (currentDir, targetPath) => { // Use sameOrSubPath: target is ancestor if current is same or sub path of target return (0, exports.sameOrSubPath)(targetPath, currentDir); }; exports.isAncestorPath = isAncestorPath; /** * Validate a scope path for export default, @scope, and @scopeDefault * These should only allow ancestor directories or "*" */ const validateScopePath = (currentDir, scopePath) => { // Always allow wildcard if (scopePath === "*") { return { isValid: true }; } // Always allow current directory if (scopePath === ".") { return { isValid: true, resolvedPath: currentDir, isAncestor: true }; } const fullPath = (0, exports.getFullScopePath)(currentDir, scopePath); if (!fullPath) { return { isValid: false }; } const isAncestor = (0, exports.isAncestorPath)(currentDir, fullPath); return { isValid: isAncestor, resolvedPath: fullPath, isAncestor, }; }; exports.validateScopePath = validateScopePath; /** * Validate an exception path - can be any valid filesystem path */ const validateExceptionPath = (currentDir, exceptionPath) => { const fullPath = (0, exports.getFullScopePath)(currentDir, exceptionPath); if (!fullPath) { return { isValid: false }; } return { isValid: (0, fs_1.existsSync)(fullPath), resolvedPath: fullPath, isAncestor: (0, exports.isAncestorPath)(currentDir, fullPath), }; }; exports.validateExceptionPath = validateExceptionPath; /** * Generate all possible ancestor paths for autocompletion */ const generateAncestorPaths = (currentDir, rootDir) => { const paths = ["."]; let current = currentDir; let levelsUp = 0; const maxLevels = 10; // Reasonable limit while (current !== rootDir && levelsUp < maxLevels) { current = (0, path_1.dirname)(current); levelsUp++; // Add relative path (../, ../../, etc.) const relativePath = Array(levelsUp).fill("..").join("/"); paths.push(relativePath); // Add absolute path from root const relativeToRoot = (0, path_1.relative)(rootDir, current); if (relativeToRoot && relativeToRoot !== ".") { paths.push(relativeToRoot); } } return paths; }; exports.generateAncestorPaths = generateAncestorPaths; /** * Get path type for determining completion behavior */ var PathContextType; (function (PathContextType) { PathContextType["SCOPE_DEFAULT_EXPORT"] = "scope_default_export"; PathContextType["SCOPE_JSDOC"] = "scope_jsdoc"; PathContextType["SCOPE_DEFAULT_JSDOC"] = "scope_default_jsdoc"; PathContextType["SCOPE_EXCEPTION_JSDOC"] = "scope_exception_jsdoc"; PathContextType["EXCEPTIONS_ARRAY"] = "exceptions_array"; })(PathContextType || (exports.PathContextType = PathContextType = {})); const getPathContext = (text, position) => { const textBeforePosition = text.substring(0, position); // Check for export default in .scope files if (textBeforePosition.includes("export default") && text.includes(".scope.")) { return PathContextType.SCOPE_DEFAULT_EXPORT; } // Check for JSDoc contexts if (textBeforePosition.includes("@scope ") && !textBeforePosition.includes("@scopeDefault") && !textBeforePosition.includes("@scopeException")) { return PathContextType.SCOPE_JSDOC; } if (textBeforePosition.includes("@scopeDefault")) { return PathContextType.SCOPE_DEFAULT_JSDOC; } if (textBeforePosition.includes("@scopeException")) { return PathContextType.SCOPE_EXCEPTION_JSDOC; } // Check for exceptions array if (textBeforePosition.includes("export const exceptions")) { return PathContextType.EXCEPTIONS_ARRAY; } return null; }; exports.getPathContext = getPathContext; //# sourceMappingURL=pathUtils.js.map