You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							692 lines
						
					
					
						
							19 KiB
						
					
					
				
			
		
		
	
	
							692 lines
						
					
					
						
							19 KiB
						
					
					
				(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.URLParse = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ | 
						|
(function (global){(function (){ | 
						|
'use strict'; | 
						|
 | 
						|
var required = require('requires-port') | 
						|
  , qs = require('querystringify') | 
						|
  , slashes = /^[A-Za-z][A-Za-z0-9+-.]*:\/\// | 
						|
  , protocolre = /^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i | 
						|
  , windowsDriveLetter = /^[a-zA-Z]:/ | 
						|
  , whitespace = '[\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF]' | 
						|
  , left = new RegExp('^'+ whitespace +'+'); | 
						|
 | 
						|
/** | 
						|
 * Trim a given string. | 
						|
 * | 
						|
 * @param {String} str String to trim. | 
						|
 * @public | 
						|
 */ | 
						|
function trimLeft(str) { | 
						|
  return (str ? str : '').toString().replace(left, ''); | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * These are the parse rules for the URL parser, it informs the parser | 
						|
 * about: | 
						|
 * | 
						|
 * 0. The char it Needs to parse, if it's a string it should be done using | 
						|
 *    indexOf, RegExp using exec and NaN means set as current value. | 
						|
 * 1. The property we should set when parsing this value. | 
						|
 * 2. Indication if it's backwards or forward parsing, when set as number it's | 
						|
 *    the value of extra chars that should be split off. | 
						|
 * 3. Inherit from location if non existing in the parser. | 
						|
 * 4. `toLowerCase` the resulting value. | 
						|
 */ | 
						|
var rules = [ | 
						|
  ['#', 'hash'],                        // Extract from the back. | 
						|
  ['?', 'query'],                       // Extract from the back. | 
						|
  function sanitize(address, url) {     // Sanitize what is left of the address | 
						|
    return isSpecial(url.protocol) ? address.replace(/\\/g, '/') : address; | 
						|
  }, | 
						|
  ['/', 'pathname'],                    // Extract from the back. | 
						|
  ['@', 'auth', 1],                     // Extract from the front. | 
						|
  [NaN, 'host', undefined, 1, 1],       // Set left over value. | 
						|
  [/:(\d+)$/, 'port', undefined, 1],    // RegExp the back. | 
						|
  [NaN, 'hostname', undefined, 1, 1]    // Set left over. | 
						|
]; | 
						|
 | 
						|
/** | 
						|
 * These properties should not be copied or inherited from. This is only needed | 
						|
 * for all non blob URL's as a blob URL does not include a hash, only the | 
						|
 * origin. | 
						|
 * | 
						|
 * @type {Object} | 
						|
 * @private | 
						|
 */ | 
						|
var ignore = { hash: 1, query: 1 }; | 
						|
 | 
						|
/** | 
						|
 * The location object differs when your code is loaded through a normal page, | 
						|
 * Worker or through a worker using a blob. And with the blobble begins the | 
						|
 * trouble as the location object will contain the URL of the blob, not the | 
						|
 * location of the page where our code is loaded in. The actual origin is | 
						|
 * encoded in the `pathname` so we can thankfully generate a good "default" | 
						|
 * location from it so we can generate proper relative URL's again. | 
						|
 * | 
						|
 * @param {Object|String} loc Optional default location object. | 
						|
 * @returns {Object} lolcation object. | 
						|
 * @public | 
						|
 */ | 
						|
function lolcation(loc) { | 
						|
  var globalVar; | 
						|
 | 
						|
  if (typeof window !== 'undefined') globalVar = window; | 
						|
  else if (typeof global !== 'undefined') globalVar = global; | 
						|
  else if (typeof self !== 'undefined') globalVar = self; | 
						|
  else globalVar = {}; | 
						|
 | 
						|
  var location = globalVar.location || {}; | 
						|
  loc = loc || location; | 
						|
 | 
						|
  var finaldestination = {} | 
						|
    , type = typeof loc | 
						|
    , key; | 
						|
 | 
						|
  if ('blob:' === loc.protocol) { | 
						|
    finaldestination = new Url(unescape(loc.pathname), {}); | 
						|
  } else if ('string' === type) { | 
						|
    finaldestination = new Url(loc, {}); | 
						|
    for (key in ignore) delete finaldestination[key]; | 
						|
  } else if ('object' === type) { | 
						|
    for (key in loc) { | 
						|
      if (key in ignore) continue; | 
						|
      finaldestination[key] = loc[key]; | 
						|
    } | 
						|
 | 
						|
    if (finaldestination.slashes === undefined) { | 
						|
      finaldestination.slashes = slashes.test(loc.href); | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  return finaldestination; | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Check whether a protocol scheme is special. | 
						|
 * | 
						|
 * @param {String} The protocol scheme of the URL | 
						|
 * @return {Boolean} `true` if the protocol scheme is special, else `false` | 
						|
 * @private | 
						|
 */ | 
						|
function isSpecial(scheme) { | 
						|
  return ( | 
						|
    scheme === 'file:' || | 
						|
    scheme === 'ftp:' || | 
						|
    scheme === 'http:' || | 
						|
    scheme === 'https:' || | 
						|
    scheme === 'ws:' || | 
						|
    scheme === 'wss:' | 
						|
  ); | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * @typedef ProtocolExtract | 
						|
 * @type Object | 
						|
 * @property {String} protocol Protocol matched in the URL, in lowercase. | 
						|
 * @property {Boolean} slashes `true` if protocol is followed by "//", else `false`. | 
						|
 * @property {String} rest Rest of the URL that is not part of the protocol. | 
						|
 */ | 
						|
 | 
						|
/** | 
						|
 * Extract protocol information from a URL with/without double slash ("//"). | 
						|
 * | 
						|
 * @param {String} address URL we want to extract from. | 
						|
 * @param {Object} location | 
						|
 * @return {ProtocolExtract} Extracted information. | 
						|
 * @private | 
						|
 */ | 
						|
function extractProtocol(address, location) { | 
						|
  address = trimLeft(address); | 
						|
  location = location || {}; | 
						|
 | 
						|
  var match = protocolre.exec(address); | 
						|
  var protocol = match[1] ? match[1].toLowerCase() : ''; | 
						|
  var forwardSlashes = !!match[2]; | 
						|
  var otherSlashes = !!match[3]; | 
						|
  var slashesCount = 0; | 
						|
  var rest; | 
						|
 | 
						|
  if (forwardSlashes) { | 
						|
    if (otherSlashes) { | 
						|
      rest = match[2] + match[3] + match[4]; | 
						|
      slashesCount = match[2].length + match[3].length; | 
						|
    } else { | 
						|
      rest = match[2] + match[4]; | 
						|
      slashesCount = match[2].length; | 
						|
    } | 
						|
  } else { | 
						|
    if (otherSlashes) { | 
						|
      rest = match[3] + match[4]; | 
						|
      slashesCount = match[3].length; | 
						|
    } else { | 
						|
      rest = match[4] | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  if (protocol === 'file:') { | 
						|
    if (slashesCount >= 2) { | 
						|
      rest = rest.slice(2); | 
						|
    } | 
						|
  } else if (isSpecial(protocol)) { | 
						|
    rest = match[4]; | 
						|
  } else if (protocol) { | 
						|
    if (forwardSlashes) { | 
						|
      rest = rest.slice(2); | 
						|
    } | 
						|
  } else if (slashesCount >= 2 && isSpecial(location.protocol)) { | 
						|
    rest = match[4]; | 
						|
  } | 
						|
 | 
						|
  return { | 
						|
    protocol: protocol, | 
						|
    slashes: forwardSlashes || isSpecial(protocol), | 
						|
    slashesCount: slashesCount, | 
						|
    rest: rest | 
						|
  }; | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Resolve a relative URL pathname against a base URL pathname. | 
						|
 * | 
						|
 * @param {String} relative Pathname of the relative URL. | 
						|
 * @param {String} base Pathname of the base URL. | 
						|
 * @return {String} Resolved pathname. | 
						|
 * @private | 
						|
 */ | 
						|
function resolve(relative, base) { | 
						|
  if (relative === '') return base; | 
						|
 | 
						|
  var path = (base || '/').split('/').slice(0, -1).concat(relative.split('/')) | 
						|
    , i = path.length | 
						|
    , last = path[i - 1] | 
						|
    , unshift = false | 
						|
    , up = 0; | 
						|
 | 
						|
  while (i--) { | 
						|
    if (path[i] === '.') { | 
						|
      path.splice(i, 1); | 
						|
    } else if (path[i] === '..') { | 
						|
      path.splice(i, 1); | 
						|
      up++; | 
						|
    } else if (up) { | 
						|
      if (i === 0) unshift = true; | 
						|
      path.splice(i, 1); | 
						|
      up--; | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  if (unshift) path.unshift(''); | 
						|
  if (last === '.' || last === '..') path.push(''); | 
						|
 | 
						|
  return path.join('/'); | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * The actual URL instance. Instead of returning an object we've opted-in to | 
						|
 * create an actual constructor as it's much more memory efficient and | 
						|
 * faster and it pleases my OCD. | 
						|
 * | 
						|
 * It is worth noting that we should not use `URL` as class name to prevent | 
						|
 * clashes with the global URL instance that got introduced in browsers. | 
						|
 * | 
						|
 * @constructor | 
						|
 * @param {String} address URL we want to parse. | 
						|
 * @param {Object|String} [location] Location defaults for relative paths. | 
						|
 * @param {Boolean|Function} [parser] Parser for the query string. | 
						|
 * @private | 
						|
 */ | 
						|
function Url(address, location, parser) { | 
						|
  address = trimLeft(address); | 
						|
 | 
						|
  if (!(this instanceof Url)) { | 
						|
    return new Url(address, location, parser); | 
						|
  } | 
						|
 | 
						|
  var relative, extracted, parse, instruction, index, key | 
						|
    , instructions = rules.slice() | 
						|
    , type = typeof location | 
						|
    , url = this | 
						|
    , i = 0; | 
						|
 | 
						|
  // | 
						|
  // The following if statements allows this module two have compatibility with | 
						|
  // 2 different API: | 
						|
  // | 
						|
  // 1. Node.js's `url.parse` api which accepts a URL, boolean as arguments | 
						|
  //    where the boolean indicates that the query string should also be parsed. | 
						|
  // | 
						|
  // 2. The `URL` interface of the browser which accepts a URL, object as | 
						|
  //    arguments. The supplied object will be used as default values / fall-back | 
						|
  //    for relative paths. | 
						|
  // | 
						|
  if ('object' !== type && 'string' !== type) { | 
						|
    parser = location; | 
						|
    location = null; | 
						|
  } | 
						|
 | 
						|
  if (parser && 'function' !== typeof parser) parser = qs.parse; | 
						|
 | 
						|
  location = lolcation(location); | 
						|
 | 
						|
  // | 
						|
  // Extract protocol information before running the instructions. | 
						|
  // | 
						|
  extracted = extractProtocol(address || '', location); | 
						|
  relative = !extracted.protocol && !extracted.slashes; | 
						|
  url.slashes = extracted.slashes || relative && location.slashes; | 
						|
  url.protocol = extracted.protocol || location.protocol || ''; | 
						|
  address = extracted.rest; | 
						|
 | 
						|
  // | 
						|
  // When the authority component is absent the URL starts with a path | 
						|
  // component. | 
						|
  // | 
						|
  if ( | 
						|
    extracted.protocol === 'file:' && ( | 
						|
      extracted.slashesCount !== 2 || windowsDriveLetter.test(address)) || | 
						|
    (!extracted.slashes && | 
						|
      (extracted.protocol || | 
						|
        extracted.slashesCount < 2 || | 
						|
        !isSpecial(url.protocol))) | 
						|
  ) { | 
						|
    instructions[3] = [/(.*)/, 'pathname']; | 
						|
  } | 
						|
 | 
						|
  for (; i < instructions.length; i++) { | 
						|
    instruction = instructions[i]; | 
						|
 | 
						|
    if (typeof instruction === 'function') { | 
						|
      address = instruction(address, url); | 
						|
      continue; | 
						|
    } | 
						|
 | 
						|
    parse = instruction[0]; | 
						|
    key = instruction[1]; | 
						|
 | 
						|
    if (parse !== parse) { | 
						|
      url[key] = address; | 
						|
    } else if ('string' === typeof parse) { | 
						|
      if (~(index = address.indexOf(parse))) { | 
						|
        if ('number' === typeof instruction[2]) { | 
						|
          url[key] = address.slice(0, index); | 
						|
          address = address.slice(index + instruction[2]); | 
						|
        } else { | 
						|
          url[key] = address.slice(index); | 
						|
          address = address.slice(0, index); | 
						|
        } | 
						|
      } | 
						|
    } else if ((index = parse.exec(address))) { | 
						|
      url[key] = index[1]; | 
						|
      address = address.slice(0, index.index); | 
						|
    } | 
						|
 | 
						|
    url[key] = url[key] || ( | 
						|
      relative && instruction[3] ? location[key] || '' : '' | 
						|
    ); | 
						|
 | 
						|
    // | 
						|
    // Hostname, host and protocol should be lowercased so they can be used to | 
						|
    // create a proper `origin`. | 
						|
    // | 
						|
    if (instruction[4]) url[key] = url[key].toLowerCase(); | 
						|
  } | 
						|
 | 
						|
  // | 
						|
  // Also parse the supplied query string in to an object. If we're supplied | 
						|
  // with a custom parser as function use that instead of the default build-in | 
						|
  // parser. | 
						|
  // | 
						|
  if (parser) url.query = parser(url.query); | 
						|
 | 
						|
  // | 
						|
  // If the URL is relative, resolve the pathname against the base URL. | 
						|
  // | 
						|
  if ( | 
						|
      relative | 
						|
    && location.slashes | 
						|
    && url.pathname.charAt(0) !== '/' | 
						|
    && (url.pathname !== '' || location.pathname !== '') | 
						|
  ) { | 
						|
    url.pathname = resolve(url.pathname, location.pathname); | 
						|
  } | 
						|
 | 
						|
  // | 
						|
  // Default to a / for pathname if none exists. This normalizes the URL | 
						|
  // to always have a / | 
						|
  // | 
						|
  if (url.pathname.charAt(0) !== '/' && isSpecial(url.protocol)) { | 
						|
    url.pathname = '/' + url.pathname; | 
						|
  } | 
						|
 | 
						|
  // | 
						|
  // We should not add port numbers if they are already the default port number | 
						|
  // for a given protocol. As the host also contains the port number we're going | 
						|
  // override it with the hostname which contains no port number. | 
						|
  // | 
						|
  if (!required(url.port, url.protocol)) { | 
						|
    url.host = url.hostname; | 
						|
    url.port = ''; | 
						|
  } | 
						|
 | 
						|
  // | 
						|
  // Parse down the `auth` for the username and password. | 
						|
  // | 
						|
  url.username = url.password = ''; | 
						|
  if (url.auth) { | 
						|
    instruction = url.auth.split(':'); | 
						|
    url.username = instruction[0] || ''; | 
						|
    url.password = instruction[1] || ''; | 
						|
  } | 
						|
 | 
						|
  url.origin = url.protocol !== 'file:' && isSpecial(url.protocol) && url.host | 
						|
    ? url.protocol +'//'+ url.host | 
						|
    : 'null'; | 
						|
 | 
						|
  // | 
						|
  // The href is just the compiled result. | 
						|
  // | 
						|
  url.href = url.toString(); | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * This is convenience method for changing properties in the URL instance to | 
						|
 * insure that they all propagate correctly. | 
						|
 * | 
						|
 * @param {String} part          Property we need to adjust. | 
						|
 * @param {Mixed} value          The newly assigned value. | 
						|
 * @param {Boolean|Function} fn  When setting the query, it will be the function | 
						|
 *                               used to parse the query. | 
						|
 *                               When setting the protocol, double slash will be | 
						|
 *                               removed from the final url if it is true. | 
						|
 * @returns {URL} URL instance for chaining. | 
						|
 * @public | 
						|
 */ | 
						|
function set(part, value, fn) { | 
						|
  var url = this; | 
						|
 | 
						|
  switch (part) { | 
						|
    case 'query': | 
						|
      if ('string' === typeof value && value.length) { | 
						|
        value = (fn || qs.parse)(value); | 
						|
      } | 
						|
 | 
						|
      url[part] = value; | 
						|
      break; | 
						|
 | 
						|
    case 'port': | 
						|
      url[part] = value; | 
						|
 | 
						|
      if (!required(value, url.protocol)) { | 
						|
        url.host = url.hostname; | 
						|
        url[part] = ''; | 
						|
      } else if (value) { | 
						|
        url.host = url.hostname +':'+ value; | 
						|
      } | 
						|
 | 
						|
      break; | 
						|
 | 
						|
    case 'hostname': | 
						|
      url[part] = value; | 
						|
 | 
						|
      if (url.port) value += ':'+ url.port; | 
						|
      url.host = value; | 
						|
      break; | 
						|
 | 
						|
    case 'host': | 
						|
      url[part] = value; | 
						|
 | 
						|
      if (/:\d+$/.test(value)) { | 
						|
        value = value.split(':'); | 
						|
        url.port = value.pop(); | 
						|
        url.hostname = value.join(':'); | 
						|
      } else { | 
						|
        url.hostname = value; | 
						|
        url.port = ''; | 
						|
      } | 
						|
 | 
						|
      break; | 
						|
 | 
						|
    case 'protocol': | 
						|
      url.protocol = value.toLowerCase(); | 
						|
      url.slashes = !fn; | 
						|
      break; | 
						|
 | 
						|
    case 'pathname': | 
						|
    case 'hash': | 
						|
      if (value) { | 
						|
        var char = part === 'pathname' ? '/' : '#'; | 
						|
        url[part] = value.charAt(0) !== char ? char + value : value; | 
						|
      } else { | 
						|
        url[part] = value; | 
						|
      } | 
						|
      break; | 
						|
 | 
						|
    default: | 
						|
      url[part] = value; | 
						|
  } | 
						|
 | 
						|
  for (var i = 0; i < rules.length; i++) { | 
						|
    var ins = rules[i]; | 
						|
 | 
						|
    if (ins[4]) url[ins[1]] = url[ins[1]].toLowerCase(); | 
						|
  } | 
						|
 | 
						|
  url.origin = url.protocol !== 'file:' && isSpecial(url.protocol) && url.host | 
						|
    ? url.protocol +'//'+ url.host | 
						|
    : 'null'; | 
						|
 | 
						|
  url.href = url.toString(); | 
						|
 | 
						|
  return url; | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Transform the properties back in to a valid and full URL string. | 
						|
 * | 
						|
 * @param {Function} stringify Optional query stringify function. | 
						|
 * @returns {String} Compiled version of the URL. | 
						|
 * @public | 
						|
 */ | 
						|
function toString(stringify) { | 
						|
  if (!stringify || 'function' !== typeof stringify) stringify = qs.stringify; | 
						|
 | 
						|
  var query | 
						|
    , url = this | 
						|
    , protocol = url.protocol; | 
						|
 | 
						|
  if (protocol && protocol.charAt(protocol.length - 1) !== ':') protocol += ':'; | 
						|
 | 
						|
  var result = protocol + (url.slashes || isSpecial(url.protocol) ? '//' : ''); | 
						|
 | 
						|
  if (url.username) { | 
						|
    result += url.username; | 
						|
    if (url.password) result += ':'+ url.password; | 
						|
    result += '@'; | 
						|
  } | 
						|
 | 
						|
  result += url.host + url.pathname; | 
						|
 | 
						|
  query = 'object' === typeof url.query ? stringify(url.query) : url.query; | 
						|
  if (query) result += '?' !== query.charAt(0) ? '?'+ query : query; | 
						|
 | 
						|
  if (url.hash) result += url.hash; | 
						|
 | 
						|
  return result; | 
						|
} | 
						|
 | 
						|
Url.prototype = { set: set, toString: toString }; | 
						|
 | 
						|
// | 
						|
// Expose the URL parser and some additional properties that might be useful for | 
						|
// others or testing. | 
						|
// | 
						|
Url.extractProtocol = extractProtocol; | 
						|
Url.location = lolcation; | 
						|
Url.trimLeft = trimLeft; | 
						|
Url.qs = qs; | 
						|
 | 
						|
module.exports = Url; | 
						|
 | 
						|
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | 
						|
},{"querystringify":2,"requires-port":3}],2:[function(require,module,exports){ | 
						|
'use strict'; | 
						|
 | 
						|
var has = Object.prototype.hasOwnProperty | 
						|
  , undef; | 
						|
 | 
						|
/** | 
						|
 * Decode a URI encoded string. | 
						|
 * | 
						|
 * @param {String} input The URI encoded string. | 
						|
 * @returns {String|Null} The decoded string. | 
						|
 * @api private | 
						|
 */ | 
						|
function decode(input) { | 
						|
  try { | 
						|
    return decodeURIComponent(input.replace(/\+/g, ' ')); | 
						|
  } catch (e) { | 
						|
    return null; | 
						|
  } | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Attempts to encode a given input. | 
						|
 * | 
						|
 * @param {String} input The string that needs to be encoded. | 
						|
 * @returns {String|Null} The encoded string. | 
						|
 * @api private | 
						|
 */ | 
						|
function encode(input) { | 
						|
  try { | 
						|
    return encodeURIComponent(input); | 
						|
  } catch (e) { | 
						|
    return null; | 
						|
  } | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Simple query string parser. | 
						|
 * | 
						|
 * @param {String} query The query string that needs to be parsed. | 
						|
 * @returns {Object} | 
						|
 * @api public | 
						|
 */ | 
						|
function querystring(query) { | 
						|
  var parser = /([^=?#&]+)=?([^&]*)/g | 
						|
    , result = {} | 
						|
    , part; | 
						|
 | 
						|
  while (part = parser.exec(query)) { | 
						|
    var key = decode(part[1]) | 
						|
      , value = decode(part[2]); | 
						|
 | 
						|
    // | 
						|
    // Prevent overriding of existing properties. This ensures that build-in | 
						|
    // methods like `toString` or __proto__ are not overriden by malicious | 
						|
    // querystrings. | 
						|
    // | 
						|
    // In the case if failed decoding, we want to omit the key/value pairs | 
						|
    // from the result. | 
						|
    // | 
						|
    if (key === null || value === null || key in result) continue; | 
						|
    result[key] = value; | 
						|
  } | 
						|
 | 
						|
  return result; | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Transform a query string to an object. | 
						|
 * | 
						|
 * @param {Object} obj Object that should be transformed. | 
						|
 * @param {String} prefix Optional prefix. | 
						|
 * @returns {String} | 
						|
 * @api public | 
						|
 */ | 
						|
function querystringify(obj, prefix) { | 
						|
  prefix = prefix || ''; | 
						|
 | 
						|
  var pairs = [] | 
						|
    , value | 
						|
    , key; | 
						|
 | 
						|
  // | 
						|
  // Optionally prefix with a '?' if needed | 
						|
  // | 
						|
  if ('string' !== typeof prefix) prefix = '?'; | 
						|
 | 
						|
  for (key in obj) { | 
						|
    if (has.call(obj, key)) { | 
						|
      value = obj[key]; | 
						|
 | 
						|
      // | 
						|
      // Edge cases where we actually want to encode the value to an empty | 
						|
      // string instead of the stringified value. | 
						|
      // | 
						|
      if (!value && (value === null || value === undef || isNaN(value))) { | 
						|
        value = ''; | 
						|
      } | 
						|
 | 
						|
      key = encode(key); | 
						|
      value = encode(value); | 
						|
 | 
						|
      // | 
						|
      // If we failed to encode the strings, we should bail out as we don't | 
						|
      // want to add invalid strings to the query. | 
						|
      // | 
						|
      if (key === null || value === null) continue; | 
						|
      pairs.push(key +'='+ value); | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  return pairs.length ? prefix + pairs.join('&') : ''; | 
						|
} | 
						|
 | 
						|
// | 
						|
// Expose the module. | 
						|
// | 
						|
exports.stringify = querystringify; | 
						|
exports.parse = querystring; | 
						|
 | 
						|
},{}],3:[function(require,module,exports){ | 
						|
'use strict'; | 
						|
 | 
						|
/** | 
						|
 * Check if we're required to add a port number. | 
						|
 * | 
						|
 * @see https://url.spec.whatwg.org/#default-port | 
						|
 * @param {Number|String} port Port number we need to check | 
						|
 * @param {String} protocol Protocol we need to check against. | 
						|
 * @returns {Boolean} Is it a default port for the given protocol | 
						|
 * @api private | 
						|
 */ | 
						|
module.exports = function required(port, protocol) { | 
						|
  protocol = protocol.split(':')[0]; | 
						|
  port = +port; | 
						|
 | 
						|
  if (!port) return false; | 
						|
 | 
						|
  switch (protocol) { | 
						|
    case 'http': | 
						|
    case 'ws': | 
						|
    return port !== 80; | 
						|
 | 
						|
    case 'https': | 
						|
    case 'wss': | 
						|
    return port !== 443; | 
						|
 | 
						|
    case 'ftp': | 
						|
    return port !== 21; | 
						|
 | 
						|
    case 'gopher': | 
						|
    return port !== 70; | 
						|
 | 
						|
    case 'file': | 
						|
    return false; | 
						|
  } | 
						|
 | 
						|
  return port !== 0; | 
						|
}; | 
						|
 | 
						|
},{}]},{},[1])(1) | 
						|
});
 | 
						|
 |