tinyglobby
Advanced tools
+37
-17
@@ -0,26 +1,46 @@ | ||
| //#region src/utils.d.ts | ||
| declare const convertPathToPattern: (path: string) => string; | ||
| declare const escapePath: (path: string) => string; | ||
| // #endregion | ||
| // #region isDynamicPattern | ||
| /* | ||
| Has a few minor differences with `fast-glob` for better accuracy: | ||
| Doesn't necessarily return false on patterns that include `\\`. | ||
| Returns true if the pattern includes parentheses, | ||
| regardless of them representing one single pattern or not. | ||
| Returns true for unfinished glob extensions i.e. `(h`, `+(h`. | ||
| Returns true for unfinished brace expansions as long as they include `,` or `..`. | ||
| */ | ||
| declare function isDynamicPattern(pattern: string, options?: { | ||
| caseSensitiveMatch: boolean; | ||
| }): boolean; | ||
| caseSensitiveMatch: boolean; | ||
| }): boolean; //#endregion | ||
| //#region src/index.d.ts | ||
| // #endregion | ||
| // #region log | ||
| interface GlobOptions { | ||
| absolute?: boolean; | ||
| cwd?: string; | ||
| patterns?: string | string[]; | ||
| ignore?: string | string[]; | ||
| dot?: boolean; | ||
| deep?: number; | ||
| followSymbolicLinks?: boolean; | ||
| caseSensitiveMatch?: boolean; | ||
| expandDirectories?: boolean; | ||
| onlyDirectories?: boolean; | ||
| onlyFiles?: boolean; | ||
| debug?: boolean; | ||
| absolute?: boolean; | ||
| cwd?: string; | ||
| patterns?: string | string[]; | ||
| ignore?: string | string[]; | ||
| dot?: boolean; | ||
| deep?: number; | ||
| followSymbolicLinks?: boolean; | ||
| caseSensitiveMatch?: boolean; | ||
| expandDirectories?: boolean; | ||
| onlyDirectories?: boolean; | ||
| onlyFiles?: boolean; | ||
| debug?: boolean; | ||
| } | ||
| declare function glob(patterns: string | string[], options?: Omit<GlobOptions, 'patterns'>): Promise<string[]>; | ||
| declare function glob(patterns: string | string[], options?: Omit<GlobOptions, "patterns">): Promise<string[]>; | ||
| declare function glob(options: GlobOptions): Promise<string[]>; | ||
| declare function globSync(patterns: string | string[], options?: Omit<GlobOptions, 'patterns'>): string[]; | ||
| declare function globSync(patterns: string | string[], options?: Omit<GlobOptions, "patterns">): string[]; | ||
| declare function globSync(options: GlobOptions): string[]; | ||
| export { type GlobOptions, convertPathToPattern, escapePath, glob, globSync, isDynamicPattern }; | ||
| //#endregion | ||
| export { GlobOptions, convertPathToPattern, escapePath, glob, globSync, isDynamicPattern }; |
+37
-17
@@ -0,26 +1,46 @@ | ||
| //#region src/utils.d.ts | ||
| declare const convertPathToPattern: (path: string) => string; | ||
| declare const escapePath: (path: string) => string; | ||
| // #endregion | ||
| // #region isDynamicPattern | ||
| /* | ||
| Has a few minor differences with `fast-glob` for better accuracy: | ||
| Doesn't necessarily return false on patterns that include `\\`. | ||
| Returns true if the pattern includes parentheses, | ||
| regardless of them representing one single pattern or not. | ||
| Returns true for unfinished glob extensions i.e. `(h`, `+(h`. | ||
| Returns true for unfinished brace expansions as long as they include `,` or `..`. | ||
| */ | ||
| declare function isDynamicPattern(pattern: string, options?: { | ||
| caseSensitiveMatch: boolean; | ||
| }): boolean; | ||
| caseSensitiveMatch: boolean; | ||
| }): boolean; //#endregion | ||
| //#region src/index.d.ts | ||
| // #endregion | ||
| // #region log | ||
| interface GlobOptions { | ||
| absolute?: boolean; | ||
| cwd?: string; | ||
| patterns?: string | string[]; | ||
| ignore?: string | string[]; | ||
| dot?: boolean; | ||
| deep?: number; | ||
| followSymbolicLinks?: boolean; | ||
| caseSensitiveMatch?: boolean; | ||
| expandDirectories?: boolean; | ||
| onlyDirectories?: boolean; | ||
| onlyFiles?: boolean; | ||
| debug?: boolean; | ||
| absolute?: boolean; | ||
| cwd?: string; | ||
| patterns?: string | string[]; | ||
| ignore?: string | string[]; | ||
| dot?: boolean; | ||
| deep?: number; | ||
| followSymbolicLinks?: boolean; | ||
| caseSensitiveMatch?: boolean; | ||
| expandDirectories?: boolean; | ||
| onlyDirectories?: boolean; | ||
| onlyFiles?: boolean; | ||
| debug?: boolean; | ||
| } | ||
| declare function glob(patterns: string | string[], options?: Omit<GlobOptions, 'patterns'>): Promise<string[]>; | ||
| declare function glob(patterns: string | string[], options?: Omit<GlobOptions, "patterns">): Promise<string[]>; | ||
| declare function glob(options: GlobOptions): Promise<string[]>; | ||
| declare function globSync(patterns: string | string[], options?: Omit<GlobOptions, 'patterns'>): string[]; | ||
| declare function globSync(patterns: string | string[], options?: Omit<GlobOptions, "patterns">): string[]; | ||
| declare function globSync(options: GlobOptions): string[]; | ||
| export { type GlobOptions, convertPathToPattern, escapePath, glob, globSync, isDynamicPattern }; | ||
| //#endregion | ||
| export { GlobOptions, convertPathToPattern, escapePath, glob, globSync, isDynamicPattern }; |
+233
-299
@@ -1,2 +0,2 @@ | ||
| "use strict"; | ||
| //#region rolldown:runtime | ||
| var __create = Object.create; | ||
@@ -8,327 +8,261 @@ var __defProp = Object.defineProperty; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { | ||
| key = keys[i]; | ||
| if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { | ||
| get: ((k) => from[k]).bind(null, key), | ||
| enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable | ||
| }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { | ||
| value: mod, | ||
| enumerable: true | ||
| }) : target, mod)); | ||
| // src/index.ts | ||
| var index_exports = {}; | ||
| __export(index_exports, { | ||
| convertPathToPattern: () => convertPathToPattern, | ||
| escapePath: () => escapePath, | ||
| glob: () => glob, | ||
| globSync: () => globSync, | ||
| isDynamicPattern: () => isDynamicPattern | ||
| }); | ||
| module.exports = __toCommonJS(index_exports); | ||
| var import_node_path = __toESM(require("path")); | ||
| var import_fdir = require("fdir"); | ||
| var import_picomatch2 = __toESM(require("picomatch")); | ||
| //#endregion | ||
| const path = __toESM(require("path")); | ||
| const fdir = __toESM(require("fdir")); | ||
| const picomatch = __toESM(require("picomatch")); | ||
| // src/utils.ts | ||
| var import_picomatch = __toESM(require("picomatch")); | ||
| var ONLY_PARENT_DIRECTORIES = /^(\/?\.\.)+$/; | ||
| //#region src/utils.ts | ||
| const ONLY_PARENT_DIRECTORIES = /^(\/?\.\.)+$/; | ||
| function getPartialMatcher(patterns, options) { | ||
| const patternsCount = patterns.length; | ||
| const patternsParts = Array(patternsCount); | ||
| const regexes = Array(patternsCount); | ||
| for (let i = 0; i < patternsCount; i++) { | ||
| const parts = splitPattern(patterns[i]); | ||
| patternsParts[i] = parts; | ||
| const partsCount = parts.length; | ||
| const partRegexes = Array(partsCount); | ||
| for (let j = 0; j < partsCount; j++) { | ||
| partRegexes[j] = import_picomatch.default.makeRe(parts[j], options); | ||
| } | ||
| regexes[i] = partRegexes; | ||
| } | ||
| return (input) => { | ||
| const inputParts = input.split("/"); | ||
| if (inputParts[0] === ".." && ONLY_PARENT_DIRECTORIES.test(input)) { | ||
| return true; | ||
| } | ||
| for (let i = 0; i < patterns.length; i++) { | ||
| const patternParts = patternsParts[i]; | ||
| const regex = regexes[i]; | ||
| const inputPatternCount = inputParts.length; | ||
| const minParts = Math.min(inputPatternCount, patternParts.length); | ||
| let j = 0; | ||
| while (j < minParts) { | ||
| const part = patternParts[j]; | ||
| if (part.includes("/")) { | ||
| return true; | ||
| } | ||
| const match = regex[j].test(inputParts[j]); | ||
| if (!match) { | ||
| break; | ||
| } | ||
| if (part === "**") { | ||
| return true; | ||
| } | ||
| j++; | ||
| } | ||
| if (j === inputPatternCount) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| }; | ||
| const patternsCount = patterns.length; | ||
| const patternsParts = Array(patternsCount); | ||
| const regexes = Array(patternsCount); | ||
| for (let i = 0; i < patternsCount; i++) { | ||
| const parts = splitPattern(patterns[i]); | ||
| patternsParts[i] = parts; | ||
| const partsCount = parts.length; | ||
| const partRegexes = Array(partsCount); | ||
| for (let j = 0; j < partsCount; j++) partRegexes[j] = picomatch.default.makeRe(parts[j], options); | ||
| regexes[i] = partRegexes; | ||
| } | ||
| return (input) => { | ||
| const inputParts = input.split("/"); | ||
| if (inputParts[0] === ".." && ONLY_PARENT_DIRECTORIES.test(input)) return true; | ||
| for (let i = 0; i < patterns.length; i++) { | ||
| const patternParts = patternsParts[i]; | ||
| const regex = regexes[i]; | ||
| const inputPatternCount = inputParts.length; | ||
| const minParts = Math.min(inputPatternCount, patternParts.length); | ||
| let j = 0; | ||
| while (j < minParts) { | ||
| const part = patternParts[j]; | ||
| if (part.includes("/")) return true; | ||
| const match = regex[j].test(inputParts[j]); | ||
| if (!match) break; | ||
| if (part === "**") return true; | ||
| j++; | ||
| } | ||
| if (j === inputPatternCount) return true; | ||
| } | ||
| return false; | ||
| }; | ||
| } | ||
| var splitPatternOptions = { parts: true }; | ||
| function splitPattern(path2) { | ||
| var _a; | ||
| const result = import_picomatch.default.scan(path2, splitPatternOptions); | ||
| return ((_a = result.parts) == null ? void 0 : _a.length) ? result.parts : [path2]; | ||
| const splitPatternOptions = { parts: true }; | ||
| function splitPattern(path$2) { | ||
| var _result$parts; | ||
| const result = picomatch.default.scan(path$2, splitPatternOptions); | ||
| return ((_result$parts = result.parts) === null || _result$parts === void 0 ? void 0 : _result$parts.length) ? result.parts : [path$2]; | ||
| } | ||
| var isWin = process.platform === "win32"; | ||
| var ESCAPED_WIN32_BACKSLASHES = /\\(?![()[\]{}!+@])/g; | ||
| function convertPosixPathToPattern(path2) { | ||
| return escapePosixPath(path2); | ||
| const isWin = process.platform === "win32"; | ||
| const ESCAPED_WIN32_BACKSLASHES = /\\(?![()[\]{}!+@])/g; | ||
| function convertPosixPathToPattern(path$2) { | ||
| return escapePosixPath(path$2); | ||
| } | ||
| function convertWin32PathToPattern(path2) { | ||
| return escapeWin32Path(path2).replace(ESCAPED_WIN32_BACKSLASHES, "/"); | ||
| function convertWin32PathToPattern(path$2) { | ||
| return escapeWin32Path(path$2).replace(ESCAPED_WIN32_BACKSLASHES, "/"); | ||
| } | ||
| var convertPathToPattern = isWin ? convertWin32PathToPattern : convertPosixPathToPattern; | ||
| var POSIX_UNESCAPED_GLOB_SYMBOLS = /(?<!\\)([()[\]{}*?|]|^!|[!+@](?=\()|\\(?![()[\]{}!*+?@|]))/g; | ||
| var WIN32_UNESCAPED_GLOB_SYMBOLS = /(?<!\\)([()[\]{}]|^!|[!+@](?=\())/g; | ||
| var escapePosixPath = (path2) => path2.replace(POSIX_UNESCAPED_GLOB_SYMBOLS, "\\$&"); | ||
| var escapeWin32Path = (path2) => path2.replace(WIN32_UNESCAPED_GLOB_SYMBOLS, "\\$&"); | ||
| var escapePath = isWin ? escapeWin32Path : escapePosixPath; | ||
| const convertPathToPattern = isWin ? convertWin32PathToPattern : convertPosixPathToPattern; | ||
| const POSIX_UNESCAPED_GLOB_SYMBOLS = /(?<!\\)([()[\]{}*?|]|^!|[!+@](?=\()|\\(?![()[\]{}!*+?@|]))/g; | ||
| const WIN32_UNESCAPED_GLOB_SYMBOLS = /(?<!\\)([()[\]{}]|^!|[!+@](?=\())/g; | ||
| const escapePosixPath = (path$2) => path$2.replace(POSIX_UNESCAPED_GLOB_SYMBOLS, "\\$&"); | ||
| const escapeWin32Path = (path$2) => path$2.replace(WIN32_UNESCAPED_GLOB_SYMBOLS, "\\$&"); | ||
| const escapePath = isWin ? escapeWin32Path : escapePosixPath; | ||
| function isDynamicPattern(pattern, options) { | ||
| if ((options == null ? void 0 : options.caseSensitiveMatch) === false) { | ||
| return true; | ||
| } | ||
| const scan = import_picomatch.default.scan(pattern); | ||
| return scan.isGlob || scan.negated; | ||
| if ((options === null || options === void 0 ? void 0 : options.caseSensitiveMatch) === false) return true; | ||
| const scan = picomatch.default.scan(pattern); | ||
| return scan.isGlob || scan.negated; | ||
| } | ||
| function log(...tasks) { | ||
| console.log(`[tinyglobby ${(/* @__PURE__ */ new Date()).toLocaleTimeString("es")}]`, ...tasks); | ||
| console.log(`[tinyglobby ${new Date().toLocaleTimeString("es")}]`, ...tasks); | ||
| } | ||
| // src/index.ts | ||
| var PARENT_DIRECTORY = /^(\/?\.\.)+/; | ||
| var ESCAPING_BACKSLASHES = /\\(?=[()[\]{}!*+?@|])/g; | ||
| var BACKSLASHES = /\\/g; | ||
| //#endregion | ||
| //#region src/index.ts | ||
| const PARENT_DIRECTORY = /^(\/?\.\.)+/; | ||
| const ESCAPING_BACKSLASHES = /\\(?=[()[\]{}!*+?@|])/g; | ||
| const BACKSLASHES = /\\/g; | ||
| function normalizePattern(pattern, expandDirectories, cwd, props, isIgnore) { | ||
| var _a; | ||
| let result = pattern; | ||
| if (pattern.endsWith("/")) { | ||
| result = pattern.slice(0, -1); | ||
| } | ||
| if (!result.endsWith("*") && expandDirectories) { | ||
| result += "/**"; | ||
| } | ||
| if (import_node_path.default.isAbsolute(result.replace(ESCAPING_BACKSLASHES, ""))) { | ||
| result = import_node_path.posix.relative(escapePath(cwd), result); | ||
| } else { | ||
| result = import_node_path.posix.normalize(result); | ||
| } | ||
| const parentDirectoryMatch = PARENT_DIRECTORY.exec(result); | ||
| if (parentDirectoryMatch == null ? void 0 : parentDirectoryMatch[0]) { | ||
| const potentialRoot = import_node_path.posix.join(cwd, parentDirectoryMatch[0]); | ||
| if (props.root.length > potentialRoot.length) { | ||
| props.root = potentialRoot; | ||
| props.depthOffset = -(parentDirectoryMatch[0].length + 1) / 3; | ||
| } | ||
| } else if (!isIgnore && props.depthOffset >= 0) { | ||
| const parts = splitPattern(result); | ||
| (_a = props.commonPath) != null ? _a : props.commonPath = parts; | ||
| const newCommonPath = []; | ||
| const length = Math.min(props.commonPath.length, parts.length); | ||
| for (let i = 0; i < length; i++) { | ||
| const part = parts[i]; | ||
| if (part === "**" && !parts[i + 1]) { | ||
| newCommonPath.pop(); | ||
| break; | ||
| } | ||
| if (part !== props.commonPath[i] || isDynamicPattern(part) || i === parts.length - 1) { | ||
| break; | ||
| } | ||
| newCommonPath.push(part); | ||
| } | ||
| props.depthOffset = newCommonPath.length; | ||
| props.commonPath = newCommonPath; | ||
| props.root = newCommonPath.length > 0 ? import_node_path.default.posix.join(cwd, ...newCommonPath) : cwd; | ||
| } | ||
| return result; | ||
| let result = pattern; | ||
| if (pattern.endsWith("/")) result = pattern.slice(0, -1); | ||
| if (!result.endsWith("*") && expandDirectories) result += "/**"; | ||
| const escapedCwd = escapePath(cwd); | ||
| if (path.default.isAbsolute(result.replace(ESCAPING_BACKSLASHES, ""))) result = path.posix.relative(escapedCwd, result); | ||
| else result = path.posix.normalize(result); | ||
| const parentDirectoryMatch = PARENT_DIRECTORY.exec(result); | ||
| const parts = splitPattern(result); | ||
| if (parentDirectoryMatch === null || parentDirectoryMatch === void 0 ? void 0 : parentDirectoryMatch[0]) { | ||
| const n = (parentDirectoryMatch[0].length + 1) / 3; | ||
| let i = 0; | ||
| const cwdParts = escapedCwd.split("/"); | ||
| while (i < n && parts[i + n] === cwdParts[cwdParts.length + i - n]) { | ||
| result = result.slice(0, (n - i - 1) * 3) + result.slice((n - i) * 3 + parts[i + n].length + 1) || "."; | ||
| i++; | ||
| } | ||
| const potentialRoot = path.posix.join(cwd, parentDirectoryMatch[0].slice(i * 3)); | ||
| if (!potentialRoot.startsWith(".") && props.root.length > potentialRoot.length) { | ||
| props.root = potentialRoot; | ||
| props.depthOffset = -n + i; | ||
| } | ||
| } | ||
| if (!isIgnore && props.depthOffset >= 0) { | ||
| var _props$commonPath; | ||
| (_props$commonPath = props.commonPath) !== null && _props$commonPath !== void 0 || (props.commonPath = parts); | ||
| const newCommonPath = []; | ||
| const length = Math.min(props.commonPath.length, parts.length); | ||
| for (let i = 0; i < length; i++) { | ||
| const part = parts[i]; | ||
| if (part === "**" && !parts[i + 1]) { | ||
| newCommonPath.pop(); | ||
| break; | ||
| } | ||
| if (part !== props.commonPath[i] || isDynamicPattern(part) || i === parts.length - 1) break; | ||
| newCommonPath.push(part); | ||
| } | ||
| props.depthOffset = newCommonPath.length; | ||
| props.commonPath = newCommonPath; | ||
| props.root = newCommonPath.length > 0 ? path.default.posix.join(cwd, ...newCommonPath) : cwd; | ||
| } | ||
| return result; | ||
| } | ||
| function processPatterns({ patterns, ignore = [], expandDirectories = true }, cwd, props) { | ||
| if (typeof patterns === "string") { | ||
| patterns = [patterns]; | ||
| } else if (!patterns) { | ||
| patterns = ["**/*"]; | ||
| } | ||
| if (typeof ignore === "string") { | ||
| ignore = [ignore]; | ||
| } | ||
| const matchPatterns = []; | ||
| const ignorePatterns = []; | ||
| for (const pattern of ignore) { | ||
| if (!pattern) { | ||
| continue; | ||
| } | ||
| if (pattern[0] !== "!" || pattern[1] === "(") { | ||
| ignorePatterns.push(normalizePattern(pattern, expandDirectories, cwd, props, true)); | ||
| } | ||
| } | ||
| for (const pattern of patterns) { | ||
| if (!pattern) { | ||
| continue; | ||
| } | ||
| if (pattern[0] !== "!" || pattern[1] === "(") { | ||
| matchPatterns.push(normalizePattern(pattern, expandDirectories, cwd, props, false)); | ||
| } else if (pattern[1] !== "!" || pattern[2] === "(") { | ||
| ignorePatterns.push(normalizePattern(pattern.slice(1), expandDirectories, cwd, props, true)); | ||
| } | ||
| } | ||
| return { match: matchPatterns, ignore: ignorePatterns }; | ||
| if (typeof patterns === "string") patterns = [patterns]; | ||
| else if (!patterns) patterns = ["**/*"]; | ||
| if (typeof ignore === "string") ignore = [ignore]; | ||
| const matchPatterns = []; | ||
| const ignorePatterns = []; | ||
| for (const pattern of ignore) { | ||
| if (!pattern) continue; | ||
| if (pattern[0] !== "!" || pattern[1] === "(") ignorePatterns.push(normalizePattern(pattern, expandDirectories, cwd, props, true)); | ||
| } | ||
| for (const pattern of patterns) { | ||
| if (!pattern) continue; | ||
| if (pattern[0] !== "!" || pattern[1] === "(") matchPatterns.push(normalizePattern(pattern, expandDirectories, cwd, props, false)); | ||
| else if (pattern[1] !== "!" || pattern[2] === "(") ignorePatterns.push(normalizePattern(pattern.slice(1), expandDirectories, cwd, props, true)); | ||
| } | ||
| return { | ||
| match: matchPatterns, | ||
| ignore: ignorePatterns | ||
| }; | ||
| } | ||
| function getRelativePath(path2, cwd, root) { | ||
| return import_node_path.posix.relative(cwd, `${root}/${path2}`) || "."; | ||
| function getRelativePath(path$2, cwd, root) { | ||
| return path.posix.relative(cwd, `${root}/${path$2}`) || "."; | ||
| } | ||
| function processPath(path2, cwd, root, isDirectory, absolute) { | ||
| const relativePath = absolute ? path2.slice(root === "/" ? 1 : root.length + 1) || "." : path2; | ||
| if (root === cwd) { | ||
| return isDirectory && relativePath !== "." ? relativePath.slice(0, -1) : relativePath; | ||
| } | ||
| return getRelativePath(relativePath, cwd, root); | ||
| function processPath(path$2, cwd, root, isDirectory, absolute) { | ||
| const relativePath = absolute ? path$2.slice(root === "/" ? 1 : root.length + 1) || "." : path$2; | ||
| if (root === cwd) return isDirectory && relativePath !== "." ? relativePath.slice(0, -1) : relativePath; | ||
| return getRelativePath(relativePath, cwd, root); | ||
| } | ||
| function formatPaths(paths, cwd, root) { | ||
| for (let i = paths.length - 1; i >= 0; i--) { | ||
| const path2 = paths[i]; | ||
| paths[i] = getRelativePath(path2, cwd, root) + (!path2 || path2.endsWith("/") ? "/" : ""); | ||
| } | ||
| return paths; | ||
| for (let i = paths.length - 1; i >= 0; i--) { | ||
| const path$2 = paths[i]; | ||
| paths[i] = getRelativePath(path$2, cwd, root) + (!path$2 || path$2.endsWith("/") ? "/" : ""); | ||
| } | ||
| return paths; | ||
| } | ||
| function crawl(options, cwd, sync) { | ||
| if (process.env.TINYGLOBBY_DEBUG) { | ||
| options.debug = true; | ||
| } | ||
| if (options.debug) { | ||
| log("globbing with options:", options, "cwd:", cwd); | ||
| } | ||
| if (Array.isArray(options.patterns) && options.patterns.length === 0) { | ||
| return sync ? [] : Promise.resolve([]); | ||
| } | ||
| const props = { | ||
| root: cwd, | ||
| commonPath: null, | ||
| depthOffset: 0 | ||
| }; | ||
| const processed = processPatterns(options, cwd, props); | ||
| const nocase = options.caseSensitiveMatch === false; | ||
| if (options.debug) { | ||
| log("internal processing patterns:", processed); | ||
| } | ||
| const matcher = (0, import_picomatch2.default)(processed.match, { | ||
| dot: options.dot, | ||
| nocase, | ||
| ignore: processed.ignore | ||
| }); | ||
| const ignore = (0, import_picomatch2.default)(processed.ignore, { | ||
| dot: options.dot, | ||
| nocase | ||
| }); | ||
| const partialMatcher = getPartialMatcher(processed.match, { | ||
| dot: options.dot, | ||
| nocase | ||
| }); | ||
| const fdirOptions = { | ||
| // use relative paths in the matcher | ||
| filters: [ | ||
| options.debug ? (p, isDirectory) => { | ||
| const path2 = processPath(p, cwd, props.root, isDirectory, options.absolute); | ||
| const matches = matcher(path2); | ||
| if (matches) { | ||
| log(`matched ${path2}`); | ||
| } | ||
| return matches; | ||
| } : (p, isDirectory) => matcher(processPath(p, cwd, props.root, isDirectory, options.absolute)) | ||
| ], | ||
| exclude: options.debug ? (_, p) => { | ||
| const relativePath = processPath(p, cwd, props.root, true, true); | ||
| const skipped = relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath); | ||
| if (skipped) { | ||
| log(`skipped ${p}`); | ||
| } else { | ||
| log(`crawling ${p}`); | ||
| } | ||
| return skipped; | ||
| } : (_, p) => { | ||
| const relativePath = processPath(p, cwd, props.root, true, true); | ||
| return relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath); | ||
| }, | ||
| pathSeparator: "/", | ||
| relativePaths: true, | ||
| resolveSymlinks: true | ||
| }; | ||
| if (options.deep) { | ||
| fdirOptions.maxDepth = Math.round(options.deep - props.depthOffset); | ||
| } | ||
| if (options.absolute) { | ||
| fdirOptions.relativePaths = false; | ||
| fdirOptions.resolvePaths = true; | ||
| fdirOptions.includeBasePath = true; | ||
| } | ||
| if (options.followSymbolicLinks === false) { | ||
| fdirOptions.resolveSymlinks = false; | ||
| fdirOptions.excludeSymlinks = true; | ||
| } | ||
| if (options.onlyDirectories) { | ||
| fdirOptions.excludeFiles = true; | ||
| fdirOptions.includeDirs = true; | ||
| } else if (options.onlyFiles === false) { | ||
| fdirOptions.includeDirs = true; | ||
| } | ||
| props.root = props.root.replace(BACKSLASHES, ""); | ||
| const root = props.root; | ||
| if (options.debug) { | ||
| log("internal properties:", props); | ||
| } | ||
| const api = new import_fdir.fdir(fdirOptions).crawl(root); | ||
| if (cwd === root || options.absolute) { | ||
| return sync ? api.sync() : api.withPromise(); | ||
| } | ||
| return sync ? formatPaths(api.sync(), cwd, root) : api.withPromise().then((paths) => formatPaths(paths, cwd, root)); | ||
| if (process.env.TINYGLOBBY_DEBUG) options.debug = true; | ||
| if (options.debug) log("globbing with options:", options, "cwd:", cwd); | ||
| if (Array.isArray(options.patterns) && options.patterns.length === 0) return sync ? [] : Promise.resolve([]); | ||
| const props = { | ||
| root: cwd, | ||
| commonPath: null, | ||
| depthOffset: 0 | ||
| }; | ||
| const processed = processPatterns(options, cwd, props); | ||
| const nocase = options.caseSensitiveMatch === false; | ||
| if (options.debug) log("internal processing patterns:", processed); | ||
| const matcher = (0, picomatch.default)(processed.match, { | ||
| dot: options.dot, | ||
| nocase, | ||
| ignore: processed.ignore | ||
| }); | ||
| const ignore = (0, picomatch.default)(processed.ignore, { | ||
| dot: options.dot, | ||
| nocase | ||
| }); | ||
| const partialMatcher = getPartialMatcher(processed.match, { | ||
| dot: options.dot, | ||
| nocase | ||
| }); | ||
| const fdirOptions = { | ||
| filters: [options.debug ? (p, isDirectory) => { | ||
| const path$2 = processPath(p, cwd, props.root, isDirectory, options.absolute); | ||
| const matches = matcher(path$2); | ||
| if (matches) log(`matched ${path$2}`); | ||
| return matches; | ||
| } : (p, isDirectory) => matcher(processPath(p, cwd, props.root, isDirectory, options.absolute))], | ||
| exclude: options.debug ? (_, p) => { | ||
| const relativePath = processPath(p, cwd, props.root, true, true); | ||
| const skipped = relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath); | ||
| if (skipped) log(`skipped ${p}`); | ||
| else log(`crawling ${p}`); | ||
| return skipped; | ||
| } : (_, p) => { | ||
| const relativePath = processPath(p, cwd, props.root, true, true); | ||
| return relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath); | ||
| }, | ||
| pathSeparator: "/", | ||
| relativePaths: true, | ||
| resolveSymlinks: true | ||
| }; | ||
| if (options.deep !== void 0) fdirOptions.maxDepth = Math.round(options.deep - props.depthOffset); | ||
| if (options.absolute) { | ||
| fdirOptions.relativePaths = false; | ||
| fdirOptions.resolvePaths = true; | ||
| fdirOptions.includeBasePath = true; | ||
| } | ||
| if (options.followSymbolicLinks === false) { | ||
| fdirOptions.resolveSymlinks = false; | ||
| fdirOptions.excludeSymlinks = true; | ||
| } | ||
| if (options.onlyDirectories) { | ||
| fdirOptions.excludeFiles = true; | ||
| fdirOptions.includeDirs = true; | ||
| } else if (options.onlyFiles === false) fdirOptions.includeDirs = true; | ||
| props.root = props.root.replace(BACKSLASHES, ""); | ||
| const root = props.root; | ||
| if (options.debug) log("internal properties:", props); | ||
| const api = new fdir.fdir(fdirOptions).crawl(root); | ||
| if (cwd === root || options.absolute) return sync ? api.sync() : api.withPromise(); | ||
| return sync ? formatPaths(api.sync(), cwd, root) : api.withPromise().then((paths) => formatPaths(paths, cwd, root)); | ||
| } | ||
| async function glob(patternsOrOptions, options) { | ||
| if (patternsOrOptions && (options == null ? void 0 : options.patterns)) { | ||
| throw new Error("Cannot pass patterns as both an argument and an option"); | ||
| } | ||
| const opts = Array.isArray(patternsOrOptions) || typeof patternsOrOptions === "string" ? { ...options, patterns: patternsOrOptions } : patternsOrOptions; | ||
| const cwd = opts.cwd ? import_node_path.default.resolve(opts.cwd).replace(BACKSLASHES, "/") : process.cwd().replace(BACKSLASHES, "/"); | ||
| return crawl(opts, cwd, false); | ||
| if (patternsOrOptions && (options === null || options === void 0 ? void 0 : options.patterns)) throw new Error("Cannot pass patterns as both an argument and an option"); | ||
| const opts = Array.isArray(patternsOrOptions) || typeof patternsOrOptions === "string" ? { | ||
| ...options, | ||
| patterns: patternsOrOptions | ||
| } : patternsOrOptions; | ||
| const cwd = opts.cwd ? path.default.resolve(opts.cwd).replace(BACKSLASHES, "/") : process.cwd().replace(BACKSLASHES, "/"); | ||
| return crawl(opts, cwd, false); | ||
| } | ||
| function globSync(patternsOrOptions, options) { | ||
| if (patternsOrOptions && (options == null ? void 0 : options.patterns)) { | ||
| throw new Error("Cannot pass patterns as both an argument and an option"); | ||
| } | ||
| const opts = Array.isArray(patternsOrOptions) || typeof patternsOrOptions === "string" ? { ...options, patterns: patternsOrOptions } : patternsOrOptions; | ||
| const cwd = opts.cwd ? import_node_path.default.resolve(opts.cwd).replace(BACKSLASHES, "/") : process.cwd().replace(BACKSLASHES, "/"); | ||
| return crawl(opts, cwd, true); | ||
| if (patternsOrOptions && (options === null || options === void 0 ? void 0 : options.patterns)) throw new Error("Cannot pass patterns as both an argument and an option"); | ||
| const opts = Array.isArray(patternsOrOptions) || typeof patternsOrOptions === "string" ? { | ||
| ...options, | ||
| patterns: patternsOrOptions | ||
| } : patternsOrOptions; | ||
| const cwd = opts.cwd ? path.default.resolve(opts.cwd).replace(BACKSLASHES, "/") : process.cwd().replace(BACKSLASHES, "/"); | ||
| return crawl(opts, cwd, true); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| convertPathToPattern, | ||
| escapePath, | ||
| glob, | ||
| globSync, | ||
| isDynamicPattern | ||
| }); | ||
| //#endregion | ||
| exports.convertPathToPattern = convertPathToPattern; | ||
| exports.escapePath = escapePath; | ||
| exports.glob = glob; | ||
| exports.globSync = globSync; | ||
| exports.isDynamicPattern = isDynamicPattern; |
+213
-267
@@ -1,294 +0,240 @@ | ||
| // src/index.ts | ||
| import path, { posix } from "path"; | ||
| import { fdir } from "fdir"; | ||
| import picomatch2 from "picomatch"; | ||
| import picomatch from "picomatch"; | ||
| // src/utils.ts | ||
| import picomatch from "picomatch"; | ||
| var ONLY_PARENT_DIRECTORIES = /^(\/?\.\.)+$/; | ||
| //#region src/utils.ts | ||
| const ONLY_PARENT_DIRECTORIES = /^(\/?\.\.)+$/; | ||
| function getPartialMatcher(patterns, options) { | ||
| const patternsCount = patterns.length; | ||
| const patternsParts = Array(patternsCount); | ||
| const regexes = Array(patternsCount); | ||
| for (let i = 0; i < patternsCount; i++) { | ||
| const parts = splitPattern(patterns[i]); | ||
| patternsParts[i] = parts; | ||
| const partsCount = parts.length; | ||
| const partRegexes = Array(partsCount); | ||
| for (let j = 0; j < partsCount; j++) { | ||
| partRegexes[j] = picomatch.makeRe(parts[j], options); | ||
| } | ||
| regexes[i] = partRegexes; | ||
| } | ||
| return (input) => { | ||
| const inputParts = input.split("/"); | ||
| if (inputParts[0] === ".." && ONLY_PARENT_DIRECTORIES.test(input)) { | ||
| return true; | ||
| } | ||
| for (let i = 0; i < patterns.length; i++) { | ||
| const patternParts = patternsParts[i]; | ||
| const regex = regexes[i]; | ||
| const inputPatternCount = inputParts.length; | ||
| const minParts = Math.min(inputPatternCount, patternParts.length); | ||
| let j = 0; | ||
| while (j < minParts) { | ||
| const part = patternParts[j]; | ||
| if (part.includes("/")) { | ||
| return true; | ||
| } | ||
| const match = regex[j].test(inputParts[j]); | ||
| if (!match) { | ||
| break; | ||
| } | ||
| if (part === "**") { | ||
| return true; | ||
| } | ||
| j++; | ||
| } | ||
| if (j === inputPatternCount) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| }; | ||
| const patternsCount = patterns.length; | ||
| const patternsParts = Array(patternsCount); | ||
| const regexes = Array(patternsCount); | ||
| for (let i = 0; i < patternsCount; i++) { | ||
| const parts = splitPattern(patterns[i]); | ||
| patternsParts[i] = parts; | ||
| const partsCount = parts.length; | ||
| const partRegexes = Array(partsCount); | ||
| for (let j = 0; j < partsCount; j++) partRegexes[j] = picomatch.makeRe(parts[j], options); | ||
| regexes[i] = partRegexes; | ||
| } | ||
| return (input) => { | ||
| const inputParts = input.split("/"); | ||
| if (inputParts[0] === ".." && ONLY_PARENT_DIRECTORIES.test(input)) return true; | ||
| for (let i = 0; i < patterns.length; i++) { | ||
| const patternParts = patternsParts[i]; | ||
| const regex = regexes[i]; | ||
| const inputPatternCount = inputParts.length; | ||
| const minParts = Math.min(inputPatternCount, patternParts.length); | ||
| let j = 0; | ||
| while (j < minParts) { | ||
| const part = patternParts[j]; | ||
| if (part.includes("/")) return true; | ||
| const match = regex[j].test(inputParts[j]); | ||
| if (!match) break; | ||
| if (part === "**") return true; | ||
| j++; | ||
| } | ||
| if (j === inputPatternCount) return true; | ||
| } | ||
| return false; | ||
| }; | ||
| } | ||
| var splitPatternOptions = { parts: true }; | ||
| function splitPattern(path2) { | ||
| var _a; | ||
| const result = picomatch.scan(path2, splitPatternOptions); | ||
| return ((_a = result.parts) == null ? void 0 : _a.length) ? result.parts : [path2]; | ||
| const splitPatternOptions = { parts: true }; | ||
| function splitPattern(path$1) { | ||
| var _result$parts; | ||
| const result = picomatch.scan(path$1, splitPatternOptions); | ||
| return ((_result$parts = result.parts) === null || _result$parts === void 0 ? void 0 : _result$parts.length) ? result.parts : [path$1]; | ||
| } | ||
| var isWin = process.platform === "win32"; | ||
| var ESCAPED_WIN32_BACKSLASHES = /\\(?![()[\]{}!+@])/g; | ||
| function convertPosixPathToPattern(path2) { | ||
| return escapePosixPath(path2); | ||
| const isWin = process.platform === "win32"; | ||
| const ESCAPED_WIN32_BACKSLASHES = /\\(?![()[\]{}!+@])/g; | ||
| function convertPosixPathToPattern(path$1) { | ||
| return escapePosixPath(path$1); | ||
| } | ||
| function convertWin32PathToPattern(path2) { | ||
| return escapeWin32Path(path2).replace(ESCAPED_WIN32_BACKSLASHES, "/"); | ||
| function convertWin32PathToPattern(path$1) { | ||
| return escapeWin32Path(path$1).replace(ESCAPED_WIN32_BACKSLASHES, "/"); | ||
| } | ||
| var convertPathToPattern = isWin ? convertWin32PathToPattern : convertPosixPathToPattern; | ||
| var POSIX_UNESCAPED_GLOB_SYMBOLS = /(?<!\\)([()[\]{}*?|]|^!|[!+@](?=\()|\\(?![()[\]{}!*+?@|]))/g; | ||
| var WIN32_UNESCAPED_GLOB_SYMBOLS = /(?<!\\)([()[\]{}]|^!|[!+@](?=\())/g; | ||
| var escapePosixPath = (path2) => path2.replace(POSIX_UNESCAPED_GLOB_SYMBOLS, "\\$&"); | ||
| var escapeWin32Path = (path2) => path2.replace(WIN32_UNESCAPED_GLOB_SYMBOLS, "\\$&"); | ||
| var escapePath = isWin ? escapeWin32Path : escapePosixPath; | ||
| const convertPathToPattern = isWin ? convertWin32PathToPattern : convertPosixPathToPattern; | ||
| const POSIX_UNESCAPED_GLOB_SYMBOLS = /(?<!\\)([()[\]{}*?|]|^!|[!+@](?=\()|\\(?![()[\]{}!*+?@|]))/g; | ||
| const WIN32_UNESCAPED_GLOB_SYMBOLS = /(?<!\\)([()[\]{}]|^!|[!+@](?=\())/g; | ||
| const escapePosixPath = (path$1) => path$1.replace(POSIX_UNESCAPED_GLOB_SYMBOLS, "\\$&"); | ||
| const escapeWin32Path = (path$1) => path$1.replace(WIN32_UNESCAPED_GLOB_SYMBOLS, "\\$&"); | ||
| const escapePath = isWin ? escapeWin32Path : escapePosixPath; | ||
| function isDynamicPattern(pattern, options) { | ||
| if ((options == null ? void 0 : options.caseSensitiveMatch) === false) { | ||
| return true; | ||
| } | ||
| const scan = picomatch.scan(pattern); | ||
| return scan.isGlob || scan.negated; | ||
| if ((options === null || options === void 0 ? void 0 : options.caseSensitiveMatch) === false) return true; | ||
| const scan = picomatch.scan(pattern); | ||
| return scan.isGlob || scan.negated; | ||
| } | ||
| function log(...tasks) { | ||
| console.log(`[tinyglobby ${(/* @__PURE__ */ new Date()).toLocaleTimeString("es")}]`, ...tasks); | ||
| console.log(`[tinyglobby ${new Date().toLocaleTimeString("es")}]`, ...tasks); | ||
| } | ||
| // src/index.ts | ||
| var PARENT_DIRECTORY = /^(\/?\.\.)+/; | ||
| var ESCAPING_BACKSLASHES = /\\(?=[()[\]{}!*+?@|])/g; | ||
| var BACKSLASHES = /\\/g; | ||
| //#endregion | ||
| //#region src/index.ts | ||
| const PARENT_DIRECTORY = /^(\/?\.\.)+/; | ||
| const ESCAPING_BACKSLASHES = /\\(?=[()[\]{}!*+?@|])/g; | ||
| const BACKSLASHES = /\\/g; | ||
| function normalizePattern(pattern, expandDirectories, cwd, props, isIgnore) { | ||
| var _a; | ||
| let result = pattern; | ||
| if (pattern.endsWith("/")) { | ||
| result = pattern.slice(0, -1); | ||
| } | ||
| if (!result.endsWith("*") && expandDirectories) { | ||
| result += "/**"; | ||
| } | ||
| if (path.isAbsolute(result.replace(ESCAPING_BACKSLASHES, ""))) { | ||
| result = posix.relative(escapePath(cwd), result); | ||
| } else { | ||
| result = posix.normalize(result); | ||
| } | ||
| const parentDirectoryMatch = PARENT_DIRECTORY.exec(result); | ||
| if (parentDirectoryMatch == null ? void 0 : parentDirectoryMatch[0]) { | ||
| const potentialRoot = posix.join(cwd, parentDirectoryMatch[0]); | ||
| if (props.root.length > potentialRoot.length) { | ||
| props.root = potentialRoot; | ||
| props.depthOffset = -(parentDirectoryMatch[0].length + 1) / 3; | ||
| } | ||
| } else if (!isIgnore && props.depthOffset >= 0) { | ||
| const parts = splitPattern(result); | ||
| (_a = props.commonPath) != null ? _a : props.commonPath = parts; | ||
| const newCommonPath = []; | ||
| const length = Math.min(props.commonPath.length, parts.length); | ||
| for (let i = 0; i < length; i++) { | ||
| const part = parts[i]; | ||
| if (part === "**" && !parts[i + 1]) { | ||
| newCommonPath.pop(); | ||
| break; | ||
| } | ||
| if (part !== props.commonPath[i] || isDynamicPattern(part) || i === parts.length - 1) { | ||
| break; | ||
| } | ||
| newCommonPath.push(part); | ||
| } | ||
| props.depthOffset = newCommonPath.length; | ||
| props.commonPath = newCommonPath; | ||
| props.root = newCommonPath.length > 0 ? path.posix.join(cwd, ...newCommonPath) : cwd; | ||
| } | ||
| return result; | ||
| let result = pattern; | ||
| if (pattern.endsWith("/")) result = pattern.slice(0, -1); | ||
| if (!result.endsWith("*") && expandDirectories) result += "/**"; | ||
| const escapedCwd = escapePath(cwd); | ||
| if (path.isAbsolute(result.replace(ESCAPING_BACKSLASHES, ""))) result = posix.relative(escapedCwd, result); | ||
| else result = posix.normalize(result); | ||
| const parentDirectoryMatch = PARENT_DIRECTORY.exec(result); | ||
| const parts = splitPattern(result); | ||
| if (parentDirectoryMatch === null || parentDirectoryMatch === void 0 ? void 0 : parentDirectoryMatch[0]) { | ||
| const n = (parentDirectoryMatch[0].length + 1) / 3; | ||
| let i = 0; | ||
| const cwdParts = escapedCwd.split("/"); | ||
| while (i < n && parts[i + n] === cwdParts[cwdParts.length + i - n]) { | ||
| result = result.slice(0, (n - i - 1) * 3) + result.slice((n - i) * 3 + parts[i + n].length + 1) || "."; | ||
| i++; | ||
| } | ||
| const potentialRoot = posix.join(cwd, parentDirectoryMatch[0].slice(i * 3)); | ||
| if (!potentialRoot.startsWith(".") && props.root.length > potentialRoot.length) { | ||
| props.root = potentialRoot; | ||
| props.depthOffset = -n + i; | ||
| } | ||
| } | ||
| if (!isIgnore && props.depthOffset >= 0) { | ||
| var _props$commonPath; | ||
| (_props$commonPath = props.commonPath) !== null && _props$commonPath !== void 0 || (props.commonPath = parts); | ||
| const newCommonPath = []; | ||
| const length = Math.min(props.commonPath.length, parts.length); | ||
| for (let i = 0; i < length; i++) { | ||
| const part = parts[i]; | ||
| if (part === "**" && !parts[i + 1]) { | ||
| newCommonPath.pop(); | ||
| break; | ||
| } | ||
| if (part !== props.commonPath[i] || isDynamicPattern(part) || i === parts.length - 1) break; | ||
| newCommonPath.push(part); | ||
| } | ||
| props.depthOffset = newCommonPath.length; | ||
| props.commonPath = newCommonPath; | ||
| props.root = newCommonPath.length > 0 ? path.posix.join(cwd, ...newCommonPath) : cwd; | ||
| } | ||
| return result; | ||
| } | ||
| function processPatterns({ patterns, ignore = [], expandDirectories = true }, cwd, props) { | ||
| if (typeof patterns === "string") { | ||
| patterns = [patterns]; | ||
| } else if (!patterns) { | ||
| patterns = ["**/*"]; | ||
| } | ||
| if (typeof ignore === "string") { | ||
| ignore = [ignore]; | ||
| } | ||
| const matchPatterns = []; | ||
| const ignorePatterns = []; | ||
| for (const pattern of ignore) { | ||
| if (!pattern) { | ||
| continue; | ||
| } | ||
| if (pattern[0] !== "!" || pattern[1] === "(") { | ||
| ignorePatterns.push(normalizePattern(pattern, expandDirectories, cwd, props, true)); | ||
| } | ||
| } | ||
| for (const pattern of patterns) { | ||
| if (!pattern) { | ||
| continue; | ||
| } | ||
| if (pattern[0] !== "!" || pattern[1] === "(") { | ||
| matchPatterns.push(normalizePattern(pattern, expandDirectories, cwd, props, false)); | ||
| } else if (pattern[1] !== "!" || pattern[2] === "(") { | ||
| ignorePatterns.push(normalizePattern(pattern.slice(1), expandDirectories, cwd, props, true)); | ||
| } | ||
| } | ||
| return { match: matchPatterns, ignore: ignorePatterns }; | ||
| if (typeof patterns === "string") patterns = [patterns]; | ||
| else if (!patterns) patterns = ["**/*"]; | ||
| if (typeof ignore === "string") ignore = [ignore]; | ||
| const matchPatterns = []; | ||
| const ignorePatterns = []; | ||
| for (const pattern of ignore) { | ||
| if (!pattern) continue; | ||
| if (pattern[0] !== "!" || pattern[1] === "(") ignorePatterns.push(normalizePattern(pattern, expandDirectories, cwd, props, true)); | ||
| } | ||
| for (const pattern of patterns) { | ||
| if (!pattern) continue; | ||
| if (pattern[0] !== "!" || pattern[1] === "(") matchPatterns.push(normalizePattern(pattern, expandDirectories, cwd, props, false)); | ||
| else if (pattern[1] !== "!" || pattern[2] === "(") ignorePatterns.push(normalizePattern(pattern.slice(1), expandDirectories, cwd, props, true)); | ||
| } | ||
| return { | ||
| match: matchPatterns, | ||
| ignore: ignorePatterns | ||
| }; | ||
| } | ||
| function getRelativePath(path2, cwd, root) { | ||
| return posix.relative(cwd, `${root}/${path2}`) || "."; | ||
| function getRelativePath(path$1, cwd, root) { | ||
| return posix.relative(cwd, `${root}/${path$1}`) || "."; | ||
| } | ||
| function processPath(path2, cwd, root, isDirectory, absolute) { | ||
| const relativePath = absolute ? path2.slice(root === "/" ? 1 : root.length + 1) || "." : path2; | ||
| if (root === cwd) { | ||
| return isDirectory && relativePath !== "." ? relativePath.slice(0, -1) : relativePath; | ||
| } | ||
| return getRelativePath(relativePath, cwd, root); | ||
| function processPath(path$1, cwd, root, isDirectory, absolute) { | ||
| const relativePath = absolute ? path$1.slice(root === "/" ? 1 : root.length + 1) || "." : path$1; | ||
| if (root === cwd) return isDirectory && relativePath !== "." ? relativePath.slice(0, -1) : relativePath; | ||
| return getRelativePath(relativePath, cwd, root); | ||
| } | ||
| function formatPaths(paths, cwd, root) { | ||
| for (let i = paths.length - 1; i >= 0; i--) { | ||
| const path2 = paths[i]; | ||
| paths[i] = getRelativePath(path2, cwd, root) + (!path2 || path2.endsWith("/") ? "/" : ""); | ||
| } | ||
| return paths; | ||
| for (let i = paths.length - 1; i >= 0; i--) { | ||
| const path$1 = paths[i]; | ||
| paths[i] = getRelativePath(path$1, cwd, root) + (!path$1 || path$1.endsWith("/") ? "/" : ""); | ||
| } | ||
| return paths; | ||
| } | ||
| function crawl(options, cwd, sync) { | ||
| if (process.env.TINYGLOBBY_DEBUG) { | ||
| options.debug = true; | ||
| } | ||
| if (options.debug) { | ||
| log("globbing with options:", options, "cwd:", cwd); | ||
| } | ||
| if (Array.isArray(options.patterns) && options.patterns.length === 0) { | ||
| return sync ? [] : Promise.resolve([]); | ||
| } | ||
| const props = { | ||
| root: cwd, | ||
| commonPath: null, | ||
| depthOffset: 0 | ||
| }; | ||
| const processed = processPatterns(options, cwd, props); | ||
| const nocase = options.caseSensitiveMatch === false; | ||
| if (options.debug) { | ||
| log("internal processing patterns:", processed); | ||
| } | ||
| const matcher = picomatch2(processed.match, { | ||
| dot: options.dot, | ||
| nocase, | ||
| ignore: processed.ignore | ||
| }); | ||
| const ignore = picomatch2(processed.ignore, { | ||
| dot: options.dot, | ||
| nocase | ||
| }); | ||
| const partialMatcher = getPartialMatcher(processed.match, { | ||
| dot: options.dot, | ||
| nocase | ||
| }); | ||
| const fdirOptions = { | ||
| // use relative paths in the matcher | ||
| filters: [ | ||
| options.debug ? (p, isDirectory) => { | ||
| const path2 = processPath(p, cwd, props.root, isDirectory, options.absolute); | ||
| const matches = matcher(path2); | ||
| if (matches) { | ||
| log(`matched ${path2}`); | ||
| } | ||
| return matches; | ||
| } : (p, isDirectory) => matcher(processPath(p, cwd, props.root, isDirectory, options.absolute)) | ||
| ], | ||
| exclude: options.debug ? (_, p) => { | ||
| const relativePath = processPath(p, cwd, props.root, true, true); | ||
| const skipped = relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath); | ||
| if (skipped) { | ||
| log(`skipped ${p}`); | ||
| } else { | ||
| log(`crawling ${p}`); | ||
| } | ||
| return skipped; | ||
| } : (_, p) => { | ||
| const relativePath = processPath(p, cwd, props.root, true, true); | ||
| return relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath); | ||
| }, | ||
| pathSeparator: "/", | ||
| relativePaths: true, | ||
| resolveSymlinks: true | ||
| }; | ||
| if (options.deep) { | ||
| fdirOptions.maxDepth = Math.round(options.deep - props.depthOffset); | ||
| } | ||
| if (options.absolute) { | ||
| fdirOptions.relativePaths = false; | ||
| fdirOptions.resolvePaths = true; | ||
| fdirOptions.includeBasePath = true; | ||
| } | ||
| if (options.followSymbolicLinks === false) { | ||
| fdirOptions.resolveSymlinks = false; | ||
| fdirOptions.excludeSymlinks = true; | ||
| } | ||
| if (options.onlyDirectories) { | ||
| fdirOptions.excludeFiles = true; | ||
| fdirOptions.includeDirs = true; | ||
| } else if (options.onlyFiles === false) { | ||
| fdirOptions.includeDirs = true; | ||
| } | ||
| props.root = props.root.replace(BACKSLASHES, ""); | ||
| const root = props.root; | ||
| if (options.debug) { | ||
| log("internal properties:", props); | ||
| } | ||
| const api = new fdir(fdirOptions).crawl(root); | ||
| if (cwd === root || options.absolute) { | ||
| return sync ? api.sync() : api.withPromise(); | ||
| } | ||
| return sync ? formatPaths(api.sync(), cwd, root) : api.withPromise().then((paths) => formatPaths(paths, cwd, root)); | ||
| if (process.env.TINYGLOBBY_DEBUG) options.debug = true; | ||
| if (options.debug) log("globbing with options:", options, "cwd:", cwd); | ||
| if (Array.isArray(options.patterns) && options.patterns.length === 0) return sync ? [] : Promise.resolve([]); | ||
| const props = { | ||
| root: cwd, | ||
| commonPath: null, | ||
| depthOffset: 0 | ||
| }; | ||
| const processed = processPatterns(options, cwd, props); | ||
| const nocase = options.caseSensitiveMatch === false; | ||
| if (options.debug) log("internal processing patterns:", processed); | ||
| const matcher = picomatch(processed.match, { | ||
| dot: options.dot, | ||
| nocase, | ||
| ignore: processed.ignore | ||
| }); | ||
| const ignore = picomatch(processed.ignore, { | ||
| dot: options.dot, | ||
| nocase | ||
| }); | ||
| const partialMatcher = getPartialMatcher(processed.match, { | ||
| dot: options.dot, | ||
| nocase | ||
| }); | ||
| const fdirOptions = { | ||
| filters: [options.debug ? (p, isDirectory) => { | ||
| const path$1 = processPath(p, cwd, props.root, isDirectory, options.absolute); | ||
| const matches = matcher(path$1); | ||
| if (matches) log(`matched ${path$1}`); | ||
| return matches; | ||
| } : (p, isDirectory) => matcher(processPath(p, cwd, props.root, isDirectory, options.absolute))], | ||
| exclude: options.debug ? (_, p) => { | ||
| const relativePath = processPath(p, cwd, props.root, true, true); | ||
| const skipped = relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath); | ||
| if (skipped) log(`skipped ${p}`); | ||
| else log(`crawling ${p}`); | ||
| return skipped; | ||
| } : (_, p) => { | ||
| const relativePath = processPath(p, cwd, props.root, true, true); | ||
| return relativePath !== "." && !partialMatcher(relativePath) || ignore(relativePath); | ||
| }, | ||
| pathSeparator: "/", | ||
| relativePaths: true, | ||
| resolveSymlinks: true | ||
| }; | ||
| if (options.deep !== void 0) fdirOptions.maxDepth = Math.round(options.deep - props.depthOffset); | ||
| if (options.absolute) { | ||
| fdirOptions.relativePaths = false; | ||
| fdirOptions.resolvePaths = true; | ||
| fdirOptions.includeBasePath = true; | ||
| } | ||
| if (options.followSymbolicLinks === false) { | ||
| fdirOptions.resolveSymlinks = false; | ||
| fdirOptions.excludeSymlinks = true; | ||
| } | ||
| if (options.onlyDirectories) { | ||
| fdirOptions.excludeFiles = true; | ||
| fdirOptions.includeDirs = true; | ||
| } else if (options.onlyFiles === false) fdirOptions.includeDirs = true; | ||
| props.root = props.root.replace(BACKSLASHES, ""); | ||
| const root = props.root; | ||
| if (options.debug) log("internal properties:", props); | ||
| const api = new fdir(fdirOptions).crawl(root); | ||
| if (cwd === root || options.absolute) return sync ? api.sync() : api.withPromise(); | ||
| return sync ? formatPaths(api.sync(), cwd, root) : api.withPromise().then((paths) => formatPaths(paths, cwd, root)); | ||
| } | ||
| async function glob(patternsOrOptions, options) { | ||
| if (patternsOrOptions && (options == null ? void 0 : options.patterns)) { | ||
| throw new Error("Cannot pass patterns as both an argument and an option"); | ||
| } | ||
| const opts = Array.isArray(patternsOrOptions) || typeof patternsOrOptions === "string" ? { ...options, patterns: patternsOrOptions } : patternsOrOptions; | ||
| const cwd = opts.cwd ? path.resolve(opts.cwd).replace(BACKSLASHES, "/") : process.cwd().replace(BACKSLASHES, "/"); | ||
| return crawl(opts, cwd, false); | ||
| if (patternsOrOptions && (options === null || options === void 0 ? void 0 : options.patterns)) throw new Error("Cannot pass patterns as both an argument and an option"); | ||
| const opts = Array.isArray(patternsOrOptions) || typeof patternsOrOptions === "string" ? { | ||
| ...options, | ||
| patterns: patternsOrOptions | ||
| } : patternsOrOptions; | ||
| const cwd = opts.cwd ? path.resolve(opts.cwd).replace(BACKSLASHES, "/") : process.cwd().replace(BACKSLASHES, "/"); | ||
| return crawl(opts, cwd, false); | ||
| } | ||
| function globSync(patternsOrOptions, options) { | ||
| if (patternsOrOptions && (options == null ? void 0 : options.patterns)) { | ||
| throw new Error("Cannot pass patterns as both an argument and an option"); | ||
| } | ||
| const opts = Array.isArray(patternsOrOptions) || typeof patternsOrOptions === "string" ? { ...options, patterns: patternsOrOptions } : patternsOrOptions; | ||
| const cwd = opts.cwd ? path.resolve(opts.cwd).replace(BACKSLASHES, "/") : process.cwd().replace(BACKSLASHES, "/"); | ||
| return crawl(opts, cwd, true); | ||
| if (patternsOrOptions && (options === null || options === void 0 ? void 0 : options.patterns)) throw new Error("Cannot pass patterns as both an argument and an option"); | ||
| const opts = Array.isArray(patternsOrOptions) || typeof patternsOrOptions === "string" ? { | ||
| ...options, | ||
| patterns: patternsOrOptions | ||
| } : patternsOrOptions; | ||
| const cwd = opts.cwd ? path.resolve(opts.cwd).replace(BACKSLASHES, "/") : process.cwd().replace(BACKSLASHES, "/"); | ||
| return crawl(opts, cwd, true); | ||
| } | ||
| export { | ||
| convertPathToPattern, | ||
| escapePath, | ||
| glob, | ||
| globSync, | ||
| isDynamicPattern | ||
| }; | ||
| //#endregion | ||
| export { convertPathToPattern, escapePath, glob, globSync, isDynamicPattern }; |
+4
-4
| { | ||
| "name": "tinyglobby", | ||
| "version": "0.2.13", | ||
| "version": "0.2.14", | ||
| "description": "A fast and minimal alternative to globby and fast-glob", | ||
@@ -41,6 +41,6 @@ "main": "dist/index.js", | ||
| "@biomejs/biome": "^1.9.4", | ||
| "@types/node": "^22.14.1", | ||
| "@types/node": "^22.15.21", | ||
| "@types/picomatch": "^4.0.0", | ||
| "fs-fixture": "^2.7.1", | ||
| "tsup": "^8.4.0", | ||
| "tsdown": "^0.12.3", | ||
| "typescript": "^5.8.3" | ||
@@ -56,3 +56,3 @@ }, | ||
| "scripts": { | ||
| "build": "tsup", | ||
| "build": "tsdown", | ||
| "check": "biome check", | ||
@@ -59,0 +59,0 @@ "format": "biome format --write", |
+2
-1
@@ -48,3 +48,3 @@ # tinyglobby | ||
| `tinyglobby` is downloaded many times by projects all around the world. Here's a list of notable projects that use it: | ||
| `tinyglobby` is downloaded many times by projects all around the world. Here's a partial list of notable projects that use it: | ||
@@ -58,2 +58,3 @@ <!-- should be sorted by weekly download count --> | ||
| - [`copy-webpack-plugin`](https://github.com/webpack-contrib/copy-webpack-plugin) | ||
| - [`storybook`](https://github.com/storybookjs/storybook) | ||
| - [`ts-morph`](https://github.com/dsherret/ts-morph) | ||
@@ -60,0 +61,0 @@ - [`nx`](https://github.com/nrwl/nx) |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
73
1.39%31120
-0.46%536
-17.03%1
Infinity%