(
path: string,
allowAboveRoot: boolean,
separator: string,
isPathSeparator: (code?: number) => boolean
)
| 95 | |
| 96 | // Resolves . and .. elements in a path with directory names |
| 97 | function normalizeString( |
| 98 | path: string, |
| 99 | allowAboveRoot: boolean, |
| 100 | separator: string, |
| 101 | isPathSeparator: (code?: number) => boolean |
| 102 | ) { |
| 103 | let res = ''; |
| 104 | let lastSegmentLength = 0; |
| 105 | let lastSlash = -1; |
| 106 | let dots = 0; |
| 107 | let code = 0; |
| 108 | for (let i = 0; i <= path.length; ++i) { |
| 109 | if (i < path.length) { |
| 110 | code = path.charCodeAt(i); |
| 111 | } else if (isPathSeparator(code)) { |
| 112 | break; |
| 113 | } else { |
| 114 | code = CHAR_FORWARD_SLASH; |
| 115 | } |
| 116 | |
| 117 | if (isPathSeparator(code)) { |
| 118 | if (lastSlash === i - 1 || dots === 1) { |
| 119 | // NOOP |
| 120 | } else if (dots === 2) { |
| 121 | if ( |
| 122 | res.length < 2 || |
| 123 | lastSegmentLength !== 2 || |
| 124 | res.charCodeAt(res.length - 1) !== CHAR_DOT || |
| 125 | res.charCodeAt(res.length - 2) !== CHAR_DOT |
| 126 | ) { |
| 127 | if (res.length > 2) { |
| 128 | const lastSlashIndex = res.lastIndexOf(separator); |
| 129 | if (lastSlashIndex === -1) { |
| 130 | res = ''; |
| 131 | lastSegmentLength = 0; |
| 132 | } else { |
| 133 | res = res.slice(0, lastSlashIndex); |
| 134 | lastSegmentLength = res.length - 1 - res.lastIndexOf(separator); |
| 135 | } |
| 136 | lastSlash = i; |
| 137 | dots = 0; |
| 138 | continue; |
| 139 | } else if (res.length !== 0) { |
| 140 | res = ''; |
| 141 | lastSegmentLength = 0; |
| 142 | lastSlash = i; |
| 143 | dots = 0; |
| 144 | continue; |
| 145 | } |
| 146 | } |
| 147 | if (allowAboveRoot) { |
| 148 | res += res.length > 0 ? `${separator}..` : '..'; |
| 149 | lastSegmentLength = 2; |
| 150 | } |
| 151 | } else { |
| 152 | if (res.length > 0) { |
| 153 | res += `${separator}${path.slice(lastSlash + 1, i)}`; |
| 154 | } else { |
no test coverage detected