UNPKG

1.61 kBJavaScriptView Raw
1'use strict';
2
3var isGlob = require('is-glob');
4var pathPosixDirname = require('path').posix.dirname;
5var isWin32 = require('os').platform() === 'win32';
6
7var slash = '/';
8var backslash = /\\/g;
9var escaped = /\\([!*?|[\](){}])/g;
10
11/**
12 * @param {string} str
13 * @param {Object} opts
14 * @param {boolean} [opts.flipBackslashes=true]
15 */
16module.exports = function globParent(str, opts) {
17 var options = Object.assign({ flipBackslashes: true }, opts);
18
19 // flip windows path separators
20 if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) {
21 str = str.replace(backslash, slash);
22 }
23
24 // special case for strings ending in enclosure containing path separator
25 if (isEnclosure(str)) {
26 str += slash;
27 }
28
29 // preserves full path in case of trailing path separator
30 str += 'a';
31
32 // remove path parts that are globby
33 do {
34 str = pathPosixDirname(str);
35 } while (isGlobby(str));
36
37 // remove escape chars and return result
38 return str.replace(escaped, '$1');
39};
40
41function isEnclosure(str) {
42 var lastChar = str.slice(-1);
43
44 var enclosureStart;
45 switch (lastChar) {
46 case '}':
47 enclosureStart = '{';
48 break;
49 case ']':
50 enclosureStart = '[';
51 break;
52 default:
53 return false;
54 }
55
56 var foundIndex = str.indexOf(enclosureStart);
57 if (foundIndex < 0) {
58 return false;
59 }
60
61 return str.slice(foundIndex + 1, -1).includes(slash);
62}
63
64function isGlobby(str) {
65 if (/\([^()]+$/.test(str)) {
66 return true;
67 }
68 if (str[0] === '{' || str[0] === '[') {
69 return true;
70 }
71 if (/[^\\][{[]/.test(str)) {
72 return true;
73 }
74 return isGlob(str);
75}