nice-path 3.1.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/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(): Path;
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>>): 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
- }): Path;
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(): Path;
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>): 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,13 +187,13 @@ 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>): 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>): Path;
196
+ replaceLast(replacement: string | Path | Array<string | Path>): this;
182
197
  /**
183
198
  * Return a boolean indicating whether this Path has the same separator and
184
199
  * segments as another Path.
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 = Path.detectSeparator(inputParts, "/");
32
- return validateSegments(inputParts.map((part) => part.split(/(?:\/|\\)/g)).flat(1), separator);
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 Path(...inputs).normalize();
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 instanceof Path) {
67
+ if (this.constructor.isPath(path)) {
67
68
  return path.isAbsolute();
68
69
  }
69
70
  else {
70
- return new Path(path).isAbsolute();
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 = Path.splitToSegments(parts);
80
- this.separator = Path.detectSeparator(parts, "/");
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 || Path.detectSeparator(segments, "/");
92
- const path = new Path();
93
- path.segments = validateSegments(segments, separatorToUse);
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 Path();
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 Path.fromRaw(newSegments, this.separator);
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 Path(others.flat(1)).segments;
154
- return Path.from(this.segments.concat(otherSegments), this.separator);
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 instanceof Path)) {
187
- dir = new Path(dir);
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 Path.from(ownSegments, this.separator);
216
+ return this.constructor.from(ownSegments, this.separator);
198
217
  }
199
218
  else {
200
- return Path.from([".", ...ownSegments], this.separator);
219
+ return this.constructor.from([".", ...ownSegments], this.separator);
201
220
  }
202
221
  }
203
222
  else {
204
223
  const dotDots = dirSegments.map((_) => "..");
205
- return Path.from([...dotDots, ...ownSegments], this.separator);
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 (isWin32DriveLetter(result)) {
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 Path(value);
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 Path(value);
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 Path(value);
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 Path(value);
341
- replacement = new Path(replacement);
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 Path.from(newSegments, this.separator);
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 Path(replacement);
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,11 @@ class Path {
383
402
  * @param replacement - The new final segment(s) for the returned Path
384
403
  */
385
404
  replaceLast(replacement) {
386
- replacement = new Path(replacement);
405
+ replacement = new this.constructor(replacement);
387
406
  const segments = [...this.segments];
388
407
  segments.pop();
389
408
  segments.push(...replacement.segments);
390
- return Path.from(segments, this.separator);
409
+ return this.constructor.from(segments, this.separator);
391
410
  }
392
411
  /**
393
412
  * Return a boolean indicating whether this Path has the same separator and
@@ -396,8 +415,8 @@ class Path {
396
415
  * To check only segments and not separator, use {@link Path.prototype.hasEqualSegments}.
397
416
  */
398
417
  equals(other) {
399
- if (!(other instanceof Path)) {
400
- other = new Path(other);
418
+ if (!this.constructor.isPath(other)) {
419
+ other = new this.constructor(other);
401
420
  }
402
421
  return other.separator === this.separator && this.hasEqualSegments(other);
403
422
  }
@@ -406,8 +425,8 @@ class Path {
406
425
  * another Path. **Separator is not checked; use {@link Path.prototype.equals} for that.**
407
426
  */
408
427
  hasEqualSegments(other) {
409
- if (!(other instanceof Path)) {
410
- other = new Path(other);
428
+ if (!this.constructor.isPath(other)) {
429
+ other = new this.constructor(other);
411
430
  }
412
431
  return (this.segments.length === other.segments.length &&
413
432
  this.segments.every((segment, index) => {
@@ -416,3 +435,5 @@ class Path {
416
435
  }
417
436
  }
418
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.1.0",
3
+ "version": "3.2.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {