@gesslar/toolkit 3.28.0 → 3.30.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/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "gesslar",
6
6
  "url": "https://gesslar.dev"
7
7
  },
8
- "version": "3.28.0",
8
+ "version": "3.30.0",
9
9
  "license": "Unlicense",
10
10
  "homepage": "https://github.com/gesslar/toolkit#readme",
11
11
  "repository": {
@@ -61,7 +61,7 @@
61
61
  "devDependencies": {
62
62
  "@gesslar/uglier": "^1.2.0",
63
63
  "eslint": "^9.39.2",
64
- "happy-dom": "^20.3.7",
64
+ "happy-dom": "^20.4.0",
65
65
  "typescript": "^5.9.3"
66
66
  },
67
67
  "scripts": {
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import {glob, mkdir, opendir, readdir, rmdir} from "node:fs/promises"
8
+ import {relative} from "node:path"
8
9
  import path from "node:path"
9
10
  import {URL} from "node:url"
10
11
 
@@ -540,75 +541,100 @@ export default class DirectoryObject extends FS {
540
541
  /**
541
542
  * Creates a new DirectoryObject by extending this directory's path.
542
543
  *
544
+ * Paths are always resolved relative to THIS directory. Any attempt to
545
+ * escape via `..` or absolute paths is constrained - the `..` segments
546
+ * are stripped and the remaining path is resolved relative to this directory.
547
+ *
548
+ * On Windows, cross-drive absolute paths (e.g., `D:\foo` when base is `C:\`)
549
+ * are also constrained - the drive root is stripped and the path is resolved
550
+ * relative to this directory.
551
+ *
543
552
  * Uses overlapping path segment detection to intelligently combine paths.
544
- * Preserves the temporary flag from the current directory.
545
553
  *
546
554
  * @param {string} newPath - The path to append to this directory's path.
547
555
  * @returns {DirectoryObject} A new DirectoryObject with the extended path.
548
556
  * @example
549
557
  * const dir = new DirectoryObject("/projects/git/toolkit")
550
- * const subDir = dir.addDirectory("src/lib")
558
+ * const subDir = dir.getDirectory("src/lib")
551
559
  * console.log(subDir.path) // "/projects/git/toolkit/src/lib"
560
+ *
561
+ * @example
562
+ * // Path traversal is constrained to this directory
563
+ * const dir = new DirectoryObject("/projects/git/toolkit")
564
+ * const escaped = dir.getDirectory("../../../foo/bar")
565
+ * console.log(escaped.path) // "/projects/git/toolkit/foo/bar"
552
566
  */
553
567
  getDirectory(newPath) {
554
568
  Valid.type(newPath, "String", {allowEmpty: false})
555
569
 
556
- // Reject absolute paths
557
- if(path.isAbsolute(newPath)) {
558
- throw Sass.new(`Absolute paths not allowed: ${newPath}`)
559
- }
560
-
561
- // Reject parent directory traversal
562
- if(newPath.includes("..")) {
563
- throw Sass.new(`Path traversal not allowed: ${newPath} contains '..'`)
564
- }
565
-
570
+ // New direction: every path is relative to THIS path. Absolute?
571
+ // ../../../..? up to this path and then down again if required.
566
572
  const thisPath = this.path
567
573
  const merged = FS.mergeOverlappingPaths(thisPath, newPath)
568
574
  const resolved = FS.resolvePath(thisPath, merged)
575
+ let local = relative(thisPath, resolved)
569
576
 
570
- // Final safety check
571
- if(!FS.pathContains(thisPath, resolved)) {
572
- throw Sass.new(`Path resolves outside directory: ${newPath}`)
573
- }
577
+ // On Windows, cross-drive paths return absolute - strip the root
578
+ if(path.isAbsolute(local))
579
+ local = local.slice(path.parse(local).root.length)
580
+
581
+ const parts = local.split(this.sep)
582
+
583
+ while(parts[0] === "..")
584
+ parts.shift()
585
+
586
+ const newLocal = parts.join(this.sep)
574
587
 
575
- return new this.constructor(resolved)
588
+ return new this.constructor(FS.resolvePath(this.path, newLocal))
576
589
  }
577
590
 
578
591
  /**
579
592
  * Creates a new FileObject by extending this directory's path.
580
593
  *
594
+ * Paths are always resolved relative to THIS directory. Any attempt to
595
+ * escape via `..` or absolute paths is constrained - the `..` segments
596
+ * are stripped and the remaining path is resolved relative to this directory.
597
+ *
598
+ * On Windows, cross-drive absolute paths (e.g., `D:\foo` when base is `C:\`)
599
+ * are also constrained - the drive root is stripped and the path is resolved
600
+ * relative to this directory.
601
+ *
581
602
  * Uses overlapping path segment detection to intelligently combine paths.
582
603
  *
583
604
  * @param {string} filename - The filename to append to this directory's path.
584
605
  * @returns {FileObject} A new FileObject with the extended path.
585
606
  * @example
586
607
  * const dir = new DirectoryObject("/projects/git/toolkit")
587
- * const file = dir.addFile("package.json")
608
+ * const file = dir.getFile("package.json")
588
609
  * console.log(file.path) // "/projects/git/toolkit/package.json"
610
+ *
611
+ * @example
612
+ * // Path traversal is constrained to this directory
613
+ * const dir = new DirectoryObject("/projects/git/toolkit")
614
+ * const escaped = dir.getFile("../../../foo/bar.js")
615
+ * console.log(escaped.path) // "/projects/git/toolkit/foo/bar.js"
589
616
  */
590
617
  getFile(filename) {
591
618
  Valid.type(filename, "String", {allowEmpty: false})
592
619
 
593
- // Reject absolute paths
594
- if(path.isAbsolute(filename)) {
595
- throw Sass.new(`Absolute paths not allowed: ${filename}`)
596
- }
597
-
598
- // Reject parent directory traversal
599
- if(filename.includes("..")) {
600
- throw Sass.new(`Path traversal not allowed: ${filename} contains '..'`)
601
- }
602
-
620
+ // Every path is relative to THIS path. Absolute or .. paths
621
+ // are constrained to this directory.
603
622
  const thisPath = this.path
604
623
  const merged = FS.mergeOverlappingPaths(thisPath, filename)
605
624
  const resolved = FS.resolvePath(thisPath, merged)
625
+ let local = relative(thisPath, resolved)
606
626
 
607
- // Final safety check
608
- if(!FS.pathContains(thisPath, resolved)) {
609
- throw Sass.new(`Path resolves outside directory: ${filename}`)
610
- }
627
+ // On Windows, cross-drive paths return absolute - strip the root
628
+ if(path.isAbsolute(local))
629
+ local = local.slice(path.parse(local).root.length)
630
+
631
+ const parts = local.split(this.sep)
632
+
633
+ while(parts[0] === "..")
634
+ parts.shift()
635
+
636
+ const newLocal = parts.join(this.sep)
611
637
 
612
- return new FileObject(resolved)
638
+ return new FileObject(newLocal, this)
613
639
  }
614
640
  }
@@ -251,11 +251,11 @@ export default class FileSystem {
251
251
  * @param {string} [sep=path.sep] - The path separator to use (defaults to system separator)
252
252
  * @returns {string|null} The relative path, empty string if paths are identical, or null if no overlap found
253
253
  * @example
254
- * FS.toRelativePath("/projects/toolkit", "/projects/toolkit/src") // "src"
255
- * FS.toRelativePath("/home/user", "/home/user") // ""
256
- * FS.toRelativePath("/projects/app", "/other/path") // null
254
+ * FS.toLocalRelativePath("/projects/toolkit", "/projects/toolkit/src") // "src"
255
+ * FS.toLocalRelativePath("/home/user", "/home/user") // ""
256
+ * FS.toLocalRelativePath("/projects/app", "/other/path") // null
257
257
  */
258
- static toRelativePath(from, to, sep=path.sep) {
258
+ static toLocalRelativePath(from, to, sep=path.sep) {
259
259
  // If they're the same, just return ""
260
260
  if(from === to)
261
261
  return ""
@@ -276,20 +276,46 @@ export default class FileSystem {
276
276
  }
277
277
 
278
278
  /**
279
- * Find the common root path between two paths by identifying overlapping segments.
280
- * Returns the portion of 'from' that matches up to the overlap point in 'to'.
279
+ * Computes the relative path from one path to another using Node's path.relative.
280
+ *
281
+ * Unlike toLocalRelativePath which uses overlap detection, this method uses
282
+ * standard relative path calculation and may return paths with ".." segments.
283
+ *
284
+ * @static
285
+ * @param {string} from - The base path to calculate relative from
286
+ * @param {string} to - The target path to make relative
287
+ * @returns {string} The relative path, or empty string if paths are identical
288
+ * @example
289
+ * FS.toRelativePath("/home/user", "/home/user/docs") // "docs"
290
+ * FS.toRelativePath("/home/user", "/home/user") // ""
291
+ * FS.toRelativePath("/home/user", "/home/other") // "../other"
292
+ */
293
+ static toRelativePath(from, to) {
294
+ // If they're the same, just return ""
295
+ if(from === to)
296
+ return ""
297
+
298
+ return path.relative(from, to)
299
+ }
300
+
301
+ /**
302
+ * Find where a path's final segment appears in another path, returning the
303
+ * portion of 'from' up to that overlap point.
304
+ *
305
+ * Looks for the last segment of `from` within `to`. If found, returns `from`
306
+ * sliced to the index where that segment appears in `to`.
281
307
  *
282
308
  * @static
283
- * @param {string} from - The first path to compare
284
- * @param {string} to - The second path to find common root with
309
+ * @param {string} from - The source path whose final segment to search for
310
+ * @param {string} to - The target path to search within
285
311
  * @param {string} [sep=path.sep] - The path separator to use (defaults to system separator)
286
- * @returns {string|null} The common root path, the original path if identical, or null if no overlap found
312
+ * @returns {string|null} The sliced portion of from, the original path if identical, or null if no overlap
287
313
  * @throws {Sass} If from is not a non-empty string
288
314
  * @throws {Sass} If to is not a non-empty string
289
315
  * @example
290
- * FS.getCommonRootPath("/projects/toolkit/src", "/projects/toolkit/tests") // "/projects/toolkit"
316
+ * FS.getCommonRootPath("/projects/toolkit", "/projects/toolkit/src") // "/projects/toolkit"
291
317
  * FS.getCommonRootPath("/home/user", "/home/user") // "/home/user"
292
- * FS.getCommonRootPath("/projects/app", "/other/path") // null
318
+ * FS.getCommonRootPath("/projects/app", "/other/path") // null (no overlap)
293
319
  */
294
320
  static getCommonRootPath(from, to, sep=path.sep) {
295
321
  Valid.type(from, "String", {allowEmpty: false})
@@ -3,9 +3,29 @@ import process from "node:process"
3
3
  import {Writable} from "node:stream"
4
4
  import supportsColor from "supports-color"
5
5
  import {stripVTControlCharacters} from "node:util"
6
+ import c from "@gesslar/colours"
6
7
 
7
8
  import Sass from "./Sass.js"
8
9
 
10
+ c.alias.set("success", "{F035}")
11
+ c.alias.set("info", "{F033}")
12
+ c.alias.set("warn", "{F208}")
13
+ c.alias.set("error", "{F032}")
14
+ c.alias.set("modified", "{F147}")
15
+
16
+ /**
17
+ * Terminal output utilities with ANSI colour support.
18
+ *
19
+ * Provides console logging wrappers, cursor control, and formatted message
20
+ * output with colour styling via `@gesslar/colours`.
21
+ *
22
+ * Predefined colour aliases:
23
+ * - `success` - green (F035)
24
+ * - `info` - blue (F033)
25
+ * - `warn` - orange (F208)
26
+ * - `error` - red (F032)
27
+ * - `modified` - purple (F147)
28
+ */
9
29
  export default class Term {
10
30
  static #cache = new Map()
11
31
 
@@ -217,17 +237,17 @@ export default class Term {
217
237
  }
218
238
 
219
239
  /**
220
- * Constructs a formatted status line.
240
+ * Constructs a formatted status line with optional colour styling.
221
241
  *
222
242
  * Input forms:
223
243
  * - string: printed as-is
224
244
  * - array: each element is either:
225
245
  * - a plain string (emitted unchanged), or
226
- * - a tuple: [level, text] where `level` maps to an ansiColors alias
227
- * (e.g. success, info, warn, error, modified).
228
- * - a tuple: [level, text, [openBracket,closeBracket]] where `level` maps to an ansiColors alias
229
- * (e.g. success, info, warn, error, modified). These are rendered as
230
- * colourised bracketed segments: [TEXT].
246
+ * - a tuple: [colourCode, text] where `colourCode` is a colour alias
247
+ * (e.g. success, info, warn, error, modified) or any valid
248
+ * `@gesslar/colours` format string.
249
+ * - a tuple: [colourCode, text, [openBracket, closeBracket]] for custom
250
+ * brackets around the colourised text.
231
251
  *
232
252
  * The function performs a shallow validation: tuple elements must both be
233
253
  * strings; otherwise a TypeError is thrown. Nested arrays beyond depth 1 are
@@ -236,8 +256,8 @@ export default class Term {
236
256
  * Recursion: array input is normalised into a single string then re-dispatched
237
257
  * through `status` to leverage the string branch (keeps logic DRY).
238
258
  *
239
- * @param {string | Array<string | [string, string] | [string, string, string]>} argList - Message spec.
240
- * @returns {void}
259
+ * @param {string | Array<string | [string, string] | [string, string, [string, string]]>} argList - Message spec.
260
+ * @returns {string} The formatted message string.
241
261
  */
242
262
  static terminalMessage(argList) {
243
263
  if(typeof argList === "string")
@@ -269,34 +289,33 @@ export default class Term {
269
289
 
270
290
  /**
271
291
  * Construct a single coloured bracketed segment from a tuple specifying
272
- * the style level and the text. The first element ("level") maps to an
273
- * `ansiColors` alias (e.g. success, info, warn, error, modified) and is
274
- * used both for the inner text colour and to locate its matching
275
- * "-bracket" alias for the surrounding square brackets. The second
276
- * element is the raw text to display.
292
+ * the colour code and text. The first element is a colour code that can be
293
+ * a predefined alias (success, info, warn, error, modified) or any valid
294
+ * `@gesslar/colours` format string. The brackets are coloured while the
295
+ * inner text remains uncoloured.
277
296
  *
278
- * Input validation: every element of `parts` must be a string; otherwise
279
- * an `Sass` error is thrown. (Additional elements beyond the first two are
280
- * ignored – the method destructures only the first pair.)
297
+ * Input validation: colourCode and text must both be strings; otherwise
298
+ * a `Sass` error is thrown.
281
299
  *
282
300
  * Example:
283
- * terminalBracket(["success", "COMPILED"]) → "[COMPILED]" with coloured
284
- * brackets + inner text (assuming colour support is available in the
285
- * terminal).
301
+ * terminalBracket(["success", "COMPILED"]) → "[COMPILED]" with green
302
+ * brackets (assuming colour support is available in the terminal).
303
+ *
304
+ * terminalBracket(["info", "STATUS", ["<", ">"]]) → "<STATUS>" with blue
305
+ * angle brackets.
286
306
  *
287
307
  * This method does not append trailing spaces; callers are responsible for
288
308
  * joining multiple segments with appropriate separators.
289
309
  *
290
- * @param {Array<string>} parts - Tuple: [level, text]. Additional entries ignored.
310
+ * @param {[string, string, [string, string]?]} parts - Tuple: [colourCode, text, brackets?].
291
311
  * @returns {string} Colourised bracketed segment (e.g. "[TEXT]").
292
- * @throws {Sass} If any element of `parts` is not a string.
312
+ * @throws {Sass} If colourCode or text is not a string.
293
313
  */
294
- static terminalBracket([level, text, brackets=["[","]"]]) {
295
- if(!(typeof level === "string" && typeof text === "string"))
314
+ static terminalBracket([colourCode="", text, brackets=["[","]"]]) {
315
+ if(!(typeof colourCode === "string" && typeof text === "string"))
296
316
  throw Sass.new("Each element must be a string.")
297
317
 
298
- // Simplified version without color support - just return bracketed text
299
- return `${brackets[0]}${text}${brackets[1]}`
318
+ return this.#preformat(c`{${colourCode}}${brackets[0]}{/}${text}{${colourCode}}${brackets[1]}{/}`)
300
319
  }
301
320
 
302
321
  /**
@@ -266,28 +266,55 @@ export default class DirectoryObject extends FS {
266
266
  /**
267
267
  * Creates a new DirectoryObject by extending this directory's path.
268
268
  *
269
+ * Paths are always resolved relative to THIS directory. Any attempt to
270
+ * escape via `..` or absolute paths is constrained - the `..` segments
271
+ * are stripped and the remaining path is resolved relative to this directory.
272
+ *
273
+ * On Windows, cross-drive absolute paths (e.g., `D:\foo` when base is `C:\`)
274
+ * are also constrained - the drive root is stripped and the path is resolved
275
+ * relative to this directory.
276
+ *
269
277
  * Uses overlapping path segment detection to intelligently combine paths.
270
- * Preserves the temporary flag from the current directory.
271
278
  *
272
279
  * @param {string} newPath - The path to append to this directory's path.
273
280
  * @returns {DirectoryObject} A new DirectoryObject with the extended path.
274
281
  * @example
275
282
  * const dir = new DirectoryObject("/projects/git/toolkit")
276
- * const subDir = dir.addDirectory("src/lib")
283
+ * const subDir = dir.getDirectory("src/lib")
277
284
  * console.log(subDir.path) // "/projects/git/toolkit/src/lib"
285
+ *
286
+ * @example
287
+ * // Path traversal is constrained to this directory
288
+ * const dir = new DirectoryObject("/projects/git/toolkit")
289
+ * const escaped = dir.getDirectory("../../../foo/bar")
290
+ * console.log(escaped.path) // "/projects/git/toolkit/foo/bar"
278
291
  */
279
292
  getDirectory(newPath: string): DirectoryObject;
280
293
  /**
281
294
  * Creates a new FileObject by extending this directory's path.
282
295
  *
296
+ * Paths are always resolved relative to THIS directory. Any attempt to
297
+ * escape via `..` or absolute paths is constrained - the `..` segments
298
+ * are stripped and the remaining path is resolved relative to this directory.
299
+ *
300
+ * On Windows, cross-drive absolute paths (e.g., `D:\foo` when base is `C:\`)
301
+ * are also constrained - the drive root is stripped and the path is resolved
302
+ * relative to this directory.
303
+ *
283
304
  * Uses overlapping path segment detection to intelligently combine paths.
284
305
  *
285
306
  * @param {string} filename - The filename to append to this directory's path.
286
307
  * @returns {FileObject} A new FileObject with the extended path.
287
308
  * @example
288
309
  * const dir = new DirectoryObject("/projects/git/toolkit")
289
- * const file = dir.addFile("package.json")
310
+ * const file = dir.getFile("package.json")
290
311
  * console.log(file.path) // "/projects/git/toolkit/package.json"
312
+ *
313
+ * @example
314
+ * // Path traversal is constrained to this directory
315
+ * const dir = new DirectoryObject("/projects/git/toolkit")
316
+ * const escaped = dir.getFile("../../../foo/bar.js")
317
+ * console.log(escaped.path) // "/projects/git/toolkit/foo/bar.js"
291
318
  */
292
319
  getFile(filename: string): FileObject;
293
320
  #private;
@@ -1 +1 @@
1
- {"version":3,"file":"DirectoryObject.d.ts","sourceRoot":"","sources":["../../../src/node/lib/DirectoryObject.js"],"names":[],"mappings":"AAgBA;;;;GAIG;AAEH;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH;IAuDE;;;;;;;;;OASG;IACH,kBALa,eAAe,CAO3B;IA7CD;;;;OAIG;IACH,uBAFW,MAAM,OAAC,EA4BjB;IAyBD;;;;OAIG;IACH,cAFa,OAAO,CAAC,OAAO,CAAC,CAI5B;IAED;;;;OAIG;IACH,gBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,YAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAFa,GAAG,CAIf;IAED;;;;OAIG;IACH,YAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,cAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,iBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAFa,MAAM,CAIlB;IAED;;;;;;;OAOG;IACH,aALa,KAAK,CAAC,MAAM,CAAC,CAOzB;IAED;;;;;;;;;;;;OAYG;IACH,cARa,eAAe,GAAC,IAAI,CAsBhC;IAED;;;;OAIG;IACH,mBAFa,OAAO,CAInB;IAmBD;;;;;;;;;;;;;;;;;OAiBG;IACH,WAZW,MAAM,iBACJ,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAAC,WAAW,EAAE,KAAK,CAAC,eAAe,CAAC,CAAA;KAAC,CAAC,CA8CpF;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,WAZW,MAAM,iBACJ,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,UAAU,GAAC,UAAU,CAAC,CAAC;QAAC,WAAW,EAAE,KAAK,CAAC,eAAe,CAAC,CAAA;KAAC,CAAC,CAiD/F;IAED;;;;;;;;;;;;OAYG;IACH,uBARW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAuBzB;IAyBD;;;;;;;;;;;;;;;OAeG;IACH,cAZa,eAAe,CAc3B;IAED;;;;;;;;;;;;;;OAcG;IACH,UARa,OAAO,CAAC,IAAI,CAAC,CAkBzB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAM5B;IAED;;;;;OAKG;IACH,sBAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAO5B;IAED;;;;;;;;;;;;OAYG;IACH,sBAPW,MAAM,GACJ,eAAe,CA6B3B;IAED;;;;;;;;;;;OAWG;IACH,kBAPW,MAAM,GACJ,UAAU,CA6BtB;;CACF;;UAnlBa,MAAY;QAAC,KAAK,EAAE,eAAe,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAC;eACnD,MAAY,aAAa;;;;;;iBAMzB,OAAO;;;;eACP,MAAM,GAAC,IAAI;;;;YACX,MAAM,GAAC,IAAI;;;;UACX,MAAM,GAAC,IAAI;;;;YACX,eAAe,GAAC,SAAS;;;;gBACzB,MAAM,GAAC,IAAI;;;;UACX,MAAM,GAAC,IAAI;;;;SACX,MAAM,GAAC,IAAI;;;;cACX,MAAM,GAAC,IAAI;;;;WACX,KAAK,CAAC,MAAM,CAAC,GAAC,IAAI;;;;SAClB,GAAG,GAAC,IAAI;;eAvBP,iBAAiB;uBADT,iBAAiB"}
1
+ {"version":3,"file":"DirectoryObject.d.ts","sourceRoot":"","sources":["../../../src/node/lib/DirectoryObject.js"],"names":[],"mappings":"AAiBA;;;;GAIG;AAEH;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH;IAuDE;;;;;;;;;OASG;IACH,kBALa,eAAe,CAO3B;IA7CD;;;;OAIG;IACH,uBAFW,MAAM,OAAC,EA4BjB;IAyBD;;;;OAIG;IACH,cAFa,OAAO,CAAC,OAAO,CAAC,CAI5B;IAED;;;;OAIG;IACH,gBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,YAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAFa,GAAG,CAIf;IAED;;;;OAIG;IACH,YAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,cAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,iBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAFa,MAAM,CAIlB;IAED;;;;;;;OAOG;IACH,aALa,KAAK,CAAC,MAAM,CAAC,CAOzB;IAED;;;;;;;;;;;;OAYG;IACH,cARa,eAAe,GAAC,IAAI,CAsBhC;IAED;;;;OAIG;IACH,mBAFa,OAAO,CAInB;IAmBD;;;;;;;;;;;;;;;;;OAiBG;IACH,WAZW,MAAM,iBACJ,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAAC,WAAW,EAAE,KAAK,CAAC,eAAe,CAAC,CAAA;KAAC,CAAC,CA8CpF;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,WAZW,MAAM,iBACJ,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,UAAU,GAAC,UAAU,CAAC,CAAC;QAAC,WAAW,EAAE,KAAK,CAAC,eAAe,CAAC,CAAA;KAAC,CAAC,CAiD/F;IAED;;;;;;;;;;;;OAYG;IACH,uBARW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAuBzB;IAyBD;;;;;;;;;;;;;;;OAeG;IACH,cAZa,eAAe,CAc3B;IAED;;;;;;;;;;;;;;OAcG;IACH,UARa,OAAO,CAAC,IAAI,CAAC,CAkBzB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAM5B;IAED;;;;;OAKG;IACH,sBAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAO5B;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,sBAbW,MAAM,GACJ,eAAe,CAkC3B;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,kBAbW,MAAM,GACJ,UAAU,CAkCtB;;CACF;;UA5mBa,MAAY;QAAC,KAAK,EAAE,eAAe,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAC;eACnD,MAAY,aAAa;;;;;;iBAMzB,OAAO;;;;eACP,MAAM,GAAC,IAAI;;;;YACX,MAAM,GAAC,IAAI;;;;UACX,MAAM,GAAC,IAAI;;;;YACX,eAAe,GAAC,SAAS;;;;gBACzB,MAAM,GAAC,IAAI;;;;UACX,MAAM,GAAC,IAAI;;;;SACX,MAAM,GAAC,IAAI;;;;cACX,MAAM,GAAC,IAAI;;;;WACX,KAAK,CAAC,MAAM,CAAC,GAAC,IAAI;;;;SAClB,GAAG,GAAC,IAAI;;eAvBP,iBAAiB;uBADT,iBAAiB"}
@@ -101,26 +101,45 @@ export default class FileSystem {
101
101
  * @param {string} [sep=path.sep] - The path separator to use (defaults to system separator)
102
102
  * @returns {string|null} The relative path, empty string if paths are identical, or null if no overlap found
103
103
  * @example
104
- * FS.toRelativePath("/projects/toolkit", "/projects/toolkit/src") // "src"
104
+ * FS.toLocalRelativePath("/projects/toolkit", "/projects/toolkit/src") // "src"
105
+ * FS.toLocalRelativePath("/home/user", "/home/user") // ""
106
+ * FS.toLocalRelativePath("/projects/app", "/other/path") // null
107
+ */
108
+ static toLocalRelativePath(from: string, to: string, sep?: string): string | null;
109
+ /**
110
+ * Computes the relative path from one path to another using Node's path.relative.
111
+ *
112
+ * Unlike toLocalRelativePath which uses overlap detection, this method uses
113
+ * standard relative path calculation and may return paths with ".." segments.
114
+ *
115
+ * @static
116
+ * @param {string} from - The base path to calculate relative from
117
+ * @param {string} to - The target path to make relative
118
+ * @returns {string} The relative path, or empty string if paths are identical
119
+ * @example
120
+ * FS.toRelativePath("/home/user", "/home/user/docs") // "docs"
105
121
  * FS.toRelativePath("/home/user", "/home/user") // ""
106
- * FS.toRelativePath("/projects/app", "/other/path") // null
122
+ * FS.toRelativePath("/home/user", "/home/other") // "../other"
107
123
  */
108
- static toRelativePath(from: string, to: string, sep?: string): string | null;
124
+ static toRelativePath(from: string, to: string): string;
109
125
  /**
110
- * Find the common root path between two paths by identifying overlapping segments.
111
- * Returns the portion of 'from' that matches up to the overlap point in 'to'.
126
+ * Find where a path's final segment appears in another path, returning the
127
+ * portion of 'from' up to that overlap point.
128
+ *
129
+ * Looks for the last segment of `from` within `to`. If found, returns `from`
130
+ * sliced to the index where that segment appears in `to`.
112
131
  *
113
132
  * @static
114
- * @param {string} from - The first path to compare
115
- * @param {string} to - The second path to find common root with
133
+ * @param {string} from - The source path whose final segment to search for
134
+ * @param {string} to - The target path to search within
116
135
  * @param {string} [sep=path.sep] - The path separator to use (defaults to system separator)
117
- * @returns {string|null} The common root path, the original path if identical, or null if no overlap found
136
+ * @returns {string|null} The sliced portion of from, the original path if identical, or null if no overlap
118
137
  * @throws {Sass} If from is not a non-empty string
119
138
  * @throws {Sass} If to is not a non-empty string
120
139
  * @example
121
- * FS.getCommonRootPath("/projects/toolkit/src", "/projects/toolkit/tests") // "/projects/toolkit"
140
+ * FS.getCommonRootPath("/projects/toolkit", "/projects/toolkit/src") // "/projects/toolkit"
122
141
  * FS.getCommonRootPath("/home/user", "/home/user") // "/home/user"
123
- * FS.getCommonRootPath("/projects/app", "/other/path") // null
142
+ * FS.getCommonRootPath("/projects/app", "/other/path") // null (no overlap)
124
143
  */
125
144
  static getCommonRootPath(from: string, to: string, sep?: string): string | null;
126
145
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"FileSystem.d.ts","sourceRoot":"","sources":["../../../src/node/lib/FileSystem.js"],"names":[],"mappings":"AA2BA;;GAEG;AACH;IACE,kCAAwB;IACxB,uCAAkC;IAClC,mBAAsB;IAsBtB;;;;;;OAMG;IACH,4BAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,2BAHW,MAAM,GACJ,MAAM,CAQlB;IAED;;;;;;;;OAQG;IACH,0BALW,MAAM,GACJ,MAAM,CAUlB;IAED;;;;;;;;;;OAUG;IACH,gCAJW,UAAU,GAAC,eAAe,MAC1B,UAAU,GAAC,eAAe,GACxB,MAAM,CAYlB;IAED;;;;;;;;;;OAUG;IACH,oCAJW,MAAM,MACN,MAAM,GACJ,MAAM,CAQlB;IAED;;;;;;;;;OASG;IACH,oCALW,MAAM,SACN,MAAM,QACN,MAAM,GACJ,MAAM,CA0BlB;IAED;;;;;;;;OAQG;IACH,6BAJW,MAAM,UACN,MAAM,GACJ,MAAM,CAmClB;IAED;;;;;;;;;;;;OAYG;IACH,+BATW,MAAM,aACN,MAAM,GACJ,OAAO,CAcnB;IAED;;;;;;;;;;;;;;OAcG;IACH,4BATW,MAAM,MACN,MAAM,QACN,MAAM,GACJ,MAAM,GAAC,IAAI,CAwBvB;IAED;;;;;;;;;;;;;;;OAeG;IACH,+BAXW,MAAM,MACN,MAAM,QACN,MAAM,GACJ,MAAM,GAAC,IAAI,CA+BvB;IAED;;;;;;;OAOG;IAEH;;;;;;;OAOG;IACH,2BAJW,MAAM;;;;cAXH,MAAM;;;;aACN,MAAM;;;;aACN,MAAM;;;;cACN,MAAM;;;;cACN,MAAM;MAenB;IAED;;;;OAIG;IACH,kBAFa,MAAM,CAIlB;IAzTD;;;;;;;;;OASG;IACH,kCAJW,UAAU,GAAC,eAAe,GACxB,MAAM,CAWlB;CAwSF;yBA3Ua,OAAO,iBAAiB,EAAE,OAAO;8BACjC,OAAO,sBAAsB,EAAE,OAAO"}
1
+ {"version":3,"file":"FileSystem.d.ts","sourceRoot":"","sources":["../../../src/node/lib/FileSystem.js"],"names":[],"mappings":"AA2BA;;GAEG;AACH;IACE,kCAAwB;IACxB,uCAAkC;IAClC,mBAAsB;IAsBtB;;;;;;OAMG;IACH,4BAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,2BAHW,MAAM,GACJ,MAAM,CAQlB;IAED;;;;;;;;OAQG;IACH,0BALW,MAAM,GACJ,MAAM,CAUlB;IAED;;;;;;;;;;OAUG;IACH,gCAJW,UAAU,GAAC,eAAe,MAC1B,UAAU,GAAC,eAAe,GACxB,MAAM,CAYlB;IAED;;;;;;;;;;OAUG;IACH,oCAJW,MAAM,MACN,MAAM,GACJ,MAAM,CAQlB;IAED;;;;;;;;;OASG;IACH,oCALW,MAAM,SACN,MAAM,QACN,MAAM,GACJ,MAAM,CA0BlB;IAED;;;;;;;;OAQG;IACH,6BAJW,MAAM,UACN,MAAM,GACJ,MAAM,CAmClB;IAED;;;;;;;;;;;;OAYG;IACH,+BATW,MAAM,aACN,MAAM,GACJ,OAAO,CAcnB;IAED;;;;;;;;;;;;;;OAcG;IACH,iCATW,MAAM,MACN,MAAM,QACN,MAAM,GACJ,MAAM,GAAC,IAAI,CAwBvB;IAED;;;;;;;;;;;;;;OAcG;IACH,4BARW,MAAM,MACN,MAAM,GACJ,MAAM,CAYlB;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,+BAXW,MAAM,MACN,MAAM,QACN,MAAM,GACJ,MAAM,GAAC,IAAI,CA+BvB;IAED;;;;;;;OAOG;IAEH;;;;;;;OAOG;IACH,2BAJW,MAAM;;;;cAXH,MAAM;;;;aACN,MAAM;;;;aACN,MAAM;;;;cACN,MAAM;;;;cACN,MAAM;MAenB;IAED;;;;OAIG;IACH,kBAFa,MAAM,CAIlB;IAnVD;;;;;;;;;OASG;IACH,kCAJW,UAAU,GAAC,eAAe,GACxB,MAAM,CAWlB;CAkUF;yBArWa,OAAO,iBAAiB,EAAE,OAAO;8BACjC,OAAO,sBAAsB,EAAE,OAAO"}
@@ -1,3 +1,16 @@
1
+ /**
2
+ * Terminal output utilities with ANSI colour support.
3
+ *
4
+ * Provides console logging wrappers, cursor control, and formatted message
5
+ * output with colour styling via `@gesslar/colours`.
6
+ *
7
+ * Predefined colour aliases:
8
+ * - `success` - green (F035)
9
+ * - `info` - blue (F033)
10
+ * - `warn` - orange (F208)
11
+ * - `error` - red (F032)
12
+ * - `modified` - purple (F147)
13
+ */
1
14
  export default class Term {
2
15
  static "__#private@#cache": Map<any, any>;
3
16
  static "__#private@#preformat"(text: any): any;
@@ -107,17 +120,17 @@ export default class Term {
107
120
  silent: boolean;
108
121
  }): void;
109
122
  /**
110
- * Constructs a formatted status line.
123
+ * Constructs a formatted status line with optional colour styling.
111
124
  *
112
125
  * Input forms:
113
126
  * - string: printed as-is
114
127
  * - array: each element is either:
115
128
  * - a plain string (emitted unchanged), or
116
- * - a tuple: [level, text] where `level` maps to an ansiColors alias
117
- * (e.g. success, info, warn, error, modified).
118
- * - a tuple: [level, text, [openBracket,closeBracket]] where `level` maps to an ansiColors alias
119
- * (e.g. success, info, warn, error, modified). These are rendered as
120
- * colourised bracketed segments: [TEXT].
129
+ * - a tuple: [colourCode, text] where `colourCode` is a colour alias
130
+ * (e.g. success, info, warn, error, modified) or any valid
131
+ * `@gesslar/colours` format string.
132
+ * - a tuple: [colourCode, text, [openBracket, closeBracket]] for custom
133
+ * brackets around the colourised text.
121
134
  *
122
135
  * The function performs a shallow validation: tuple elements must both be
123
136
  * strings; otherwise a TypeError is thrown. Nested arrays beyond depth 1 are
@@ -126,35 +139,35 @@ export default class Term {
126
139
  * Recursion: array input is normalised into a single string then re-dispatched
127
140
  * through `status` to leverage the string branch (keeps logic DRY).
128
141
  *
129
- * @param {string | Array<string | [string, string] | [string, string, string]>} argList - Message spec.
130
- * @returns {void}
142
+ * @param {string | Array<string | [string, string] | [string, string, [string, string]]>} argList - Message spec.
143
+ * @returns {string} The formatted message string.
131
144
  */
132
- static terminalMessage(argList: string | Array<string | [string, string] | [string, string, string]>): void;
145
+ static terminalMessage(argList: string | Array<string | [string, string] | [string, string, [string, string]]>): string;
133
146
  /**
134
147
  * Construct a single coloured bracketed segment from a tuple specifying
135
- * the style level and the text. The first element ("level") maps to an
136
- * `ansiColors` alias (e.g. success, info, warn, error, modified) and is
137
- * used both for the inner text colour and to locate its matching
138
- * "-bracket" alias for the surrounding square brackets. The second
139
- * element is the raw text to display.
148
+ * the colour code and text. The first element is a colour code that can be
149
+ * a predefined alias (success, info, warn, error, modified) or any valid
150
+ * `@gesslar/colours` format string. The brackets are coloured while the
151
+ * inner text remains uncoloured.
140
152
  *
141
- * Input validation: every element of `parts` must be a string; otherwise
142
- * an `Sass` error is thrown. (Additional elements beyond the first two are
143
- * ignored – the method destructures only the first pair.)
153
+ * Input validation: colourCode and text must both be strings; otherwise
154
+ * a `Sass` error is thrown.
144
155
  *
145
156
  * Example:
146
- * terminalBracket(["success", "COMPILED"]) → "[COMPILED]" with coloured
147
- * brackets + inner text (assuming colour support is available in the
148
- * terminal).
157
+ * terminalBracket(["success", "COMPILED"]) → "[COMPILED]" with green
158
+ * brackets (assuming colour support is available in the terminal).
159
+ *
160
+ * terminalBracket(["info", "STATUS", ["<", ">"]]) → "<STATUS>" with blue
161
+ * angle brackets.
149
162
  *
150
163
  * This method does not append trailing spaces; callers are responsible for
151
164
  * joining multiple segments with appropriate separators.
152
165
  *
153
- * @param {Array<string>} parts - Tuple: [level, text]. Additional entries ignored.
166
+ * @param {[string, string, [string, string]?]} parts - Tuple: [colourCode, text, brackets?].
154
167
  * @returns {string} Colourised bracketed segment (e.g. "[TEXT]").
155
- * @throws {Sass} If any element of `parts` is not a string.
168
+ * @throws {Sass} If colourCode or text is not a string.
156
169
  */
157
- static terminalBracket([level, text, brackets]: Array<string>): string;
170
+ static terminalBracket([colourCode, text, brackets]: [string, string, [string, string]?]): string;
158
171
  /**
159
172
  * ANSI escape sequence to move cursor to start of line.
160
173
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Term.d.ts","sourceRoot":"","sources":["../../../src/node/lib/Term.js"],"names":[],"mappings":"AAQA;IACE,0CAAyB;IAEzB,+CAIC;IAED;;;;OAIG;IACH,sBAFU,MAAM,GAAG,SAAS,CAI3B;IAED;;;;OAIG;IACH,mBAFU,MAAM,GAAG,SAAS,CAI3B;IAED;;;;OAIG;IACH,kBAFU;QAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;KAAC,CAIhE;IAED;;;;OAIG;IACH,4BAFU,OAAO,CAMhB;IAED;;;;OAIG;IACH,uBAFU,OAAO,CAMhB;IAED;;;;OAIG;IACH,oBAFc,OAAO,EAAA,QAIpB;IAED;;;;OAIG;IACH,qBAFc,OAAO,EAAA,QAIpB;IAED;;;;OAIG;IACH,qBAFc,OAAO,EAAA,QAIpB;IAED;;;;OAIG;IACH,sBAFc,OAAO,EAAA,QAIpB;IAED;;;;OAIG;IACH,sBAFc,OAAO,EAAA,QAIpB;IAED;;;;OAIG;IACH,sBAFc,OAAO,EAAA,QAIpB;IAED;;OAEG;IACH,wBAEC;IAED;;;;;;;;OAQG;IACH,0BANW,MAAM,QAAQ,YAEtB;QAAgC,UAAU,GAAlC,KAAK,CAAC,MAAM,CAAC;QACK,UAAU,GAA5B,OAAO;QACW,aAAa,GAA/B,OAAO;KACjB,QA2DA;IAED;;;;;;;;;;;;;;OAcG;IACH,oBALW,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,eAEjD;QAAyB,MAAM,EAAvB,OAAO;KACf,GAAU,IAAI,CAOhB;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,gCAHW,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,GAClE,IAAI,CA4BhB;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,gDAJW,KAAK,CAAC,MAAM,CAAC,GACX,MAAM,CASlB;IAED;;;;OAIG;IACH,oBAFU,MAAM,CAIf;IAED;;;;OAIG;IACH,oBAFa,OAAO,IAAI,CAMvB;IAED;;;;OAIG;IACH,kBAFU,MAAM,CAIf;IAED;;;;OAIG;IACH,kBAFa,OAAO,IAAI,CAMvB;IAED;;;;OAIG;IACH,iBAFU,MAAM,CAIf;IAED;;;;;OAKG;IACH,mBAHW,MAAM,GACJ,OAAO,IAAI,CAMvB;IAED;;;;OAIG;IACH,qBAFa,OAAO,IAAI,CAMvB;IAED;;;;OAIG;IACH,qBAFa,OAAO,IAAI,CAMvB;IAED;;;;OAIG;IACH,yBAFU,OAAO,CAOhB;IAED;;;;OAIG;IACH,yBAFU,OAAO,CAOhB;IAED;;;;OAIG;IACH,sBAFa,OAAO,IAAI,CAMvB;IAED;;;;OAIG;IACH,sBAFa,OAAO,IAAI,CAMvB;IAED;;;;OAIG;IACH,oBAFa,OAAO,IAAI,CAMvB;IAED;;;;;OAKG;IACH,uBAHW,MAAM,GACJ,OAAO,IAAI,CAOvB;IAED;;;;;OAKG;IACH,qBAHW,MAAM,GACJ,OAAO,IAAI,CAMvB;IAED;;;;;;OAMG;IACH,yBAHW,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GACvB,OAAO,CAAC,MAAM,CAAC,CAyD3B;IAED;;;;OAIG;IACH,4BAFa,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAqCrC;IAED;;;;;OAKG;IACH,2BAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAMzB;IAID,0CAAuE;CAYxE"}
1
+ {"version":3,"file":"Term.d.ts","sourceRoot":"","sources":["../../../src/node/lib/Term.js"],"names":[],"mappings":"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"}