diff options
Diffstat (limited to 'resolve-pathname/modules/index.js')
-rw-r--r-- | resolve-pathname/modules/index.js | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/resolve-pathname/modules/index.js b/resolve-pathname/modules/index.js new file mode 100644 index 0000000..77afb3e --- /dev/null +++ b/resolve-pathname/modules/index.js @@ -0,0 +1,75 @@ +function isAbsolute(pathname) { + return pathname.charAt(0) === '/'; +} + +// About 1.5x faster than the two-arg version of Array#splice() +function spliceOne(list, index) { + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) { + list[i] = list[k]; + } + + list.pop(); +} + +// This implementation is based heavily on node's url.parse +function resolvePathname(to, from) { + if (from === undefined) from = ''; + + var toParts = (to && to.split('/')) || []; + var fromParts = (from && from.split('/')) || []; + + var isToAbs = to && isAbsolute(to); + var isFromAbs = from && isAbsolute(from); + var mustEndAbs = isToAbs || isFromAbs; + + if (to && isAbsolute(to)) { + // to is absolute + fromParts = toParts; + } else if (toParts.length) { + // to is relative, drop the filename + fromParts.pop(); + fromParts = fromParts.concat(toParts); + } + + if (!fromParts.length) return '/'; + + var hasTrailingSlash; + if (fromParts.length) { + var last = fromParts[fromParts.length - 1]; + hasTrailingSlash = last === '.' || last === '..' || last === ''; + } else { + hasTrailingSlash = false; + } + + var up = 0; + for (var i = fromParts.length; i >= 0; i--) { + var part = fromParts[i]; + + if (part === '.') { + spliceOne(fromParts, i); + } else if (part === '..') { + spliceOne(fromParts, i); + up++; + } else if (up) { + spliceOne(fromParts, i); + up--; + } + } + + if (!mustEndAbs) for (; up--; up) fromParts.unshift('..'); + + if ( + mustEndAbs && + fromParts[0] !== '' && + (!fromParts[0] || !isAbsolute(fromParts[0])) + ) + fromParts.unshift(''); + + var result = fromParts.join('/'); + + if (hasTrailingSlash && result.substr(-1) !== '/') result += '/'; + + return result; +} + +export default resolvePathname; |