@reliverse/pathkit 1.0.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/LICENSE +21 -0
- package/README.md +253 -0
- package/bin/mod.d.ts +4 -0
- package/bin/mod.js +23 -0
- package/bin/pathkit-impl/_internal.d.ts +1 -0
- package/bin/pathkit-impl/_internal.js +7 -0
- package/bin/pathkit-impl/_path.d.ts +26 -0
- package/bin/pathkit-impl/_path.js +206 -0
- package/bin/pathkit-impl/args-impl.d.ts +9 -0
- package/bin/pathkit-impl/args-impl.js +16 -0
- package/bin/pathkit-impl/args-utils.d.ts +30 -0
- package/bin/pathkit-impl/args-utils.js +75 -0
- package/package.json +23 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Nazar Kornienko (blefnk), Reliverse
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# pathkit • cross‑platform path manipulation
|
|
2
|
+
|
|
3
|
+
> @reliverse/pathkit is a slash‑consistent, cross‑platform path manipulation—drop‑in for `node:path`, always POSIX "/".
|
|
4
|
+
|
|
5
|
+
[sponsor](https://github.com/sponsors/blefnk) • [discord](https://discord.gg/Pb8uKbwpsJ) • [npm](https://npmjs.com/package/@reliverse/pathkit) • [repo](https://github.com/reliverse/pathkit)
|
|
6
|
+
|
|
7
|
+
## Key Features
|
|
8
|
+
|
|
9
|
+
- 🔹 **`node:path` on Steroids** – `@reliverse/pathkit`: drop in and replace `node:path` instantly.
|
|
10
|
+
- ➕ **`unjs/pathe` on Steroids** – `@reliverse/pathkit-plus`: alias resolution, import parsing, and more.
|
|
11
|
+
- 🌀 **Always `/`** – POSIX separators 100% of the time (buh‑bye `\\`).
|
|
12
|
+
- ⚙️ **Node.js API compatible** – familiar methods, no learning curve.
|
|
13
|
+
- 🚀 **Modern & Fast** – TypeScript, pure ESM, Bun & Node‑ready.
|
|
14
|
+
- 🧠 **Predictable & Testable** – deterministic output across Windows / macOS / Linux.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# bun • pnpm • yarn • npm
|
|
20
|
+
bun add @reliverse/pathkit
|
|
21
|
+
bun add -D @reliverse/pathkit-plus
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
_In most cases_ you may need to install `@reliverse/pathkit` as **regular dependency**.
|
|
25
|
+
_In most cases_ you may need to install `@reliverse/pathkit-plus` as **dev dependency**.
|
|
26
|
+
|
|
27
|
+
**Migrate**:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
bun rm pathe
|
|
31
|
+
# soon:
|
|
32
|
+
# bun add -D @reliverse/dler
|
|
33
|
+
# bun dler pathkit path-to-pathkit
|
|
34
|
+
# bun dler pathkit pathe-to-pathkit
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### `pathkit` vs `pathkit-plus`
|
|
38
|
+
|
|
39
|
+
| Package | What you get | When to use |
|
|
40
|
+
|---------|--------------|-------------|
|
|
41
|
+
| **`@reliverse/pathkit`** | Core path API (POSIX everywhere) | You only need a drop‑in for `node:path` |
|
|
42
|
+
| **`@reliverse/pathkit-plus`** | Everything in `pathkit` **+** advanced utilities | You need alias resolution, import transforms, etc. |
|
|
43
|
+
|
|
44
|
+
## Why Pathkit? — The Problem with Native Paths
|
|
45
|
+
|
|
46
|
+
Native `node:path` flips behavior between operating systems, spurring subtle bugs and OS checks.
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
// With node:path – the same call may yield different separators on each OS
|
|
50
|
+
import path from "node:path";
|
|
51
|
+
|
|
52
|
+
const project = "users/blefnk/project";
|
|
53
|
+
const full = path.join("C:\\", project);
|
|
54
|
+
console.log(full); // "C:\\users\\blefnk\\project" (Windows) vs ??? (others)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### ✅ The `pathkit` Fix
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
import { join } from "@reliverse/pathkit";
|
|
61
|
+
|
|
62
|
+
const full = join("C:", "users", "blefnk", "project");
|
|
63
|
+
console.log(full); // "C:/users/blefnk/project" on **every** OS 🎉
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
| Pain Point | `@reliverse/pathkit` Solution |
|
|
67
|
+
| :----------------------------- | :--------------------------- |
|
|
68
|
+
| Inconsistent separators | ✅ Always `/` |
|
|
69
|
+
| OS‑specific work‑arounds | ✅ One code path |
|
|
70
|
+
| Needs TypeScript + ESM | ✅ Built‑in |
|
|
71
|
+
| Works in Bun / Deno / Node | ✅ Out of the box |
|
|
72
|
+
|
|
73
|
+
## Quick Start
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { resolve, join, normalize } from "@reliverse/pathkit";
|
|
77
|
+
|
|
78
|
+
// Mixed slashes & dot‑segments? No problem.
|
|
79
|
+
const messy = "src\\..\\./dist///file.js";
|
|
80
|
+
console.log(resolve(messy)); // → "dist/file.js"
|
|
81
|
+
|
|
82
|
+
// Join is predictable everywhere:
|
|
83
|
+
console.log(join("users", "blefnk")); // → "users/blefnk"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Side‑by‑Side Demo**:
|
|
87
|
+
|
|
88
|
+
| Code | Windows Output | macOS / Linux Output |
|
|
89
|
+
|------|----------------|----------------------|
|
|
90
|
+
| `join("a", "b")` | `a/b` | `a/b` |
|
|
91
|
+
| `resolve("..", "x")` | `x` | `x` |
|
|
92
|
+
|
|
93
|
+
Say goodbye to `process.platform` conditionals 👋.
|
|
94
|
+
|
|
95
|
+
## pathkit-plus Features
|
|
96
|
+
|
|
97
|
+
`@reliverse/pathkit-plus` extends the core functionality with powerful utilities for working with imports, aliases, and more.
|
|
98
|
+
|
|
99
|
+
### Import/Export Analysis
|
|
100
|
+
|
|
101
|
+
The `getFileImportsExports` function provides detailed analysis of ES module imports and exports:
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import { getFileImportsExports } from "@reliverse/pathkit-plus";
|
|
105
|
+
|
|
106
|
+
const code = `
|
|
107
|
+
import { ref } from "vue";
|
|
108
|
+
import utils from "@/utils";
|
|
109
|
+
import type { Config } from "./types";
|
|
110
|
+
export { default as MyComponent } from "./MyComponent";
|
|
111
|
+
`;
|
|
112
|
+
|
|
113
|
+
const analysis = getFileImportsExports(code, {
|
|
114
|
+
kind: "all", // "import" | "export" | "all"
|
|
115
|
+
pathTypes: ["alias"], // Filter by path types
|
|
116
|
+
limitPerType: 2 // Limit results per type
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The analysis provides rich information about each import/export:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
interface ImportExportInfo {
|
|
124
|
+
statement: string; // Full original statement
|
|
125
|
+
type: "static" | "dynamic"; // Import type
|
|
126
|
+
kind: "import" | "export"; // Statement kind
|
|
127
|
+
source?: string; // Import/export source path
|
|
128
|
+
pathType?: "alias" | "relative" | "absolute" | "bare" | "module";
|
|
129
|
+
pathTypeSymbol?: string; // Path prefix (e.g., "@/", "~/")
|
|
130
|
+
isTypeOnly?: boolean; // Type-only import/export
|
|
131
|
+
specifiers?: { // Imported/exported items
|
|
132
|
+
type: "named" | "default" | "namespace" | "all";
|
|
133
|
+
name: string;
|
|
134
|
+
alias?: string;
|
|
135
|
+
isType?: boolean;
|
|
136
|
+
}[];
|
|
137
|
+
start: number; // Position in source
|
|
138
|
+
end: number;
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Features:
|
|
143
|
+
|
|
144
|
+
- ✨ Handles all import/export syntax variants
|
|
145
|
+
- 🔍 Type imports/exports support
|
|
146
|
+
- 💬 Preserves comments
|
|
147
|
+
- 🎯 Path type detection
|
|
148
|
+
- 🔄 Multi-line statement support
|
|
149
|
+
|
|
150
|
+
### Path Transformation
|
|
151
|
+
|
|
152
|
+
Convert between different path formats:
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
import { convertImportPaths } from "@reliverse/pathkit-plus";
|
|
156
|
+
|
|
157
|
+
await convertImportPaths({
|
|
158
|
+
baseDir: "./src",
|
|
159
|
+
fromType: "relative", // "./components/Button"
|
|
160
|
+
toType: "alias", // "@/components/Button"
|
|
161
|
+
aliasPrefix: "@/",
|
|
162
|
+
generateSourceMap: true
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Extension Conversion
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import { convertImportExtensionsJsToTs } from "@reliverse/pathkit-plus";
|
|
170
|
+
|
|
171
|
+
await convertImportExtensionsJsToTs({
|
|
172
|
+
dirPath: "./src",
|
|
173
|
+
generateSourceMap: true
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Alias Resolution
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
import {
|
|
181
|
+
normalizeAliases,
|
|
182
|
+
resolveAlias,
|
|
183
|
+
reverseResolveAlias
|
|
184
|
+
} from "@reliverse/pathkit-plus";
|
|
185
|
+
|
|
186
|
+
const aliases = { "@/": "/src/", "~/": "/home/user/" };
|
|
187
|
+
|
|
188
|
+
// Normalize alias config
|
|
189
|
+
console.log(normalizeAliases(aliases));
|
|
190
|
+
|
|
191
|
+
// Resolve alias to absolute path
|
|
192
|
+
console.log(resolveAlias("@/components", aliases)); // "/src/components"
|
|
193
|
+
|
|
194
|
+
// Convert absolute path back to alias
|
|
195
|
+
console.log(reverseResolveAlias("/src/utils", aliases)); // "@/utils"
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Utility Functions
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
import {
|
|
202
|
+
filename, // Strip extension
|
|
203
|
+
extractPackageName, // Get package name from import
|
|
204
|
+
normalizeQuotes, // Standardize quote style
|
|
205
|
+
matchesGlob // Test glob patterns
|
|
206
|
+
} from "@reliverse/pathkit-plus";
|
|
207
|
+
|
|
208
|
+
console.log(filename("/path/component.vue")); // "component"
|
|
209
|
+
console.log(extractPackageName("@scope/pkg")); // "@scope/pkg"
|
|
210
|
+
console.log(normalizeQuotes("import 'pkg'")); // 'import "pkg"'
|
|
211
|
+
console.log(matchesGlob("file.ts", "**/*.ts")); // true
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Use Cases / Ideal For
|
|
215
|
+
|
|
216
|
+
- 🛠️ **CLI tools**
|
|
217
|
+
- 🌍 **Cross‑platform dev environments**
|
|
218
|
+
- 🔄 **Bundlers, linters, compilers**
|
|
219
|
+
- 🏗️ **Framework & library authors**
|
|
220
|
+
- 📜 **Scripts / test runners**
|
|
221
|
+
- …anywhere file‑paths roam!
|
|
222
|
+
|
|
223
|
+
## Examples & Contributing
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
git clone https://github.com/reliverse/pathkit.git
|
|
227
|
+
cd pathkit
|
|
228
|
+
bun install
|
|
229
|
+
bun dev
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Bug reports & PRs are warmly welcome—come on in!
|
|
233
|
+
|
|
234
|
+
## Related
|
|
235
|
+
|
|
236
|
+
- [`@reliverse/rempts`](https://npmjs.com/package/@reliverse/rempts) – Terminal Prompts Engine
|
|
237
|
+
|
|
238
|
+
## Community
|
|
239
|
+
|
|
240
|
+
- ⭐ **Star** the repo if this helped you.
|
|
241
|
+
- 💖 **Sponsor** [@blefnk](https://github.com/sponsors/blefnk) to keep the lights on.
|
|
242
|
+
- 💬 **Chat** with us on [Discord](https://discord.gg/Pb8uKbwpsJ).
|
|
243
|
+
|
|
244
|
+
## License
|
|
245
|
+
|
|
246
|
+
[MIT](LICENSE) © [Nazar Kornienko (blefnk)](https://github.com/blefnk), [Reliverse](https://github.com/reliverse)
|
|
247
|
+
|
|
248
|
+
## Badges
|
|
249
|
+
|
|
250
|
+
[](https://npmjs.com/package/@reliverse/pathkit)
|
|
251
|
+
[](https://npmjs.com/package/@reliverse/pathkit)
|
|
252
|
+
[](https://github.com/reliverse/pathkit)
|
|
253
|
+
[](LICENSE)
|
package/bin/mod.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { delimiter, posix, win32 } from "./pathkit-impl/args-impl.js";
|
|
2
|
+
export { normalizeAliases, resolveAlias, reverseResolveAlias, filename, } from "./pathkit-impl/args-utils.js";
|
|
3
|
+
export { normalizeWindowsPath } from "./pathkit-impl/_internal.js";
|
|
4
|
+
export { sep, normalize, join, resolve, normalizeString, isAbsolute, toNamespacedPath, extname, relative, dirname, format, basename, parse, } from "./pathkit-impl/_path.js";
|
package/bin/mod.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export { delimiter, posix, win32 } from "./pathkit-impl/args-impl.js";
|
|
2
|
+
export {
|
|
3
|
+
normalizeAliases,
|
|
4
|
+
resolveAlias,
|
|
5
|
+
reverseResolveAlias,
|
|
6
|
+
filename
|
|
7
|
+
} from "./pathkit-impl/args-utils.js";
|
|
8
|
+
export { normalizeWindowsPath } from "./pathkit-impl/_internal.js";
|
|
9
|
+
export {
|
|
10
|
+
sep,
|
|
11
|
+
normalize,
|
|
12
|
+
join,
|
|
13
|
+
resolve,
|
|
14
|
+
normalizeString,
|
|
15
|
+
isAbsolute,
|
|
16
|
+
toNamespacedPath,
|
|
17
|
+
extname,
|
|
18
|
+
relative,
|
|
19
|
+
dirname,
|
|
20
|
+
format,
|
|
21
|
+
basename,
|
|
22
|
+
parse
|
|
23
|
+
} from "./pathkit-impl/_path.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function normalizeWindowsPath(input?: string): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type path from "node:path";
|
|
2
|
+
/**
|
|
3
|
+
* Constant for path separator.
|
|
4
|
+
*
|
|
5
|
+
* Always equals to `"/"`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const sep = "/";
|
|
8
|
+
export declare const normalize: typeof path.normalize;
|
|
9
|
+
export declare const join: typeof path.join;
|
|
10
|
+
export declare const resolve: typeof path.resolve;
|
|
11
|
+
/**
|
|
12
|
+
* Resolves a string path, resolving '.' and '.' segments and allowing paths above the root.
|
|
13
|
+
*
|
|
14
|
+
* @param path - The path to normalise.
|
|
15
|
+
* @param allowAboveRoot - Whether to allow the resulting path to be above the root directory.
|
|
16
|
+
* @returns the normalised path string.
|
|
17
|
+
*/
|
|
18
|
+
export declare function normalizeString(path: string, allowAboveRoot: boolean): string;
|
|
19
|
+
export declare const isAbsolute: typeof path.isAbsolute;
|
|
20
|
+
export declare const toNamespacedPath: typeof path.toNamespacedPath;
|
|
21
|
+
export declare const extname: typeof path.extname;
|
|
22
|
+
export declare const relative: typeof path.relative;
|
|
23
|
+
export declare const dirname: typeof path.dirname;
|
|
24
|
+
export declare const format: typeof path.format;
|
|
25
|
+
export declare const basename: typeof path.basename;
|
|
26
|
+
export declare const parse: typeof path.parse;
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { normalizeWindowsPath } from "./_internal.js";
|
|
2
|
+
const _UNC_REGEX = /^[/\\]{2}/;
|
|
3
|
+
const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
4
|
+
const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
|
|
5
|
+
const _ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/;
|
|
6
|
+
const _EXTNAME_RE = /.(\.[^./]+|\.)$/;
|
|
7
|
+
const _PATH_ROOT_RE = /^[/\\]|^[a-zA-Z]:[/\\]/;
|
|
8
|
+
export const sep = "/";
|
|
9
|
+
export const normalize = (path) => {
|
|
10
|
+
if (path.length === 0) {
|
|
11
|
+
return ".";
|
|
12
|
+
}
|
|
13
|
+
path = normalizeWindowsPath(path);
|
|
14
|
+
const isUNCPath = _UNC_REGEX.exec(path);
|
|
15
|
+
const isPathAbsolute = isAbsolute(path);
|
|
16
|
+
const trailingSeparator = path.endsWith("/");
|
|
17
|
+
path = normalizeString(path, !isPathAbsolute);
|
|
18
|
+
if (path.length === 0) {
|
|
19
|
+
if (isPathAbsolute) {
|
|
20
|
+
return "/";
|
|
21
|
+
}
|
|
22
|
+
return trailingSeparator ? "./" : ".";
|
|
23
|
+
}
|
|
24
|
+
if (trailingSeparator) {
|
|
25
|
+
path += "/";
|
|
26
|
+
}
|
|
27
|
+
if (_DRIVE_LETTER_RE.test(path)) {
|
|
28
|
+
path += "/";
|
|
29
|
+
}
|
|
30
|
+
if (isUNCPath) {
|
|
31
|
+
if (!isPathAbsolute) {
|
|
32
|
+
return `//./${path}`;
|
|
33
|
+
}
|
|
34
|
+
return `//${path}`;
|
|
35
|
+
}
|
|
36
|
+
return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
|
|
37
|
+
};
|
|
38
|
+
export const join = (...segments) => {
|
|
39
|
+
let path = "";
|
|
40
|
+
for (const seg of segments) {
|
|
41
|
+
if (!seg) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (path.length > 0) {
|
|
45
|
+
const pathTrailing = path.endsWith("/");
|
|
46
|
+
const segLeading = seg.startsWith("/");
|
|
47
|
+
const both = pathTrailing && segLeading;
|
|
48
|
+
if (both) {
|
|
49
|
+
path += seg.slice(1);
|
|
50
|
+
} else {
|
|
51
|
+
path += pathTrailing || segLeading ? seg : `/${seg}`;
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
path += seg;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return normalize(path);
|
|
58
|
+
};
|
|
59
|
+
function cwd() {
|
|
60
|
+
if (typeof process !== "undefined" && typeof process.cwd === "function") {
|
|
61
|
+
return process.cwd().replace(/\\/g, "/");
|
|
62
|
+
}
|
|
63
|
+
return "/";
|
|
64
|
+
}
|
|
65
|
+
export const resolve = (...arguments_) => {
|
|
66
|
+
arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
|
|
67
|
+
let resolvedPath = "";
|
|
68
|
+
let resolvedAbsolute = false;
|
|
69
|
+
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
|
|
70
|
+
const path = index >= 0 ? arguments_[index] : cwd();
|
|
71
|
+
if (!path || path.length === 0) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
resolvedPath = `${path}/${resolvedPath}`;
|
|
75
|
+
resolvedAbsolute = isAbsolute(path);
|
|
76
|
+
}
|
|
77
|
+
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
|
78
|
+
if (resolvedAbsolute && !isAbsolute(resolvedPath)) {
|
|
79
|
+
return `/${resolvedPath}`;
|
|
80
|
+
}
|
|
81
|
+
return resolvedPath.length > 0 ? resolvedPath : ".";
|
|
82
|
+
};
|
|
83
|
+
export function normalizeString(path, allowAboveRoot) {
|
|
84
|
+
let res = "";
|
|
85
|
+
let lastSegmentLength = 0;
|
|
86
|
+
let lastSlash = -1;
|
|
87
|
+
let dots = 0;
|
|
88
|
+
let char = null;
|
|
89
|
+
for (let index = 0; index <= path.length; ++index) {
|
|
90
|
+
if (index < path.length) {
|
|
91
|
+
char = path[index];
|
|
92
|
+
} else if (char === "/") {
|
|
93
|
+
break;
|
|
94
|
+
} else {
|
|
95
|
+
char = "/";
|
|
96
|
+
}
|
|
97
|
+
if (char === "/") {
|
|
98
|
+
if (lastSlash === index - 1 || dots === 1) {
|
|
99
|
+
} else if (dots === 2) {
|
|
100
|
+
if (res.length < 2 || lastSegmentLength !== 2 || !res.endsWith(".") || res[res.length - 2] !== ".") {
|
|
101
|
+
if (res.length > 2) {
|
|
102
|
+
const lastSlashIndex = res.lastIndexOf("/");
|
|
103
|
+
if (lastSlashIndex === -1) {
|
|
104
|
+
res = "";
|
|
105
|
+
lastSegmentLength = 0;
|
|
106
|
+
} else {
|
|
107
|
+
res = res.slice(0, lastSlashIndex);
|
|
108
|
+
lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
|
109
|
+
}
|
|
110
|
+
lastSlash = index;
|
|
111
|
+
dots = 0;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (res.length > 0) {
|
|
115
|
+
res = "";
|
|
116
|
+
lastSegmentLength = 0;
|
|
117
|
+
lastSlash = index;
|
|
118
|
+
dots = 0;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (allowAboveRoot) {
|
|
123
|
+
res += res.length > 0 ? "/.." : "..";
|
|
124
|
+
lastSegmentLength = 2;
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
if (res.length > 0) {
|
|
128
|
+
res += `/${path.slice(lastSlash + 1, index)}`;
|
|
129
|
+
} else {
|
|
130
|
+
res = path.slice(lastSlash + 1, index);
|
|
131
|
+
}
|
|
132
|
+
lastSegmentLength = index - lastSlash - 1;
|
|
133
|
+
}
|
|
134
|
+
lastSlash = index;
|
|
135
|
+
dots = 0;
|
|
136
|
+
} else if (char === "." && dots !== -1) {
|
|
137
|
+
++dots;
|
|
138
|
+
} else {
|
|
139
|
+
dots = -1;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return res;
|
|
143
|
+
}
|
|
144
|
+
export const isAbsolute = (p) => _IS_ABSOLUTE_RE.test(p);
|
|
145
|
+
export const toNamespacedPath = (p) => normalizeWindowsPath(p);
|
|
146
|
+
export const extname = (p) => {
|
|
147
|
+
if (p === "..") return "";
|
|
148
|
+
const match = _EXTNAME_RE.exec(normalizeWindowsPath(p));
|
|
149
|
+
return match?.[1] || "";
|
|
150
|
+
};
|
|
151
|
+
export const relative = (from, to) => {
|
|
152
|
+
const _from = resolve(from).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
153
|
+
const _to = resolve(to).replace(_ROOT_FOLDER_RE, "$1").split("/");
|
|
154
|
+
if (_to[0][1] === ":" && _from[0][1] === ":" && _from[0] !== _to[0]) {
|
|
155
|
+
return _to.join("/");
|
|
156
|
+
}
|
|
157
|
+
const _fromCopy = [..._from];
|
|
158
|
+
for (const segment of _fromCopy) {
|
|
159
|
+
if (_to[0] !== segment) {
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
_from.shift();
|
|
163
|
+
_to.shift();
|
|
164
|
+
}
|
|
165
|
+
return [..._from.map(() => ".."), ..._to].join("/");
|
|
166
|
+
};
|
|
167
|
+
export const dirname = (p) => {
|
|
168
|
+
const segments = normalizeWindowsPath(p).replace(/\/$/, "").split("/").slice(0, -1);
|
|
169
|
+
if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) {
|
|
170
|
+
segments[0] += "/";
|
|
171
|
+
}
|
|
172
|
+
return segments.join("/") || (isAbsolute(p) ? "/" : ".");
|
|
173
|
+
};
|
|
174
|
+
export const format = (p) => {
|
|
175
|
+
const ext = p.ext ? p.ext.startsWith(".") ? p.ext : `.${p.ext}` : "";
|
|
176
|
+
const segments = [p.root, p.dir, p.base ?? (p.name ?? "") + ext].filter(
|
|
177
|
+
Boolean
|
|
178
|
+
);
|
|
179
|
+
return normalizeWindowsPath(
|
|
180
|
+
segments.length > 0 ? resolve(...segments) : segments.join("/")
|
|
181
|
+
);
|
|
182
|
+
};
|
|
183
|
+
export const basename = (p, extension) => {
|
|
184
|
+
const segments = normalizeWindowsPath(p).split("/");
|
|
185
|
+
let lastSegment = "";
|
|
186
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
187
|
+
const val = segments[i];
|
|
188
|
+
if (val) {
|
|
189
|
+
lastSegment = val;
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return extension && lastSegment.endsWith(extension) ? lastSegment.slice(0, -extension.length) : lastSegment;
|
|
194
|
+
};
|
|
195
|
+
export const parse = (p) => {
|
|
196
|
+
const root = _PATH_ROOT_RE.exec(p)?.[0]?.replace(/\\/g, "/") || "";
|
|
197
|
+
const base = basename(p);
|
|
198
|
+
const extension = extname(base);
|
|
199
|
+
return {
|
|
200
|
+
root,
|
|
201
|
+
dir: dirname(p),
|
|
202
|
+
base,
|
|
203
|
+
ext: extension,
|
|
204
|
+
name: base.slice(0, base.length - extension.length)
|
|
205
|
+
};
|
|
206
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./_path.js";
|
|
2
|
+
/**
|
|
3
|
+
* The platform-specific file delimiter.
|
|
4
|
+
*
|
|
5
|
+
* Equals to `";"` in windows and `":"` in all other platforms.
|
|
6
|
+
*/
|
|
7
|
+
export declare const delimiter: ";" | ":";
|
|
8
|
+
export declare const posix: import("path").PlatformPath;
|
|
9
|
+
export declare const win32: import("path").PlatformPath;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as _path from "./_path.js";
|
|
2
|
+
export * from "./_path.js";
|
|
3
|
+
export const delimiter = /* @__PURE__ */ (() => globalThis.process?.platform === "win32" ? ";" : ":")();
|
|
4
|
+
const _platforms = { posix: void 0, win32: void 0 };
|
|
5
|
+
const mix = (del = delimiter) => {
|
|
6
|
+
return new Proxy(_path, {
|
|
7
|
+
get(_, prop) {
|
|
8
|
+
if (prop === "delimiter") return del;
|
|
9
|
+
if (prop === "posix") return posix;
|
|
10
|
+
if (prop === "win32") return win32;
|
|
11
|
+
return _platforms[prop] || _path[prop];
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
export const posix = /* @__PURE__ */ mix(":");
|
|
16
|
+
export const win32 = /* @__PURE__ */ mix(";");
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalises alias mappings, ensuring that more specific aliases are resolved before less specific ones.
|
|
3
|
+
* This function also ensures that aliases do not resolve to themselves cyclically.
|
|
4
|
+
*
|
|
5
|
+
* @param _aliases - A set of alias mappings where each key is an alias and its value is the actual path it points to.
|
|
6
|
+
* @returns a set of normalised alias mappings.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeAliases(_aliases: Record<string, string>): Record<string, string>;
|
|
9
|
+
/**
|
|
10
|
+
* Resolves a path string to its alias if applicable, otherwise returns the original path.
|
|
11
|
+
* This function normalises the path, resolves the alias and then joins it to the alias target if necessary.
|
|
12
|
+
*
|
|
13
|
+
* @param path - The path string to resolve.
|
|
14
|
+
* @param aliases - A set of alias mappings to use for resolution.
|
|
15
|
+
* @returns the resolved path as a string.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveAlias(path: string, aliases: Record<string, string>): any;
|
|
18
|
+
/**
|
|
19
|
+
* Resolves a path string to its possible alias.
|
|
20
|
+
*
|
|
21
|
+
* Returns an array of possible alias resolutions (could be empty), sorted by specificity (longest first).
|
|
22
|
+
*/
|
|
23
|
+
export declare function reverseResolveAlias(path: string, aliases: Record<string, string>): string[];
|
|
24
|
+
/**
|
|
25
|
+
* Extracts the filename from a given path, excluding any directory paths and the file extension.
|
|
26
|
+
*
|
|
27
|
+
* @param path - The full path of the file from which to extract the filename.
|
|
28
|
+
* @returns the filename without the extension, or `undefined` if the filename cannot be extracted.
|
|
29
|
+
*/
|
|
30
|
+
export declare function filename(path: string): string | undefined;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { normalizeWindowsPath } from "./_internal.js";
|
|
2
|
+
import { join } from "./_path.js";
|
|
3
|
+
const pathSeparators = /* @__PURE__ */ new Set(["/", "\\", void 0]);
|
|
4
|
+
const normalizedAliasSymbol = Symbol.for("pathkit:normalizedAlias");
|
|
5
|
+
const SLASH_RE = /[/\\]/;
|
|
6
|
+
export function normalizeAliases(_aliases) {
|
|
7
|
+
if (_aliases[normalizedAliasSymbol]) {
|
|
8
|
+
return _aliases;
|
|
9
|
+
}
|
|
10
|
+
const aliases = Object.fromEntries(
|
|
11
|
+
Object.entries(_aliases).sort(([a], [b]) => _compareAliases(a, b))
|
|
12
|
+
);
|
|
13
|
+
for (const key in aliases) {
|
|
14
|
+
for (const alias in aliases) {
|
|
15
|
+
if (alias === key || key.startsWith(alias)) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (aliases[key]?.startsWith(alias) && pathSeparators.has(aliases[key][alias.length])) {
|
|
19
|
+
aliases[key] = aliases[alias] + aliases[key].slice(alias.length);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(aliases, normalizedAliasSymbol, {
|
|
24
|
+
value: true,
|
|
25
|
+
enumerable: false
|
|
26
|
+
});
|
|
27
|
+
return aliases;
|
|
28
|
+
}
|
|
29
|
+
export function resolveAlias(path, aliases) {
|
|
30
|
+
const _path = normalizeWindowsPath(path);
|
|
31
|
+
aliases = normalizeAliases(aliases);
|
|
32
|
+
for (const [alias, to] of Object.entries(aliases)) {
|
|
33
|
+
if (!_path.startsWith(alias)) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const _alias = hasTrailingSlash(alias) ? alias.slice(0, -1) : alias;
|
|
37
|
+
if (hasTrailingSlash(_path[_alias.length])) {
|
|
38
|
+
return join(to, _path.slice(alias.length));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return _path;
|
|
42
|
+
}
|
|
43
|
+
export function reverseResolveAlias(path, aliases) {
|
|
44
|
+
const _path = normalizeWindowsPath(path);
|
|
45
|
+
aliases = normalizeAliases(aliases);
|
|
46
|
+
const matches = [];
|
|
47
|
+
for (const [to, alias] of Object.entries(aliases)) {
|
|
48
|
+
if (!_path.startsWith(alias)) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const _alias = hasTrailingSlash(alias) ? alias.slice(0, -1) : alias;
|
|
52
|
+
if (hasTrailingSlash(_path[_alias.length])) {
|
|
53
|
+
matches.push(join(to, _path.slice(alias.length)));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return matches.sort((a, b) => b.length - a.length);
|
|
57
|
+
}
|
|
58
|
+
export function filename(path) {
|
|
59
|
+
const base = path.split(SLASH_RE).pop();
|
|
60
|
+
if (!base) {
|
|
61
|
+
return void 0;
|
|
62
|
+
}
|
|
63
|
+
const separatorIndex = base.lastIndexOf(".");
|
|
64
|
+
if (separatorIndex <= 0) {
|
|
65
|
+
return base;
|
|
66
|
+
}
|
|
67
|
+
return base.slice(0, separatorIndex);
|
|
68
|
+
}
|
|
69
|
+
function _compareAliases(a, b) {
|
|
70
|
+
return b.split("/").length - a.split("/").length;
|
|
71
|
+
}
|
|
72
|
+
function hasTrailingSlash(path = "/") {
|
|
73
|
+
const lastChar = path[path.length - 1];
|
|
74
|
+
return lastChar === "/" || lastChar === "\\";
|
|
75
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "@reliverse/pathkit delivers slash-consistent, cross-platform path manipulation that just works. Ensures predictable POSIX (/) separators everywhere, simplifying your code and eliminating OS-specific pathing issues.",
|
|
3
|
+
"license": "MIT",
|
|
4
|
+
"name": "@reliverse/pathkit",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"version": "1.0.0",
|
|
7
|
+
"dependencies": {},
|
|
8
|
+
"devDependencies": {},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./bin/mod.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"bin",
|
|
14
|
+
"package.json",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"main": "./bin/mod.js",
|
|
19
|
+
"module": "./bin/mod.js",
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
}
|
|
23
|
+
}
|