"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.__testing__ = exports.normalizeGlobToRoot = exports.normalizeGlobPattern = exports.normalizeGlobPatterns = exports.isGlobPatternNormalized = exports.isGlobPatternWithRoot = exports.isGlobPatternWithOptionalRoot = exports.doesRootContainPath = exports.fileOrGlobToGlob = void 0; /* eslint-disable no-irregular-whitespace */ const Path = __importStar(require("path")); const { posix } = Path; const relRegExp = /^\.[\\/]/; /** * This function tries its best to determine if `fileOrGlob` is a path to a file or a glob pattern. * @param fileOrGlob - file (with absolute path) or glob. * @param root - absolute path to the directory that will be considered the root when testing the glob pattern. * @param path - optional node path methods - used for testing */ function fileOrGlobToGlob(fileOrGlob, root, path = Path) { var _a; const pathToGlob = path.sep === '\\' ? (p) => p.replace(/\\/g, '/') : (p) => p; if (typeof fileOrGlob !== 'string') { const useRoot = (_a = fileOrGlob.root) !== null && _a !== void 0 ? _a : root; return { ...fileOrGlob, root: useRoot }; } if (doesRootContainPath(root, fileOrGlob, path) || relRegExp.test(fileOrGlob)) { const rel = path.relative(root, path.resolve(root, fileOrGlob)); return { glob: pathToGlob(rel), root, }; } return { glob: pathToGlob(fileOrGlob), root, }; } exports.fileOrGlobToGlob = fileOrGlobToGlob; /** * Decide if a childPath is contained within a root or at the same level. * @param root - absolute path * @param childPath - absolute path */ function doesRootContainPath(root, child, path) { if (child.startsWith(root)) return true; const rel = path.relative(root, child); return !rel || (rel !== child && !rel.startsWith('..') && !path.isAbsolute(rel)); } exports.doesRootContainPath = doesRootContainPath; function isGlobPatternWithOptionalRoot(g) { return typeof g !== 'string' && typeof g.glob === 'string'; } exports.isGlobPatternWithOptionalRoot = isGlobPatternWithOptionalRoot; function isGlobPatternWithRoot(g) { return !!g.root; } exports.isGlobPatternWithRoot = isGlobPatternWithRoot; function isGlobPatternNormalized(g) { if (!isGlobPatternWithOptionalRoot(g)) return false; if (!isGlobPatternWithRoot(g)) return false; const gr = g; return 'rawGlob' in gr && 'rawRoot' in gr && typeof gr.rawGlob === 'string'; } exports.isGlobPatternNormalized = isGlobPatternNormalized; /** * @param pattern glob pattern * @param nested when true add `**​//​**` * @returns the set of matching globs. */ function normalizePattern(pattern, nested) { pattern = pattern.replace(/^(!!)+/, ''); const isNeg = pattern.startsWith('!'); const prefix = isNeg ? '!' : ''; pattern = isNeg ? pattern.slice(1) : pattern; const patterns = nested ? normalizePatternNested(pattern) : normalizePatternGeneral(pattern); return patterns.map((p) => prefix + p); } function normalizePatternNested(pattern) { // no slashes will match files names or folders if (!pattern.includes('/')) { if (pattern === '**') return ['**']; return ['**/' + pattern, '**/' + pattern + '/**']; } const hasLeadingSlash = pattern.startsWith('/'); pattern = hasLeadingSlash ? pattern.slice(1) : pattern; if (pattern.endsWith('/')) { // legacy behavior, if it only has a trailing slash, allow matching against a nested directory. return hasLeadingSlash || pattern.slice(0, -1).includes('/') ? [pattern + '**/*'] : ['**/' + pattern + '**/*']; } if (pattern.endsWith('**')) { return [pattern]; } return [pattern, pattern + '/**']; } function normalizePatternGeneral(pattern) { pattern = pattern.startsWith('/') ? pattern.slice(1) : pattern; pattern = pattern.endsWith('/') ? pattern + '**/*' : pattern; return [pattern]; } /** * * @param patterns - glob patterns to normalize. * @param options - Normalization options. */ function normalizeGlobPatterns(patterns, options) { function* normalize() { for (const glob of patterns) { if (isGlobPatternNormalized(glob)) { yield glob; continue; } yield* normalizeGlobPattern(glob, options); } } return [...normalize()]; } exports.normalizeGlobPatterns = normalizeGlobPatterns; function normalizeGlobPattern(g, options) { var _a; const { root, nodePath: path = Path, nested, cwd = Path.resolve() } = options; g = !isGlobPatternWithOptionalRoot(g) ? { glob: g } : g; const gr = { ...g, root: (_a = g.root) !== null && _a !== void 0 ? _a : root }; const rawRoot = gr.root; const rawGlob = g.glob; gr.glob = gr.glob.trim(); // trimGlob(g.glob); if (gr.glob.startsWith('${cwd}')) { gr.glob = gr.glob.replace('${cwd}', ''); gr.root = '${cwd}'; } if (gr.root.startsWith('${cwd}')) { gr.root = path.resolve(gr.root.replace('${cwd}', cwd)); } gr.root = path.resolve(root, path.normalize(gr.root)); const globs = normalizePattern(gr.glob, nested); return globs.map((glob) => ({ ...gr, glob, rawGlob, rawRoot })); } exports.normalizeGlobPattern = normalizeGlobPattern; /** * Try to adjust the root of a glob to match a new root. If it is not possible, the original glob is returned. * Note: this does NOT generate absolutely correct glob patterns. The results are intended to be used as a * first pass only filter. Followed by testing against the original glob/root pair. * @param glob - glob to map * @param root - new root to use if possible * @param path - Node Path modules to use (testing only) */ function normalizeGlobToRoot(glob, root, path) { function relToGlob(relativePath) { return path.sep === '\\' ? relativePath.replace(/\\/g, '/') : relativePath; } if (glob.root === root) { return glob; } const relFromRootToGlob = path.relative(root, glob.root); if (!relFromRootToGlob) { return glob; } const relFromGlobToRoot = path.relative(glob.root, root); const globIsUnderRoot = relFromRootToGlob[0] !== '.' && !path.isAbsolute(relFromRootToGlob); const rootIsUnderGlob = relFromGlobToRoot[0] !== '.' && !path.isAbsolute(relFromGlobToRoot); // Root and Glob are not in the same part of the directory tree. if (!globIsUnderRoot && !rootIsUnderGlob) { return glob; } const isNeg = glob.glob.startsWith('!'); const g = isNeg ? glob.glob.slice(1) : glob.glob; const prefix = isNeg ? '!' : ''; // prefix with root if (globIsUnderRoot) { const relGlob = relToGlob(relFromRootToGlob); return { ...glob, glob: prefix + posix.join(relGlob, g), root, }; } // The root is under the glob root // The more difficult case, the glob is higher than the root // A best effort is made, but does not do advanced matching. const relGlob = relToGlob(relFromGlobToRoot) + '/'; const rebasedGlob = rebaseGlob(g, relGlob); return rebasedGlob ? { ...glob, glob: prefix + rebasedGlob, root } : glob; } exports.normalizeGlobToRoot = normalizeGlobToRoot; /** * Rebase a glob string to a new prefix * @param glob - glob string * @param rebaseTo - glob prefix */ function rebaseGlob(glob, rebaseTo) { if (!rebaseTo || rebaseTo === '/') return glob; if (glob.startsWith('**')) return glob; rebaseTo = rebaseTo.endsWith('/') ? rebaseTo : rebaseTo + '/'; if (glob.startsWith(rebaseTo)) { return glob.slice(rebaseTo.length); } const relParts = rebaseTo.split('/'); const globParts = glob.split('/'); for (let i = 0; i < relParts.length && i < globParts.length; ++i) { const relSeg = relParts[i]; const globSeg = globParts[i]; // the empty segment due to the end relGlob / allows for us to test against an empty segment. if (!relSeg || globSeg === '**') { return globParts.slice(i).join('/'); } if (relSeg !== globSeg && globSeg !== '*') { break; } } return undefined; } /** * Trims any trailing spaces, tabs, line-feeds, new-lines, and comments * @param glob - glob string * @returns trimmed glob */ function trimGlob(glob) { glob = glob.replace(/(? * @param glob - glob string * @returns glob string with space to the right removed. */ function trimGlobRight(glob) { const lenMin1 = glob.length - 1; let i = lenMin1; while (i >= 0 && glob[i] in spaces) { --i; } if (glob[i] === '\\' && i < lenMin1) { ++i; } ++i; return i ? glob.slice(0, i) : ''; } /** * Trim any leading spaces, tabs, line-feeds, or new-lines * @param glob - any string * @returns string with leading spaces removed. */ function trimGlobLeft(glob) { let i = 0; while (i < glob.length && glob[i] in spaces) { ++i; } return glob.slice(i); } exports.__testing__ = { rebaseGlob, trimGlob, }; //# sourceMappingURL=globHelper.js.map