Browse Source

Update to fix failing test. Rewrite of the resolveObject function, and some tweaks to format.

v0.7.4-release
isaacs 15 years ago
committed by Ryan Dahl
parent
commit
4526308560
  1. 122
      lib/uri.js
  2. 8
      test/mjsunit/test-uri.js

122
lib/uri.js

@ -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;
return relative;
source = uri_parse(source); // parse a string, or get new objects
relative = uri_parse(relative); source = uri_parse(uri_format(source));
relative = uri_parse(uri_format(relative));
if (relative.url == "") if (relative.url === "") return source;
return source;
delete source.url; // links to xyz:... from abc:... are always absolute.
delete source.authority; if (relative.protocol && source.protocol && relative.protocol !== source.protocol) {
delete source.domain; return relative;
delete source.userInfo; }
delete source.path;
delete source.directory;
if (
relative.protocol && relative.protocol != source.protocol ||
relative.authority && relative.authority != source.authority
) {
source = relative;
} else {
if (relative.root) {
source.directories = relative.directories;
} else {
var directories = relative.directories; // if there's an authority root, but no protocol, then keep the current protocol
for (var i = 0; i < directories.length; i++) { if (relative.authorityRoot && !relative.protocol) {
var directory = directories[i]; relative.protocol = source.protocol;
if (directory == ".") {
} else if (directory == "..") {
if (source.directories.length) {
source.directories.pop();
} else {
source.directories.push('..');
} }
// if we have an authority root, then it's absolute
if (relative.authorityRoot) return relative;
// at this point, we start doing the tricky stuff
// we know that relative doesn't have an authority, but might have root,
// path, file, query, etc.
// also, the directory segments might contain .. or .
// start mutating "source", and then return that.
// relative urls that start with / are absolute to the authority/protocol
if (relative.root) {
[
"path", "root", "directory", "directories", "file", "query", "anchor"
].forEach(function (part) { source[part] = relative[part] });
} else { } else {
source.directories.push(directory); // if you have /a/b/c and you're going to x/y/z, then that's /a/b/x/y/z
} // if you have /a/b/c/ and you're going ot x/y/z, then that's /a/b/c/x/y/z
// if you have /a/b/c and you're going to ?foo, then that's /a/b/c?foo
if (relative.file || relative.directory) {
source.file = relative.file;
source.query = relative.query;
source.anchor = relative.anchor;
} }
if (relative.query) source.query = relative.query;
if (relative.query || relative.anchor) source.anchor = relative.anchor;
if (relative.file == ".") { // just append the dirs. we'll sort out .. and . later
relative.file = ""; source.directories = source.directories.concat(relative.directories);
} else if (relative.file == "..") {
source.directories.pop();
relative.file = "";
}
} }
// back up "file" to the first non-dot
// one step for ., two for ..
var file = source.file;
while (file === ".." || file === ".") {
if (file === "..") source.directories.pop();
file = source.directories.pop();
} }
source.file = file || "";
if (relative.root) // walk over the dirs, replacing a/b/c/.. with a/b/ and a/b/c/. with a/b/c
source.root = relative.root; var dirs = [];
if (relative.protcol) source.directories.forEach(function (dir, i) {
source.protocol = relative.protocol; if (dir === "..") dirs.pop();
if (!(!relative.path && relative.anchor)) else if (dir !== "." && dir !== "") dirs.push(dir);
source.file = relative.file; });
source.query = relative.query;
source.anchor = relative.anchor;
// 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.
*/ */

8
test/mjsunit/test-uri.js

@ -168,6 +168,7 @@ for (var url in parseTests) {
var expected = url, var expected = url,
actual = uri.format(parseTests[url]); actual = uri.format(parseTests[url]);
assert.equal(expected, actual, "format("+url+") == "+url+"\nactual:"+actual); assert.equal(expected, actual, "format("+url+") == "+url+"\nactual:"+actual);
} }
@ -175,12 +176,13 @@ for (var url in parseTests) {
// [from, path, expected] // [from, path, expected]
["/foo/bar/baz", "quux", "/foo/bar/quux"], ["/foo/bar/baz", "quux", "/foo/bar/quux"],
["/foo/bar/baz", "quux/asdf", "/foo/bar/quux/asdf"], ["/foo/bar/baz", "quux/asdf", "/foo/bar/quux/asdf"],
["/foo/bar/baz", "quux/baz", "/foo/bar/quux/baz"], //TODO: failing test ["/foo/bar/baz", "quux/baz", "/foo/bar/quux/baz"],
["/foo/bar/baz", "../quux/baz", "/foo/quux/baz"], //TODO: failing test ["/foo/bar/baz", "../quux/baz", "/foo/quux/baz"],
["/foo/bar/baz", "/bar", "/bar"], ["/foo/bar/baz", "/bar", "/bar"],
["/foo/bar/baz/", "quux", "/foo/bar/baz/quux"], ["/foo/bar/baz/", "quux", "/foo/bar/baz/quux"],
["/foo/bar/baz/", "quux/baz", "/foo/bar/baz/quux/baz"], ["/foo/bar/baz/", "quux/baz", "/foo/bar/baz/quux/baz"],
["/foo/bar/baz", "../../../../../../../../quux/baz", "/quux/baz"] ["/foo/bar/baz", "../../../../../../../../quux/baz", "/quux/baz"],
["/foo/bar/baz", "../../../../../../../quux/baz", "/quux/baz"]
].forEach(function (relativeTest) { ].forEach(function (relativeTest) {
var a = uri.resolve(relativeTest[0], relativeTest[1]), var a = uri.resolve(relativeTest[0], relativeTest[1]),
e = relativeTest[2]; e = relativeTest[2];

Loading…
Cancel
Save