Skip to content
This repository was archived by the owner on Aug 15, 2024. It is now read-only.

Commit 7332919

Browse files
committed
use less regexp and more performance parsing
1 parent bca2616 commit 7332919

File tree

1 file changed

+85
-37
lines changed

1 file changed

+85
-37
lines changed

lib/normalize.js

Lines changed: 85 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,86 @@
1-
var doubleSlashWinRegExp = /\\+/g;
2-
var doubleSlashNixRegExp = /\/+/g;
3-
var currentDirectoryWinMiddleRegExp = /\\(\.\\)+/;
4-
var currentDirectoryWinEndRegExp = /\\\.$/;
5-
var parentDirectoryWinMiddleRegExp = /\\+[^\\]+\\+\.\.\\/;
6-
var parentDirectoryWinEndRegExp1 = /([A-Z]:\\)\\*[^\\]+\\+\.\.$/i;
7-
var parentDirectoryWinEndRegExp2 = /\\+[^\\]+\\+\.\.$/;
8-
var currentDirectoryNixMiddleRegExp = /\/+(\.\/)+/;
9-
var currentDirectoryNixEndRegExp1 = /^\/+\.$/;
10-
var currentDirectoryNixEndRegExp2 = /\/+\.$/;
11-
var parentDirectoryNixMiddleRegExp = /(^|\/[^\/]+)\/+\.\.\/+/;
12-
var parentDirectoryNixEndRegExp1 = /^\/[^\/]+\/+\.\.$/;
13-
var parentDirectoryNixEndRegExp2 = /\/+[^\/]+\/+\.\.$/;
14-
var parentDirectoryNixEndRegExp3 = /^\/+\.\.$/;
15-
16-
// RegExp magic :)
17-
181
module.exports = function normalize(path) {
19-
while(currentDirectoryWinMiddleRegExp.test(path))
20-
path = path.replace(currentDirectoryWinMiddleRegExp, "\\");
21-
path = path.replace(currentDirectoryWinEndRegExp, "");
22-
while(parentDirectoryWinMiddleRegExp.test(path))
23-
path = path.replace(parentDirectoryWinMiddleRegExp, "\\");
24-
path = path.replace(parentDirectoryWinEndRegExp1, "$1");
25-
path = path.replace(parentDirectoryWinEndRegExp2, "");
26-
27-
while(currentDirectoryNixMiddleRegExp.test(path))
28-
path = path.replace(currentDirectoryNixMiddleRegExp, "/");
29-
path = path.replace(currentDirectoryNixEndRegExp1, "/");
30-
path = path.replace(currentDirectoryNixEndRegExp2, "");
31-
while(parentDirectoryNixMiddleRegExp.test(path))
32-
path = path.replace(parentDirectoryNixMiddleRegExp, "/");
33-
path = path.replace(parentDirectoryNixEndRegExp1, "/");
34-
path = path.replace(parentDirectoryNixEndRegExp2, "");
35-
path = path.replace(parentDirectoryNixEndRegExp3, "/");
36-
37-
return path.replace(doubleSlashWinRegExp, "\\").replace(doubleSlashNixRegExp, "/");
38-
};
2+
var parts = path.split(/(\\+|\/+)/);
3+
if(parts.length === 1)
4+
return path;
5+
var result = [];
6+
var absolutePathStart = 0;
7+
for(var i = 0, sep = false; i < parts.length; i++, sep = !sep) {
8+
var part = parts[i];
9+
if(i === 0 && /^([A-Z]:)?$/i.test(part)) {
10+
result.push(part);
11+
absolutePathStart = 2;
12+
} else if(sep) {
13+
result.push(part[0]);
14+
} else if(part === "..") {
15+
switch(result.length) {
16+
case 0:
17+
// i. e. ".." => ".."
18+
// i. e. "../a/b/c" => "../a/b/c"
19+
result.push(part);
20+
break;
21+
case 2:
22+
// i. e. "a/.." => ""
23+
// i. e. "/.." => "/"
24+
// i. e. "C:\.." => "C:\"
25+
// i. e. "a/../b/c" => "b/c"
26+
// i. e. "/../b/c" => "/b/c"
27+
// i. e. "C:\..\a\b\c" => "C:\a\b\c"
28+
i++;
29+
sep = !sep;
30+
result.length = absolutePathStart;
31+
break;
32+
case 4:
33+
// i. e. "a/b/.." => "a"
34+
// i. e. "/a/.." => "/"
35+
// i. e. "C:\a\.." => "C:\"
36+
// i. e. "/a/../b/c" => "/b/c"
37+
if(absolutePathStart === 0) {
38+
result.length -= 3;
39+
} else {
40+
i++;
41+
sep = !sep;
42+
result.length = 2;
43+
}
44+
break;
45+
default:
46+
// i. e. "/a/b/.." => "/a"
47+
// i. e. "/a/b/../c" => "/a/c"
48+
result.length -= 3;
49+
break;
50+
}
51+
} else if(part === ".") {
52+
switch(result.length) {
53+
case 0:
54+
// i. e. "." => "."
55+
// i. e. "./a/b/c" => "./a/b/c"
56+
result.push(part);
57+
break;
58+
case 2:
59+
// i. e. "a/." => "a"
60+
// i. e. "/." => "/"
61+
// i. e. "C:\." => "C:\"
62+
// i. e. "C:\.\a\b\c" => "C:\a\b\c"
63+
if(absolutePathStart === 0) {
64+
result.length--;
65+
} else {
66+
i++;
67+
sep = !sep;
68+
}
69+
break;
70+
default:
71+
// i. e. "a/b/." => "a/b"
72+
// i. e. "/a/." => "/"
73+
// i. e. "C:\a\." => "C:\"
74+
// i. e. "a/./b/c" => "a/b/c"
75+
// i. e. "/a/./b/c" => "/a/b/c"
76+
result.length--;
77+
break;
78+
}
79+
} else if(part) {
80+
result.push(part);
81+
}
82+
}
83+
if(result.length === 1 && /^[A-Za-z]:$/.test(result))
84+
return result[0] + "\\";
85+
return result.join("");
86+
};

0 commit comments

Comments
 (0)