-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnormalize.mts
158 lines (135 loc) · 3.81 KB
/
normalize.mts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**
* @file normalize
* @module pathe/lib/normalize
*/
import { DRIVE_PATH_REGEX, sepWindows } from '#internal/constants'
import normalizeString from '#internal/normalize-string'
import validateString from '#internal/validate-string'
import dot from '#lib/dot'
import isAbsolute from '#lib/is-absolute'
import isSep from '#lib/is-sep'
import sep from '#lib/sep'
import toPosix from '#lib/to-posix'
/**
* Normalize `path`, resolving `'..'` and `'.'` segments.
*
* When multiple, sequential path segment separators are found, they are
* replaced by a single instance of {@linkcode sep}. Trailing separators are
* preserved.
*
* If `path` is a zero-length string, {@linkcode dot} is returned, representing
* the current working directory.
*
* @category
* core
*
* @this {void}
*
* @param {string} path
* The path to normalize
* @return {string}
* Normalized `path`
*/
function normalize(this: void, path: string): string {
validateString(path, 'path')
/**
* Normalized path.
*
* @var {string} normalized
*/
let normalized: string = ''
if (path.length <= 1) {
normalized = path || dot
} else {
/**
* Absolute path check.
*
* @var {boolean} absolute
*/
let absolute: boolean = false
/**
* Drive letter or UNC path component(s), if any.
*
* @var {string} device
*/
let device: string = ''
/**
* End index of root.
*
* @var {number} rootEnd
*/
let rootEnd: number = 0
if (isSep(path[0])) {
absolute = true
if (!isSep(path[1])) {
rootEnd = 1
} else {
/**
* Current position in {@linkcode path}.
*
* @var {number} j
*/
let j: number = 2
/**
* Last visited position in {@linkcode path}.
*
* @var {number} last
*/
let last: number = j
// match 1 or more non-path separators
while (j < path.length && !isSep(path[j])) j++
if (j < path.length && j !== last) {
/**
* Path component.
*
* @const {string} comp
*/
const comp: string = path.slice(last, j)
// matched!
last = j
// match 1 or more path separators
while (j < path.length && isSep(path[j])) j++
if (j < path.length && j !== last) {
// matched!
last = j
// match 1 or more non-path separators
while (j < path.length && !isSep(path[j])) j++
if (j === path.length || j !== last) {
device = sepWindows.repeat(2) + comp
if (comp === dot || comp === '?') {
// matched device root (i.e. `//./PHYSICALDRIVE0`)
rootEnd = 4
} else if (j === path.length) {
// matched unc root only: return normalized version of UNC root
// since there is nothing left to process
device += sepWindows + path.slice(last) + sepWindows
return toPosix(device)
} else {
// matched unc root with leftovers
device += sepWindows + path.slice(last, j)
rootEnd = j
}
}
}
}
}
} else if (DRIVE_PATH_REGEX.test(path)) {
device = path.slice(0, rootEnd = 2)
if ((absolute = isAbsolute(path))) rootEnd++
}
/**
* Tail end of normalized path.
*
* @var {string} tail
*/
let tail: string = ''
if (rootEnd < path.length) {
tail = normalizeString(path.slice(rootEnd), !absolute)
}
if (!tail.length && !absolute) tail = dot
if (tail.length && isSep(path[path.length - 1])) tail += sep
normalized = device + (absolute ? sep : '') + tail
}
return toPosix(normalized)
}
export default normalize