|
@ -126,6 +126,7 @@ function uri_format (object) { |
|
|
throw new Error("UrlError: URL undefined for urls#format"); |
|
|
throw new Error("UrlError: URL undefined for urls#format"); |
|
|
if (object instanceof String || typeof(object) === 'string') |
|
|
if (object instanceof String || typeof(object) === 'string') |
|
|
return object; |
|
|
return object; |
|
|
|
|
|
|
|
|
var domain = |
|
|
var domain = |
|
|
object.domains ? |
|
|
object.domains ? |
|
|
object.domains.join(".") : |
|
|
object.domains.join(".") : |
|
@ -138,7 +139,7 @@ function uri_format (object) { |
|
|
(object.password ? ":" + object.password : "") |
|
|
(object.password ? ":" + object.password : "") |
|
|
) : |
|
|
) : |
|
|
object.userInfo; |
|
|
object.userInfo; |
|
|
var authority = ( |
|
|
var authority = object.authority || (( |
|
|
userInfo || |
|
|
userInfo || |
|
|
domain || |
|
|
domain || |
|
|
object.port |
|
|
object.port |
|
@ -146,20 +147,18 @@ function uri_format (object) { |
|
|
(userInfo ? userInfo + "@" : "") + |
|
|
(userInfo ? userInfo + "@" : "") + |
|
|
(domain || "") + |
|
|
(domain || "") + |
|
|
(object.port ? ":" + object.port : "") |
|
|
(object.port ? ":" + object.port : "") |
|
|
) : |
|
|
) : ""); |
|
|
object.authority || ""; |
|
|
|
|
|
|
|
|
|
|
|
var directory = |
|
|
var directory = |
|
|
object.directories ? |
|
|
object.directories ? |
|
|
object.directories.join("/") : |
|
|
object.directories.join("/") : |
|
|
object.directory; |
|
|
object.directory; |
|
|
var path = |
|
|
var path = |
|
|
directory || object.file ? |
|
|
object.path ? object.path.substr(1) : ( |
|
|
( |
|
|
(directory || object.file) ? ( |
|
|
(directory ? directory + "/" : "") + |
|
|
(directory ? directory + "/" : "") + |
|
|
(object.file || "") |
|
|
(object.file || "") |
|
|
) : |
|
|
) : ""); |
|
|
object.path; |
|
|
|
|
|
var authorityRoot = |
|
|
var authorityRoot = |
|
|
object.authorityRoot |
|
|
object.authorityRoot |
|
|
|| authority ? "//" : ""; |
|
|
|| authority ? "//" : ""; |
|
@ -175,74 +174,79 @@ function uri_format (object) { |
|
|
) || object.url || ""); |
|
|
) || object.url || ""); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
/**** resolveObject |
|
|
|
|
|
returns an object representing a URL resolved from |
|
|
|
|
|
a relative location and a source location. |
|
|
|
|
|
*/ |
|
|
|
|
|
function uri_resolveObject (source, relative) { |
|
|
function uri_resolveObject (source, relative) { |
|
|
if (!source) |
|
|
if (!source) return relative; |
|
|
|
|
|
|
|
|
|
|
|
// parse a string, or get new objects
|
|
|
|
|
|
source = uri_parse(uri_format(source)); |
|
|
|
|
|
relative = uri_parse(uri_format(relative)); |
|
|
|
|
|
|
|
|
|
|
|
if (relative.url === "") return source; |
|
|
|
|
|
|
|
|
|
|
|
// links to xyz:... from abc:... are always absolute.
|
|
|
|
|
|
if (relative.protocol && source.protocol && relative.protocol !== source.protocol) { |
|
|
return relative; |
|
|
return relative; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// if there's an authority root, but no protocol, then keep the current protocol
|
|
|
|
|
|
if (relative.authorityRoot && !relative.protocol) { |
|
|
|
|
|
relative.protocol = source.protocol; |
|
|
|
|
|
} |
|
|
|
|
|
// if we have an authority root, then it's absolute
|
|
|
|
|
|
if (relative.authorityRoot) return relative; |
|
|
|
|
|
|
|
|
source = uri_parse(source); |
|
|
|
|
|
relative = uri_parse(relative); |
|
|
// at this point, we start doing the tricky stuff
|
|
|
|
|
|
// we know that relative doesn't have an authority, but might have root,
|
|
|
if (relative.url == "") |
|
|
// path, file, query, etc.
|
|
|
return source; |
|
|
// also, the directory segments might contain .. or .
|
|
|
|
|
|
// start mutating "source", and then return that.
|
|
|
delete source.url; |
|
|
|
|
|
delete source.authority; |
|
|
|
|
|
delete source.domain; |
|
|
|
|
|
delete source.userInfo; |
|
|
|
|
|
delete source.path; |
|
|
|
|
|
delete source.directory; |
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
// relative urls that start with / are absolute to the authority/protocol
|
|
|
relative.protocol && relative.protocol != source.protocol || |
|
|
if (relative.root) { |
|
|
relative.authority && relative.authority != source.authority |
|
|
[ |
|
|
) { |
|
|
"path", "root", "directory", "directories", "file", "query", "anchor" |
|
|
source = relative; |
|
|
].forEach(function (part) { source[part] = relative[part] }); |
|
|
} else { |
|
|
} else { |
|
|
if (relative.root) { |
|
|
// if you have /a/b/c and you're going to x/y/z, then that's /a/b/x/y/z
|
|
|
source.directories = relative.directories; |
|
|
// if you have /a/b/c/ and you're going ot x/y/z, then that's /a/b/c/x/y/z
|
|
|
} else { |
|
|
// if you have /a/b/c and you're going to ?foo, then that's /a/b/c?foo
|
|
|
|
|
|
if (relative.file || relative.directory) { |
|
|
var directories = relative.directories; |
|
|
source.file = relative.file; |
|
|
for (var i = 0; i < directories.length; i++) { |
|
|
source.query = relative.query; |
|
|
var directory = directories[i]; |
|
|
source.anchor = relative.anchor; |
|
|
if (directory == ".") { |
|
|
|
|
|
} else if (directory == "..") { |
|
|
|
|
|
if (source.directories.length) { |
|
|
|
|
|
source.directories.pop(); |
|
|
|
|
|
} else { |
|
|
|
|
|
source.directories.push('..'); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
source.directories.push(directory); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (relative.file == ".") { |
|
|
|
|
|
relative.file = ""; |
|
|
|
|
|
} else if (relative.file == "..") { |
|
|
|
|
|
source.directories.pop(); |
|
|
|
|
|
relative.file = ""; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
if (relative.query) source.query = relative.query; |
|
|
|
|
|
if (relative.query || relative.anchor) source.anchor = relative.anchor; |
|
|
|
|
|
|
|
|
|
|
|
// just append the dirs. we'll sort out .. and . later
|
|
|
|
|
|
source.directories = source.directories.concat(relative.directories); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (relative.root) |
|
|
// back up "file" to the first non-dot
|
|
|
source.root = relative.root; |
|
|
// one step for ., two for ..
|
|
|
if (relative.protcol) |
|
|
var file = source.file; |
|
|
source.protocol = relative.protocol; |
|
|
while (file === ".." || file === ".") { |
|
|
if (!(!relative.path && relative.anchor)) |
|
|
if (file === "..") source.directories.pop(); |
|
|
source.file = relative.file; |
|
|
file = source.directories.pop(); |
|
|
source.query = relative.query; |
|
|
} |
|
|
source.anchor = relative.anchor; |
|
|
source.file = file || ""; |
|
|
|
|
|
|
|
|
|
|
|
// walk over the dirs, replacing a/b/c/.. with a/b/ and a/b/c/. with a/b/c
|
|
|
|
|
|
var dirs = []; |
|
|
|
|
|
source.directories.forEach(function (dir, i) { |
|
|
|
|
|
if (dir === "..") dirs.pop(); |
|
|
|
|
|
else if (dir !== "." && dir !== "") dirs.push(dir); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// now construct path/etc.
|
|
|
|
|
|
source.directories = dirs; |
|
|
|
|
|
source.directory = dirs.concat("").join("/"); |
|
|
|
|
|
source.path = source.root + source.directory + source.file; |
|
|
|
|
|
source.url = uri_format(source); |
|
|
return source; |
|
|
return source; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**** resolve |
|
|
/**** resolve |
|
|
returns a URL resovled to a relative URL from a source URL. |
|
|
returns a URL resovled to a relative URL from a source URL. |
|
|
*/ |
|
|
*/ |
|
|