UNPKG

8.6 kBJavaScriptView Raw
1// *****************************************************************************
2// Copyright (C) 2018 Red Hat, Inc. and others.
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License v. 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0.
7//
8// This Source Code may also be made available under the following Secondary
9// Licenses when the conditions for such availability set forth in the Eclipse
10// Public License v. 2.0 are satisfied: GNU General Public License, version 2
11// with the GNU Classpath Exception which is available at
12// https://www.gnu.org/software/classpath/license.html.
13//
14// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15// *****************************************************************************
16// copied from https://github.com/Microsoft/vscode/blob/bf7ac9201e7a7d01741d4e6e64b5dc9f3197d97b/src/vs/base/common/paths.ts
17/*---------------------------------------------------------------------------------------------
18 * Copyright (c) Microsoft Corporation. All rights reserved.
19 * Licensed under the MIT License. See License.txt in the project root for license information.
20 *--------------------------------------------------------------------------------------------*/
21/* eslint-disable no-void */
22/* eslint-disable no-null/no-null */
23'use strict';
24Object.defineProperty(exports, "__esModule", { value: true });
25exports.isEqualOrParent = exports.getRoot = exports.normalize = exports.extname = exports.basename = exports.nativeSep = exports.sep = void 0;
26const os_1 = require("./os");
27const strings_1 = require("./strings");
28/**
29 * The forward slash path separator.
30 */
31exports.sep = '/';
32/**
33 * The native path separator depending on the OS.
34 */
35exports.nativeSep = os_1.isWindows ? '\\' : '/';
36const _posixBadPath = /(\/\.\.?\/)|(\/\.\.?)$|^(\.\.?\/)|(\/\/+)|(\\)/;
37const _winBadPath = /(\\\.\.?\\)|(\\\.\.?)$|^(\.\.?\\)|(\\\\+)|(\/)/;
38function _isNormal(path, win) {
39 return win
40 ? !_winBadPath.test(path)
41 : !_posixBadPath.test(path);
42}
43/**
44 * @returns the base name of a path.
45 */
46function basename(path) {
47 const idx = ~path.lastIndexOf('/') || ~path.lastIndexOf('\\');
48 if (idx === 0) {
49 return path;
50 }
51 else if (~idx === path.length - 1) {
52 return basename(path.substring(0, path.length - 1));
53 }
54 else {
55 return path.substr(~idx + 1);
56 }
57}
58exports.basename = basename;
59/**
60 * @returns `.far` from `boo.far` or the empty string.
61 */
62function extname(path) {
63 path = basename(path);
64 const idx = ~path.lastIndexOf('.');
65 return idx ? path.substring(~idx) : '';
66}
67exports.extname = extname;
68function normalize(path, toOSPath) {
69 if (path === null || path === void 0) {
70 return path;
71 }
72 const len = path.length;
73 if (len === 0) {
74 return '.';
75 }
76 const wantsBackslash = os_1.isWindows && toOSPath;
77 if (_isNormal(path, wantsBackslash)) {
78 return path;
79 }
80 // eslint-disable-next-line @typescript-eslint/no-shadow
81 const sep = wantsBackslash ? '\\' : '/';
82 const root = getRoot(path, sep);
83 // skip the root-portion of the path
84 let start = root.length;
85 let skip = false;
86 let res = '';
87 for (let end = root.length; end <= len; end++) {
88 // either at the end or at a path-separator character
89 if (end === len || path.charCodeAt(end) === 47 /* Slash */ || path.charCodeAt(end) === 92 /* Backslash */) {
90 if (streql(path, start, end, '..')) {
91 // skip current and remove parent (if there is already something)
92 const prev_start = res.lastIndexOf(sep);
93 const prev_part = res.slice(prev_start + 1);
94 if ((root || prev_part.length > 0) && prev_part !== '..') {
95 res = prev_start === -1 ? '' : res.slice(0, prev_start);
96 skip = true;
97 }
98 }
99 else if (streql(path, start, end, '.') && (root || res || end < len - 1)) {
100 // skip current (if there is already something or if there is more to come)
101 skip = true;
102 }
103 if (!skip) {
104 const part = path.slice(start, end);
105 if (res !== '' && res[res.length - 1] !== sep) {
106 res += sep;
107 }
108 res += part;
109 }
110 start = end + 1;
111 skip = false;
112 }
113 }
114 return root + res;
115}
116exports.normalize = normalize;
117function streql(value, start, end, other) {
118 return start + other.length === end && value.indexOf(other, start) === start;
119}
120/**
121 * Computes the _root_ this path, like `getRoot('c:\files') === c:\`,
122 * `getRoot('files:///files/path') === files:///`,
123 * or `getRoot('\\server\shares\path') === \\server\shares\`
124 */
125// eslint-disable-next-line @typescript-eslint/no-shadow
126function getRoot(path, sep = '/') {
127 if (!path) {
128 return '';
129 }
130 const len = path.length;
131 let code = path.charCodeAt(0);
132 if (code === 47 /* Slash */ || code === 92 /* Backslash */) {
133 code = path.charCodeAt(1);
134 if (code === 47 /* Slash */ || code === 92 /* Backslash */) {
135 // UNC candidate \\localhost\shares\ddd
136 // ^^^^^^^^^^^^^^^^^^^
137 code = path.charCodeAt(2);
138 if (code !== 47 /* Slash */ && code !== 92 /* Backslash */) {
139 // eslint-disable-next-line @typescript-eslint/no-shadow
140 let pos = 3;
141 const start = pos;
142 for (; pos < len; pos++) {
143 code = path.charCodeAt(pos);
144 if (code === 47 /* Slash */ || code === 92 /* Backslash */) {
145 break;
146 }
147 }
148 code = path.charCodeAt(pos + 1);
149 if (start !== pos && code !== 47 /* Slash */ && code !== 92 /* Backslash */) {
150 pos += 1;
151 for (; pos < len; pos++) {
152 code = path.charCodeAt(pos);
153 if (code === 47 /* Slash */ || code === 92 /* Backslash */) {
154 return path.slice(0, pos + 1) // consume this separator
155 .replace(/[\\/]/g, sep);
156 }
157 }
158 }
159 }
160 }
161 // /user/far
162 // ^
163 return sep;
164 }
165 else if ((code >= 65 /* A */ && code <= 90 /* Z */) || (code >= 97 /* a */ && code <= 122 /* z */)) {
166 // check for windows drive letter c:\ or c:
167 if (path.charCodeAt(1) === 58 /* Colon */) {
168 code = path.charCodeAt(2);
169 if (code === 47 /* Slash */ || code === 92 /* Backslash */) {
170 // C:\fff
171 // ^^^
172 return path.slice(0, 2) + sep;
173 }
174 else {
175 // C:
176 // ^^
177 return path.slice(0, 2);
178 }
179 }
180 }
181 // check for URI
182 // scheme://authority/path
183 // ^^^^^^^^^^^^^^^^^^^
184 let pos = path.indexOf('://');
185 if (pos !== -1) {
186 pos += 3; // 3 -> "://".length
187 for (; pos < len; pos++) {
188 code = path.charCodeAt(pos);
189 if (code === 47 /* Slash */ || code === 92 /* Backslash */) {
190 return path.slice(0, pos + 1); // consume this separator
191 }
192 }
193 }
194 return '';
195}
196exports.getRoot = getRoot;
197function isEqualOrParent(path, candidate, ignoreCase) {
198 if (path === candidate) {
199 return true;
200 }
201 if (!path || !candidate) {
202 return false;
203 }
204 if (candidate.length > path.length) {
205 return false;
206 }
207 if (ignoreCase) {
208 const beginsWith = (0, strings_1.startsWithIgnoreCase)(path, candidate);
209 if (!beginsWith) {
210 return false;
211 }
212 if (candidate.length === path.length) {
213 return true; // same path, different casing
214 }
215 let sepOffset = candidate.length;
216 if (candidate.charAt(candidate.length - 1) === exports.nativeSep) {
217 sepOffset--; // adjust the expected sep offset in case our candidate already ends in separator character
218 }
219 return path.charAt(sepOffset) === exports.nativeSep;
220 }
221 if (candidate.charAt(candidate.length - 1) !== exports.nativeSep) {
222 candidate += exports.nativeSep;
223 }
224 return path.indexOf(candidate) === 0;
225}
226exports.isEqualOrParent = isEqualOrParent;
227//# sourceMappingURL=paths.js.map
\No newline at end of file