File: application/webfan/node_modules/webfan/frdl-main.js

Recommend this page to a friend!
  Classes of Till Wehowski   µ.Flow   application/webfan/node_modules/webfan/frdl-main.js   Download  
File: application/webfan/node_modules/webfan/frdl-main.js
Role: Class source
Content type: text/plain
Description: Class source
Class: µ.Flow
General purpose library of objects
Author: By
Last change:
Date: 6 years ago
Size: 65,976 bytes
 

Contents

Class file image Download
/* webfan (C) Till Wehowski, Webfan.de - All rights reserved. */ function Boot(scope, require, webfan, jQuery){ var main = this; var Scope = scope; main.state = new frdl.EventEmitter(); var dependency = [ 'loading', 'frdl::ready', ]; if(false===isWorker){ dependency.push('load flow'); dependency.push('module $1:ui/frdlui loaded'); // dependency.push('module $1:libraries/angular/angular loaded'); } // dependency.push('frdl.Registry.Types.Classes'); /** e.g. main.dependency.add('module $frdl.inX loaded'); */ main.dependency = main.state.required(dependency, function (dataArray) { try{ if(false===isWorker) main.dependency.stateGet('load flow').emitter.emit('main modules', dataArray, main); }catch(err){ console.error(err); } }, main); Object.defineProperty(main, 'isLoading', { 'get':function() { if('loading'=== document.readyState)return true; if('complete'!== document.readyState && false === main.isReady)return true; return false; } }); Object.defineProperty(main, 'isReady', { 'get':function() { if(true !== main.dependency.stateReady())return false; // if(false!==main.interactive())return false; return true; } }); require.state.on('resolved', function(){ var args = Array.prototype.slice.call(arguments); main.state.emit('module $'+args[0].identifier+' loaded', args[0].module); }); frdl.ready(function(){ main.state.emit('frdl::ready', true); }); main.init(scope, require, webfan, jQuery); return main; } Boot.prototype.init = function(scope, require, webfan, jQuery){ var main = this; var Scope = scope; var dummy = false; main .querystring(require) .punnycode(require) .util(require) .url(require) ; scope.url = require.cache('url'); require('common/x2js', function(){ }); if('undefined' === typeof Array.from) { require('es6-array-extras/lib/es6-array-extras', function() { }); } var __extend = function(from, to) { if (from === null || typeof from !== 'object') return from; if (from.constructor !== Object && from.constructor !== Array) return from; if (from.constructor === Date || from.constructor === RegExp || from.constructor === Function || from.constructor === String || from.constructor === Number || from.constructor === Boolean) return new from.constructor(from); to = to || new from.constructor(); var name; for (name in from) { to[name] = typeof to[name] === 'undefined' ? __extend(from[name], null) : to[name]; } return to; }; frdl.Registry.Types.Functions.extend = __extend; Object.defineProperty(frdl, 'reg', { 'get':function() { return require('symbol-registry'); }, 'set':function(v) { throw 'Illegal set of frdl.reg'; } }); require('common/json2', function(JSON) { JSON = JSON; if('undefined' === typeof global.JSON || 'undefined' === typeof global.JSON.parse || 'undefined' === typeof global.JSON.stringify)global.JSON=window.JSON=JSON; }); Object.defineProperty(frdl, 'sql', { 'get':function() { return require('webfan/ql'); }, 'set':function(v) { frdl.sql = v; }/* , configurable : true, writable :true */ }); Object.defineProperty(Scope, 'cipher', { 'get':function() { return require('sjcl/sjcl'); } }); Object.defineProperty(global, 'Buffer', { 'get':function() { return require('buffer'); } }); if('undefined' === typeof localStorage){ var _localStorage = {}; localStorage = frdl.globalScope.localStorage = global.localStorage = window.localStorage = self.localStorage = { setItem : function(id, val) { return _localStorage[id] = String(val); }, getItem : function(id) { return _localStorage.hasOwnProperty(id) ? _localStorage[id] : null; }, removeItem : function(id) { return delete _localStorage[id]; }, clear : function() { return _localStorage = {}; } }; } if('undefined' === typeof sessionStorage){ var _sessionStorage = {}; sessionStorage = frdl.globalScope.sessionStorage = global.sessionStorage = window.sessionStorage = self.sessionStorage = { setItem : function(id, val) { return _sessionStorage[id] = String(val); }, getItem : function(id) { return _sessionStorage.hasOwnProperty(id) ? _sessionStorage[id] : null; }, removeItem : function(id) { return delete _sessionStorage[id]; }, clear : function() { return _sessionStorage = {}; } }; } require('webfan/navigator/WebkitWebfanStorage', function(mod){ Scope.$S = mod; Scope.$DB = new Scope.$S({ prefix : 'frdl://$S/schema.info/', user :null, crypt : false, pwd : null }, false); require.state.emit('resolved', { identifier : 'frdl.$DB', module :Scope.$DB }); require.state.emit('resolved frdl.$DB', { identifier : 'frdl.$DB', module : Scope.$DB }); try{ var debugmode = parseInt( frdl.$DB.load('settings/debugmode').toString() ); if(!debugmode || isNaN(debugmode))debugmode=0; } catch(err){ var debugmode = 0; } frdl.debug.mode(debugmode); frdl.ready(function(){ webfan.$Async(function(){ if(0<frdl.debug.mode()){ if('undefined'!==frdl.alert)frdl.alert.log('DEBUG ENABLED ('+frdl.debug.mode()+')'); } },3000); }); }); require('webfan/navigator/dom-observer', function(_watchFor){ scope.watchFor = new _watchFor().watchFor; }); require.state.on('resolved 1:ui/frdlui', function(){ var args = Array.prototype.slice.call(arguments); var UI = args[0].module; UI.emitter.once('dependency.resolved', function(){ if(1<frdl.debug.mode())console.log('dependency.resolved => frdl.main.state.emit'); }); require.state.emit('resolved', { identifier : 'UI', module : UI }); require.state.emit('resolved UI', { identifier : 'UI', module : UI }); main.state.emit('load flow', UI); }); Object.defineProperty(frdl, 'a', { 'get':function() { return require('1:libraries/angular/angular'); } }); require('1:ui/frdlui', function(UI){ scope.UI =UI; }); require.state.on('resolved 3:webfan/navigator/simpledialog', function(){ var args = Array.prototype.slice.call(arguments); var alert = args[0].module; webfan.$Async(function(){ require.state.emit('resolved', { identifier : 'frdl.alert', module : alert }); require.state.emit('resolved frdl.alert', { identifier : 'frdl.alert', module : alert }); },1); }); Object.defineProperty(scope, 'alert', { 'get':function() { return require('webfan/navigator/simpledialog'); } }); require('webfan/navigator/anchor-routing', function(HashHandler) { frdl.Hash = HashHandler; require.state.emit('resolved', { identifier : 'frdl.Hash', module :frdl.Hash }); require.state.emit('resolved frdl.Hash', { identifier : 'frdl.Hash', module : frdl.Hash }); }); if(false===isWorker){ webfan.$Async(function(){ var _url='5:'+location.protocol+'//'+frdl.route('HOST_CDN_PUBLIC_FRDL')+'/cdn/frdl/flow/components/locale/jsin/jsin.js'; require(_url, function(Translator) { frdl.inX = Translator; webfan.$Async(function(){ Scope.inX.start(); },250); require.state.emit('resolved', { identifier : 'frdl.inX', module :frdl.inX }); require.state.emit('resolved frdl.inX', { identifier : 'frdl.inX', module : frdl.inX }); }); },1); } frdl.formatBytes = function(bytes,decimals) { if(bytes == 0) return '0 Byte'; // var k = 1000; // or 1024 for binary var k = 1024; var dm = decimals + 1 || 3; var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; var i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; }; (function(){ function symbolReplacer(key, value) { if (typeof value === 'symbol') { return '@@' + Symbol.keyFor(value) + '@@'; } return value; } const REGEX_SYMOBL_STRING = /^@@(.*)@@$/; function symbolReviver(key, value) { if (typeof value === 'string') { let match = REGEX_SYMOBL_STRING.test(value); if (match) { return Symbol.for(match[1]) } } return value; } /* const MY_SYMBOL = Symbol.for('http://example.com/my_symbol'); let obj = { [MY_SYMBOL]: 123 }; let str = JSON.stringify(obj, symbolReplacer); console.log(str); let parsed = JSON.parse(str, symbolReviver); console.log(parse); */ frdl.symbolReplacer = symbolReplacer; frdl.symbolReviver = symbolReviver; }()); //deprectaed... webfan.plug('$fs --local', function(){ if(!!frdl.nw){ return require('fs'); } return frdl.fs5.polyfill.getFiler(); }); webfan.plug('$fs --local root', function(){ try{ return webfan['$fs --local']().fs.root.toURL(); }catch(err){ return document.base || window.location.href; } }); webfan.plug('file://', function(){ try{ return webfan['$fs --local']().fs.root.toURL(); }catch(err){ return document.base || window.location.href; } }); webfan.plug('app://', function(){ try{ if('temp' === Array.prototype.slice.call(arguments)[0])return webfan['$fs --local']('temp').fs.root.toURL(); return webfan['$fs --local']().fs.root.toURL(); }catch(err){ return window.location.href; } }); webfan.plug('path.exec', function(){ try{ return webfan['$fs --local']().fs.root.toURL(); }catch(err){ return document.base || window.location.href; } }); webfan.plug('$win open', function(){ var args = Array.prototype.slice.call(arguments); return window.open(args[0][0]); }); require.state.emit('resolved frdl.main', { identifier : 'frdl.main', module : main }); require.state.emit('resolved', { identifier : 'frdl.main', module : main }); return this; }; Boot.prototype.ready = function(){ if(true===this.isReady){ this.state.emit('ready', true); return true; } return false; }; Boot.prototype.interactive = function(){ var body; return !( body = !!document.body && 'complete' ) && 'complete' === document.readyState; }; Boot.prototype.complete = function(){ if(false===this.isLoading && true===this.isReady){ this.state.emit('complete', true); return true; } return false; }; Boot.prototype.loading = function(){ this.state.emit('loading', true); if(true===this.isLoading){ return true; } return false; }; Boot.prototype.querystring = function(require){ //exports = module.exports = require('querystring/index'); // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. (function(){ 'use strict'; // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } var parse = function(qs, sep, eq, options) { sep = sep || '&'; eq = eq || '='; var obj = {}; if (typeof qs !== 'string' || qs.length === 0) { return obj; } var regexp = /\+/g; qs = qs.split(sep); var maxKeys = 1000; if (options && typeof options.maxKeys === 'number') { maxKeys = options.maxKeys; } var len = qs.length; // maxKeys <= 0 means that we should not limit keys count if (maxKeys > 0 && len > maxKeys) { len = maxKeys; } for (var i = 0; i < len; ++i) { var x = qs[i].replace(regexp, '%20'), idx = x.indexOf(eq), kstr, vstr, k, v; if (idx >= 0) { kstr = x.substr(0, idx); vstr = x.substr(idx + 1); } else { kstr = x; vstr = ''; } k = decodeURIComponent(kstr); v = decodeURIComponent(vstr); if (!hasOwnProperty(obj, k)) { obj[k] = v; } else if (Array.isArray(obj[k])) { obj[k].push(v); } else { obj[k] = [obj[k], v]; } } return obj; }; // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. var stringifyPrimitive = function(v) { if('undefined'===typeof v){ return 'undefined'; } switch (typeof v) { case 'string': return v; case 'boolean': return v ? 'true' : 'false'; case 'number': return isFinite(v) ? v : ''; default: return ''; } }; var stringify = function(obj, sep, eq, name) { sep = sep || '&'; eq = eq || '='; if (obj === null) { obj = undefined; } if (typeof obj === 'object') { return Object.keys(obj).map(function(k) { var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; if (Array.isArray(obj[k])) { return obj[k].map(function(v) { return ks + encodeURIComponent(stringifyPrimitive(v)); }).join(sep); } else { return ks + encodeURIComponent(stringifyPrimitive(obj[k])); } }).join(sep); } if (!name) return ''; return encodeURIComponent(stringifyPrimitive(name)) + eq + encodeURIComponent(stringifyPrimitive(obj)); }; var querystring = { }; //exports.decode = exports.parse = module.exports.decode = module.exports.parse = parse; //exports.encode = exports.stringify = module.exports.encode = module.exports.stringify = stringify; querystring.decode = querystring.parse =parse; querystring.encode = querystring.stringify = stringify; require.cache('querystring', querystring); }()); return this; }; Boot.prototype.punnycode = function(require){ /*/ Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. */ (function(){ //var punycode = require('punycode'); /** Highest positive signed 32-bit float value */ var maxInt = 2147483647; /** Bootstring parameters */ var base = 36; var tMin = 1; var tMax = 26; var skew = 38; var damp = 700; var initialBias = 72; var initialN = 128; var delimiter = '-'; /** Regular expressions */ var regexPunycode = /^xn--/; var regexNonASCII = /[^x20-x7E]/; var regexSeparators = /[x2E\u3002\uFF0E\uFF61]/g; /** Error messages */ var errors = { 'overflow': 'Overflow: input needs wider integers to process', 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', 'invalid-input': 'Invalid input' }; /** Convenience shortcuts */ var baseMinusTMin = base - tMin; var floor = Math.floor; var stringFromCharCode = String.fromCharCode; /*--------------------------------------------------------------------------*/ /** * A generic error utility function. * @private * @param {String} type The error type. * @returns {Error} Throws a `RangeError` with the applicable error message. */ function error(type) { throw new RangeError(errors[type]); } /** * A generic `Array#map` utility function. * @private * @param {Array} array The array to iterate over. * @param {Function} callback The function that gets called for every array * item. * @returns {Array} A new array of values returned by the callback function. */ function map(array, fn) { var result = []; var length = array.length; while (length--) { result[length] = fn(array[length]); } return result; } /** * A simple `Array#map`-like wrapper to work with domain name strings or email * addresses. * @private * @param {String} domain The domain name or email address. * @param {Function} callback The function that gets called for every * character. * @returns {Array} A new string of characters returned by the callback * function. */ function mapDomain(string, fn) { var parts = string.split('\@'); var result = ''; if (parts.length > 1) { result = parts[0] + '@'; string = parts[1]; } string = string.replace(regexSeparators, 'x2E'); var labels = string.split('.'); var encoded = map(labels, fn).join('.'); return result + encoded; } /** * Creates an array containing the numeric code points of each Unicode * character in the string. While JavaScript uses UCS-2 internally, * this function will convert a pair of surrogate halves (each of which * UCS-2 exposes as separate characters) into a single code point, * matching UTF-16. * @see `punycode.ucs2.encode` * @see <https://mathiasbynens.be/notes/javascript-encoding> * @memberOf punycode.ucs2 * @name decode * @param {String} string The Unicode input string (UCS-2). * @returns {Array} The new array of code points. */ function ucs2decode(string) { var output = []; var counter = 0; var length = string.length; while (counter < length) { var value = string.charCodeAt(counter++); if (value >= 0xD800 && value <= 0xDBFF && counter < length) { var extra = string.charCodeAt(counter++); if ((extra & 0xFC00) == 0xDC00) { output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); } else { output.push(value); counter--; } } else { output.push(value); } } return output; } /** * Creates a string based on an array of numeric code points. * @see `punycode.ucs2.decode` * @memberOf punycode.ucs2 * @name encode * @param {Array} codePoints The array of numeric code points. * @returns {String} The new Unicode string (UCS-2). */ var ucs2encode = function(array){String.fromCodePoint(array);}; /** * Converts a basic code point into a digit/integer. * @see `digitToBasic()` * @private * @param {Number} codePoint The basic numeric code point value. * @returns {Number} The numeric value of a basic code point (for use in * representing integers) in the range `0` to `base - 1`, or `base` if * the code point does not represent a value. */ var basicToDigit = function(codePoint) { if (codePoint - 0x30 < 0x0A) { return codePoint - 0x16; } if (codePoint - 0x41 < 0x1A) { return codePoint - 0x41; } if (codePoint - 0x61 < 0x1A) { return codePoint - 0x61; } return base; }; /** * Converts a digit/integer into a basic code point. * @see `basicToDigit()` * @private * @param {Number} digit The numeric value of a basic code point. * @returns {Number} The basic code point whose value (when used for * representing integers) is `digit`, which needs to be in the range * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is * used; else, the lowercase form is used. The behavior is undefined * if `flag` is non-zero and `digit` has no uppercase form. */ var digitToBasic = function(digit, flag) { return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); }; /** * Bias adaptation function as per section 3.4 of RFC 3492. * https://tools.ietf.org/html/rfc3492#section-3.4 * @private */ var adapt = function(delta, numPoints, firstTime) { var k = 0; delta = firstTime ? floor(delta / damp) : delta >> 1; delta += floor(delta / numPoints); while( delta > baseMinusTMin * tMax >> 1) { k += base; delta = floor(delta / baseMinusTMin); } return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); }; /** * Converts a Punycode string of ASCII-only symbols to a string of Unicode * symbols. * @memberOf punycode * @param {String} input The Punycode string of ASCII-only symbols. * @returns {String} The resulting string of Unicode symbols. */ var decode = function(input) { var output = []; var inputLength = input.length; var i = 0, j = 0; var n = initialN; var bias = initialBias; var basic = input.lastIndexOf(delimiter); if(basic < 0){ basic = 0; } for( j = 0; j < basic; ++j) { if (input.charCodeAt(j) >= 0x80) { error('not-basic'); } output.push(input.charCodeAt(j)); } for (var index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { var oldi = i; for (var w = 1, k = base; /* no condition */; k += base) { if (index >= inputLength) { error('invalid-input'); } var digit = basicToDigit(input.charCodeAt(index++)); if (digit >= base || digit > floor((maxInt - i) / w)) { error('overflow'); } i += digit * w; var t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); if (digit < t) { break; } var baseMinusT = base - t; if (w > floor(maxInt / baseMinusT)) { error('overflow'); } w *= baseMinusT; } var out = output.length + 1; bias = adapt(i - oldi, out, oldi == 0); if (floor(i / out) > maxInt - n) { error('overflow'); } n += floor(i / out); i %= out; output.splice(i++, 0, n); } return String.fromCodePoint(output); }; /** * Converts a string of Unicode symbols (e.g. a domain name label) to a * Punycode string of ASCII-only symbols. * @memberOf punycode * @param {String} input The string of Unicode symbols. * @returns {String} The resulting Punycode string of ASCII-only symbols. */ var encode = function(input) { var output = []; input = ucs2decode(input); var inputLength = input.length; var currentValue; var n = initialN; var delta = 0; var bias = initialBias; for ( currentValue in input) { if (currentValue < 0x80) { output.push(stringFromCharCode(currentValue)); } } var basicLength = output.length; var handledCPCount = basicLength; if (basicLength) { output.push(delimiter); } while (handledCPCount < inputLength) { var m = maxInt; for ( currentValue in input) { if (currentValue >= n && currentValue < m) { m = currentValue; } } var handledCPCountPlusOne = handledCPCount + 1; if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { error('overflow'); } delta += (m - n) * handledCPCountPlusOne; n = m; for ( currentValue in input) { if (currentValue < n && ++delta > maxInt) { error('overflow'); } if (currentValue == n) { var q = delta; for (var k = base; /* no condition */; k += base) { var t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); if (q < t) { break; } var qMinusT = q - t; var baseMinusT = base - t; output.push( stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) ); q = floor(qMinusT / baseMinusT); } output.push(stringFromCharCode(digitToBasic(q, 0))); bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); delta = 0; ++handledCPCount; } } ++delta; ++n; } return output.join(''); }; /** * Converts a Punycode string representing a domain name or an email address * to Unicode. Only the Punycoded parts of the input will be converted, i.e. * it doesn't matter if you call it on a string that has already been * converted to Unicode. * @memberOf punycode * @param {String} input The Punycoded domain name or email address to * convert to Unicode. * @returns {String} The Unicode representation of the given Punycode * string. */ var toUnicode = function(input) { return mapDomain(input, function(string) { return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string; }); }; /** * Converts a Unicode string representing a domain name or an email address to * Punycode. Only the non-ASCII parts of the domain name will be converted, * i.e. it doesn't matter if you call it with a domain that's already in * ASCII. * @memberOf punycode * @param {String} input The domain name or email address to convert, as a * Unicode string. * @returns {String} The Punycode representation of the given domain name or * email address. */ var toASCII = function(input) { return mapDomain(input, function(string) { return regexNonASCII.test(string) ? 'xn--' + encode(string) : string; }); }; /*--------------------------------------------------------------------------*/ /** Define the public API */ var punycode = { /** * A string representing the current Punycode.js version number. * @memberOf punycode * @type String */ 'version': '2.0.0', /** * An object of methods to convert from JavaScript's internal character * representation (UCS-2) to Unicode code points, and back. * @see <https://mathiasbynens.be/notes/javascript-encoding> * @memberOf punycode * @type Object */ 'ucs2': { 'decode': ucs2decode, 'encode': ucs2encode }, 'decode': decode, 'encode': encode, 'toASCII': toASCII, 'toUnicode': toUnicode }; require.cache('punycode', punycode); }()); return this; }; Boot.prototype.util = function(require){ (function(){ //var util = require('util'); /*/ Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. */ var punycode=require.cache('punycode'); var util = {}; var formatRegExp = /%[sdj%]/g; util.format = function(f) { if (!isString(f)) { var objects = []; for (var i = 0; i < arguments.length; i++) { objects.push(inspect(arguments[i])); } return objects.join(' '); } var i = 1; var args = arguments; var len = args.length; var str = String(f).replace(formatRegExp, function(x) { if (x === '%%') return '%'; if (i >= len) return x; switch (x) { case '%s': return String(args[i++]); case '%d': return Number(args[i++]); case '%j': try { return JSON.stringify(args[i++]); } catch (_) { return '[Circular]'; } default: return x; } }); for (var x = args[i]; i < len; x = args[++i]) { if (isNull(x) || !isObject(x)) { str += ' ' + x; } else { str += ' ' + inspect(x); } } return str; }; /** * Echos the value of a value. Trys to print the value out * in the best way possible given the different types. * * @param {Object} obj The object to print out. * @param {Object} opts Optional options object that alters the output. */ /* legacy: obj, showHidden, depth, colors*/ function inspect(obj, opts) { var ctx = { seen: [], stylize: stylizeNoColor }; if (arguments.length >= 3) ctx.depth = arguments[2]; if (arguments.length >= 4) ctx.colors = arguments[3]; if (isBoolean(opts)) { ctx.showHidden = opts; } else if (opts) { util._extend(ctx, opts); } if (isUndefined(ctx.showHidden)) ctx.showHidden = false; if (isUndefined(ctx.depth)) ctx.depth = 2; if (isUndefined(ctx.colors)) ctx.colors = false; if (isUndefined(ctx.customInspect)) ctx.customInspect = true; if (ctx.colors) ctx.stylize = stylizeWithColor; return formatValue(ctx, obj, ctx.depth); } util.inspect = inspect; inspect.colors = { 'bold' : [1, 22], 'italic' : [3, 23], 'underline' : [4, 24], 'inverse' : [7, 27], 'white' : [37, 39], 'grey' : [90, 39], 'black' : [30, 39], 'blue' : [34, 39], 'cyan' : [36, 39], 'green' : [32, 39], 'magenta' : [35, 39], 'red' : [31, 39], 'yellow' : [33, 39] }; inspect.styles = { 'special': 'cyan', 'number': 'yellow', 'boolean': 'yellow', 'undefined': 'grey', 'null': 'bold', 'string': 'green', 'date': 'magenta', 'regexp': 'red' }; function stylizeWithColor(str, styleType) { var style = inspect.styles[styleType]; if (style) { return '\u001b[' + inspect.colors[style][0] + 'm' + str + '\u001b[' + inspect.colors[style][1] + 'm'; } else { return str; } } function stylizeNoColor(str, styleType) { return str; } function arrayToHash(array) { var hash = {}; array.forEach(function(val, idx) { hash[val] = true; }); return hash; } function formatValue(ctx, value, recurseTimes) { var shims = {}; if (new Error().hasOwnProperty('description')) { var ERROR_PROPERTY_FILTER = function (obj, array) { if (Object.prototype.toString.call(obj) === '[object Error]') { array = array.filter(function (name) { return name !== 'description' && name !== 'number'; }); } return array; }; shims.keys = function (object) { return ERROR_PROPERTY_FILTER(object, Object.keys(object)); }; shims.getOwnPropertyNames = function (object) { return ERROR_PROPERTY_FILTER(object, Object.getOwnPropertyNames(object)); }; } else { shims.keys = Object.keys; shims.getOwnPropertyNames = Object.getOwnPropertyNames; } if (ctx.customInspect && value && isFunction(value.inspect) && value.inspect !== util.inspect && !(value.constructor && value.constructor.prototype === value)) { var ret = value.inspect(recurseTimes); if (!isString(ret)) { ret = formatValue(ctx, ret, recurseTimes); } return ret; } var primitive = formatPrimitive(ctx, value); if (primitive) { return primitive; } var keys = shims.keys(value); var visibleKeys = arrayToHash(keys); if (ctx.showHidden) { keys = shims.getOwnPropertyNames(value); } if (keys.length === 0) { if (isFunction(value)) { var name = value.name ? ': ' + value.name : ''; return ctx.stylize('[Function' + name + ']', 'special'); } if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } if (isDate(value)) { return ctx.stylize(Date.prototype.toString.call(value), 'date'); } if (isError(value)) { return formatError(value); } } var base = '', array = false, braces = ['{', '}']; if (isArray(value)) { array = true; braces = ['[', ']']; } if (isFunction(value)) { var n = value.name ? ': ' + value.name : ''; base = ' [Function' + n + ']'; } if (isRegExp(value)) { base = ' ' + RegExp.prototype.toString.call(value); } if (isDate(value)) { base = ' ' + Date.prototype.toUTCString.call(value); } if (isError(value)) { base = ' ' + formatError(value); } if (keys.length === 0 && (!array || value.length == 0)) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } else { return ctx.stylize('[Object]', 'special'); } } ctx.seen.push(value); var output; if (array) { output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); } else { output = keys.map(function(key) { return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); }); } ctx.seen.pop(); return reduceToSingleString(output, base, braces); } function formatPrimitive(ctx, value) { if (isUndefined(value)) return ctx.stylize('undefined', 'undefined'); if (isString(value)) { var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return ctx.stylize(simple, 'string'); } if (isNumber(value)) return ctx.stylize('' + value, 'number'); if (isBoolean(value)) return ctx.stylize('' + value, 'boolean'); // For some reason typeof null is "object", so special case here. if (isNull(value)) return ctx.stylize('null', 'null'); } function formatError(value) { return '[' + Error.prototype.toString.call(value) + ']'; } function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { var output = []; for (var i = 0, l = value.length; i < l; ++i) { if (hasOwnProperty(value, String(i))) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); } else { output.push(''); } } keys.forEach(function(key) { if (!key.match(/^\d+$/)) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); } }); return output; } function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { var name, str, desc; desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; if (desc.get) { if (desc.set) { str = ctx.stylize('[Getter/Setter]', 'special'); } else { str = ctx.stylize('[Getter]', 'special'); } } else { if (desc.set) { str = ctx.stylize('[Setter]', 'special'); } } if (!hasOwnProperty(visibleKeys, key)) { name = '[' + key + ']'; } if (!str) { if (ctx.seen.indexOf(desc.value) < 0) { if (isNull(recurseTimes)) { str = formatValue(ctx, desc.value, null); } else { str = formatValue(ctx, desc.value, recurseTimes - 1); } if (str.indexOf('\n') > -1) { if (array) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); } else { str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); } } } else { str = ctx.stylize('[Circular]', 'special'); } } if (isUndefined(name)) { if (array && key.match(/^\d+$/)) { return str; } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = ctx.stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') .replace(/(^"|"$)/g, "'"); name = ctx.stylize(name, 'string'); } } return name + ': ' + str; } function reduceToSingleString(output, base, braces) { var numLinesEst = 0; var length = output.reduce(function(prev, cur) { numLinesEst++; if (cur.indexOf('\n') >= 0) numLinesEst++; return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; }, 0); if (length > 60) { return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1]; } return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; } // NOTE: These type checking functions intentionally don't use `instanceof` // because it is fragile and can be easily faked with `Object.create()`. function isArray(ar) { return Array.isArray(ar); } util.isArray = isArray; function isBoolean(arg) { return typeof arg === 'boolean'; } util.isBoolean = isBoolean; function isNull(arg) { return arg === null; } util.isNull = isNull; function isNullOrUndefined(arg) { return arg == null; } util.isNullOrUndefined = isNullOrUndefined; function isNumber(arg) { return typeof arg === 'number'; } util.isNumber = isNumber; function isString(arg) { return typeof arg === 'string'; } util.isString = isString; function isSymbol(arg) { return typeof arg === 'symbol'; } util.isSymbol = isSymbol; function isUndefined(arg) { return arg === void 0; } util.isUndefined = isUndefined; function isRegExp(re) { return isObject(re) && objectToString(re) === '[object RegExp]'; } util.isRegExp = isRegExp; function isObject(arg) { return typeof arg === 'object' && arg; } util.isObject = isObject; function isDate(d) { return isObject(d) && objectToString(d) === '[object Date]'; } util.isDate = isDate; function isError(e) { return isObject(e) && objectToString(e) === '[object Error]'; } util.isError = isError; function isFunction(arg) { return typeof arg === 'function'; } util.isFunction = isFunction; function isPrimitive(arg) { return arg === null || typeof arg === 'boolean' || typeof arg === 'number' || typeof arg === 'string' || typeof arg === 'symbol' || // ES6 symbol typeof arg === 'undefined'; } util.isPrimitive = isPrimitive; function isBuffer(arg) { return arg && typeof arg === 'object' && typeof arg.copy === 'function' && typeof arg.fill === 'function' && typeof arg.binarySlice === 'function' ; } util.isBuffer = isBuffer; function objectToString(o) { return Object.prototype.toString.call(o); } function pad(n) { return n < 10 ? '0' + n.toString(10) : n.toString(10); } var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; // 26 Feb 16:19:34 function timestamp() { var d = new Date(); var time = [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join(':'); return [d.getDate(), months[d.getMonth()], time].join(' '); } // log is just a thin wrapper to console.log that prepends a timestamp util.log = function() { console.log('%s - %s', timestamp(), util.format.apply(util, arguments)); }; /** * Inherit the prototype methods from one constructor into another. * * The Function.prototype.inherits from lang.js rewritten as a standalone * function (not on Function.prototype). NOTE: If this file is to be loaded * during bootstrapping this function needs to be rewritten using some native * functions as prototype setup using normal JavaScript does not work as * expected during bootstrapping (see mirror.js in r114903). * * @param {function} ctor Constructor function which needs to inherit the * prototype. * @param {function} superCtor Constructor function to inherit prototype from. */ util.inherits = function(ctor, superCtor) { ctor.super_ = superCtor; ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; util._extend = function(origin, add) { // Don't do anything if add isn't an object if (!add || !isObject(add)) return origin; var keys = Object.keys(add); var i = keys.length; while (i--) { origin[keys[i]] = add[keys[i]]; } return origin; }; function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } require.cache('util', util); }()); return this; }; Boot.prototype.url = function(require){ (function(){ /* exports.parse = urlParse; exports.resolve = urlResolve; exports.resolveObject = urlResolveObject; exports.format = urlFormat; exports.Url = Url; */ var util=require.cache('util'); var punycode=require.cache('punycode'); var url = { }; url.parse = urlParse; url.resolve = urlResolve; url.resolveObject = urlResolveObject; url.format = urlFormat; url.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 // define these here so at least they only have to be // compiled once on the first module load. var protocolPattern = /^([a-z0-9.+-]+:)/i, portPattern = /:[0-9]*$/, // Special case for a simple path URL simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/, // RFC 2396: characters reserved for delimiting URLs. // We actually just auto-escape these. delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], // RFC 2396: characters not allowed for various reasons. unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), // Allowed by RFCs, but cause of XSS attacks. Always escape these. autoEscape = ['\''].concat(unwise), // Characters that are never ever allowed in a hostname. // Note that any invalid chars are also handled, but these // are the ones that are *expected* to be seen, so we fast-path // them. nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), hostEndingChars = ['/', '?', '#'], hostnameMaxLen = 255, hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/, hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/, // protocols that can allow "unsafe" and "unwise" chars. unsafeProtocol = { 'javascript': true, 'javascript:': true }, // protocols that never have a hostname. hostlessProtocol = { 'javascript': true, 'javascript:': true }, // protocols that always contain a // bit. slashedProtocol = { 'http': true, 'https': true, 'ftp': true, 'gopher': true, 'file': true, 'http:': true, 'https:': true, 'ftp:': true, 'gopher:': true, 'file:': true }, querystring = require.cache('querystring'); Url.prototype.toString = function(){ return this.format(); }; Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { if (!util.isString(url)) { // throw new TypeError("Parameter 'url' must be a string, not " + typeof url); console.error("Parameter 'url' must be a string, not " + typeof url); return; } // Copy chrome, IE, opera backslash-handling behavior. // Back slashes before the query string get converted to forward slashes // See: https://code.google.com/p/chromium/issues/detail?id=25916 var queryIndex = url.indexOf('?'), splitter = (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#', uSplit = url.split(splitter), slashRegex = /\\/g; uSplit[0] = uSplit[0].replace(slashRegex, '/'); url = uSplit.join(splitter); var rest = url; // trim before proceeding. // This is to support parse stuff like " http://foo.com \n" rest = rest.trim(); if (!slashesDenoteHost && url.split('#').length === 1) { // Try fast path regexp var simplePath = simplePathPattern.exec(rest); if (simplePath) { this.path = rest; this.href = rest; this.pathname = simplePath[1]; if (simplePath[2]) { this.search = simplePath[2]; if (parseQueryString) { this.query = querystring.parse(this.search.substr(1)); } else { this.query = this.search.substr(1); } } else if (parseQueryString) { this.search = ''; this.query = {}; } return this; } } var proto = protocolPattern.exec(rest); if (proto) { proto = proto[0]; var lowerProto = proto.toLowerCase(); this.protocol = lowerProto; rest = rest.substr(proto.length); } // figure out if it's got a host // user@server is *always* interpreted as a hostname, and url // resolution will treat //foo/bar as host=foo,path=bar because that's // how the browser resolves relative URLs. if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { var slashes = rest.substr(0, 2) === '//'; if (slashes && !(proto && hostlessProtocol[proto])) { rest = rest.substr(2); this.slashes = true; } } if (!hostlessProtocol[proto] && (slashes || (proto && !slashedProtocol[proto]))) { // there's a hostname. // the first instance of /, ?, ;, or # ends the host. // // If there is an @ in the hostname, then non-host chars *are* allowed // to the left of the last @ sign, unless some host-ending character // comes *before* the @-sign. // URLs are obnoxious. // // ex: // http://a@b@c/ => user:a@b host:c // http://a@b?@c => user:a host:c path:/?@c // v0.12 TODO(isaacs): This is not quite how Chrome does things. // Review our test case against browsers more comprehensively. // 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; } // 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); } // 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); } // 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. this.hostname = this.hostname || ''; // if hostname begins with [ and ends with ] // assume that it's an IPv6 address. var ipv6Hostname = this.hostname[0] === '[' && this.hostname[this.hostname.length - 1] === ']'; // validate a little. if (!ipv6Hostname) { var hostparts = this.hostname.split(/\./); for (var i = 0, l = hostparts.length; i < l; i++) { var part = hostparts[i]; if (!part) continue; if (!part.match(hostnamePartPattern)) { var newpart = ''; for (var j = 0, k = part.length; j < k; j++) { if (part.charCodeAt(j) > 127) { // we replace non-ASCII char with a temporary placeholder // we need this to make sure size of hostname is not // broken by replacing non-ASCII by nothing newpart += 'x'; } else { newpart += part[j]; } } // we test again with ASCII char only if (!newpart.match(hostnamePartPattern)) { var validParts = hostparts.slice(0, i); var notHost = hostparts.slice(i + 1); var bit = part.match(hostnamePartStart); if (bit) { validParts.push(bit[1]); notHost.unshift(bit[2]); } if (notHost.length) { rest = '/' + notHost.join('.') + rest; } this.hostname = validParts.join('.'); break; } } } } if (this.hostname.length > hostnameMaxLen) { this.hostname = ''; } else { // hostnames are always lower case. this.hostname = this.hostname.toLowerCase(); } if (!ipv6Hostname) { // var punycode = require('punycode'); // IDNA Support: Returns a punycoded representation of "domain". // It only converts parts of the domain name that // have non-ASCII characters, i.e. it doesn't matter if // you call it with a domain that already is ASCII-only. this.hostname = punycode.toASCII(this.hostname); } 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) { this.hostname = this.hostname.substr(1, this.hostname.length - 2); if (rest[0] !== '/') { rest = '/' + rest; } } } // now rest is set to the post-host stuff. // chop off any delim chars. if (!unsafeProtocol[lowerProto]) { // First, make 100% sure that any "autoEscape" chars get // escaped, even if encodeURIComponent doesn't think they // need to be. for (var i = 0, l = autoEscape.length; i < l; i++) { var ae = autoEscape[i]; if (rest.indexOf(ae) === -1) continue; var esc = encodeURIComponent(ae); if (esc === ae) { esc = escape(ae); } rest = rest.split(ae).join(esc); } } // chop off from the tail first. var hash = rest.indexOf('#'); if (hash !== -1) { // got a fragment string. this.hash = rest.substr(hash); rest = rest.slice(0, hash); } var qm = rest.indexOf('?'); if (qm !== -1) { this.search = rest.substr(qm); this.query = rest.substr(qm + 1); if (parseQueryString) { this.query = querystring.parse(this.query); } rest = rest.slice(0, qm); } else if (parseQueryString) { // no query string, but parseQueryString still requested this.search = ''; this.query = {}; } if (rest) this.pathname = rest; if (slashedProtocol[lowerProto] && this.hostname && !this.pathname) { this.pathname = '/'; } //to support http.request 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. this.href = this.format(); return this; }; function urlParse(url, parseQueryString, slashesDenoteHost) { if (url && util.isObject(url) && url instanceof Url) return url; try{ var u = new Url(); if('function'===typeof u.parse)u.parse(url, parseQueryString, slashesDenoteHost); }catch(err){ var u = new Url(); console.notice(err); } return u; } // format a parsed object into a url string function urlFormat(obj) { // ensure it's an object, and not a string url. // If it's an obj, this is a no-op. // this way, you can call url_format() on strings // to clean up potentially wonky urls. if (util.isString(obj)) obj = urlParse(obj); if (!(obj instanceof Url)) return Url.prototype.format.call(obj); return obj.format(); } Url.prototype.format = function() { var auth = this.auth || ''; if (auth) { auth = encodeURIComponent(auth); auth = auth.replace(/%3A/i, ':'); auth += '@'; } var protocol = this.protocol || '', pathname = this.pathname || '', hash = this.hash || '', host = false, query = ''; 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 (this.query && util.isObject(this.query) && Object.keys(this.query).length) { query = querystring.stringify(this.query); } var search = this.search || (query && ('?' + query)) || ''; if (protocol && protocol.substr(-1) !== ':') protocol += ':'; // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. // unless they had them to begin with. if (this.slashes || (!protocol || slashedProtocol[protocol]) && host !== false) { host = '//' + (host || ''); if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; } else if (!host) { host = ''; } if (hash && hash.charAt(0) !== '#') hash = '#' + hash; if (search && search.charAt(0) !== '?') search = '?' + search; pathname = pathname.replace(/[?#]/g, function(match) { return encodeURIComponent(match); }); search = search.replace('#', '%23'); return protocol + host + pathname + search + hash; }; function urlResolve(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); } Url.prototype.resolveObject = function(relative) { if (util.isString(relative)) { var rel = new Url(); rel.parse(relative, false, true); relative = rel; } var result = new Url(); var tkeys = Object.keys(this); for (var tk = 0; tk < tkeys.length; tk++) { var tkey = tkeys[tk]; result[tkey] = this[tkey]; } // hash is always overridden, no matter what. // 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 === '') { result.href = result.format(); return result; } // hrefs like //foo/bar always cut to the protocol. if (relative.slashes && !relative.protocol) { // take everything except the protocol from relative var rkeys = Object.keys(relative); for (var rk = 0; rk < rkeys.length; rk++) { var rkey = rkeys[rk]; if (rkey !== 'protocol') result[rkey] = relative[rkey]; } //urlParse appends trailing / to urls like http://www.example.com if (slashedProtocol[result.protocol] && result.hostname && !result.pathname) { result.path = result.pathname = '/'; } result.href = result.format(); return result; } if (relative.protocol && relative.protocol !== result.protocol) { // if it's a known url protocol, then changing // the protocol does weird things // first, if it's not file:, then we MUST have a host, // and if there was a path // to begin with, then we MUST have a path. // if it is file:, then the host is dropped, // because that's known to be hostless. // anything else is assumed to be absolute. if (!slashedProtocol[relative.protocol]) { var keys = Object.keys(relative); for (var v = 0; v < keys.length; v++) { var k = keys[v]; result[k] = relative[k]; } result.href = result.format(); return result; } result.protocol = relative.protocol; if (!relative.host && !hostlessProtocol[relative.protocol]) { var relPath = (relative.pathname || '').split('/'); while (relPath.length && !(relative.host = relPath.shift())); if (!relative.host) relative.host = ''; if (!relative.hostname) relative.hostname = ''; if (relPath[0] !== '') relPath.unshift(''); if (relPath.length < 2) relPath.unshift(''); result.pathname = relPath.join('/'); } else { result.pathname = relative.pathname; } 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; } result.slashes = result.slashes || relative.slashes; result.href = result.format(); return result; } var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), isRelAbs = ( relative.host || relative.pathname && relative.pathname.charAt(0) === '/' ), mustEndAbs = (isRelAbs || isSourceAbs || (result.host && relative.pathname)), removeAllDots = mustEndAbs, srcPath = result.pathname && result.pathname.split('/') || [], relPath = relative.pathname && relative.pathname.split('/') || [], psychotic = result.protocol && !slashedProtocol[result.protocol]; // if the url is a non-slashed url, then relative // links like ../.. should be able // to crawl up to the hostname, as well. This is strange. // result.protocol has already been set by now. // Later on, put the first path part into the host field. if (psychotic) { result.hostname = ''; result.port = null; if (result.host) { if (srcPath[0] === '') srcPath[0] = result.host; else srcPath.unshift(result.host); } result.host = ''; if (relative.protocol) { relative.hostname = null; relative.port = null; if (relative.host) { if (relPath[0] === '') relPath[0] = relative.host; else relPath.unshift(relative.host); } relative.host = null; } mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); } if (isRelAbs) { // it's absolute. 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; // fall through to the dot-handling below. } else if (relPath.length) { // it's relative // throw away the existing file, and take the new path instead. if (!srcPath) srcPath = []; srcPath.pop(); srcPath = srcPath.concat(relPath); result.search = relative.search; result.query = relative.query; } else if (!util.isNullOrUndefined(relative.search)) { // just pull out the search. // like href='?foo'. // Put this after the other two cases because it simplifies the booleans if (psychotic) { result.hostname = result.host = srcPath.shift(); //occationaly the auth can get stuck only in host //this especially happens in cases like //url.resolveObject('mailto:local1@domain1', 'local2@domain2') var authInHost = result.host && result.host.indexOf('@') > 0 ? result.host.split('@') : false; if (authInHost) { result.auth = authInHost.shift(); result.host = result.hostname = authInHost.shift(); } } result.search = relative.search; result.query = relative.query; //to support http.request if (!util.isNull(result.pathname) || !util.isNull(result.search)) { result.path = (result.pathname ? result.pathname : '') + (result.search ? result.search : ''); } result.href = result.format(); return result; } if (!srcPath.length) { // no path at all. easy. // we've already handled the other stuff above. result.pathname = null; //to support http.request if (result.search) { result.path = '/' + result.search; } else { result.path = null; } result.href = result.format(); return result; } // if a url ENDs in . or .., then it must get a trailing slash. // however, if it ends in anything else non-slashy, // then it must NOT get a trailing slash. var last = srcPath.slice(-1)[0]; var hasTrailingSlash = ( (result.host || relative.host || srcPath.length > 1) && (last === '.' || last === '..') || last === ''); // strip single dots, resolve double dots to parent dir // if the path tries to go above the root, `up` ends up > 0 var up = 0; for (var i = srcPath.length; i >= 0; i--) { last = srcPath[i]; if (last === '.') { srcPath.splice(i, 1); } else if (last === '..') { srcPath.splice(i, 1); up++; } else if (up) { srcPath.splice(i, 1); up--; } } // if the path is allowed to go above the root, restore leading ..s if (!mustEndAbs && !removeAllDots) { for (; up--; up) { srcPath.unshift('..'); } } if (mustEndAbs && srcPath[0] !== '' && (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { srcPath.unshift(''); } if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { srcPath.push(''); } var isAbsolute = srcPath[0] === '' || (srcPath[0] && srcPath[0].charAt(0) === '/'); // put the host back if (psychotic) { result.hostname = result.host = isAbsolute ? '' : srcPath.length ? srcPath.shift() : ''; //occationaly the auth can get stuck only in host //this especially happens in cases like //url.resolveObject('mailto:local1@domain1', 'local2@domain2') var authInHost = result.host && result.host.indexOf('@') > 0 ? result.host.split('@') : false; if (authInHost) { result.auth = authInHost.shift(); result.host = result.hostname = authInHost.shift(); } } mustEndAbs = mustEndAbs || (result.host && srcPath.length); if (mustEndAbs && !isAbsolute) { srcPath.unshift(''); } if (!srcPath.length) { result.pathname = null; result.path = null; } else { result.pathname = srcPath.join('/'); } //to support request.http if (!util.isNull(result.pathname) || !util.isNull(result.search)) { result.path = (result.pathname ? result.pathname : '') + (result.search ? result.search : ''); } result.auth = relative.auth || result.auth; result.slashes = result.slashes || relative.slashes; result.href = result.format(); return result; }; Url.prototype.parseHost = function() { var host = this.host; var port = portPattern.exec(host); if (port) { port = port[0]; if (port !== ':') { this.port = port.substr(1); } host = host.substr(0, host.length - port.length); } if (host) this.hostname = host; }; require.cache('url', url); }()); return this; }; exports =module.exports = Boot;