Comparing version 0.7.9 to 0.10.0
{ | ||
"author": "Joyent (http://www.joyent.com)", | ||
"name": "url", | ||
"description": "Node.JS url module", | ||
"keywords": [ | ||
"ender", | ||
"pakmanager", | ||
"url" | ||
], | ||
"publishConfig": { | ||
"registry": "http://registry.npmjs.org" | ||
"description": "The core `url` packaged standalone for use with Browserify.", | ||
"version": "0.10.0", | ||
"dependencies": { | ||
"punycode": "1.2.4" | ||
}, | ||
"version": "0.7.9", | ||
"homepage": "http://nodejs.org/api/url.html", | ||
"devDependencies": { | ||
"assert": "1.1.1", | ||
"mocha": "1.18.2", | ||
"zuul": "1.6.3" | ||
}, | ||
"scripts": { | ||
"test": "mocha --ui qunit test.js && zuul -- test.js", | ||
"test-local": "zuul --local -- test.js" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/coolaj86/node.git" | ||
}, | ||
"main": "./url.js", | ||
"directories": { | ||
"lib": "." | ||
}, | ||
"engines": { | ||
"node": ">= 0.2.0", | ||
"ender": ">= 0.5.0" | ||
}, | ||
"dependencies": { | ||
"querystring": ">=0.1.0 <0.2.0", | ||
"punycode": ">=1.0.0 <1.1.0" | ||
}, | ||
"devDependencies": {} | ||
"url": "https://github.com/defunctzombie/node-url.git" | ||
} | ||
} |
504
url.js
@@ -1,5 +0,1 @@ | ||
/*jshint strict:true node:true es5:true onevar:true laxcomma:true laxbreak:true eqeqeq:true immed:true latedef:true*/ | ||
(function () { | ||
"use strict"; | ||
// Copyright Joyent, Inc. and other Node contributors. | ||
@@ -33,2 +29,19 @@ // | ||
exports.Url = Url; | ||
function Url() { | ||
this.protocol = null; | ||
this.slashes = null; | ||
this.auth = null; | ||
this.host = null; | ||
this.port = null; | ||
this.hostname = null; | ||
this.hash = null; | ||
this.search = null; | ||
this.query = null; | ||
this.pathname = null; | ||
this.path = null; | ||
this.href = null; | ||
} | ||
// Reference: RFC 3986, RFC 1808, RFC 2396 | ||
@@ -46,6 +59,6 @@ | ||
// RFC 2396: characters not allowed for various reasons. | ||
unwise = ['{', '}', '|', '\\', '^', '~', '`'].concat(delims), | ||
unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), | ||
// Allowed by RFCs, but cause of XSS attacks. Always escape these. | ||
autoEscape = ['\''].concat(delims), | ||
autoEscape = ['\''].concat(unwise), | ||
// Characters that are never ever allowed in a hostname. | ||
@@ -55,8 +68,7 @@ // Note that any invalid chars are also handled, but these | ||
// them. | ||
nonHostChars = ['%', '/', '?', ';', '#'] | ||
.concat(unwise).concat(autoEscape), | ||
nonAuthChars = ['/', '@', '?', '#'].concat(delims), | ||
nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), | ||
hostEndingChars = ['/', '?', '#'], | ||
hostnameMaxLen = 255, | ||
hostnamePartPattern = /^[a-zA-Z0-9][a-z0-9A-Z_-]{0,62}$/, | ||
hostnamePartStart = /^([a-zA-Z0-9][a-z0-9A-Z_-]{0,62})(.*)$/, | ||
hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, | ||
hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, | ||
// protocols that can allow "unsafe" and "unwise" chars. | ||
@@ -72,14 +84,2 @@ unsafeProtocol = { | ||
}, | ||
// protocols that always have a path component. | ||
pathedProtocol = { | ||
'http': true, | ||
'https': true, | ||
'ftp': true, | ||
'gopher': true, | ||
'file': true, | ||
'http:': true, | ||
'ftp:': true, | ||
'gopher:': true, | ||
'file:': true | ||
}, | ||
// protocols that always contain a // bit. | ||
@@ -101,10 +101,15 @@ slashedProtocol = { | ||
function urlParse(url, parseQueryString, slashesDenoteHost) { | ||
if (url && typeof(url) === 'object' && url.href) return url; | ||
if (url && isObject(url) && url instanceof Url) return url; | ||
if (typeof url !== 'string') { | ||
var u = new Url; | ||
u.parse(url, parseQueryString, slashesDenoteHost); | ||
return u; | ||
} | ||
Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { | ||
if (!isString(url)) { | ||
throw new TypeError("Parameter 'url' must be a string, not " + typeof url); | ||
} | ||
var out = {}, | ||
rest = url; | ||
var rest = url; | ||
@@ -119,3 +124,3 @@ // trim before proceeding. | ||
var lowerProto = proto.toLowerCase(); | ||
out.protocol = lowerProto; | ||
this.protocol = lowerProto; | ||
rest = rest.substr(proto.length); | ||
@@ -132,3 +137,3 @@ } | ||
rest = rest.substr(2); | ||
out.slashes = true; | ||
this.slashes = true; | ||
} | ||
@@ -139,68 +144,75 @@ } | ||
(slashes || (proto && !slashedProtocol[proto]))) { | ||
// there's a hostname. | ||
// the first instance of /, ?, ;, or # ends the host. | ||
// don't enforce full RFC correctness, just be unstupid about it. | ||
// | ||
// If there is an @ in the hostname, then non-host chars *are* allowed | ||
// to the left of the first @ sign, unless some non-auth character | ||
// to the left of the last @ sign, unless some host-ending character | ||
// comes *before* the @-sign. | ||
// URLs are obnoxious. | ||
var atSign = rest.indexOf('@'); | ||
if (atSign !== -1) { | ||
var auth = rest.slice(0, atSign); | ||
// | ||
// ex: | ||
// http://a@b@c/ => user:a@b host:c | ||
// http://a@b?@c => user:a host:c path:/?@c | ||
// there *may be* an auth | ||
var hasAuth = true; | ||
for (var i = 0, l = nonAuthChars.length; i < l; i++) { | ||
if (auth.indexOf(nonAuthChars[i]) !== -1) { | ||
// not a valid auth. Something like http://foo.com/bar@baz/ | ||
hasAuth = false; | ||
break; | ||
} | ||
} | ||
// v0.12 TODO(isaacs): This is not quite how Chrome does things. | ||
// Review our test case against browsers more comprehensively. | ||
if (hasAuth) { | ||
// pluck off the auth portion. | ||
out.auth = decodeURIComponent(auth); | ||
rest = rest.substr(atSign + 1); | ||
} | ||
// find the first instance of any hostEndingChars | ||
var hostEnd = -1; | ||
for (var i = 0; i < hostEndingChars.length; i++) { | ||
var hec = rest.indexOf(hostEndingChars[i]); | ||
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) | ||
hostEnd = hec; | ||
} | ||
var firstNonHost = -1; | ||
for (var i = 0, l = nonHostChars.length; i < l; i++) { | ||
var index = rest.indexOf(nonHostChars[i]); | ||
if (index !== -1 && | ||
(firstNonHost < 0 || index < firstNonHost)) firstNonHost = index; | ||
// at this point, either we have an explicit point where the | ||
// auth portion cannot go past, or the last @ char is the decider. | ||
var auth, atSign; | ||
if (hostEnd === -1) { | ||
// atSign can be anywhere. | ||
atSign = rest.lastIndexOf('@'); | ||
} else { | ||
// atSign must be in auth portion. | ||
// http://a@b/c@d => host:b auth:a path:/c@d | ||
atSign = rest.lastIndexOf('@', hostEnd); | ||
} | ||
if (firstNonHost !== -1) { | ||
out.host = rest.substr(0, firstNonHost); | ||
rest = rest.substr(firstNonHost); | ||
} else { | ||
out.host = rest; | ||
rest = ''; | ||
// Now we have a portion which is definitely the auth. | ||
// Pull that off. | ||
if (atSign !== -1) { | ||
auth = rest.slice(0, atSign); | ||
rest = rest.slice(atSign + 1); | ||
this.auth = decodeURIComponent(auth); | ||
} | ||
// pull out port. | ||
var p = parseHost(out.host); | ||
var keys = Object.keys(p); | ||
for (var i = 0, l = keys.length; i < l; i++) { | ||
var key = keys[i]; | ||
out[key] = p[key]; | ||
// the host is the remaining to the left of the first non-host char | ||
hostEnd = -1; | ||
for (var i = 0; i < nonHostChars.length; i++) { | ||
var hec = rest.indexOf(nonHostChars[i]); | ||
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) | ||
hostEnd = hec; | ||
} | ||
// if we still have not hit it, then the entire thing is a host. | ||
if (hostEnd === -1) | ||
hostEnd = rest.length; | ||
this.host = rest.slice(0, hostEnd); | ||
rest = rest.slice(hostEnd); | ||
// pull out port. | ||
this.parseHost(); | ||
// we've indicated that there is a hostname, | ||
// so even if it's empty, it has to be present. | ||
out.hostname = out.hostname || ''; | ||
this.hostname = this.hostname || ''; | ||
// if hostname begins with [ and ends with ] | ||
// assume that it's an IPv6 address. | ||
var ipv6Hostname = out.hostname[0] === '[' && | ||
out.hostname[out.hostname.length - 1] === ']'; | ||
var ipv6Hostname = this.hostname[0] === '[' && | ||
this.hostname[this.hostname.length - 1] === ']'; | ||
// validate a little. | ||
if (out.hostname.length > hostnameMaxLen) { | ||
out.hostname = ''; | ||
} else if (!ipv6Hostname) { | ||
var hostparts = out.hostname.split(/\./); | ||
if (!ipv6Hostname) { | ||
var hostparts = this.hostname.split(/\./); | ||
for (var i = 0, l = hostparts.length; i < l; i++) { | ||
@@ -233,3 +245,3 @@ var part = hostparts[i]; | ||
} | ||
out.hostname = validParts.join('.'); | ||
this.hostname = validParts.join('.'); | ||
break; | ||
@@ -241,4 +253,8 @@ } | ||
// hostnames are always lower case. | ||
out.hostname = out.hostname.toLowerCase(); | ||
if (this.hostname.length > hostnameMaxLen) { | ||
this.hostname = ''; | ||
} else { | ||
// hostnames are always lower case. | ||
this.hostname = this.hostname.toLowerCase(); | ||
} | ||
@@ -250,3 +266,3 @@ if (!ipv6Hostname) { | ||
// you call it with a domain that already is in ASCII. | ||
var domainArray = out.hostname.split('.'); | ||
var domainArray = this.hostname.split('.'); | ||
var newOut = []; | ||
@@ -258,12 +274,14 @@ for (var i = 0; i < domainArray.length; ++i) { | ||
} | ||
out.hostname = newOut.join('.'); | ||
this.hostname = newOut.join('.'); | ||
} | ||
out.host = (out.hostname || '') + | ||
((out.port) ? ':' + out.port : ''); | ||
out.href += out.host; | ||
var p = this.port ? ':' + this.port : ''; | ||
var h = this.hostname || ''; | ||
this.host = h + p; | ||
this.href += this.host; | ||
// strip [ and ] from the hostname | ||
// the host field still retains them, though | ||
if (ipv6Hostname) { | ||
out.hostname = out.hostname.substr(1, out.hostname.length - 2); | ||
this.hostname = this.hostname.substr(1, this.hostname.length - 2); | ||
if (rest[0] !== '/') { | ||
@@ -297,3 +315,3 @@ rest = '/' + rest; | ||
// got a fragment string. | ||
out.hash = rest.substr(hash); | ||
this.hash = rest.substr(hash); | ||
rest = rest.slice(0, hash); | ||
@@ -303,6 +321,6 @@ } | ||
if (qm !== -1) { | ||
out.search = rest.substr(qm); | ||
out.query = rest.substr(qm + 1); | ||
this.search = rest.substr(qm); | ||
this.query = rest.substr(qm + 1); | ||
if (parseQueryString) { | ||
out.query = querystring.parse(out.query); | ||
this.query = querystring.parse(this.query); | ||
} | ||
@@ -312,21 +330,22 @@ rest = rest.slice(0, qm); | ||
// no query string, but parseQueryString still requested | ||
out.search = ''; | ||
out.query = {}; | ||
this.search = ''; | ||
this.query = {}; | ||
} | ||
if (rest) out.pathname = rest; | ||
if (slashedProtocol[proto] && | ||
out.hostname && !out.pathname) { | ||
out.pathname = '/'; | ||
if (rest) this.pathname = rest; | ||
if (slashedProtocol[lowerProto] && | ||
this.hostname && !this.pathname) { | ||
this.pathname = '/'; | ||
} | ||
//to support http.request | ||
if (out.pathname || out.search) { | ||
out.path = (out.pathname ? out.pathname : '') + | ||
(out.search ? out.search : ''); | ||
if (this.pathname || this.search) { | ||
var p = this.pathname || ''; | ||
var s = this.search || ''; | ||
this.path = p + s; | ||
} | ||
// finally, reconstruct the href based on what has been validated. | ||
out.href = urlFormat(out); | ||
return out; | ||
} | ||
this.href = this.format(); | ||
return this; | ||
}; | ||
@@ -339,5 +358,9 @@ // format a parsed object into a url string | ||
// to clean up potentially wonky urls. | ||
if (typeof(obj) === 'string') obj = urlParse(obj); | ||
if (isString(obj)) obj = urlParse(obj); | ||
if (!(obj instanceof Url)) return Url.prototype.format.call(obj); | ||
return obj.format(); | ||
} | ||
var auth = obj.auth || ''; | ||
Url.prototype.format = function() { | ||
var auth = this.auth || ''; | ||
if (auth) { | ||
@@ -349,25 +372,26 @@ auth = encodeURIComponent(auth); | ||
var protocol = obj.protocol || '', | ||
pathname = obj.pathname || '', | ||
hash = obj.hash || '', | ||
var protocol = this.protocol || '', | ||
pathname = this.pathname || '', | ||
hash = this.hash || '', | ||
host = false, | ||
query = ''; | ||
if (obj.host !== undefined) { | ||
host = auth + obj.host; | ||
} else if (obj.hostname !== undefined) { | ||
host = auth + (obj.hostname.indexOf(':') === -1 ? | ||
obj.hostname : | ||
'[' + obj.hostname + ']'); | ||
if (obj.port) { | ||
host += ':' + obj.port; | ||
if (this.host) { | ||
host = auth + this.host; | ||
} else if (this.hostname) { | ||
host = auth + (this.hostname.indexOf(':') === -1 ? | ||
this.hostname : | ||
'[' + this.hostname + ']'); | ||
if (this.port) { | ||
host += ':' + this.port; | ||
} | ||
} | ||
if (obj.query && typeof obj.query === 'object' && | ||
Object.keys(obj.query).length) { | ||
query = querystring.stringify(obj.query); | ||
if (this.query && | ||
isObject(this.query) && | ||
Object.keys(this.query).length) { | ||
query = querystring.stringify(this.query); | ||
} | ||
var search = obj.search || (query && ('?' + query)) || ''; | ||
var search = this.search || (query && ('?' + query)) || ''; | ||
@@ -378,3 +402,3 @@ if (protocol && protocol.substr(-1) !== ':') protocol += ':'; | ||
// unless they had them to begin with. | ||
if (obj.slashes || | ||
if (this.slashes || | ||
(!protocol || slashedProtocol[protocol]) && host !== false) { | ||
@@ -390,21 +414,43 @@ host = '//' + (host || ''); | ||
pathname = pathname.replace(/[?#]/g, function(match) { | ||
return encodeURIComponent(match); | ||
}); | ||
search = search.replace('#', '%23'); | ||
return protocol + host + pathname + search + hash; | ||
} | ||
}; | ||
function urlResolve(source, relative) { | ||
return urlFormat(urlResolveObject(source, relative)); | ||
return urlParse(source, false, true).resolve(relative); | ||
} | ||
Url.prototype.resolve = function(relative) { | ||
return this.resolveObject(urlParse(relative, false, true)).format(); | ||
}; | ||
function urlResolveObject(source, relative) { | ||
if (!source) return relative; | ||
return urlParse(source, false, true).resolveObject(relative); | ||
} | ||
source = urlParse(urlFormat(source), false, true); | ||
relative = urlParse(urlFormat(relative), false, true); | ||
Url.prototype.resolveObject = function(relative) { | ||
if (isString(relative)) { | ||
var rel = new Url(); | ||
rel.parse(relative, false, true); | ||
relative = rel; | ||
} | ||
var result = new Url(); | ||
Object.keys(this).forEach(function(k) { | ||
result[k] = this[k]; | ||
}, this); | ||
// hash is always overridden, no matter what. | ||
source.hash = relative.hash; | ||
// even href="" will remove it. | ||
result.hash = relative.hash; | ||
// if the relative url is empty, then there's nothing left to do here. | ||
if (relative.href === '') { | ||
source.href = urlFormat(source); | ||
return source; | ||
result.href = result.format(); | ||
return result; | ||
} | ||
@@ -414,13 +460,19 @@ | ||
if (relative.slashes && !relative.protocol) { | ||
relative.protocol = source.protocol; | ||
// take everything except the protocol from relative | ||
Object.keys(relative).forEach(function(k) { | ||
if (k !== 'protocol') | ||
result[k] = relative[k]; | ||
}); | ||
//urlParse appends trailing / to urls like http://www.example.com | ||
if (slashedProtocol[relative.protocol] && | ||
relative.hostname && !relative.pathname) { | ||
relative.path = relative.pathname = '/'; | ||
if (slashedProtocol[result.protocol] && | ||
result.hostname && !result.pathname) { | ||
result.path = result.pathname = '/'; | ||
} | ||
relative.href = urlFormat(relative); | ||
return relative; | ||
result.href = result.format(); | ||
return result; | ||
} | ||
if (relative.protocol && relative.protocol !== source.protocol) { | ||
if (relative.protocol && relative.protocol !== result.protocol) { | ||
// if it's a known url protocol, then changing | ||
@@ -435,6 +487,10 @@ // the protocol does weird things | ||
if (!slashedProtocol[relative.protocol]) { | ||
relative.href = urlFormat(relative); | ||
return relative; | ||
Object.keys(relative).forEach(function(k) { | ||
result[k] = relative[k]; | ||
}); | ||
result.href = result.format(); | ||
return result; | ||
} | ||
source.protocol = relative.protocol; | ||
result.protocol = relative.protocol; | ||
if (!relative.host && !hostlessProtocol[relative.protocol]) { | ||
@@ -447,33 +503,34 @@ var relPath = (relative.pathname || '').split('/'); | ||
if (relPath.length < 2) relPath.unshift(''); | ||
relative.pathname = relPath.join('/'); | ||
result.pathname = relPath.join('/'); | ||
} else { | ||
result.pathname = relative.pathname; | ||
} | ||
source.pathname = relative.pathname; | ||
source.search = relative.search; | ||
source.query = relative.query; | ||
source.host = relative.host || ''; | ||
source.auth = relative.auth; | ||
source.hostname = relative.hostname || relative.host; | ||
source.port = relative.port; | ||
//to support http.request | ||
if (source.pathname !== undefined || source.search !== undefined) { | ||
source.path = (source.pathname ? source.pathname : '') + | ||
(source.search ? source.search : ''); | ||
result.search = relative.search; | ||
result.query = relative.query; | ||
result.host = relative.host || ''; | ||
result.auth = relative.auth; | ||
result.hostname = relative.hostname || relative.host; | ||
result.port = relative.port; | ||
// to support http.request | ||
if (result.pathname || result.search) { | ||
var p = result.pathname || ''; | ||
var s = result.search || ''; | ||
result.path = p + s; | ||
} | ||
source.slashes = source.slashes || relative.slashes; | ||
source.href = urlFormat(source); | ||
return source; | ||
result.slashes = result.slashes || relative.slashes; | ||
result.href = result.format(); | ||
return result; | ||
} | ||
var isSourceAbs = (source.pathname && source.pathname.charAt(0) === '/'), | ||
var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), | ||
isRelAbs = ( | ||
relative.host !== undefined || | ||
relative.host || | ||
relative.pathname && relative.pathname.charAt(0) === '/' | ||
), | ||
mustEndAbs = (isRelAbs || isSourceAbs || | ||
(source.host && relative.pathname)), | ||
(result.host && relative.pathname)), | ||
removeAllDots = mustEndAbs, | ||
srcPath = source.pathname && source.pathname.split('/') || [], | ||
srcPath = result.pathname && result.pathname.split('/') || [], | ||
relPath = relative.pathname && relative.pathname.split('/') || [], | ||
psychotic = source.protocol && | ||
!slashedProtocol[source.protocol]; | ||
psychotic = result.protocol && !slashedProtocol[result.protocol]; | ||
@@ -483,16 +540,15 @@ // if the url is a non-slashed url, then relative | ||
// to crawl up to the hostname, as well. This is strange. | ||
// source.protocol has already been set by now. | ||
// result.protocol has already been set by now. | ||
// Later on, put the first path part into the host field. | ||
if (psychotic) { | ||
delete source.hostname; | ||
delete source.port; | ||
if (source.host) { | ||
if (srcPath[0] === '') srcPath[0] = source.host; | ||
else srcPath.unshift(source.host); | ||
result.hostname = ''; | ||
result.port = null; | ||
if (result.host) { | ||
if (srcPath[0] === '') srcPath[0] = result.host; | ||
else srcPath.unshift(result.host); | ||
} | ||
delete source.host; | ||
result.host = ''; | ||
if (relative.protocol) { | ||
delete relative.hostname; | ||
delete relative.port; | ||
relative.hostname = null; | ||
relative.port = null; | ||
if (relative.host) { | ||
@@ -502,3 +558,3 @@ if (relPath[0] === '') relPath[0] = relative.host; | ||
} | ||
delete relative.host; | ||
relative.host = null; | ||
} | ||
@@ -510,8 +566,8 @@ mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); | ||
// it's absolute. | ||
source.host = (relative.host || relative.host === '') ? | ||
relative.host : source.host; | ||
source.hostname = (relative.hostname || relative.hostname === '') ? | ||
relative.hostname : source.hostname; | ||
source.search = relative.search; | ||
source.query = relative.query; | ||
result.host = (relative.host || relative.host === '') ? | ||
relative.host : result.host; | ||
result.hostname = (relative.hostname || relative.hostname === '') ? | ||
relative.hostname : result.hostname; | ||
result.search = relative.search; | ||
result.query = relative.query; | ||
srcPath = relPath; | ||
@@ -525,5 +581,5 @@ // fall through to the dot-handling below. | ||
srcPath = srcPath.concat(relPath); | ||
source.search = relative.search; | ||
source.query = relative.query; | ||
} else if ('search' in relative) { | ||
result.search = relative.search; | ||
result.query = relative.query; | ||
} else if (!isNullOrUndefined(relative.search)) { | ||
// just pull out the search. | ||
@@ -533,36 +589,38 @@ // like href='?foo'. | ||
if (psychotic) { | ||
source.hostname = source.host = srcPath.shift(); | ||
result.hostname = result.host = srcPath.shift(); | ||
//occationaly the auth can get stuck only in host | ||
//this especialy happens in cases like | ||
//url.resolveObject('mailto:local1@domain1', 'local2@domain2') | ||
var authInHost = source.host && source.host.indexOf('@') > 0 ? | ||
source.host.split('@') : false; | ||
var authInHost = result.host && result.host.indexOf('@') > 0 ? | ||
result.host.split('@') : false; | ||
if (authInHost) { | ||
source.auth = authInHost.shift(); | ||
source.host = source.hostname = authInHost.shift(); | ||
result.auth = authInHost.shift(); | ||
result.host = result.hostname = authInHost.shift(); | ||
} | ||
} | ||
source.search = relative.search; | ||
source.query = relative.query; | ||
result.search = relative.search; | ||
result.query = relative.query; | ||
//to support http.request | ||
if (source.pathname !== undefined || source.search !== undefined) { | ||
source.path = (source.pathname ? source.pathname : '') + | ||
(source.search ? source.search : ''); | ||
if (!isNull(result.pathname) || !isNull(result.search)) { | ||
result.path = (result.pathname ? result.pathname : '') + | ||
(result.search ? result.search : ''); | ||
} | ||
source.href = urlFormat(source); | ||
return source; | ||
result.href = result.format(); | ||
return result; | ||
} | ||
if (!srcPath.length) { | ||
// no path at all. easy. | ||
// we've already handled the other stuff above. | ||
delete source.pathname; | ||
result.pathname = null; | ||
//to support http.request | ||
if (!source.search) { | ||
source.path = '/' + source.search; | ||
if (result.search) { | ||
result.path = '/' + result.search; | ||
} else { | ||
delete source.path; | ||
result.path = null; | ||
} | ||
source.href = urlFormat(source); | ||
return source; | ||
result.href = result.format(); | ||
return result; | ||
} | ||
// if a url ENDs in . or .., then it must get a trailing slash. | ||
@@ -573,3 +631,3 @@ // however, if it ends in anything else non-slashy, | ||
var hasTrailingSlash = ( | ||
(source.host || relative.host) && (last === '.' || last === '..') || | ||
(result.host || relative.host) && (last === '.' || last === '..') || | ||
last === ''); | ||
@@ -614,3 +672,3 @@ | ||
if (psychotic) { | ||
source.hostname = source.host = isAbsolute ? '' : | ||
result.hostname = result.host = isAbsolute ? '' : | ||
srcPath.length ? srcPath.shift() : ''; | ||
@@ -620,11 +678,11 @@ //occationaly the auth can get stuck only in host | ||
//url.resolveObject('mailto:local1@domain1', 'local2@domain2') | ||
var authInHost = source.host && source.host.indexOf('@') > 0 ? | ||
source.host.split('@') : false; | ||
var authInHost = result.host && result.host.indexOf('@') > 0 ? | ||
result.host.split('@') : false; | ||
if (authInHost) { | ||
source.auth = authInHost.shift(); | ||
source.host = source.hostname = authInHost.shift(); | ||
result.auth = authInHost.shift(); | ||
result.host = result.hostname = authInHost.shift(); | ||
} | ||
} | ||
mustEndAbs = mustEndAbs || (source.host && srcPath.length); | ||
mustEndAbs = mustEndAbs || (result.host && srcPath.length); | ||
@@ -635,16 +693,22 @@ if (mustEndAbs && !isAbsolute) { | ||
source.pathname = srcPath.join('/'); | ||
if (!srcPath.length) { | ||
result.pathname = null; | ||
result.path = null; | ||
} else { | ||
result.pathname = srcPath.join('/'); | ||
} | ||
//to support request.http | ||
if (source.pathname !== undefined || source.search !== undefined) { | ||
source.path = (source.pathname ? source.pathname : '') + | ||
(source.search ? source.search : ''); | ||
if (!isNull(result.pathname) || !isNull(result.search)) { | ||
result.path = (result.pathname ? result.pathname : '') + | ||
(result.search ? result.search : ''); | ||
} | ||
source.auth = relative.auth || source.auth; | ||
source.slashes = source.slashes || relative.slashes; | ||
source.href = urlFormat(source); | ||
return source; | ||
} | ||
result.auth = relative.auth || result.auth; | ||
result.slashes = result.slashes || relative.slashes; | ||
result.href = result.format(); | ||
return result; | ||
}; | ||
function parseHost(host) { | ||
var out = {}; | ||
Url.prototype.parseHost = function() { | ||
var host = this.host; | ||
var port = portPattern.exec(host); | ||
@@ -654,10 +718,22 @@ if (port) { | ||
if (port !== ':') { | ||
out.port = port.substr(1); | ||
this.port = port.substr(1); | ||
} | ||
host = host.substr(0, host.length - port.length); | ||
} | ||
if (host) out.hostname = host; | ||
return out; | ||
if (host) this.hostname = host; | ||
}; | ||
function isString(arg) { | ||
return typeof arg === "string"; | ||
} | ||
}()); | ||
function isObject(arg) { | ||
return typeof arg === 'object' && arg !== null; | ||
} | ||
function isNull(arg) { | ||
return arg === null; | ||
} | ||
function isNullOrUndefined(arg) { | ||
return arg == null; | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
Non-existent author
Supply chain riskThe package was published by an npm account that no longer exists.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
70628
1
7
1967
0
109
0
3
2
2
2
+ Addedpunycode@1.2.4(transitive)
- Removedquerystring@>=0.1.0 <0.2.0
- Removedpunycode@1.0.0(transitive)
- Removedquerystring@0.1.0(transitive)
Updatedpunycode@1.2.4