nice-path 3.0.0 → 3.2.0
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/.node-version +1 -1
- package/.npm-version +1 -0
- package/dist/index.d.ts +34 -7
- package/dist/index.js +95 -49
- package/package.json +5 -5
package/.node-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
v24.3.0
|
package/.npm-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
11.4.2
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
/** An object that represents a filesystem path. */
|
|
2
2
|
export declare class Path {
|
|
3
|
+
/** Used by {@link _isWin32DriveLetter}. */
|
|
4
|
+
protected static _WIN32_DRIVE_LETTER_REGEXP: RegExp;
|
|
5
|
+
/** Used by {@link Path.prototype.toString}. */
|
|
6
|
+
protected static _isWin32DriveLetter(pathString: string): boolean;
|
|
7
|
+
/** Filter out empty path segments except for 1-2 leading empty segments. */
|
|
8
|
+
protected static _validateSegments(segments: Array<string>, separator: string): Array<string>;
|
|
3
9
|
/** Split one or more path strings into an array of path segments. */
|
|
4
10
|
static splitToSegments(inputParts: Array<string> | string): Array<string>;
|
|
5
11
|
/**
|
|
@@ -32,6 +38,7 @@ export declare class Path {
|
|
|
32
38
|
* Will be either `/` or `\`.
|
|
33
39
|
*/
|
|
34
40
|
separator: string;
|
|
41
|
+
protected __is_Path: true;
|
|
35
42
|
/** Create a new Path object using the provided input(s). */
|
|
36
43
|
constructor(...inputs: Array<string | Path | Array<string | Path>>);
|
|
37
44
|
/**
|
|
@@ -54,14 +61,14 @@ export declare class Path {
|
|
|
54
61
|
/**
|
|
55
62
|
* Resolve all non-leading `.` and `..` segments in this path.
|
|
56
63
|
*/
|
|
57
|
-
normalize():
|
|
64
|
+
normalize(): this;
|
|
58
65
|
/**
|
|
59
66
|
* Create a new Path by appending additional path segments onto the end of
|
|
60
67
|
* this Path's segments.
|
|
61
68
|
*
|
|
62
69
|
* The returned path will use this path's separator.
|
|
63
70
|
*/
|
|
64
|
-
concat(...others: Array<string | Path | Array<string | Path>>):
|
|
71
|
+
concat(...others: Array<string | Path | Array<string | Path>>): this;
|
|
65
72
|
/**
|
|
66
73
|
* Return whether this path is absolute; that is, whether it starts with
|
|
67
74
|
* either `/`, `\`, or a drive letter (ie `C:`).
|
|
@@ -72,6 +79,14 @@ export declare class Path {
|
|
|
72
79
|
* this one.
|
|
73
80
|
*/
|
|
74
81
|
clone(): this;
|
|
82
|
+
/**
|
|
83
|
+
* Returns a boolean indicating whether `other` is a Path instance.
|
|
84
|
+
*
|
|
85
|
+
* Works cross-context/realm/iframe/etc.
|
|
86
|
+
*
|
|
87
|
+
* @param other - Any value
|
|
88
|
+
*/
|
|
89
|
+
static isPath(other: unknown): other is Path;
|
|
75
90
|
/**
|
|
76
91
|
* Express this path relative to `dir`.
|
|
77
92
|
*
|
|
@@ -80,7 +95,7 @@ export declare class Path {
|
|
|
80
95
|
*/
|
|
81
96
|
relativeTo(dir: Path | string, options?: {
|
|
82
97
|
noLeadingDot?: boolean;
|
|
83
|
-
}):
|
|
98
|
+
}): this;
|
|
84
99
|
/**
|
|
85
100
|
* Turn this path into a string by joining its segments using its separator.
|
|
86
101
|
*/
|
|
@@ -101,7 +116,7 @@ export declare class Path {
|
|
|
101
116
|
* Return a new Path containing all of the path segments in this one except
|
|
102
117
|
* for the last one; ie. the path to the directory that contains this path.
|
|
103
118
|
*/
|
|
104
|
-
dirname():
|
|
119
|
+
dirname(): this;
|
|
105
120
|
/**
|
|
106
121
|
* Return whether this path starts with the provided value, by comparing one
|
|
107
122
|
* path segment at a time.
|
|
@@ -163,7 +178,7 @@ export declare class Path {
|
|
|
163
178
|
*
|
|
164
179
|
* NOTE: to remove segments, use an empty Array for `replacement`.
|
|
165
180
|
*/
|
|
166
|
-
replace(value: string | Path | Array<string | Path>, replacement: string | Path | Array<string | Path>):
|
|
181
|
+
replace(value: string | Path | Array<string | Path>, replacement: string | Path | Array<string | Path>): this;
|
|
167
182
|
/**
|
|
168
183
|
* Return a new Path wherein all occurrences of the segments in `value` have
|
|
169
184
|
* been replaced with the segments in `replacement`. If the segments in
|
|
@@ -172,11 +187,23 @@ export declare class Path {
|
|
|
172
187
|
* @param value - What should be replaced
|
|
173
188
|
* @param replacement - What it should be replaced with
|
|
174
189
|
*/
|
|
175
|
-
replaceAll(value: string | Path | Array<string | Path>, replacement: string | Path | Array<string | Path>):
|
|
190
|
+
replaceAll(value: string | Path | Array<string | Path>, replacement: string | Path | Array<string | Path>): this;
|
|
176
191
|
/**
|
|
177
192
|
* Return a copy of this path but with the final segment replaced with `replacement`
|
|
178
193
|
*
|
|
179
194
|
* @param replacement - The new final segment(s) for the returned Path
|
|
180
195
|
*/
|
|
181
|
-
replaceLast(replacement: string | Path | Array<string | Path>):
|
|
196
|
+
replaceLast(replacement: string | Path | Array<string | Path>): this;
|
|
197
|
+
/**
|
|
198
|
+
* Return a boolean indicating whether this Path has the same separator and
|
|
199
|
+
* segments as another Path.
|
|
200
|
+
*
|
|
201
|
+
* To check only segments and not separator, use {@link Path.prototype.hasEqualSegments}.
|
|
202
|
+
*/
|
|
203
|
+
equals(other: string | Path | Array<string | Path>): boolean;
|
|
204
|
+
/**
|
|
205
|
+
* Return a boolean indicating whether this Path has the same segments as
|
|
206
|
+
* another Path. **Separator is not checked; use {@link Path.prototype.equals} for that.**
|
|
207
|
+
*/
|
|
208
|
+
hasEqualSegments(other: string | Path | Array<string | Path>): boolean;
|
|
182
209
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Path = void 0;
|
|
4
|
-
const WIN32_DRIVE_LETTER_REGEXP = /^[A-Za-z]:$/;
|
|
5
|
-
function isWin32DriveLetter(pathString) {
|
|
6
|
-
return WIN32_DRIVE_LETTER_REGEXP.test(pathString);
|
|
7
|
-
}
|
|
8
|
-
function validateSegments(segments, separator) {
|
|
9
|
-
return segments.filter((part, index) => {
|
|
10
|
-
// first part can be "" to represent left side of root "/"
|
|
11
|
-
// second part can be "" to support windows UNC paths
|
|
12
|
-
if (part === "" && index === 0) {
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
15
|
-
else if (part === "" &&
|
|
16
|
-
index === 1 &&
|
|
17
|
-
separator === "\\" &&
|
|
18
|
-
segments[0] === "") {
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
return Boolean(part);
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
4
|
/** An object that represents a filesystem path. */
|
|
25
5
|
class Path {
|
|
6
|
+
/** Used by {@link Path.prototype.toString}. */
|
|
7
|
+
static _isWin32DriveLetter(pathString) {
|
|
8
|
+
return this._WIN32_DRIVE_LETTER_REGEXP.test(pathString);
|
|
9
|
+
}
|
|
10
|
+
/** Filter out empty path segments except for 1-2 leading empty segments. */
|
|
11
|
+
static _validateSegments(segments, separator) {
|
|
12
|
+
return segments.filter((part, index) => {
|
|
13
|
+
// first part can be "" to represent left side of root "/"
|
|
14
|
+
// second part can be "" to support windows UNC paths
|
|
15
|
+
if (part === "" && index === 0) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
else if (part === "" &&
|
|
19
|
+
index === 1 &&
|
|
20
|
+
separator === "\\" &&
|
|
21
|
+
segments[0] === "") {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
return Boolean(part);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
26
27
|
/** Split one or more path strings into an array of path segments. */
|
|
27
28
|
static splitToSegments(inputParts) {
|
|
28
29
|
if (!Array.isArray(inputParts)) {
|
|
29
30
|
inputParts = [inputParts];
|
|
30
31
|
}
|
|
31
|
-
const separator =
|
|
32
|
-
return
|
|
32
|
+
const separator = this.detectSeparator(inputParts, "/");
|
|
33
|
+
return this._validateSegments(inputParts.map((part) => part.split(/(?:\/|\\)/g)).flat(1), separator);
|
|
33
34
|
}
|
|
34
35
|
/**
|
|
35
36
|
* Search the provided path string or strings for a path separator character
|
|
@@ -56,18 +57,18 @@ class Path {
|
|
|
56
57
|
* `..` segments.
|
|
57
58
|
*/
|
|
58
59
|
static normalize(...inputs) {
|
|
59
|
-
return new
|
|
60
|
+
return new this(...inputs).normalize();
|
|
60
61
|
}
|
|
61
62
|
/**
|
|
62
63
|
* Return whether the provided path is absolute; that is, whether it
|
|
63
64
|
* starts with either `/`, `\`, or a drive letter (ie `C:`).
|
|
64
65
|
*/
|
|
65
66
|
static isAbsolute(path) {
|
|
66
|
-
if (path
|
|
67
|
+
if (this.constructor.isPath(path)) {
|
|
67
68
|
return path.isAbsolute();
|
|
68
69
|
}
|
|
69
70
|
else {
|
|
70
|
-
return new
|
|
71
|
+
return new this(path).isAbsolute();
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
/** Create a new Path object using the provided input(s). */
|
|
@@ -76,8 +77,13 @@ class Path {
|
|
|
76
77
|
.flat(1)
|
|
77
78
|
.map((part) => (typeof part === "string" ? part : part.segments))
|
|
78
79
|
.flat(1);
|
|
79
|
-
this.segments =
|
|
80
|
-
this.separator =
|
|
80
|
+
this.segments = this.constructor.splitToSegments(parts);
|
|
81
|
+
this.separator = this.constructor.detectSeparator(parts, "/");
|
|
82
|
+
Object.defineProperty(this, "__is_Path", {
|
|
83
|
+
configurable: true,
|
|
84
|
+
enumerable: false,
|
|
85
|
+
value: true,
|
|
86
|
+
});
|
|
81
87
|
}
|
|
82
88
|
/**
|
|
83
89
|
* Create a new Path object using the provided segments and, optionally,
|
|
@@ -88,9 +94,9 @@ class Path {
|
|
|
88
94
|
* `.segments` directly, use {@link fromRaw}.
|
|
89
95
|
*/
|
|
90
96
|
static from(segments, separator) {
|
|
91
|
-
const separatorToUse = separator ||
|
|
92
|
-
const path = new
|
|
93
|
-
path.segments =
|
|
97
|
+
const separatorToUse = separator || this.detectSeparator(segments, "/");
|
|
98
|
+
const path = new this();
|
|
99
|
+
path.segments = this._validateSegments(segments, separatorToUse);
|
|
94
100
|
path.separator = separatorToUse;
|
|
95
101
|
return path;
|
|
96
102
|
}
|
|
@@ -102,7 +108,7 @@ class Path {
|
|
|
102
108
|
* {@link from} instead.
|
|
103
109
|
*/
|
|
104
110
|
static fromRaw(segments, separator) {
|
|
105
|
-
const path = new
|
|
111
|
+
const path = new this();
|
|
106
112
|
path.segments = segments;
|
|
107
113
|
path.separator = separator;
|
|
108
114
|
return path;
|
|
@@ -141,7 +147,7 @@ class Path {
|
|
|
141
147
|
}
|
|
142
148
|
}
|
|
143
149
|
}
|
|
144
|
-
return
|
|
150
|
+
return this.constructor.fromRaw(newSegments, this.separator);
|
|
145
151
|
}
|
|
146
152
|
/**
|
|
147
153
|
* Create a new Path by appending additional path segments onto the end of
|
|
@@ -150,8 +156,9 @@ class Path {
|
|
|
150
156
|
* The returned path will use this path's separator.
|
|
151
157
|
*/
|
|
152
158
|
concat(...others) {
|
|
153
|
-
const otherSegments = new
|
|
154
|
-
|
|
159
|
+
const otherSegments = new this.constructor(others.flat(1))
|
|
160
|
+
.segments;
|
|
161
|
+
return this.constructor.from(this.segments.concat(otherSegments), this.separator);
|
|
155
162
|
}
|
|
156
163
|
/**
|
|
157
164
|
* Return whether this path is absolute; that is, whether it starts with
|
|
@@ -176,6 +183,18 @@ class Path {
|
|
|
176
183
|
const theClone = this.constructor.fromRaw([...this.segments], this.separator);
|
|
177
184
|
return theClone;
|
|
178
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Returns a boolean indicating whether `other` is a Path instance.
|
|
188
|
+
*
|
|
189
|
+
* Works cross-context/realm/iframe/etc.
|
|
190
|
+
*
|
|
191
|
+
* @param other - Any value
|
|
192
|
+
*/
|
|
193
|
+
static isPath(other) {
|
|
194
|
+
return (typeof other === "object" &&
|
|
195
|
+
other !== null &&
|
|
196
|
+
other.__is_Path === true);
|
|
197
|
+
}
|
|
179
198
|
/**
|
|
180
199
|
* Express this path relative to `dir`.
|
|
181
200
|
*
|
|
@@ -183,8 +202,8 @@ class Path {
|
|
|
183
202
|
* @param options - Options that affect the resulting path.
|
|
184
203
|
*/
|
|
185
204
|
relativeTo(dir, options = {}) {
|
|
186
|
-
if (!(dir
|
|
187
|
-
dir = new
|
|
205
|
+
if (!this.constructor.isPath(dir)) {
|
|
206
|
+
dir = new this.constructor(dir);
|
|
188
207
|
}
|
|
189
208
|
const ownSegments = [...this.segments];
|
|
190
209
|
const dirSegments = [...dir.segments];
|
|
@@ -194,15 +213,15 @@ class Path {
|
|
|
194
213
|
}
|
|
195
214
|
if (dirSegments.length === 0) {
|
|
196
215
|
if (options.noLeadingDot) {
|
|
197
|
-
return
|
|
216
|
+
return this.constructor.from(ownSegments, this.separator);
|
|
198
217
|
}
|
|
199
218
|
else {
|
|
200
|
-
return
|
|
219
|
+
return this.constructor.from([".", ...ownSegments], this.separator);
|
|
201
220
|
}
|
|
202
221
|
}
|
|
203
222
|
else {
|
|
204
223
|
const dotDots = dirSegments.map((_) => "..");
|
|
205
|
-
return
|
|
224
|
+
return this.constructor.from([...dotDots, ...ownSegments], this.separator);
|
|
206
225
|
}
|
|
207
226
|
}
|
|
208
227
|
/**
|
|
@@ -214,7 +233,7 @@ class Path {
|
|
|
214
233
|
return "/";
|
|
215
234
|
}
|
|
216
235
|
else {
|
|
217
|
-
if (
|
|
236
|
+
if (this.constructor._isWin32DriveLetter(result)) {
|
|
218
237
|
return result + this.separator;
|
|
219
238
|
}
|
|
220
239
|
else {
|
|
@@ -271,7 +290,7 @@ class Path {
|
|
|
271
290
|
* Path B does *not* start with Path A, because `".config" !== ".config2"`.
|
|
272
291
|
*/
|
|
273
292
|
startsWith(value) {
|
|
274
|
-
value = new
|
|
293
|
+
value = new this.constructor(value);
|
|
275
294
|
return value.segments.every((segment, index) => this.segments[index] === segment);
|
|
276
295
|
}
|
|
277
296
|
/**
|
|
@@ -291,7 +310,7 @@ class Path {
|
|
|
291
310
|
* Path A does *not* end with Path B, because `"1user" !== "user"`.
|
|
292
311
|
*/
|
|
293
312
|
endsWith(value) {
|
|
294
|
-
value = new
|
|
313
|
+
value = new this.constructor(value);
|
|
295
314
|
const valueSegmentsReversed = [...value.segments].reverse();
|
|
296
315
|
const ownSegmentsReversed = [...this.segments].reverse();
|
|
297
316
|
return valueSegmentsReversed.every((segment, index) => ownSegmentsReversed[index] === segment);
|
|
@@ -304,7 +323,7 @@ class Path {
|
|
|
304
323
|
* @param fromIndex - The index into this path's segments to begin searching at. Defaults to `0`.
|
|
305
324
|
*/
|
|
306
325
|
indexOf(value, fromIndex = 0) {
|
|
307
|
-
value = new
|
|
326
|
+
value = new this.constructor(value);
|
|
308
327
|
const ownSegmentsLength = this.segments.length;
|
|
309
328
|
for (let i = fromIndex; i < ownSegmentsLength; i++) {
|
|
310
329
|
if (value.segments.every((valueSegment, valueIndex) => {
|
|
@@ -337,8 +356,8 @@ class Path {
|
|
|
337
356
|
* NOTE: to remove segments, use an empty Array for `replacement`.
|
|
338
357
|
*/
|
|
339
358
|
replace(value, replacement) {
|
|
340
|
-
value = new
|
|
341
|
-
replacement = new
|
|
359
|
+
value = new this.constructor(value);
|
|
360
|
+
replacement = new this.constructor(replacement);
|
|
342
361
|
const matchIndex = this.indexOf(value);
|
|
343
362
|
if (matchIndex === -1) {
|
|
344
363
|
return this.clone();
|
|
@@ -349,7 +368,7 @@ class Path {
|
|
|
349
368
|
...replacement.segments,
|
|
350
369
|
...this.segments.slice(matchIndex + value.segments.length),
|
|
351
370
|
];
|
|
352
|
-
return
|
|
371
|
+
return this.constructor.from(newSegments, this.separator);
|
|
353
372
|
}
|
|
354
373
|
}
|
|
355
374
|
/**
|
|
@@ -361,7 +380,7 @@ class Path {
|
|
|
361
380
|
* @param replacement - What it should be replaced with
|
|
362
381
|
*/
|
|
363
382
|
replaceAll(value, replacement) {
|
|
364
|
-
replacement = new
|
|
383
|
+
replacement = new this.constructor(replacement);
|
|
365
384
|
let searchIndex = 0;
|
|
366
385
|
let currentPath = this;
|
|
367
386
|
const ownLength = this.segments.length;
|
|
@@ -383,11 +402,38 @@ class Path {
|
|
|
383
402
|
* @param replacement - The new final segment(s) for the returned Path
|
|
384
403
|
*/
|
|
385
404
|
replaceLast(replacement) {
|
|
386
|
-
replacement = new
|
|
405
|
+
replacement = new this.constructor(replacement);
|
|
387
406
|
const segments = [...this.segments];
|
|
388
407
|
segments.pop();
|
|
389
408
|
segments.push(...replacement.segments);
|
|
390
|
-
return
|
|
409
|
+
return this.constructor.from(segments, this.separator);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Return a boolean indicating whether this Path has the same separator and
|
|
413
|
+
* segments as another Path.
|
|
414
|
+
*
|
|
415
|
+
* To check only segments and not separator, use {@link Path.prototype.hasEqualSegments}.
|
|
416
|
+
*/
|
|
417
|
+
equals(other) {
|
|
418
|
+
if (!this.constructor.isPath(other)) {
|
|
419
|
+
other = new this.constructor(other);
|
|
420
|
+
}
|
|
421
|
+
return other.separator === this.separator && this.hasEqualSegments(other);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Return a boolean indicating whether this Path has the same segments as
|
|
425
|
+
* another Path. **Separator is not checked; use {@link Path.prototype.equals} for that.**
|
|
426
|
+
*/
|
|
427
|
+
hasEqualSegments(other) {
|
|
428
|
+
if (!this.constructor.isPath(other)) {
|
|
429
|
+
other = new this.constructor(other);
|
|
430
|
+
}
|
|
431
|
+
return (this.segments.length === other.segments.length &&
|
|
432
|
+
this.segments.every((segment, index) => {
|
|
433
|
+
return segment === other.segments[index];
|
|
434
|
+
}));
|
|
391
435
|
}
|
|
392
436
|
}
|
|
393
437
|
exports.Path = Path;
|
|
438
|
+
/** Used by {@link _isWin32DriveLetter}. */
|
|
439
|
+
Path._WIN32_DRIVE_LETTER_REGEXP = /^[A-Za-z]:$/;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nice-path",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"repository": {
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"file"
|
|
18
18
|
],
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@types/node": "^
|
|
21
|
-
"prettier": "^3.
|
|
22
|
-
"typescript": "^5.
|
|
23
|
-
"vitest": "^
|
|
20
|
+
"@types/node": "^24.0.11",
|
|
21
|
+
"prettier": "^3.6.2",
|
|
22
|
+
"typescript": "^5.8.3",
|
|
23
|
+
"vitest": "^3.2.4"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "rm -rf dist && tsc",
|