minimatch-fast 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +950 -0
- package/dist/cjs/brace-expand.d.ts +42 -0
- package/dist/cjs/brace-expand.d.ts.map +1 -0
- package/dist/cjs/brace-expand.js +172 -0
- package/dist/cjs/brace-expand.js.map +1 -0
- package/dist/cjs/cache.d.ts +36 -0
- package/dist/cjs/cache.d.ts.map +1 -0
- package/dist/cjs/cache.js +91 -0
- package/dist/cjs/cache.js.map +1 -0
- package/dist/cjs/escape.d.ts +40 -0
- package/dist/cjs/escape.d.ts.map +1 -0
- package/dist/cjs/escape.js +52 -0
- package/dist/cjs/escape.js.map +1 -0
- package/dist/cjs/fast-paths.d.ts +54 -0
- package/dist/cjs/fast-paths.d.ts.map +1 -0
- package/dist/cjs/fast-paths.js +213 -0
- package/dist/cjs/fast-paths.js.map +1 -0
- package/dist/cjs/index.d.ts +150 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +250 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/minimatch-class.d.ts +153 -0
- package/dist/cjs/minimatch-class.d.ts.map +1 -0
- package/dist/cjs/minimatch-class.js +618 -0
- package/dist/cjs/minimatch-class.js.map +1 -0
- package/dist/cjs/options.d.ts +31 -0
- package/dist/cjs/options.d.ts.map +1 -0
- package/dist/cjs/options.js +67 -0
- package/dist/cjs/options.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/types.d.ts +194 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +19 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/unescape.d.ts +36 -0
- package/dist/cjs/unescape.d.ts.map +1 -0
- package/dist/cjs/unescape.js +49 -0
- package/dist/cjs/unescape.js.map +1 -0
- package/dist/cjs/utils.d.ts +62 -0
- package/dist/cjs/utils.d.ts.map +1 -0
- package/dist/cjs/utils.js +126 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/esm/brace-expand.d.ts +42 -0
- package/dist/esm/brace-expand.d.ts.map +1 -0
- package/dist/esm/brace-expand.js +165 -0
- package/dist/esm/brace-expand.js.map +1 -0
- package/dist/esm/cache.d.ts +36 -0
- package/dist/esm/cache.d.ts.map +1 -0
- package/dist/esm/cache.js +86 -0
- package/dist/esm/cache.js.map +1 -0
- package/dist/esm/escape.d.ts +40 -0
- package/dist/esm/escape.d.ts.map +1 -0
- package/dist/esm/escape.js +49 -0
- package/dist/esm/escape.js.map +1 -0
- package/dist/esm/fast-paths.d.ts +54 -0
- package/dist/esm/fast-paths.d.ts.map +1 -0
- package/dist/esm/fast-paths.js +209 -0
- package/dist/esm/fast-paths.js.map +1 -0
- package/dist/esm/index.d.ts +150 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +240 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/minimatch-class.d.ts +153 -0
- package/dist/esm/minimatch-class.d.ts.map +1 -0
- package/dist/esm/minimatch-class.js +611 -0
- package/dist/esm/minimatch-class.js.map +1 -0
- package/dist/esm/options.d.ts +31 -0
- package/dist/esm/options.d.ts.map +1 -0
- package/dist/esm/options.js +63 -0
- package/dist/esm/options.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/types.d.ts +194 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +16 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/unescape.d.ts +36 -0
- package/dist/esm/unescape.d.ts.map +1 -0
- package/dist/esm/unescape.js +46 -0
- package/dist/esm/unescape.js.map +1 -0
- package/dist/esm/utils.d.ts +62 -0
- package/dist/esm/utils.d.ts.map +1 -0
- package/dist/esm/utils.js +116 -0
- package/dist/esm/utils.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Brace expansion using the 'braces' package
|
|
3
|
+
*
|
|
4
|
+
* This module is critical because picomatch does NOT perform full brace expansion.
|
|
5
|
+
* picomatch only does brace matching, meaning {a,b} will match 'a' or 'b'
|
|
6
|
+
* but won't expand the pattern into ['a', 'b'].
|
|
7
|
+
*
|
|
8
|
+
* minimatch uses brace-expansion to fully expand patterns like:
|
|
9
|
+
* - {a,b,c} -> ['a', 'b', 'c']
|
|
10
|
+
* - {1..3} -> ['1', '2', '3']
|
|
11
|
+
* - {a..c} -> ['a', 'b', 'c']
|
|
12
|
+
* - a{b,c}d -> ['abd', 'acd']
|
|
13
|
+
*
|
|
14
|
+
* We use 'braces' package which is maintained by the same author as picomatch
|
|
15
|
+
* and is what micromatch uses internally.
|
|
16
|
+
*
|
|
17
|
+
* Security considerations:
|
|
18
|
+
* - Maximum expansion length is limited to prevent DoS attacks
|
|
19
|
+
* - Range expansion is limited (e.g., {1..1000000} is restricted)
|
|
20
|
+
*
|
|
21
|
+
* @author 686f6c61
|
|
22
|
+
* @see https://github.com/686f6c61/minimatch-fast
|
|
23
|
+
* @license MIT
|
|
24
|
+
*/
|
|
25
|
+
import braces from 'braces';
|
|
26
|
+
/**
|
|
27
|
+
* Maximum number of patterns that can be generated from brace expansion
|
|
28
|
+
* This prevents DoS attacks from patterns like {1..1000000}
|
|
29
|
+
*/
|
|
30
|
+
const MAX_EXPANSION_LENGTH = 10000;
|
|
31
|
+
/**
|
|
32
|
+
* Cache for brace expansion results.
|
|
33
|
+
* Key is the pattern, value is the expanded array.
|
|
34
|
+
* Limited to prevent memory issues.
|
|
35
|
+
*/
|
|
36
|
+
const BRACE_CACHE_SIZE = 200;
|
|
37
|
+
const braceCache = new Map();
|
|
38
|
+
/**
|
|
39
|
+
* Simple brace pattern regex: prefix{a,b,c}suffix
|
|
40
|
+
* Matches patterns with a single brace group containing comma-separated values
|
|
41
|
+
* without nesting or ranges.
|
|
42
|
+
*/
|
|
43
|
+
const SIMPLE_BRACE_RE = /^([^{]*)\{([^{}]+)\}([^{]*)$/;
|
|
44
|
+
/**
|
|
45
|
+
* Try fast path for simple brace patterns like prefix{a,b,c}suffix
|
|
46
|
+
* Returns null if pattern is not a simple brace pattern.
|
|
47
|
+
*/
|
|
48
|
+
function trySimpleBraceExpand(pattern) {
|
|
49
|
+
const m = pattern.match(SIMPLE_BRACE_RE);
|
|
50
|
+
if (!m)
|
|
51
|
+
return null;
|
|
52
|
+
const [, prefix, content, suffix] = m;
|
|
53
|
+
// Check if it's a range pattern (contains ..)
|
|
54
|
+
if (content.includes('..'))
|
|
55
|
+
return null;
|
|
56
|
+
// Split by comma and expand
|
|
57
|
+
const items = content.split(',');
|
|
58
|
+
return items.map(item => prefix + item + suffix);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Expand brace patterns like {a,b,c} and {1..3}
|
|
62
|
+
*
|
|
63
|
+
* Optimized with:
|
|
64
|
+
* 1. Cache for repeated patterns
|
|
65
|
+
* 2. Fast path for simple {a,b,c} patterns
|
|
66
|
+
*
|
|
67
|
+
* @param pattern - The glob pattern to expand
|
|
68
|
+
* @param options - Minimatch options
|
|
69
|
+
* @returns Array of expanded patterns
|
|
70
|
+
*/
|
|
71
|
+
export function braceExpand(pattern, options = {}) {
|
|
72
|
+
// If nobrace is set, return pattern unchanged
|
|
73
|
+
if (options.nobrace) {
|
|
74
|
+
return [pattern];
|
|
75
|
+
}
|
|
76
|
+
// Quick check: pattern must contain both { and }
|
|
77
|
+
const braceIdx = pattern.indexOf('{');
|
|
78
|
+
if (braceIdx === -1 || pattern.indexOf('}', braceIdx) === -1) {
|
|
79
|
+
return [pattern];
|
|
80
|
+
}
|
|
81
|
+
// Check cache first
|
|
82
|
+
const cached = braceCache.get(pattern);
|
|
83
|
+
if (cached) {
|
|
84
|
+
// Return a copy to prevent mutation
|
|
85
|
+
return [...cached];
|
|
86
|
+
}
|
|
87
|
+
// Try fast path for simple brace patterns
|
|
88
|
+
const fastResult = trySimpleBraceExpand(pattern);
|
|
89
|
+
if (fastResult !== null) {
|
|
90
|
+
// Cache and return
|
|
91
|
+
if (braceCache.size >= BRACE_CACHE_SIZE) {
|
|
92
|
+
const firstKey = braceCache.keys().next().value;
|
|
93
|
+
if (firstKey !== undefined) {
|
|
94
|
+
braceCache.delete(firstKey);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
braceCache.set(pattern, fastResult);
|
|
98
|
+
return [...fastResult];
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
// Use braces with expand: true for full bash-like expansion
|
|
102
|
+
const expanded = braces(pattern, {
|
|
103
|
+
expand: true,
|
|
104
|
+
// Limit range expansion to prevent DoS
|
|
105
|
+
// e.g., {1..10000} will be limited
|
|
106
|
+
rangeLimit: 1000,
|
|
107
|
+
});
|
|
108
|
+
// Check if expansion is too large (additional safety)
|
|
109
|
+
if (expanded.length > MAX_EXPANSION_LENGTH) {
|
|
110
|
+
// Return original pattern if expansion is too large
|
|
111
|
+
console.warn(`Brace expansion for "${pattern}" produced ${expanded.length} patterns, limiting to original pattern`);
|
|
112
|
+
return [pattern];
|
|
113
|
+
}
|
|
114
|
+
// Remove duplicates using Set (faster than manual loop for larger arrays)
|
|
115
|
+
const unique = [...new Set(expanded)];
|
|
116
|
+
const result = unique.length > 0 ? unique : [pattern];
|
|
117
|
+
// Cache the result
|
|
118
|
+
if (braceCache.size >= BRACE_CACHE_SIZE) {
|
|
119
|
+
const firstKey = braceCache.keys().next().value;
|
|
120
|
+
if (firstKey !== undefined) {
|
|
121
|
+
braceCache.delete(firstKey);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
braceCache.set(pattern, result);
|
|
125
|
+
return [...result];
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
// If expansion fails for any reason, return original pattern
|
|
129
|
+
// This matches minimatch's behavior of being lenient with invalid patterns
|
|
130
|
+
return [pattern];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check if a pattern contains brace expansion syntax
|
|
135
|
+
*/
|
|
136
|
+
export function hasBraces(pattern) {
|
|
137
|
+
// Simple check for balanced braces with content
|
|
138
|
+
let depth = 0;
|
|
139
|
+
let hasContent = false;
|
|
140
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
141
|
+
const char = pattern[i];
|
|
142
|
+
const prevChar = i > 0 ? pattern[i - 1] : '';
|
|
143
|
+
// Skip escaped braces
|
|
144
|
+
if (prevChar === '\\') {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (char === '{') {
|
|
148
|
+
depth++;
|
|
149
|
+
}
|
|
150
|
+
else if (char === '}') {
|
|
151
|
+
if (depth > 0) {
|
|
152
|
+
depth--;
|
|
153
|
+
if (depth === 0 && hasContent) {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
else if (depth > 0 && (char === ',' || char === '.')) {
|
|
159
|
+
// Has content (comma for list, dots for range)
|
|
160
|
+
hasContent = true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=brace-expand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brace-expand.js","sourceRoot":"","sources":["../../src/brace-expand.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview LRU Cache for compiled Minimatch patterns
|
|
3
|
+
*
|
|
4
|
+
* This module provides a simple LRU (Least Recently Used) cache for Minimatch
|
|
5
|
+
* instances. Caching compiled patterns significantly improves performance
|
|
6
|
+
* when the same pattern is used multiple times with the minimatch() function.
|
|
7
|
+
*
|
|
8
|
+
* The cache stores compiled Minimatch instances keyed by a combination of
|
|
9
|
+
* the pattern string and relevant options that affect compilation.
|
|
10
|
+
*
|
|
11
|
+
* @author 686f6c61
|
|
12
|
+
* @see https://github.com/686f6c61/minimatch-fast
|
|
13
|
+
* @license MIT
|
|
14
|
+
*/
|
|
15
|
+
import type { MinimatchOptions } from './types.js';
|
|
16
|
+
import { Minimatch } from './minimatch-class.js';
|
|
17
|
+
/**
|
|
18
|
+
* Get a cached Minimatch instance or create a new one.
|
|
19
|
+
* Implements LRU eviction when cache is full.
|
|
20
|
+
*
|
|
21
|
+
* @param pattern - The glob pattern
|
|
22
|
+
* @param options - Minimatch options
|
|
23
|
+
* @returns A Minimatch instance (cached or new)
|
|
24
|
+
*/
|
|
25
|
+
export declare function getOrCreateMatcher(pattern: string, options: MinimatchOptions): Minimatch;
|
|
26
|
+
/**
|
|
27
|
+
* Clear the pattern cache.
|
|
28
|
+
* Useful for testing or when memory pressure is high.
|
|
29
|
+
*/
|
|
30
|
+
export declare function clearCache(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Get the current cache size.
|
|
33
|
+
* Useful for monitoring and testing.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getCacheSize(): number;
|
|
36
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AA4CjD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,gBAAgB,GACxB,SAAS,CA4BX;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview LRU Cache for compiled Minimatch patterns
|
|
3
|
+
*
|
|
4
|
+
* This module provides a simple LRU (Least Recently Used) cache for Minimatch
|
|
5
|
+
* instances. Caching compiled patterns significantly improves performance
|
|
6
|
+
* when the same pattern is used multiple times with the minimatch() function.
|
|
7
|
+
*
|
|
8
|
+
* The cache stores compiled Minimatch instances keyed by a combination of
|
|
9
|
+
* the pattern string and relevant options that affect compilation.
|
|
10
|
+
*
|
|
11
|
+
* @author 686f6c61
|
|
12
|
+
* @see https://github.com/686f6c61/minimatch-fast
|
|
13
|
+
* @license MIT
|
|
14
|
+
*/
|
|
15
|
+
import { Minimatch } from './minimatch-class.js';
|
|
16
|
+
/**
|
|
17
|
+
* Maximum number of patterns to cache.
|
|
18
|
+
* This prevents unbounded memory growth while still providing
|
|
19
|
+
* good cache hit rates for typical usage patterns.
|
|
20
|
+
*/
|
|
21
|
+
const CACHE_SIZE = 500;
|
|
22
|
+
/**
|
|
23
|
+
* LRU cache for compiled Minimatch instances.
|
|
24
|
+
* Uses Map which maintains insertion order, making it easy
|
|
25
|
+
* to implement LRU eviction by deleting the oldest entry.
|
|
26
|
+
*/
|
|
27
|
+
const patternCache = new Map();
|
|
28
|
+
/**
|
|
29
|
+
* Generate a cache key from pattern and options.
|
|
30
|
+
* Only includes options that affect pattern compilation.
|
|
31
|
+
*
|
|
32
|
+
* @param pattern - The glob pattern
|
|
33
|
+
* @param options - Minimatch options
|
|
34
|
+
* @returns A unique cache key string
|
|
35
|
+
*/
|
|
36
|
+
function getCacheKey(pattern, options) {
|
|
37
|
+
// Use null byte as separator (cannot appear in patterns)
|
|
38
|
+
// Include all options that affect compilation
|
|
39
|
+
return `${pattern}\0${options.nocase ? '1' : '0'}${options.dot ? '1' : '0'}${options.noglobstar ? '1' : '0'}${options.nobrace ? '1' : '0'}${options.noext ? '1' : '0'}${options.nonegate ? '1' : '0'}${options.nocomment ? '1' : '0'}${options.matchBase ? '1' : '0'}${options.flipNegate ? '1' : '0'}${options.windowsPathsNoEscape ? '1' : '0'}${options.preserveMultipleSlashes ? '1' : '0'}${options.partial ? '1' : '0'}${options.platform ?? ''}`;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get a cached Minimatch instance or create a new one.
|
|
43
|
+
* Implements LRU eviction when cache is full.
|
|
44
|
+
*
|
|
45
|
+
* @param pattern - The glob pattern
|
|
46
|
+
* @param options - Minimatch options
|
|
47
|
+
* @returns A Minimatch instance (cached or new)
|
|
48
|
+
*/
|
|
49
|
+
export function getOrCreateMatcher(pattern, options) {
|
|
50
|
+
const key = getCacheKey(pattern, options);
|
|
51
|
+
// Check cache first
|
|
52
|
+
let mm = patternCache.get(key);
|
|
53
|
+
if (mm) {
|
|
54
|
+
// Move to end (most recently used) by re-inserting
|
|
55
|
+
patternCache.delete(key);
|
|
56
|
+
patternCache.set(key, mm);
|
|
57
|
+
return mm;
|
|
58
|
+
}
|
|
59
|
+
// Create new Minimatch instance
|
|
60
|
+
mm = new Minimatch(pattern, options);
|
|
61
|
+
// Evict oldest entry if cache is full
|
|
62
|
+
if (patternCache.size >= CACHE_SIZE) {
|
|
63
|
+
const firstKey = patternCache.keys().next().value;
|
|
64
|
+
if (firstKey !== undefined) {
|
|
65
|
+
patternCache.delete(firstKey);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Add to cache
|
|
69
|
+
patternCache.set(key, mm);
|
|
70
|
+
return mm;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Clear the pattern cache.
|
|
74
|
+
* Useful for testing or when memory pressure is high.
|
|
75
|
+
*/
|
|
76
|
+
export function clearCache() {
|
|
77
|
+
patternCache.clear();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get the current cache size.
|
|
81
|
+
* Useful for monitoring and testing.
|
|
82
|
+
*/
|
|
83
|
+
export function getCacheSize() {
|
|
84
|
+
return patternCache.size;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD;;;;GAIG;AACH,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB;;;;GAIG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,EAAqB,CAAC;AAElD;;;;;;;GAOG;AACH,SAAS,WAAW,CAAC,OAAe,EAAE,OAAyB;IAC7D,yDAAyD;IACzD,8CAA8C;IAC9C,OAAO,GAAG,OAAO,KACf,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GACzB,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GACxB,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAC7B,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAC5B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GACxB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAC7B,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAC5B,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAC9B,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAC7B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GACzC,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAC1C,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAC5B,OAAO,CAAC,QAAQ,IAAI,EACtB,EAAE,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAe,EACf,OAAyB;IAEzB,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAE1C,oBAAoB;IACpB,IAAI,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAE/B,IAAI,EAAE,EAAE,CAAC;QACP,mDAAmD;QACnD,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,gCAAgC;IAChC,EAAE,GAAG,IAAI,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAErC,sCAAsC;IACtC,IAAI,YAAY,CAAC,IAAI,IAAI,UAAU,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QAClD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,eAAe;IACf,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAE1B,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,YAAY,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,YAAY,CAAC,IAAI,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Escape glob magic characters
|
|
3
|
+
*
|
|
4
|
+
* This module provides functionality to escape special glob characters in strings,
|
|
5
|
+
* making them match literally instead of being interpreted as patterns.
|
|
6
|
+
*
|
|
7
|
+
* Escape modes:
|
|
8
|
+
* - Default mode: Uses backslash escaping (\* \? etc.)
|
|
9
|
+
* - Windows mode: Uses character class escaping ([*] [?] etc.)
|
|
10
|
+
*
|
|
11
|
+
* This is useful when you need to match file paths that contain glob
|
|
12
|
+
* special characters like *, ?, [], {}, etc.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* escape('*.js') // Returns '\\*.js'
|
|
16
|
+
* escape('[test].js') // Returns '\\[test\\].js'
|
|
17
|
+
* escape('*.js', { windowsPathsNoEscape: true }) // Returns '[*].js'
|
|
18
|
+
*
|
|
19
|
+
* @author 686f6c61
|
|
20
|
+
* @see https://github.com/686f6c61/minimatch-fast
|
|
21
|
+
* @license MIT
|
|
22
|
+
*/
|
|
23
|
+
import type { MinimatchOptions } from './types.js';
|
|
24
|
+
/**
|
|
25
|
+
* Escape all magic characters in a glob pattern so it matches literally.
|
|
26
|
+
*
|
|
27
|
+
* If windowsPathsNoEscape is true, characters are escaped by wrapping in [],
|
|
28
|
+
* because a magic character wrapped in a character class can only be satisfied
|
|
29
|
+
* by that exact character. Backslash is NOT escaped in this mode because it
|
|
30
|
+
* is treated as a path separator.
|
|
31
|
+
*
|
|
32
|
+
* If windowsPathsNoEscape is false (default), characters are escaped with
|
|
33
|
+
* backslash.
|
|
34
|
+
*
|
|
35
|
+
* @param str - The string to escape
|
|
36
|
+
* @param options - Options controlling escape behavior
|
|
37
|
+
* @returns Escaped string
|
|
38
|
+
*/
|
|
39
|
+
export declare function escape(str: string, options?: Pick<MinimatchOptions, 'windowsPathsNoEscape'>): string;
|
|
40
|
+
//# sourceMappingURL=escape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escape.d.ts","sourceRoot":"","sources":["../../src/escape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,MAAM,CACpB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,sBAAsB,CAAM,GAC3D,MAAM,CAYR"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Escape glob magic characters
|
|
3
|
+
*
|
|
4
|
+
* This module provides functionality to escape special glob characters in strings,
|
|
5
|
+
* making them match literally instead of being interpreted as patterns.
|
|
6
|
+
*
|
|
7
|
+
* Escape modes:
|
|
8
|
+
* - Default mode: Uses backslash escaping (\* \? etc.)
|
|
9
|
+
* - Windows mode: Uses character class escaping ([*] [?] etc.)
|
|
10
|
+
*
|
|
11
|
+
* This is useful when you need to match file paths that contain glob
|
|
12
|
+
* special characters like *, ?, [], {}, etc.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* escape('*.js') // Returns '\\*.js'
|
|
16
|
+
* escape('[test].js') // Returns '\\[test\\].js'
|
|
17
|
+
* escape('*.js', { windowsPathsNoEscape: true }) // Returns '[*].js'
|
|
18
|
+
*
|
|
19
|
+
* @author 686f6c61
|
|
20
|
+
* @see https://github.com/686f6c61/minimatch-fast
|
|
21
|
+
* @license MIT
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Escape all magic characters in a glob pattern so it matches literally.
|
|
25
|
+
*
|
|
26
|
+
* If windowsPathsNoEscape is true, characters are escaped by wrapping in [],
|
|
27
|
+
* because a magic character wrapped in a character class can only be satisfied
|
|
28
|
+
* by that exact character. Backslash is NOT escaped in this mode because it
|
|
29
|
+
* is treated as a path separator.
|
|
30
|
+
*
|
|
31
|
+
* If windowsPathsNoEscape is false (default), characters are escaped with
|
|
32
|
+
* backslash.
|
|
33
|
+
*
|
|
34
|
+
* @param str - The string to escape
|
|
35
|
+
* @param options - Options controlling escape behavior
|
|
36
|
+
* @returns Escaped string
|
|
37
|
+
*/
|
|
38
|
+
export function escape(str, options = {}) {
|
|
39
|
+
const { windowsPathsNoEscape = false } = options;
|
|
40
|
+
if (windowsPathsNoEscape) {
|
|
41
|
+
// Escape by wrapping in character class []
|
|
42
|
+
// Don't escape backslash since it's a path separator in this mode
|
|
43
|
+
return str.replace(/[?*()[\]{}]/g, '[$&]');
|
|
44
|
+
}
|
|
45
|
+
// Default: escape with backslash
|
|
46
|
+
// Include backslash in the escape set
|
|
47
|
+
return str.replace(/[?*()[\]{}\\]/g, '\\$&');
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=escape.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escape.js","sourceRoot":"","sources":["../../src/escape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,MAAM,CACpB,GAAW,EACX,UAA0D,EAAE;IAE5D,MAAM,EAAE,oBAAoB,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAEjD,IAAI,oBAAoB,EAAE,CAAC;QACzB,2CAA2C;QAC3C,kEAAkE;QAClE,OAAO,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAED,iCAAiC;IACjC,sCAAsC;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Fast path handlers for common glob patterns
|
|
3
|
+
*
|
|
4
|
+
* This module provides optimized matching for the most common glob patterns,
|
|
5
|
+
* avoiding the overhead of full regex compilation. These fast paths use
|
|
6
|
+
* simple string operations like startsWith(), endsWith(), and includes()
|
|
7
|
+
* which are significantly faster than regex matching.
|
|
8
|
+
*
|
|
9
|
+
* Supported fast path patterns:
|
|
10
|
+
* - `*` - Match any single path segment (except dotfiles by default)
|
|
11
|
+
* - `*.ext` - Match files with specific extension (e.g., `*.js`, `*.ts`)
|
|
12
|
+
* - `*.*` - Match files with any extension
|
|
13
|
+
* - `.*` - Match hidden files (dotfiles)
|
|
14
|
+
* - `???` - Match files with exact length (question mark patterns)
|
|
15
|
+
*
|
|
16
|
+
* When a pattern doesn't match any fast path, null is returned and the
|
|
17
|
+
* caller should fall back to full pattern matching.
|
|
18
|
+
*
|
|
19
|
+
* @author 686f6c61
|
|
20
|
+
* @see https://github.com/686f6c61/minimatch-fast
|
|
21
|
+
* @license MIT
|
|
22
|
+
*/
|
|
23
|
+
import type { MinimatchOptions } from './types.js';
|
|
24
|
+
/**
|
|
25
|
+
* Try to match a path against a pattern using a fast path.
|
|
26
|
+
*
|
|
27
|
+
* This function attempts to use optimized string operations for common
|
|
28
|
+
* glob patterns instead of full regex compilation. If the pattern is not
|
|
29
|
+
* a simple pattern that can be handled by a fast path, null is returned.
|
|
30
|
+
*
|
|
31
|
+
* @param path - The path to match (should be a filename without directory)
|
|
32
|
+
* @param pattern - The glob pattern to match against
|
|
33
|
+
* @param options - Minimatch options (dot, nocase are relevant)
|
|
34
|
+
* @returns true if matches, false if doesn't match, null if no fast path available
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* tryFastPath('foo.js', '*.js', {}); // true
|
|
39
|
+
* tryFastPath('foo.txt', '*.js', {}); // false
|
|
40
|
+
* tryFastPath('.hidden', '*', {}); // false
|
|
41
|
+
* tryFastPath('.hidden', '*', { dot: true }); // true
|
|
42
|
+
* tryFastPath('foo.js', '**\/*.js', {}); // null (has /, need full matching)
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function tryFastPath(path: string, pattern: string, options: MinimatchOptions): boolean | null;
|
|
46
|
+
/**
|
|
47
|
+
* Check if a pattern might be eligible for fast path.
|
|
48
|
+
* This is a quick pre-check to avoid expensive regex tests.
|
|
49
|
+
*
|
|
50
|
+
* @param pattern - The glob pattern
|
|
51
|
+
* @returns true if pattern might use fast path
|
|
52
|
+
*/
|
|
53
|
+
export declare function mightUseFastPath(pattern: string): boolean;
|
|
54
|
+
//# sourceMappingURL=fast-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fast-paths.d.ts","sourceRoot":"","sources":["../../src/fast-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA4CnD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,gBAAgB,GACxB,OAAO,GAAG,IAAI,CAmHhB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAYzD"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Fast path handlers for common glob patterns
|
|
3
|
+
*
|
|
4
|
+
* This module provides optimized matching for the most common glob patterns,
|
|
5
|
+
* avoiding the overhead of full regex compilation. These fast paths use
|
|
6
|
+
* simple string operations like startsWith(), endsWith(), and includes()
|
|
7
|
+
* which are significantly faster than regex matching.
|
|
8
|
+
*
|
|
9
|
+
* Supported fast path patterns:
|
|
10
|
+
* - `*` - Match any single path segment (except dotfiles by default)
|
|
11
|
+
* - `*.ext` - Match files with specific extension (e.g., `*.js`, `*.ts`)
|
|
12
|
+
* - `*.*` - Match files with any extension
|
|
13
|
+
* - `.*` - Match hidden files (dotfiles)
|
|
14
|
+
* - `???` - Match files with exact length (question mark patterns)
|
|
15
|
+
*
|
|
16
|
+
* When a pattern doesn't match any fast path, null is returned and the
|
|
17
|
+
* caller should fall back to full pattern matching.
|
|
18
|
+
*
|
|
19
|
+
* @author 686f6c61
|
|
20
|
+
* @see https://github.com/686f6c61/minimatch-fast
|
|
21
|
+
* @license MIT
|
|
22
|
+
*/
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// PATTERN DETECTION REGEXES
|
|
25
|
+
// These regexes detect which fast path to use. They are compiled once at
|
|
26
|
+
// module load time and reused for all pattern checks.
|
|
27
|
+
// ============================================================================
|
|
28
|
+
/**
|
|
29
|
+
* Matches pure star patterns: *, **, ***
|
|
30
|
+
* Used for "match anything" patterns.
|
|
31
|
+
*/
|
|
32
|
+
const STAR_RE = /^\*+$/;
|
|
33
|
+
/**
|
|
34
|
+
* Matches star-dot-extension patterns: *.js, *.ts, *.txt
|
|
35
|
+
* Captures the extension (including the dot).
|
|
36
|
+
* Excludes patterns with special glob characters in the extension.
|
|
37
|
+
*/
|
|
38
|
+
const STAR_DOT_EXT_RE = /^\*+(\.[^+@!?\*\[\(]+)$/;
|
|
39
|
+
/**
|
|
40
|
+
* Matches star-dot-star patterns: *.*, **.*
|
|
41
|
+
* Used for "any file with an extension" matching.
|
|
42
|
+
*/
|
|
43
|
+
const STAR_DOT_STAR_RE = /^\*+\.\*+$/;
|
|
44
|
+
/**
|
|
45
|
+
* Matches dot-star patterns: .*, .**
|
|
46
|
+
* Used for dotfile/hidden file matching.
|
|
47
|
+
*/
|
|
48
|
+
const DOT_STAR_RE = /^\.\*+$/;
|
|
49
|
+
/**
|
|
50
|
+
* Matches question mark patterns: ?, ??, ???, ???.js
|
|
51
|
+
* Captures optional extension after the question marks.
|
|
52
|
+
* Used for exact-length matching.
|
|
53
|
+
*/
|
|
54
|
+
const QMARKS_RE = /^(\?+)(\.[^+@!?\*\[\(]+)?$/;
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// FAST PATH IMPLEMENTATION
|
|
57
|
+
// ============================================================================
|
|
58
|
+
/**
|
|
59
|
+
* Try to match a path against a pattern using a fast path.
|
|
60
|
+
*
|
|
61
|
+
* This function attempts to use optimized string operations for common
|
|
62
|
+
* glob patterns instead of full regex compilation. If the pattern is not
|
|
63
|
+
* a simple pattern that can be handled by a fast path, null is returned.
|
|
64
|
+
*
|
|
65
|
+
* @param path - The path to match (should be a filename without directory)
|
|
66
|
+
* @param pattern - The glob pattern to match against
|
|
67
|
+
* @param options - Minimatch options (dot, nocase are relevant)
|
|
68
|
+
* @returns true if matches, false if doesn't match, null if no fast path available
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* tryFastPath('foo.js', '*.js', {}); // true
|
|
73
|
+
* tryFastPath('foo.txt', '*.js', {}); // false
|
|
74
|
+
* tryFastPath('.hidden', '*', {}); // false
|
|
75
|
+
* tryFastPath('.hidden', '*', { dot: true }); // true
|
|
76
|
+
* tryFastPath('foo.js', '**\/*.js', {}); // null (has /, need full matching)
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export function tryFastPath(path, pattern, options) {
|
|
80
|
+
// Skip if path contains / (need full path matching)
|
|
81
|
+
if (path.includes('/'))
|
|
82
|
+
return null;
|
|
83
|
+
// Skip if pattern has path separators (need full matching)
|
|
84
|
+
if (pattern.includes('/'))
|
|
85
|
+
return null;
|
|
86
|
+
// Skip if negated (need full matching for proper negation handling)
|
|
87
|
+
if (!options.nonegate && pattern.startsWith('!'))
|
|
88
|
+
return null;
|
|
89
|
+
// Skip if pattern has braces (need brace expansion)
|
|
90
|
+
if (!options.nobrace && pattern.includes('{'))
|
|
91
|
+
return null;
|
|
92
|
+
// Skip if pattern has extglob (need extglob handling)
|
|
93
|
+
if (!options.noext && /[@!?+*]\(/.test(pattern))
|
|
94
|
+
return null;
|
|
95
|
+
// Skip if pattern has character class (need regex)
|
|
96
|
+
if (pattern.includes('['))
|
|
97
|
+
return null;
|
|
98
|
+
const dot = options.dot ?? false;
|
|
99
|
+
const nocase = options.nocase ?? false;
|
|
100
|
+
let m;
|
|
101
|
+
// -------------------------------------------------------------------------
|
|
102
|
+
// Fast path: * (pure star)
|
|
103
|
+
// Matches any non-empty filename, respecting dot option
|
|
104
|
+
// -------------------------------------------------------------------------
|
|
105
|
+
if ((m = pattern.match(STAR_RE))) {
|
|
106
|
+
if (path.length === 0)
|
|
107
|
+
return false;
|
|
108
|
+
if (dot) {
|
|
109
|
+
// With dot option, match anything except . and ..
|
|
110
|
+
return path !== '.' && path !== '..';
|
|
111
|
+
}
|
|
112
|
+
// Without dot option, don't match dotfiles
|
|
113
|
+
return !path.startsWith('.');
|
|
114
|
+
}
|
|
115
|
+
// -------------------------------------------------------------------------
|
|
116
|
+
// Fast path: *.ext (star-dot-extension)
|
|
117
|
+
// Matches files ending with specific extension
|
|
118
|
+
// -------------------------------------------------------------------------
|
|
119
|
+
if ((m = pattern.match(STAR_DOT_EXT_RE))) {
|
|
120
|
+
const ext = m[1]; // Includes the dot, e.g., ".js"
|
|
121
|
+
if (path.length === 0)
|
|
122
|
+
return false;
|
|
123
|
+
if (nocase) {
|
|
124
|
+
const lpath = path.toLowerCase();
|
|
125
|
+
const lext = ext.toLowerCase();
|
|
126
|
+
if (dot)
|
|
127
|
+
return lpath.endsWith(lext);
|
|
128
|
+
return !path.startsWith('.') && lpath.endsWith(lext);
|
|
129
|
+
}
|
|
130
|
+
if (dot)
|
|
131
|
+
return path.endsWith(ext);
|
|
132
|
+
return !path.startsWith('.') && path.endsWith(ext);
|
|
133
|
+
}
|
|
134
|
+
// -------------------------------------------------------------------------
|
|
135
|
+
// Fast path: *.* (star-dot-star)
|
|
136
|
+
// Matches any file with an extension (contains a dot)
|
|
137
|
+
// -------------------------------------------------------------------------
|
|
138
|
+
if ((m = pattern.match(STAR_DOT_STAR_RE))) {
|
|
139
|
+
if (path.length === 0)
|
|
140
|
+
return false;
|
|
141
|
+
if (dot) {
|
|
142
|
+
// With dot, match anything with a dot except . and ..
|
|
143
|
+
return path !== '.' && path !== '..' && path.includes('.');
|
|
144
|
+
}
|
|
145
|
+
// Without dot, must have extension and not be a dotfile
|
|
146
|
+
return !path.startsWith('.') && path.includes('.');
|
|
147
|
+
}
|
|
148
|
+
// -------------------------------------------------------------------------
|
|
149
|
+
// Fast path: .* (dot-star)
|
|
150
|
+
// Matches hidden files (starting with dot)
|
|
151
|
+
// -------------------------------------------------------------------------
|
|
152
|
+
if ((m = pattern.match(DOT_STAR_RE))) {
|
|
153
|
+
// Must start with dot but not be . or ..
|
|
154
|
+
return path.startsWith('.') && path !== '.' && path !== '..';
|
|
155
|
+
}
|
|
156
|
+
// -------------------------------------------------------------------------
|
|
157
|
+
// Fast path: ??? (question marks with optional extension)
|
|
158
|
+
// Matches files with exact length
|
|
159
|
+
// -------------------------------------------------------------------------
|
|
160
|
+
if ((m = pattern.match(QMARKS_RE))) {
|
|
161
|
+
const qmarks = m[1]; // The question marks, e.g., "???"
|
|
162
|
+
const ext = m[2] ?? ''; // Optional extension, e.g., ".js"
|
|
163
|
+
const qLen = qmarks.length;
|
|
164
|
+
const expectedLen = qLen + ext.length;
|
|
165
|
+
if (path.length !== expectedLen)
|
|
166
|
+
return false;
|
|
167
|
+
// Never match . or .. (special directories)
|
|
168
|
+
if (path === '.' || path === '..')
|
|
169
|
+
return false;
|
|
170
|
+
if (ext) {
|
|
171
|
+
// Has extension - check length and extension match
|
|
172
|
+
if (nocase) {
|
|
173
|
+
const lpath = path.toLowerCase();
|
|
174
|
+
const lext = ext.toLowerCase();
|
|
175
|
+
if (!lpath.endsWith(lext))
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
if (!path.endsWith(ext))
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Check dotfile restriction
|
|
184
|
+
if (!dot && path.startsWith('.'))
|
|
185
|
+
return false;
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
// No fast path available
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Check if a pattern might be eligible for fast path.
|
|
193
|
+
* This is a quick pre-check to avoid expensive regex tests.
|
|
194
|
+
*
|
|
195
|
+
* @param pattern - The glob pattern
|
|
196
|
+
* @returns true if pattern might use fast path
|
|
197
|
+
*/
|
|
198
|
+
export function mightUseFastPath(pattern) {
|
|
199
|
+
// Fast paths only work for simple patterns without:
|
|
200
|
+
// - Path separators
|
|
201
|
+
// - Braces
|
|
202
|
+
// - Character classes
|
|
203
|
+
// - Extglob patterns
|
|
204
|
+
return (!pattern.includes('/') &&
|
|
205
|
+
!pattern.includes('{') &&
|
|
206
|
+
!pattern.includes('[') &&
|
|
207
|
+
!/[@!?+*]\(/.test(pattern));
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=fast-paths.js.map
|