286 lines
10 KiB
JavaScript
286 lines
10 KiB
JavaScript
"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 `**/<glob>/**`
|
||
* @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(/(?<!\\)#.*/g, '');
|
||
glob = trimGlobLeft(glob);
|
||
glob = trimGlobRight(glob);
|
||
return glob;
|
||
}
|
||
const spaces = {
|
||
' ': true,
|
||
'\t': true,
|
||
'\n': true,
|
||
'\r': true,
|
||
};
|
||
/**
|
||
* Trim any trailing spaces, tabs, line-feeds, or new-lines
|
||
* Handles a trailing \<space>
|
||
* @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
|