| "use strict"; |
| |
| // eslint-disable-next-line complexity |
| module.exports = function normalize(path) { |
| var parts = path.split(/(\\+|\/+)/); |
| if(parts.length === 1) |
| return path; |
| var result = []; |
| var absolutePathStart = 0; |
| for(var i = 0, sep = false; i < parts.length; i += 1, sep = !sep) { |
| var part = parts[i]; |
| if(i === 0 && /^([A-Z]:)?$/i.test(part)) { |
| result.push(part); |
| absolutePathStart = 2; |
| } else if(sep) { |
| // UNC paths on Windows begin with a double backslash. |
| if (i === 1 && parts[0].length === 0 && part === "\\\\") { |
| result.push(part); |
| } else { |
| result.push(part[0]); |
| } |
| } else if(part === "..") { |
| switch(result.length) { |
| case 0: |
| // i. e. ".." => ".." |
| // i. e. "../a/b/c" => "../a/b/c" |
| result.push(part); |
| break; |
| case 2: |
| // i. e. "a/.." => "" |
| // i. e. "/.." => "/" |
| // i. e. "C:\.." => "C:\" |
| // i. e. "a/../b/c" => "b/c" |
| // i. e. "/../b/c" => "/b/c" |
| // i. e. "C:\..\a\b\c" => "C:\a\b\c" |
| if (result[0] !== ".") { |
| i += 1; |
| sep = !sep; |
| result.length = absolutePathStart; |
| } else { |
| result.length = 0; |
| result.push(part); |
| } |
| break; |
| case 4: |
| // i. e. "a/b/.." => "a" |
| // i. e. "/a/.." => "/" |
| // i. e. "C:\a\.." => "C:\" |
| // i. e. "/a/../b/c" => "/b/c" |
| if(absolutePathStart === 0) { |
| result.length -= 3; |
| } else { |
| i += 1; |
| sep = !sep; |
| result.length = 2; |
| } |
| break; |
| default: |
| // i. e. "/a/b/.." => "/a" |
| // i. e. "/a/b/../c" => "/a/c" |
| result.length -= 3; |
| break; |
| } |
| } else if(part === ".") { |
| switch(result.length) { |
| case 0: |
| // i. e. "." => "." |
| // i. e. "./a/b/c" => "./a/b/c" |
| result.push(part); |
| break; |
| case 2: |
| // i. e. "a/." => "a" |
| // i. e. "/." => "/" |
| // i. e. "C:\." => "C:\" |
| // i. e. "C:\.\a\b\c" => "C:\a\b\c" |
| if(absolutePathStart === 0) { |
| result.length -= 1; |
| } else { |
| i += 1; |
| sep = !sep; |
| } |
| break; |
| default: |
| // i. e. "a/b/." => "a/b" |
| // i. e. "/a/." => "/" |
| // i. e. "C:\a\." => "C:\" |
| // i. e. "a/./b/c" => "a/b/c" |
| // i. e. "/a/./b/c" => "/a/b/c" |
| result.length -= 1; |
| break; |
| } |
| } else if(part) { |
| result.push(part); |
| } |
| } |
| if(result.length === 1 && /^[A-Za-z]:$/.test(result[0])) |
| return result[0] + "\\"; |
| return result.join(""); |
| }; |