@jsarc/pajo 0.0.0 → 0.0.1-beta.0.1
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/README.md +2 -2
- package/index.ts +1 -1
- package/package.json +1 -1
- package/pajo.ts +271 -0
- package/ts/index.ts +277 -0
- package/ts/pajo.ts +271 -0
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ const { Pajo } = require('@jsarc/pajo');
|
|
|
73
73
|
```html
|
|
74
74
|
<script src="@jsarc/pajo/pajo.all.js"></script>
|
|
75
75
|
<script>
|
|
76
|
-
// Disponible globalement via window.Pajo
|
|
76
|
+
// Disponible globalement via (window as any).Pajo
|
|
77
77
|
console.log(Pajo.join('path', 'to', 'file.txt'));
|
|
78
78
|
</script>
|
|
79
79
|
```
|
|
@@ -247,7 +247,7 @@ Expose la classe Pajo à l'objet global (window) pour une utilisation dans les n
|
|
|
247
247
|
```javascript
|
|
248
248
|
// Dans un navigateur, après avoir chargé le script
|
|
249
249
|
Pajo.exposeToGlobal();
|
|
250
|
-
console.log(window.Pajo); // La classe Pajo est disponible
|
|
250
|
+
console.log((window as any).Pajo); // La classe Pajo est disponible
|
|
251
251
|
```
|
|
252
252
|
|
|
253
253
|
## 🔧 Utilisation Détaillée
|
package/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.0.0",
|
|
6
|
+
"version": "0.0.1-beta.0.1",
|
|
7
7
|
"description": "Pajo est une bibliothèque TypeScript légère et robuste pour la manipulation de chemins de fichiers et d'URLs. Elle offre une API unifiée et type-safe pour travailler avec des chemins de fichiers sur différentes plateformes (Windows, Linux, macOS) et pour construire des URLs de manière cohérente.",
|
|
8
8
|
"main": "index.ts",
|
|
9
9
|
"keywords": [],
|
package/pajo.ts
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
|
|
3
|
+
interface Window {
|
|
4
|
+
default: typeof defaultElementGF;
|
|
5
|
+
Pajo: any;
|
|
6
|
+
__bundledModules: any;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const globalFunct = (function(global: any) {
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Pajo {
|
|
16
|
+
private static readonly PROTOCOL_REGEX = new RegExp('^[a-zA-Z]+://');
|
|
17
|
+
private static readonly DOUBLE_SLASH_REGEX = new RegExp('/+', 'g');
|
|
18
|
+
private static readonly DOUBLE_BACKSLASH_REGEX = new RegExp('\\\\+', 'g');
|
|
19
|
+
private static readonly TRAILING_SLASH_REGEX = new RegExp('/+$');
|
|
20
|
+
private static readonly TRAILING_BACKSLASH_REGEX = new RegExp('\\\\+$');
|
|
21
|
+
private static readonly LEADING_SLASH_REGEX = new RegExp('^/+');
|
|
22
|
+
private static readonly WINDOWS_DRIVE_REGEX = new RegExp('^[a-zA-Z]:\\\\');
|
|
23
|
+
private static readonly MIXED_SEPARATORS_REGEX = new RegExp('[\\\\/]+', 'g');
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Joint plusieurs segments de chemin en normalisant les séparateurs
|
|
27
|
+
* @param paths Segments de chemin à joindre
|
|
28
|
+
* @returns Le chemin normalisé ou undefined si aucun chemin valide
|
|
29
|
+
*/
|
|
30
|
+
static join(...paths: string[]): string | undefined {
|
|
31
|
+
if (paths.length === 0) return undefined;
|
|
32
|
+
|
|
33
|
+
// Détection du style de chemin (Windows ou Unix)
|
|
34
|
+
const isWindowsPath = paths.some(path => this.isWindowsPath(path));
|
|
35
|
+
|
|
36
|
+
// Filtre les chemins vides et nettoie chaque segment
|
|
37
|
+
const cleanPaths = paths
|
|
38
|
+
.filter(path => path != null && path.trim().length > 0)
|
|
39
|
+
.map(path => this.normalizePathSegment(path, isWindowsPath));
|
|
40
|
+
|
|
41
|
+
if (cleanPaths.length === 0) return undefined;
|
|
42
|
+
|
|
43
|
+
// Reconstruction du chemin final avec le séparateur approprié
|
|
44
|
+
const separator = isWindowsPath ? '\\' : '/';
|
|
45
|
+
let result = cleanPaths.join(separator);
|
|
46
|
+
|
|
47
|
+
if (isWindowsPath) {
|
|
48
|
+
result = result.replace(this.DOUBLE_BACKSLASH_REGEX, '\\');
|
|
49
|
+
} else {
|
|
50
|
+
result = result.replace(this.DOUBLE_SLASH_REGEX, '/');
|
|
51
|
+
|
|
52
|
+
// Préservation du slash initial pour les chemins absolus Linux
|
|
53
|
+
const hasLeadingSlash = paths[0]?.startsWith('/') || false;
|
|
54
|
+
if (hasLeadingSlash && !result.startsWith('/')) {
|
|
55
|
+
result = '/' + result;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return result || undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Joint un hôte avec des segments de chemin
|
|
64
|
+
* @param host Hôte (peut inclure le protocole)
|
|
65
|
+
* @param paths Segments de chemin à joindre
|
|
66
|
+
* @returns L'URL complète normalisée ou undefined si invalide
|
|
67
|
+
*/
|
|
68
|
+
static joinWithHost(host: string, ...paths: string[]): string | undefined {
|
|
69
|
+
if (!host || host.trim().length === 0) {
|
|
70
|
+
return this.join(...paths);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const cleanHost = host.trim().replace(this.TRAILING_SLASH_REGEX, '');
|
|
74
|
+
|
|
75
|
+
const hasProtocol = this.PROTOCOL_REGEX.test(cleanHost);
|
|
76
|
+
const normalizedHost = hasProtocol ? cleanHost : `https://${cleanHost}`;
|
|
77
|
+
|
|
78
|
+
const joinedPath = this.join(...paths);
|
|
79
|
+
if (!joinedPath) {
|
|
80
|
+
return normalizedHost;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const cleanPath = joinedPath.replace(new RegExp('\\\\', 'g'), '/').replace(this.LEADING_SLASH_REGEX, '');
|
|
84
|
+
return `${normalizedHost}/${cleanPath}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Normalise un segment de chemin individuel
|
|
89
|
+
* @param path Segment de chemin à normaliser
|
|
90
|
+
* @param isWindowsStyle Si on doit utiliser le style Windows
|
|
91
|
+
* @returns Le segment normalisé
|
|
92
|
+
*/
|
|
93
|
+
private static normalizePathSegment(path: string, isWindowsStyle: boolean): string {
|
|
94
|
+
if (!path || path.trim().length === 0) return '';
|
|
95
|
+
|
|
96
|
+
const trimmed = path.trim();
|
|
97
|
+
|
|
98
|
+
if (isWindowsStyle) {
|
|
99
|
+
return trimmed
|
|
100
|
+
.replace(this.DOUBLE_BACKSLASH_REGEX, '\\')
|
|
101
|
+
.replace(this.TRAILING_BACKSLASH_REGEX, '');
|
|
102
|
+
} else {
|
|
103
|
+
return trimmed
|
|
104
|
+
.replace(this.DOUBLE_SLASH_REGEX, '/')
|
|
105
|
+
.replace(this.TRAILING_SLASH_REGEX, '');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private static isWindowsPath(path: string): boolean {
|
|
110
|
+
return this.WINDOWS_DRIVE_REGEX.test(path) || path.includes('\\');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Résout les chemins avec . et .. (simplifié)
|
|
115
|
+
* @param paths Segments de chemin à résoudre
|
|
116
|
+
* @returns Chemin résolu
|
|
117
|
+
*/
|
|
118
|
+
static resolve(...paths: string[]): string | undefined {
|
|
119
|
+
const joined = this.join(...paths);
|
|
120
|
+
if (!joined) return undefined;
|
|
121
|
+
|
|
122
|
+
const isWindows = this.isWindowsPath(joined);
|
|
123
|
+
const separator = isWindows ? '\\' : '/';
|
|
124
|
+
const parts = joined.split(separator);
|
|
125
|
+
const resolved: string[] = [];
|
|
126
|
+
|
|
127
|
+
for (const part of parts) {
|
|
128
|
+
if (part === '..') {
|
|
129
|
+
if (resolved.length > 0 && resolved[resolved.length - 1] !== '..') {
|
|
130
|
+
resolved.pop();
|
|
131
|
+
} else {
|
|
132
|
+
resolved.push(part);
|
|
133
|
+
}
|
|
134
|
+
} else if (part !== '.' && part !== '') {
|
|
135
|
+
resolved.push(part);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let result = resolved.join(separator);
|
|
140
|
+
|
|
141
|
+
if (isWindows && this.WINDOWS_DRIVE_REGEX.test(parts[0])) {
|
|
142
|
+
result = parts[0] + separator + result;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static isAbsolute(path: string): boolean {
|
|
149
|
+
if (!path) return false;
|
|
150
|
+
|
|
151
|
+
return path.startsWith('/') ||
|
|
152
|
+
this.WINDOWS_DRIVE_REGEX.test(path) ||
|
|
153
|
+
this.PROTOCOL_REGEX.test(path);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
static dirname(path: string): string | undefined {
|
|
157
|
+
if (!path) return undefined;
|
|
158
|
+
|
|
159
|
+
const isWindows = this.isWindowsPath(path);
|
|
160
|
+
const separator = isWindows ? '\\' : '/';
|
|
161
|
+
const normalized = this.normalizePathSegment(path, isWindows);
|
|
162
|
+
const lastSeparatorIndex = normalized.lastIndexOf(separator);
|
|
163
|
+
|
|
164
|
+
if (lastSeparatorIndex === -1) return isWindows ? '.' : '.';
|
|
165
|
+
if (lastSeparatorIndex === 0) return isWindows ? normalized.substring(0, 2) : '/';
|
|
166
|
+
|
|
167
|
+
return normalized.substring(0, lastSeparatorIndex) || (isWindows ? '.' : '/');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Extrait le nom de fichier d'un chemin
|
|
172
|
+
* @param path Chemin source
|
|
173
|
+
* @param ext Extension optionnelle à retirer
|
|
174
|
+
* @returns Le nom de fichier ou undefined
|
|
175
|
+
*/
|
|
176
|
+
static basename(path: string, ext?: string): string | undefined {
|
|
177
|
+
if (!path) return undefined;
|
|
178
|
+
|
|
179
|
+
const isWindows = this.isWindowsPath(path);
|
|
180
|
+
const separator = isWindows ? '\\' : '/';
|
|
181
|
+
const normalized = this.normalizePathSegment(path, isWindows);
|
|
182
|
+
const lastSeparatorIndex = normalized.lastIndexOf(separator);
|
|
183
|
+
let basename = lastSeparatorIndex === -1 ? normalized : normalized.substring(lastSeparatorIndex + 1);
|
|
184
|
+
|
|
185
|
+
// Gestion de l'extension optionnelle
|
|
186
|
+
if (ext && basename.endsWith(ext)) {
|
|
187
|
+
basename = basename.substring(0, basename.length - ext.length);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return basename || undefined;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
static extname(path: string): string | undefined {
|
|
194
|
+
if (!path) return undefined;
|
|
195
|
+
|
|
196
|
+
const basename = this.basename(path);
|
|
197
|
+
if (!basename) return undefined;
|
|
198
|
+
|
|
199
|
+
const lastDotIndex = basename.lastIndexOf('.');
|
|
200
|
+
return lastDotIndex > 0 ? basename.substring(lastDotIndex) : undefined;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
static toUnixPath(path: string): string {
|
|
204
|
+
return path.replace(new RegExp('\\\\', 'g'), '/');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Convertit un chemin Unix en chemin Windows
|
|
209
|
+
* @param path Chemin Unix
|
|
210
|
+
* @returns Chemin Windows
|
|
211
|
+
*/
|
|
212
|
+
static toWindowsPath(path: string): string {
|
|
213
|
+
return path.replace(new RegExp('/', 'g'), '\\\\');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
static exposeToGlobal(): void {
|
|
217
|
+
if (typeof window !== "undefined") {
|
|
218
|
+
(window as any).Pajo = Pajo;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (typeof window !== "undefined") {
|
|
224
|
+
Pajo.exposeToGlobal();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
const globalFunctModule = {
|
|
231
|
+
default: Pajo,
|
|
232
|
+
Pajo: Pajo,
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
const __bundledModules = globalFunctModule;
|
|
237
|
+
|
|
238
|
+
if (typeof global !== 'undefined') {
|
|
239
|
+
(global as any).default = Pajo;
|
|
240
|
+
(global as any).Pajo = Pajo;
|
|
241
|
+
(global as any).__bundledModules = __bundledModules;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (typeof window !== "undefined") {
|
|
245
|
+
(window as any).default = Pajo;
|
|
246
|
+
(window as any).Pajo = Pajo;
|
|
247
|
+
(window as any).__bundledModules = __bundledModules;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (typeof exports !== 'undefined') {
|
|
251
|
+
exports.default = Pajo;
|
|
252
|
+
exports.Pajo = Pajo;
|
|
253
|
+
}
|
|
254
|
+
return globalFunctModule;
|
|
255
|
+
|
|
256
|
+
})(typeof global !== 'undefined' ? global :
|
|
257
|
+
typeof window !== 'undefined' ? window :
|
|
258
|
+
typeof self !== 'undefined' ? self :
|
|
259
|
+
typeof globalThis !== 'undefined' ? globalThis :
|
|
260
|
+
{});
|
|
261
|
+
|
|
262
|
+
type PajoElementTypeGF = typeof globalFunct.Pajo;
|
|
263
|
+
|
|
264
|
+
type DefaultElementTypeGF = typeof globalFunct.default;
|
|
265
|
+
|
|
266
|
+
const PajoElementGF: PajoElementTypeGF = globalFunct.Pajo;
|
|
267
|
+
|
|
268
|
+
const defaultElementGF: DefaultElementTypeGF = globalFunct.default;
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
|
package/ts/index.ts
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
|
|
3
|
+
interface Window {
|
|
4
|
+
default: typeof defaultElementGF;
|
|
5
|
+
Pajo: any;
|
|
6
|
+
__bundledModules: any;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const globalFunct = (function(global: any) {
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Pajo {
|
|
16
|
+
private static readonly PROTOCOL_REGEX = new RegExp('^[a-zA-Z]+://');
|
|
17
|
+
private static readonly DOUBLE_SLASH_REGEX = new RegExp('/+', 'g');
|
|
18
|
+
private static readonly DOUBLE_BACKSLASH_REGEX = new RegExp('\\\\+', 'g');
|
|
19
|
+
private static readonly TRAILING_SLASH_REGEX = new RegExp('/+$');
|
|
20
|
+
private static readonly TRAILING_BACKSLASH_REGEX = new RegExp('\\\\+$');
|
|
21
|
+
private static readonly LEADING_SLASH_REGEX = new RegExp('^/+');
|
|
22
|
+
private static readonly WINDOWS_DRIVE_REGEX = new RegExp('^[a-zA-Z]:\\\\');
|
|
23
|
+
private static readonly MIXED_SEPARATORS_REGEX = new RegExp('[\\\\/]+', 'g');
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Joint plusieurs segments de chemin en normalisant les séparateurs
|
|
27
|
+
* @param paths Segments de chemin à joindre
|
|
28
|
+
* @returns Le chemin normalisé ou undefined si aucun chemin valide
|
|
29
|
+
*/
|
|
30
|
+
static join(...paths: string[]): string | undefined {
|
|
31
|
+
if (paths.length === 0) return undefined;
|
|
32
|
+
|
|
33
|
+
// Détection du style de chemin (Windows ou Unix)
|
|
34
|
+
const isWindowsPath = paths.some(path => this.isWindowsPath(path));
|
|
35
|
+
|
|
36
|
+
// Filtre les chemins vides et nettoie chaque segment
|
|
37
|
+
const cleanPaths = paths
|
|
38
|
+
.filter(path => path != null && path.trim().length > 0)
|
|
39
|
+
.map(path => this.normalizePathSegment(path, isWindowsPath));
|
|
40
|
+
|
|
41
|
+
if (cleanPaths.length === 0) return undefined;
|
|
42
|
+
|
|
43
|
+
// Reconstruction du chemin final avec le séparateur approprié
|
|
44
|
+
const separator = isWindowsPath ? '\\' : '/';
|
|
45
|
+
let result = cleanPaths.join(separator);
|
|
46
|
+
|
|
47
|
+
if (isWindowsPath) {
|
|
48
|
+
result = result.replace(this.DOUBLE_BACKSLASH_REGEX, '\\');
|
|
49
|
+
} else {
|
|
50
|
+
result = result.replace(this.DOUBLE_SLASH_REGEX, '/');
|
|
51
|
+
|
|
52
|
+
// Préservation du slash initial pour les chemins absolus Linux
|
|
53
|
+
const hasLeadingSlash = paths[0]?.startsWith('/') || false;
|
|
54
|
+
if (hasLeadingSlash && !result.startsWith('/')) {
|
|
55
|
+
result = '/' + result;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return result || undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Joint un hôte avec des segments de chemin
|
|
64
|
+
* @param host Hôte (peut inclure le protocole)
|
|
65
|
+
* @param paths Segments de chemin à joindre
|
|
66
|
+
* @returns L'URL complète normalisée ou undefined si invalide
|
|
67
|
+
*/
|
|
68
|
+
static joinWithHost(host: string, ...paths: string[]): string | undefined {
|
|
69
|
+
if (!host || host.trim().length === 0) {
|
|
70
|
+
return this.join(...paths);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const cleanHost = host.trim().replace(this.TRAILING_SLASH_REGEX, '');
|
|
74
|
+
|
|
75
|
+
const hasProtocol = this.PROTOCOL_REGEX.test(cleanHost);
|
|
76
|
+
const normalizedHost = hasProtocol ? cleanHost : `https://${cleanHost}`;
|
|
77
|
+
|
|
78
|
+
const joinedPath = this.join(...paths);
|
|
79
|
+
if (!joinedPath) {
|
|
80
|
+
return normalizedHost;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const cleanPath = joinedPath.replace(new RegExp('\\\\', 'g'), '/').replace(this.LEADING_SLASH_REGEX, '');
|
|
84
|
+
return `${normalizedHost}/${cleanPath}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Normalise un segment de chemin individuel
|
|
89
|
+
* @param path Segment de chemin à normaliser
|
|
90
|
+
* @param isWindowsStyle Si on doit utiliser le style Windows
|
|
91
|
+
* @returns Le segment normalisé
|
|
92
|
+
*/
|
|
93
|
+
private static normalizePathSegment(path: string, isWindowsStyle: boolean): string {
|
|
94
|
+
if (!path || path.trim().length === 0) return '';
|
|
95
|
+
|
|
96
|
+
const trimmed = path.trim();
|
|
97
|
+
|
|
98
|
+
if (isWindowsStyle) {
|
|
99
|
+
return trimmed
|
|
100
|
+
.replace(this.DOUBLE_BACKSLASH_REGEX, '\\')
|
|
101
|
+
.replace(this.TRAILING_BACKSLASH_REGEX, '');
|
|
102
|
+
} else {
|
|
103
|
+
return trimmed
|
|
104
|
+
.replace(this.DOUBLE_SLASH_REGEX, '/')
|
|
105
|
+
.replace(this.TRAILING_SLASH_REGEX, '');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private static isWindowsPath(path: string): boolean {
|
|
110
|
+
return this.WINDOWS_DRIVE_REGEX.test(path) || path.includes('\\');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Résout les chemins avec . et .. (simplifié)
|
|
115
|
+
* @param paths Segments de chemin à résoudre
|
|
116
|
+
* @returns Chemin résolu
|
|
117
|
+
*/
|
|
118
|
+
static resolve(...paths: string[]): string | undefined {
|
|
119
|
+
const joined = this.join(...paths);
|
|
120
|
+
if (!joined) return undefined;
|
|
121
|
+
|
|
122
|
+
const isWindows = this.isWindowsPath(joined);
|
|
123
|
+
const separator = isWindows ? '\\' : '/';
|
|
124
|
+
const parts = joined.split(separator);
|
|
125
|
+
const resolved: string[] = [];
|
|
126
|
+
|
|
127
|
+
for (const part of parts) {
|
|
128
|
+
if (part === '..') {
|
|
129
|
+
if (resolved.length > 0 && resolved[resolved.length - 1] !== '..') {
|
|
130
|
+
resolved.pop();
|
|
131
|
+
} else {
|
|
132
|
+
resolved.push(part);
|
|
133
|
+
}
|
|
134
|
+
} else if (part !== '.' && part !== '') {
|
|
135
|
+
resolved.push(part);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let result = resolved.join(separator);
|
|
140
|
+
|
|
141
|
+
if (isWindows && this.WINDOWS_DRIVE_REGEX.test(parts[0])) {
|
|
142
|
+
result = parts[0] + separator + result;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static isAbsolute(path: string): boolean {
|
|
149
|
+
if (!path) return false;
|
|
150
|
+
|
|
151
|
+
return path.startsWith('/') ||
|
|
152
|
+
this.WINDOWS_DRIVE_REGEX.test(path) ||
|
|
153
|
+
this.PROTOCOL_REGEX.test(path);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
static dirname(path: string): string | undefined {
|
|
157
|
+
if (!path) return undefined;
|
|
158
|
+
|
|
159
|
+
const isWindows = this.isWindowsPath(path);
|
|
160
|
+
const separator = isWindows ? '\\' : '/';
|
|
161
|
+
const normalized = this.normalizePathSegment(path, isWindows);
|
|
162
|
+
const lastSeparatorIndex = normalized.lastIndexOf(separator);
|
|
163
|
+
|
|
164
|
+
if (lastSeparatorIndex === -1) return isWindows ? '.' : '.';
|
|
165
|
+
if (lastSeparatorIndex === 0) return isWindows ? normalized.substring(0, 2) : '/';
|
|
166
|
+
|
|
167
|
+
return normalized.substring(0, lastSeparatorIndex) || (isWindows ? '.' : '/');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Extrait le nom de fichier d'un chemin
|
|
172
|
+
* @param path Chemin source
|
|
173
|
+
* @param ext Extension optionnelle à retirer
|
|
174
|
+
* @returns Le nom de fichier ou undefined
|
|
175
|
+
*/
|
|
176
|
+
static basename(path: string, ext?: string): string | undefined {
|
|
177
|
+
if (!path) return undefined;
|
|
178
|
+
|
|
179
|
+
const isWindows = this.isWindowsPath(path);
|
|
180
|
+
const separator = isWindows ? '\\' : '/';
|
|
181
|
+
const normalized = this.normalizePathSegment(path, isWindows);
|
|
182
|
+
const lastSeparatorIndex = normalized.lastIndexOf(separator);
|
|
183
|
+
let basename = lastSeparatorIndex === -1 ? normalized : normalized.substring(lastSeparatorIndex + 1);
|
|
184
|
+
|
|
185
|
+
// Gestion de l'extension optionnelle
|
|
186
|
+
if (ext && basename.endsWith(ext)) {
|
|
187
|
+
basename = basename.substring(0, basename.length - ext.length);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return basename || undefined;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
static extname(path: string): string | undefined {
|
|
194
|
+
if (!path) return undefined;
|
|
195
|
+
|
|
196
|
+
const basename = this.basename(path);
|
|
197
|
+
if (!basename) return undefined;
|
|
198
|
+
|
|
199
|
+
const lastDotIndex = basename.lastIndexOf('.');
|
|
200
|
+
return lastDotIndex > 0 ? basename.substring(lastDotIndex) : undefined;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
static toUnixPath(path: string): string {
|
|
204
|
+
return path.replace(new RegExp('\\\\', 'g'), '/');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Convertit un chemin Unix en chemin Windows
|
|
209
|
+
* @param path Chemin Unix
|
|
210
|
+
* @returns Chemin Windows
|
|
211
|
+
*/
|
|
212
|
+
static toWindowsPath(path: string): string {
|
|
213
|
+
return path.replace(new RegExp('/', 'g'), '\\\\');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
static exposeToGlobal(): void {
|
|
217
|
+
if (typeof window !== "undefined") {
|
|
218
|
+
(window as any).Pajo = Pajo;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (typeof window !== "undefined") {
|
|
224
|
+
Pajo.exposeToGlobal();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
const globalFunctModule = {
|
|
231
|
+
default: Pajo,
|
|
232
|
+
Pajo: Pajo,
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
const __bundledModules = globalFunctModule;
|
|
237
|
+
|
|
238
|
+
if (typeof global !== 'undefined') {
|
|
239
|
+
(global as any).default = Pajo;
|
|
240
|
+
(global as any).Pajo = Pajo;
|
|
241
|
+
(global as any).__bundledModules = __bundledModules;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (typeof window !== "undefined") {
|
|
245
|
+
(window as any).default = Pajo;
|
|
246
|
+
(window as any).Pajo = Pajo;
|
|
247
|
+
(window as any).__bundledModules = __bundledModules;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (typeof exports !== 'undefined') {
|
|
251
|
+
exports.default = Pajo;
|
|
252
|
+
exports.Pajo = Pajo;
|
|
253
|
+
}
|
|
254
|
+
return globalFunctModule;
|
|
255
|
+
|
|
256
|
+
})(typeof global !== 'undefined' ? global :
|
|
257
|
+
typeof window !== 'undefined' ? window :
|
|
258
|
+
typeof self !== 'undefined' ? self :
|
|
259
|
+
typeof globalThis !== 'undefined' ? globalThis :
|
|
260
|
+
{});
|
|
261
|
+
|
|
262
|
+
type PajoElementTypeGF = typeof globalFunct.Pajo;
|
|
263
|
+
|
|
264
|
+
type DefaultElementTypeGF = typeof globalFunct.default;
|
|
265
|
+
|
|
266
|
+
const PajoElementGF: PajoElementTypeGF = globalFunct.Pajo;
|
|
267
|
+
|
|
268
|
+
const defaultElementGF: DefaultElementTypeGF = globalFunct.default;
|
|
269
|
+
|
|
270
|
+
export {
|
|
271
|
+
defaultElementGF as default,
|
|
272
|
+
PajoElementGF as Pajo,
|
|
273
|
+
};
|
|
274
|
+
export type {
|
|
275
|
+
DefaultElementTypeGF,
|
|
276
|
+
PajoElementTypeGF,
|
|
277
|
+
};
|
package/ts/pajo.ts
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
|
|
3
|
+
interface Window {
|
|
4
|
+
default: typeof defaultElementGF;
|
|
5
|
+
Pajo: any;
|
|
6
|
+
__bundledModules: any;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const globalFunct = (function(global: any) {
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Pajo {
|
|
16
|
+
private static readonly PROTOCOL_REGEX = new RegExp('^[a-zA-Z]+://');
|
|
17
|
+
private static readonly DOUBLE_SLASH_REGEX = new RegExp('/+', 'g');
|
|
18
|
+
private static readonly DOUBLE_BACKSLASH_REGEX = new RegExp('\\\\+', 'g');
|
|
19
|
+
private static readonly TRAILING_SLASH_REGEX = new RegExp('/+$');
|
|
20
|
+
private static readonly TRAILING_BACKSLASH_REGEX = new RegExp('\\\\+$');
|
|
21
|
+
private static readonly LEADING_SLASH_REGEX = new RegExp('^/+');
|
|
22
|
+
private static readonly WINDOWS_DRIVE_REGEX = new RegExp('^[a-zA-Z]:\\\\');
|
|
23
|
+
private static readonly MIXED_SEPARATORS_REGEX = new RegExp('[\\\\/]+', 'g');
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Joint plusieurs segments de chemin en normalisant les séparateurs
|
|
27
|
+
* @param paths Segments de chemin à joindre
|
|
28
|
+
* @returns Le chemin normalisé ou undefined si aucun chemin valide
|
|
29
|
+
*/
|
|
30
|
+
static join(...paths: string[]): string | undefined {
|
|
31
|
+
if (paths.length === 0) return undefined;
|
|
32
|
+
|
|
33
|
+
// Détection du style de chemin (Windows ou Unix)
|
|
34
|
+
const isWindowsPath = paths.some(path => this.isWindowsPath(path));
|
|
35
|
+
|
|
36
|
+
// Filtre les chemins vides et nettoie chaque segment
|
|
37
|
+
const cleanPaths = paths
|
|
38
|
+
.filter(path => path != null && path.trim().length > 0)
|
|
39
|
+
.map(path => this.normalizePathSegment(path, isWindowsPath));
|
|
40
|
+
|
|
41
|
+
if (cleanPaths.length === 0) return undefined;
|
|
42
|
+
|
|
43
|
+
// Reconstruction du chemin final avec le séparateur approprié
|
|
44
|
+
const separator = isWindowsPath ? '\\' : '/';
|
|
45
|
+
let result = cleanPaths.join(separator);
|
|
46
|
+
|
|
47
|
+
if (isWindowsPath) {
|
|
48
|
+
result = result.replace(this.DOUBLE_BACKSLASH_REGEX, '\\');
|
|
49
|
+
} else {
|
|
50
|
+
result = result.replace(this.DOUBLE_SLASH_REGEX, '/');
|
|
51
|
+
|
|
52
|
+
// Préservation du slash initial pour les chemins absolus Linux
|
|
53
|
+
const hasLeadingSlash = paths[0]?.startsWith('/') || false;
|
|
54
|
+
if (hasLeadingSlash && !result.startsWith('/')) {
|
|
55
|
+
result = '/' + result;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return result || undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Joint un hôte avec des segments de chemin
|
|
64
|
+
* @param host Hôte (peut inclure le protocole)
|
|
65
|
+
* @param paths Segments de chemin à joindre
|
|
66
|
+
* @returns L'URL complète normalisée ou undefined si invalide
|
|
67
|
+
*/
|
|
68
|
+
static joinWithHost(host: string, ...paths: string[]): string | undefined {
|
|
69
|
+
if (!host || host.trim().length === 0) {
|
|
70
|
+
return this.join(...paths);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const cleanHost = host.trim().replace(this.TRAILING_SLASH_REGEX, '');
|
|
74
|
+
|
|
75
|
+
const hasProtocol = this.PROTOCOL_REGEX.test(cleanHost);
|
|
76
|
+
const normalizedHost = hasProtocol ? cleanHost : `https://${cleanHost}`;
|
|
77
|
+
|
|
78
|
+
const joinedPath = this.join(...paths);
|
|
79
|
+
if (!joinedPath) {
|
|
80
|
+
return normalizedHost;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const cleanPath = joinedPath.replace(new RegExp('\\\\', 'g'), '/').replace(this.LEADING_SLASH_REGEX, '');
|
|
84
|
+
return `${normalizedHost}/${cleanPath}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Normalise un segment de chemin individuel
|
|
89
|
+
* @param path Segment de chemin à normaliser
|
|
90
|
+
* @param isWindowsStyle Si on doit utiliser le style Windows
|
|
91
|
+
* @returns Le segment normalisé
|
|
92
|
+
*/
|
|
93
|
+
private static normalizePathSegment(path: string, isWindowsStyle: boolean): string {
|
|
94
|
+
if (!path || path.trim().length === 0) return '';
|
|
95
|
+
|
|
96
|
+
const trimmed = path.trim();
|
|
97
|
+
|
|
98
|
+
if (isWindowsStyle) {
|
|
99
|
+
return trimmed
|
|
100
|
+
.replace(this.DOUBLE_BACKSLASH_REGEX, '\\')
|
|
101
|
+
.replace(this.TRAILING_BACKSLASH_REGEX, '');
|
|
102
|
+
} else {
|
|
103
|
+
return trimmed
|
|
104
|
+
.replace(this.DOUBLE_SLASH_REGEX, '/')
|
|
105
|
+
.replace(this.TRAILING_SLASH_REGEX, '');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private static isWindowsPath(path: string): boolean {
|
|
110
|
+
return this.WINDOWS_DRIVE_REGEX.test(path) || path.includes('\\');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Résout les chemins avec . et .. (simplifié)
|
|
115
|
+
* @param paths Segments de chemin à résoudre
|
|
116
|
+
* @returns Chemin résolu
|
|
117
|
+
*/
|
|
118
|
+
static resolve(...paths: string[]): string | undefined {
|
|
119
|
+
const joined = this.join(...paths);
|
|
120
|
+
if (!joined) return undefined;
|
|
121
|
+
|
|
122
|
+
const isWindows = this.isWindowsPath(joined);
|
|
123
|
+
const separator = isWindows ? '\\' : '/';
|
|
124
|
+
const parts = joined.split(separator);
|
|
125
|
+
const resolved: string[] = [];
|
|
126
|
+
|
|
127
|
+
for (const part of parts) {
|
|
128
|
+
if (part === '..') {
|
|
129
|
+
if (resolved.length > 0 && resolved[resolved.length - 1] !== '..') {
|
|
130
|
+
resolved.pop();
|
|
131
|
+
} else {
|
|
132
|
+
resolved.push(part);
|
|
133
|
+
}
|
|
134
|
+
} else if (part !== '.' && part !== '') {
|
|
135
|
+
resolved.push(part);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let result = resolved.join(separator);
|
|
140
|
+
|
|
141
|
+
if (isWindows && this.WINDOWS_DRIVE_REGEX.test(parts[0])) {
|
|
142
|
+
result = parts[0] + separator + result;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static isAbsolute(path: string): boolean {
|
|
149
|
+
if (!path) return false;
|
|
150
|
+
|
|
151
|
+
return path.startsWith('/') ||
|
|
152
|
+
this.WINDOWS_DRIVE_REGEX.test(path) ||
|
|
153
|
+
this.PROTOCOL_REGEX.test(path);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
static dirname(path: string): string | undefined {
|
|
157
|
+
if (!path) return undefined;
|
|
158
|
+
|
|
159
|
+
const isWindows = this.isWindowsPath(path);
|
|
160
|
+
const separator = isWindows ? '\\' : '/';
|
|
161
|
+
const normalized = this.normalizePathSegment(path, isWindows);
|
|
162
|
+
const lastSeparatorIndex = normalized.lastIndexOf(separator);
|
|
163
|
+
|
|
164
|
+
if (lastSeparatorIndex === -1) return isWindows ? '.' : '.';
|
|
165
|
+
if (lastSeparatorIndex === 0) return isWindows ? normalized.substring(0, 2) : '/';
|
|
166
|
+
|
|
167
|
+
return normalized.substring(0, lastSeparatorIndex) || (isWindows ? '.' : '/');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Extrait le nom de fichier d'un chemin
|
|
172
|
+
* @param path Chemin source
|
|
173
|
+
* @param ext Extension optionnelle à retirer
|
|
174
|
+
* @returns Le nom de fichier ou undefined
|
|
175
|
+
*/
|
|
176
|
+
static basename(path: string, ext?: string): string | undefined {
|
|
177
|
+
if (!path) return undefined;
|
|
178
|
+
|
|
179
|
+
const isWindows = this.isWindowsPath(path);
|
|
180
|
+
const separator = isWindows ? '\\' : '/';
|
|
181
|
+
const normalized = this.normalizePathSegment(path, isWindows);
|
|
182
|
+
const lastSeparatorIndex = normalized.lastIndexOf(separator);
|
|
183
|
+
let basename = lastSeparatorIndex === -1 ? normalized : normalized.substring(lastSeparatorIndex + 1);
|
|
184
|
+
|
|
185
|
+
// Gestion de l'extension optionnelle
|
|
186
|
+
if (ext && basename.endsWith(ext)) {
|
|
187
|
+
basename = basename.substring(0, basename.length - ext.length);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return basename || undefined;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
static extname(path: string): string | undefined {
|
|
194
|
+
if (!path) return undefined;
|
|
195
|
+
|
|
196
|
+
const basename = this.basename(path);
|
|
197
|
+
if (!basename) return undefined;
|
|
198
|
+
|
|
199
|
+
const lastDotIndex = basename.lastIndexOf('.');
|
|
200
|
+
return lastDotIndex > 0 ? basename.substring(lastDotIndex) : undefined;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
static toUnixPath(path: string): string {
|
|
204
|
+
return path.replace(new RegExp('\\\\', 'g'), '/');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Convertit un chemin Unix en chemin Windows
|
|
209
|
+
* @param path Chemin Unix
|
|
210
|
+
* @returns Chemin Windows
|
|
211
|
+
*/
|
|
212
|
+
static toWindowsPath(path: string): string {
|
|
213
|
+
return path.replace(new RegExp('/', 'g'), '\\\\');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
static exposeToGlobal(): void {
|
|
217
|
+
if (typeof window !== "undefined") {
|
|
218
|
+
(window as any).Pajo = Pajo;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (typeof window !== "undefined") {
|
|
224
|
+
Pajo.exposeToGlobal();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
const globalFunctModule = {
|
|
231
|
+
default: Pajo,
|
|
232
|
+
Pajo: Pajo,
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
const __bundledModules = globalFunctModule;
|
|
237
|
+
|
|
238
|
+
if (typeof global !== 'undefined') {
|
|
239
|
+
(global as any).default = Pajo;
|
|
240
|
+
(global as any).Pajo = Pajo;
|
|
241
|
+
(global as any).__bundledModules = __bundledModules;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (typeof window !== "undefined") {
|
|
245
|
+
(window as any).default = Pajo;
|
|
246
|
+
(window as any).Pajo = Pajo;
|
|
247
|
+
(window as any).__bundledModules = __bundledModules;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (typeof exports !== 'undefined') {
|
|
251
|
+
exports.default = Pajo;
|
|
252
|
+
exports.Pajo = Pajo;
|
|
253
|
+
}
|
|
254
|
+
return globalFunctModule;
|
|
255
|
+
|
|
256
|
+
})(typeof global !== 'undefined' ? global :
|
|
257
|
+
typeof window !== 'undefined' ? window :
|
|
258
|
+
typeof self !== 'undefined' ? self :
|
|
259
|
+
typeof globalThis !== 'undefined' ? globalThis :
|
|
260
|
+
{});
|
|
261
|
+
|
|
262
|
+
type PajoElementTypeGF = typeof globalFunct.Pajo;
|
|
263
|
+
|
|
264
|
+
type DefaultElementTypeGF = typeof globalFunct.default;
|
|
265
|
+
|
|
266
|
+
const PajoElementGF: PajoElementTypeGF = globalFunct.Pajo;
|
|
267
|
+
|
|
268
|
+
const defaultElementGF: DefaultElementTypeGF = globalFunct.default;
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
|