{“ast”:null,“code”:“// Copyright Joyent, Inc. and other Node contributors.n//n// Permission is hereby granted, free of charge, to any person obtaining an// copy of this software and associated documentation files (then// "Software"), to deal in the Software without restriction, includingn// without limitation the rights to use, copy, modify, merge, publish,n// distribute, sublicense, and/or sell copies of the Software, and to permitn// persons to whom the Software is furnished to do so, subject to then// following conditions:n//n// The above copyright notice and this permission notice shall be includedn// in all copies or substantial portions of the Software.n//n// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESSn// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OFn// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. INn// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT ORn// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THEn// USE OR OTHER DEALINGS IN THE SOFTWARE.n'use strict';nnfunction _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }nnvar punycode = require('punycode');nnvar util = require('./util');nnexports.parse = urlParse;nexports.resolve = urlResolve;nexports.resolveObject = urlResolveObject;nexports.format = urlFormat;nexports.Url = Url;nnfunction Url() {n this.protocol = null;n this.slashes = null;n this.auth = null;n this.host = null;n this.port = null;n this.hostname = null;n this.hash = null;n this.search = null;n this.query = null;n this.pathname = null;n this.path = null;n this.href = null;n} // Reference: RFC 3986, RFC 1808, RFC 2396n// define these here so at least they only have to ben// compiled once on the first module load.nnnvar protocolPattern = /^([a-z0-9.-]
:)/i,n portPattern = /:[0-9]*$/,n // Special case for a simple path URLnsimplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?*)?$/,n // RFC 2396: characters reserved for delimiting URLs.n// We actually just auto-escape these.ndelims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],n // RFC 2396: characters not allowed for various reasons.nunwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),n // Allowed by RFCs, but cause of XSS attacks. Always escape these.nautoEscape = ['\''].concat(unwise),n // Characters that are never ever allowed in a hostname.n// Note that any invalid chars are also handled, but thesen// are the ones that are expected to be seen, so we fast-pathn// them.nnonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),n hostEndingChars = ['/', '?', '#'],n hostnameMaxLen = 255,n hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,n hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,n // protocols that can allow "unsafe" and "unwise" chars.nunsafeProtocol = {n 'javascript': true,n 'javascript:': truen},n // protocols that never have a hostname.nhostlessProtocol = {n 'javascript': true,n 'javascript:': truen},n // protocols that always contain a // bit.nslashedProtocol = {n 'http': true,n 'https': true,n 'ftp': true,n 'gopher': true,n 'file': true,n 'http:': true,n 'https:': true,n 'ftp:': true,n 'gopher:': true,n 'file:': truen},n querystring = require('querystring');nnfunction urlParse(url, parseQueryString, slashesDenoteHost) {n if (url && util.isObject(url) && url instanceof Url) return url;n var u = new Url();n u.parse(url, parseQueryString, slashesDenoteHost);n return u;n}nnUrl.prototype.parse = function (url, parseQueryString, slashesDenoteHost) {n if (!util.isString(url)) {n throw new TypeError("Parameter 'url' must be a string, not " + _typeof(url));n } // Copy
chrome, IE, opera backslash-handling behavior.n // Back slashes before the query string get converted to forward slashesn // See: code.google.com/p/chromium/issues/detail?id=25916nnn var queryIndex = url.indexOf('?'),n splitter = queryIndex !== -1 && queryIndex < url.indexOf('#') ? '?' : '#',n uSplit = url.split(splitter),n slashRegex = /\\/g;n uSplit = uSplit.replace(slashRegex, '/');n url = uSplit.join(splitter);n var rest = url; // trim before proceeding.n // This is to support parse stuff like " foo.com \n"nn rest = rest.trim();nn if (!slashesDenoteHost && url.split('#').length === 1) {n // Try fast path regexpn var simplePath = simplePathPattern.exec(rest);nn if (simplePath) {n this.path = rest;n this.href = rest;n this.pathname = simplePath;nn if (simplePath) {n this.search = simplePath;nn if (parseQueryString) {n this.query = querystring.parse(this.search.substr(1));n } else {n this.query = this.search.substr(1);n }n } else if (parseQueryString) {n this.search = '';n this.query = {};n }nn return this;n }n }nn var proto = protocolPattern.exec(rest);nn if (proto) {n proto = proto;n var lowerProto = proto.toLowerCase();n this.protocol = lowerProto;n rest = rest.substr(proto.length);n } // figure out if it's got a hostn // user@server is always interpreted as a hostname, and urln // resolution will treat //foo/bar as host=foo,path=bar because that'sn // how the browser resolves relative URLs.nnn if (slashesDenoteHost || proto || \/] at rest.match(/^\/\/[^
+@[^@\/]+/)) {n var slashes = rest.substr(0, 2) === '//';nn if (slashes && !(proto && hostlessProtocol)) {n rest = rest.substr(2);n this.slashes = true;n }n }nn if (!hostlessProtocol && (slashes || proto && !slashedProtocol)) {n // there's a hostname.n // the first instance of /, ?, ;, or # ends the host.n //n // If there is an @ in the hostname, then non-host chars are allowedn // to the left of the last @ sign, unless some host-ending charactern // comes before the @-sign.n // URLs are obnoxious.n //n // ex:n // a@b@c/ => user:a@b host:cn // a@b?@c => user:a host:c path:/?@cn // v0.12 TODO(isaacs): This is not quite how Chrome does things.n // Review our test case against browsers more comprehensively.n // find the first instance of any hostEndingCharsn var hostEnd = -1;nn for (var i = 0; i < hostEndingChars.length; i++) {n var hec = rest.indexOf(hostEndingChars);n if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) hostEnd = hec;n } // at this point, either we have an explicit point where then // auth portion cannot go past, or the last @ char is the decider.nnn var auth, atSign;nn if (hostEnd === -1) {n // atSign can be anywhere.n atSign = rest.lastIndexOf('@');n } else {n // atSign must be in auth portion.n // a@b/c@d => host:b auth:a path:/c@dn atSign = rest.lastIndexOf('@', hostEnd);n } // Now we have a portion which is definitely the auth.n // Pull that off.nnn if (atSign !== -1) {n auth = rest.slice(0, atSign);n rest = rest.slice(atSign + 1);n this.auth = decodeURIComponent(auth);n } // the host is the remaining to the left of the first non-host charnnn hostEnd = -1;nn for (var i = 0; i < nonHostChars.length; i++) {n var hec = rest.indexOf(nonHostChars);n if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) hostEnd = hec;n } // if we still have not hit it, then the entire thing is a host.nnn if (hostEnd === -1) hostEnd = rest.length;n this.host = rest.slice(0, hostEnd);n rest = rest.slice(hostEnd); // pull out port.nn this.parseHost(); // we've indicated that there is a hostname,n // so even if it's empty, it has to be present.nn this.hostname = this.hostname || ''; // if hostname begins with [ and ends with ]n // assume that it's an IPv6 address.nn var ipv6Hostname = this.hostname === '[' && this.hostname[this.hostname.length - 1] === ']'; // validate a little.nn if (!ipv6Hostname) {n var hostparts = this.hostname.split(/\./);nn for (var i = 0, l = hostparts.length; i < l; i++) {n var part = hostparts;n if (!part) continue;nn if (!part.match(hostnamePartPattern)) {n var newpart = '';nn for (var j = 0, k = part.length; j < k; j++) {n if (part.charCodeAt(j) > 127) {n // we replace non-ASCII char with a temporary placeholdern // we need this to make sure size of hostname is notn // broken by replacing non-ASCII by nothingn newpart += 'x';n } else {n newpart += part;n }n } // we test again with ASCII char onlynnn if (!newpart.match(hostnamePartPattern)) {n var validParts = hostparts.slice(0, i);n var notHost = hostparts.slice(i + 1);n var bit = part.match(hostnamePartStart);nn if (bit) {n validParts.push(bit);n notHost.unshift(bit);n }nn if (notHost.length) {n rest = '/' + notHost.join('.') + rest;n }nn this.hostname = validParts.join('.');n break;n }n }n }n }nn if (this.hostname.length > hostnameMaxLen) {n this.hostname = '';n } else {n // hostnames are always lower case.n this.hostname = this.hostname.toLowerCase();n }nn if (!ipv6Hostname) {n // IDNA Support: Returns a punycoded representation of "domain".n // It only converts parts of the domain name thatn // have non-ASCII characters, i.e. it doesn't matter ifn // you call it with a domain that already is ASCII-only.n this.hostname = punycode.toASCII(this.hostname);n }nn var p = this.port ? ':' + this.port : '';n var h = this.hostname || '';n this.host = h + p;n this.href += this.host; // strip [ and ] from the hostnamen // the host field still retains them, thoughnn if (ipv6Hostname) {n this.hostname = this.hostname.substr(1, this.hostname.length - 2);nn if (rest !== '/') {n rest = '/' + rest;n }n }n } // now rest is set to the post-host stuff.n // chop off any delim chars.nnn if (!unsafeProtocol) {n // First, make 100% sure that any "autoEscape" chars getn // escaped, even if encodeURIComponent doesn't think theyn // need to be.n for (var i = 0, l = autoEscape.length; i < l; i++) {n var ae = autoEscape;n if (rest.indexOf(ae) === -1) continue;n var esc = encodeURIComponent(ae);nn if (esc === ae) {n esc = escape(ae);n }nn rest = rest.split(ae).join(esc);n }n } // chop off from the tail first.nnn var hash = rest.indexOf('#');nn if (hash !== -1) {n // got a fragment string.n this.hash = rest.substr(hash);n rest = rest.slice(0, hash);n }nn var qm = rest.indexOf('?');nn if (qm !== -1) {n this.search = rest.substr(qm);n this.query = rest.substr(qm + 1);nn if (parseQueryString) {n this.query = querystring.parse(this.query);n }nn rest = rest.slice(0, qm);n } else if (parseQueryString) {n // no query string, but parseQueryString still requestedn this.search = '';n this.query = {};n }nn if (rest) this.pathname = rest;nn if (slashedProtocol && this.hostname && !this.pathname) {n this.pathname = '/';n } //to support http.requestnnn if (this.pathname || this.search) {n var p = this.pathname || '';n var s = this.search || '';n this.path = p + s;n } // finally, reconstruct the href based on what has been validated.nnn this.href = this.format();n return this;n}; // format a parsed object into a url stringnnnfunction urlFormat(obj) {n // ensure it's an object, and not a string url.n // If it's an obj, this is a no-op.n // this way, you can call url_format() on stringsn // to clean up potentially wonky urls.n if (util.isString(obj)) obj = urlParse(obj);n if (!(obj instanceof Url)) return Url.prototype.format.call(obj);n return obj.format();n}nnUrl.prototype.format = function () {n var auth = this.auth || '';nn if (auth) {n auth = encodeURIComponent(auth);n auth = auth.replace(/%3A/i, ':');n auth += '@';n }nn var protocol = this.protocol || '',n pathname = this.pathname || '',n hash = this.hash || '',n host = false,n query = '';nn if (this.host) {n host = auth + this.host;n } else if (this.hostname) {n host = auth + (this.hostname.indexOf(':') === -1 ? this.hostname : '[' + this.hostname + ']');nn if (this.port) {n host += ':' + this.port;n }n }nn if (this.query && util.isObject(this.query) && Object.keys(this.query).length) {n query = querystring.stringify(this.query);n }nn var search = this.search || query && '?' + query || '';n if (protocol && protocol.substr(-1) !== ':') protocol += ':'; // only the slashedProtocols get the //. Not mailto:, xmpp:, etc.n // unless they had them to begin with.nn if (this.slashes || (!protocol || slashedProtocol) && host !== false) {n host = '//' + (host || '');n if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;n } else if (!host) {n host = '';n }nn if (hash && hash.charAt(0) !== '#') hash = '#' + hash;n if (search && search.charAt(0) !== '?') search = '?' + search;n pathname = pathname.replace(//g, function (match) {n return encodeURIComponent(match);n });n search = search.replace('#', '%23');n return protocol + host + pathname + search + hash;n};nnfunction urlResolve(source, relative) {n return urlParse(source, false, true).resolve(relative);n}nnUrl.prototype.resolve = function (relative) {n return this.resolveObject(urlParse(relative, false, true)).format();n};nnfunction urlResolveObject(source, relative) {n if (!source) return relative;n return urlParse(source, false, true).resolveObject(relative);n}nnUrl.prototype.resolveObject = function (relative) {n if (util.isString(relative)) {n var rel = new Url();n rel.parse(relative, false, true);n relative = rel;n }nn var result = new Url();n var tkeys = Object.keys(this);nn for (var tk = 0; tk < tkeys.length; tk++) {n var tkey = tkeys;n result = this;n } // hash is always overridden, no matter what.n // even href="" will remove it.nnn result.hash = relative.hash; // if the relative url is empty, then there's nothing left to do here.nn if (relative.href === '') {n result.href = result.format();n return result;n } // hrefs like //foo/bar always cut to the protocol.nnn if (relative.slashes && !relative.protocol) {n // take everything except the protocol from relativen var rkeys = Object.keys(relative);nn for (var rk = 0; rk < rkeys.length; rk++) {n var rkey = rkeys;n if (rkey !== 'protocol') result = relative;n } //urlParse appends trailing / to urls like www.example.comnnn if (slashedProtocol && result.hostname && !result.pathname) {n result.path = result.pathname = '/';n }nn result.href = result.format();n return result;n }nn if (relative.protocol && relative.protocol !== result.protocol) {n // if it's a known url protocol, then changingn // the protocol does weird thingsn // first, if it's not file:, then we MUST have a host,n // and if there was a pathn // to begin with, then we MUST have a path.n // if it is file:, then the host is dropped,n // because that's known to be hostless.n // anything else is assumed to be absolute.n if (!slashedProtocol) {n var keys = Object.keys(relative);nn for (var v = 0; v < keys.length; v++) {n var k = keys;n result = relative;n }nn result.href = result.format();n return result;n }nn result.protocol = relative.protocol;nn if (!relative.host && !hostlessProtocol) {n var relPath = (relative.pathname || '').split('/');nn while (relPath.length && !(relative.host = relPath.shift())) {n ;n }nn if (!relative.host) relative.host = '';n if (!relative.hostname) relative.hostname = '';n if (relPath !== '') relPath.unshift('');n if (relPath.length < 2) relPath.unshift('');n result.pathname = relPath.join('/');n } else {n result.pathname = relative.pathname;n }nn result.search = relative.search;n result.query = relative.query;n result.host = relative.host || '';n result.auth = relative.auth;n result.hostname = relative.hostname || relative.host;n result.port = relative.port; // to support http.requestnn if (result.pathname || result.search) {n var p = result.pathname || '';n var s = result.search || '';n result.path = p + s;n }nn result.slashes = result.slashes || relative.slashes;n result.href = result.format();n return result;n }nn var isSourceAbs = result.pathname && result.pathname.charAt(0) === '/',n isRelAbs = relative.host || relative.pathname && relative.pathname.charAt(0) === '/',n mustEndAbs = isRelAbs || isSourceAbs || result.host && relative.pathname,n removeAllDots = mustEndAbs,n srcPath = result.pathname && result.pathname.split('/') || [],n relPath = relative.pathname && relative.pathname.split('/') || [],n psychotic = result.protocol && !slashedProtocol; // if the url is a non-slashed url, then relativen // links like ../.. should be ablen // to crawl up to the hostname, as well. This is strange.n // result.protocol has already been set by now.n // Later on, put the first path part into the host field.nn if (psychotic) {n result.hostname = '';n result.port = null;nn if (result.host) {n if (srcPath === '') srcPath = result.host;else srcPath.unshift(result.host);n }nn result.host = '';nn if (relative.protocol) {n relative.hostname = null;n relative.port = null;nn if (relative.host) {n if (relPath === '') relPath = relative.host;else relPath.unshift(relative.host);n }nn relative.host = null;n }nn mustEndAbs = mustEndAbs && (relPath === '' || srcPath === '');n }nn if (isRelAbs) {n // it's absolute.n result.host = relative.host || relative.host === '' ? relative.host : result.host;n result.hostname = relative.hostname || relative.hostname === '' ? relative.hostname : result.hostname;n result.search = relative.search;n result.query = relative.query;n srcPath = relPath; // fall through to the dot-handling below.n } else if (relPath.length) {n // it's relativen // throw away the existing file, and take the new path instead.n if (!srcPath) srcPath = [];n srcPath.pop();n srcPath = srcPath.concat(relPath);n result.search = relative.search;n result.query = relative.query;n } else if (!util.isNullOrUndefined(relative.search)) {n // just pull out the search.n // like href='?foo'.n // Put this after the other two cases because it simplifies the booleansn if (psychotic) {n result.hostname = result.host = srcPath.shift(); //occationaly the auth can get stuck only in hostn //this especially happens in cases liken //url.resolveObject('local1@domain1', 'local2@domain2')nn var authInHost = result.host && result.host.indexOf('@') > 0 ? result.host.split('@') : false;nn if (authInHost) {n result.auth = authInHost.shift();n result.host = result.hostname = authInHost.shift();n }n }nn result.search = relative.search;n result.query = relative.query; //to support http.requestnn if (!util.isNull(result.pathname) || !util.isNull(result.search)) {n result.path = (result.pathname ? result.pathname : '') + (result.search ? result.search : '');n }nn result.href = result.format();n return result;n }nn if (!srcPath.length) {n // no path at all. easy.n // we've already handled the other stuff above.n result.pathname = null; //to support http.requestnn if (result.search) {n result.path = '/' + result.search;n } else {n result.path = null;n }nn result.href = result.format();n return result;n } // if a url ENDs in . or .., then it must get a trailing slash.n // however, if it ends in anything else non-slashy,n // then it must NOT get a trailing slash.nnn var last = srcPath.slice(-1);n var hasTrailingSlash = (result.host || relative.host || srcPath.length > 1) && (last === '.' || last === '..') || last === ''; // strip single dots, resolve double dots to parent dirn // if the path tries to go above the root, `up` ends up > 0nn var up = 0;nn for (var i = srcPath.length; i >= 0; i–) {n last = srcPath;nn if (last === '.') {n srcPath.splice(i, 1);n } else if (last === '..') {n srcPath.splice(i, 1);n up++;n } else if (up) {n srcPath.splice(i, 1);n up–;n }n } // if the path is allowed to go above the root, restore leading ..snnn if (!mustEndAbs && !removeAllDots) {n for (; up–; up) {n srcPath.unshift('..');n }n }nn if (mustEndAbs && srcPath !== '' && (!srcPath || srcPath.charAt(0) !== '/')) {n srcPath.unshift('');n }nn if (hasTrailingSlash && srcPath.join('/').substr(-1) !== '/') {n srcPath.push('');n }nn var isAbsolute = srcPath === '' || srcPath && srcPath.charAt(0) === '/'; // put the host backnn if (psychotic) {n result.hostname = result.host = isAbsolute ? '' : srcPath.length ? srcPath.shift() : ''; //occationaly the auth can get stuck only in hostn //this especially happens in cases liken //url.resolveObject('local1@domain1', 'local2@domain2')nn var authInHost = result.host && result.host.indexOf('@') > 0 ? result.host.split('@') : false;nn if (authInHost) {n result.auth = authInHost.shift();n result.host = result.hostname = authInHost.shift();n }n }nn mustEndAbs = mustEndAbs || result.host && srcPath.length;nn if (mustEndAbs && !isAbsolute) {n srcPath.unshift('');n }nn if (!srcPath.length) {n result.pathname = null;n result.path = null;n } else {n result.pathname = srcPath.join('/');n } //to support request.httpnnn if (!util.isNull(result.pathname) || !util.isNull(result.search)) {n result.path = (result.pathname ? result.pathname : '') + (result.search ? result.search : '');n }nn result.auth = relative.auth || result.auth;n result.slashes = result.slashes || relative.slashes;n result.href = result.format();n return result;n};nnUrl.prototype.parseHost = function () {n var host = this.host;n var port = portPattern.exec(host);nn if (port) {n port = port;nn if (port !== ':') {n this.port = port.substr(1);n }nn host = host.substr(0, host.length - port.length);n }nn if (host) this.hostname = host;n};”,“map”:null,“metadata”:{},“sourceType”:“module”}