summaryrefslogtreecommitdiff
path: root/resolve-pathname/modules/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'resolve-pathname/modules/index.js')
-rw-r--r--resolve-pathname/modules/index.js75
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;