<commit_before>// ==UserScript==
// @name         hostloc_image
// @namespace    https://github.com/reruin
// @version      0.2
// @license      MIT
// @description  hostloc_image
// @author       reruin@gmail.com
// @grant        none
// @include      http://www.hostloc.com/*
// @include      https://hostloc.com/*
// @connect      *
// @run-at       document-start
// ==/UserScript==

(function(root){
  var nw = root.nw = {};
  var stack = [];
  var ArrayProto = Array.prototype, ObjProto = Object.prototype;
  var hasOwnProperty   = ObjProto.hasOwnProperty;

  var page  = {
    addStyle : function(css){
        var el = document.createElement("style");
        el.innerHTML = css;
        document.getElementsByTagName('head')[0].appendChild(el);
    },
    addScript : function(script , pos){
      var el = document.createElement("script");
      el.textContent = script;
      if(typeof pos == 'object'){
        pos.appendChild(el);
      }
      else if(pos == 'head'){
        document.getElementsByTagName('head')[0].appendChild(el);
      }else{
        document.getElementsByTagName('body')[0].appendChild(el);
      }
    },
    addScriptLink : function( data , pos){
      var el = document.createElement("script");
      for(var i in data){
        el.setAttribute(i , data[i]);
      }

      if(typeof pos == 'object'){
        pos.appendChild(el);
      }
      else if(pos == 'head'){
        document.getElementsByTagName('head')[0].appendChild(el);
      }else{
        document.getElementsByTagName('body')[0].appendChild(el);
      }
    },
    addHtml : function(dom){
      var el = document.createElement("dom");
      el.innerHTML = dom;
      document.getElementsByTagName('body')[0].appendChild(el);
    }
  };

  function $(e){
    return document.querySelector(e);
  }
  function $$(e){
    return document.querySelectorAll(e);
  }

  function noop(){

  }

  function has(obj, key) {
      return obj != null && hasOwnProperty.call(obj, key);
  }

  function key(obj){
      var k = [];
      for(var i in obj){
          if(has(obj , i)) k.push(i);
      }
      return k;
  }

  function isString(v){
    return typeof v === 'string';
  }

  function is(v , b){
    return ObjProto.toString.call(v) === "[object "+b+"]";
  }

  function isArray(v){
    return is(v , 'Array');
  }

  function isRegExp(v){
    return is(v , 'RegExp');
  }

  function isObject(v){
    return is(v , 'Object');
  }

  function isFunction(v){
    return is(v , 'Function');
  }

  function create(expr , handler){
    if(expr && handler){
      stack.push({rule:expr , post:handler});
    }
    else{
      stack.push(expr);
    }
  }

  function replace(str,obj , format){
      return str.replace(RegExp('(?:' + key(obj).join('|').replace(/([\:\'\)\(\{\}])/g,'\\$1') + ')','g') , function(match){
          return format ? format(obj[match]) : obj[match];
      });
  }

  function toArray(a){
    return Array.prototype.slice.call(a);
  }

  function formatLink(newurl , m){
    return newurl.replace(/\$(\d+)/g , function($0,$1){
      return m[$1];
    });
  }

  function hit(obj){
    var ret = [];
    for(var i in stack){
        var rule = stack[i].rule;
        if( isRegExp(rule) ){
          var m = obj.url.match(rule);
            // console.log(stack[i].post,m)
          if( m ){
            if(isString(stack[i].post)){
              ret.push({
                redirect : formatLink(stack[i].post , toArray(m))
              });
            }else{
              ret.push({
                pre : stack[i].pre || noop,
                post : stack[i].post || noop,
                args : toArray(m)
              });

            }
          }

        }
        else if(isObject(rule)){
          var flag = true;
          var m = null, ret_t = {};
          for(var key in rule){
            m = obj[key].match(rule[key]);
            if(!m){
              flag = false;
              break;
            }else{
              if(m.length>1){
                ret_t[key] = toArray(m);
              }
            }
          }
          if(flag){
            ret.push({
              pre : stack[i].pre || noop,
              post : stack[i].post || noop,
              args : ret_t
            });
          }
        }
        else if(isFunction(rule)){
          if( rule() ){
            ret.push({
              pre : stack[i].pre || noop,
              post : stack[i].post || noop,
              args : {}
            });
          }
        }
        else if(isArray(rule)){
          var flag = false;
          for (var j = rule.length - 1; j >= 0; j--) {
            if(obj.url.match(rule[j])){
              flag = true;
              break;
            }
          }
          if(flag){
            ret.push({
              pre : stack[i].pre || noop,
              post : stack[i].post || noop,
              args : {}
            });
          }
        }
    }
    return ret;
  }

  function init(){
    var loc = window.location;

    var obj = {
      url : loc.href,
      scheme: loc.protocol.slice(0, -1),
      host: loc.hostname,
      port: loc.port,
      path: loc.pathname,
      search: loc.search,
      hash: loc.hash
    };

    var handlers = hit(obj);
    if(handlers.length){
      handlers.forEach(function(handler){
        if(handler.redirect){
          open(handler.redirect);
        }
        else if(handler.pre) handler.pre(handler.args);
      });
    }

    document.addEventListener('DOMContentLoaded' , function(){
      if(handlers.length){
        handlers.forEach(function(handler){
          if(handler.post) {
            console.log(handler.post)
            handler.post(handler.args);
          }
        });
      }
    })
  }

  function monitor(tag , expr , callback){
    var d = tag.split(':');
    var evts = {
      'removed':'DOMNodeRemoved',
      'inserted':'DOMNodeInserted',
      'modified':'DOMSubtreeModified'
    };

    tag = d[0];

    var evt = evts[d[1] || 'modified'];

    var watch = d[2] === undefined ? false : true;

    if(isFunction(expr))  {
      callback = expr;
      expr =  null ;
    }

    var matchSpan = function(target , t){
      var k = document.createElement('div');
      k.appendChild(target.cloneNode(false));
      var ret = k.querySelector(t);
      k = null;
      return ret;
    }

    //return new promise(function(resolve, reject){
      var handler = function(event){
        var target = event.target;
        if(matchSpan(target , tag)){
          if(expr){
            var m = target.textContent.match(expr);
            if(m){
              if(callback) callback(m);
              if(!watch) document.removeEventListener(evt , handler);
            }
          }else{
            if(callback) callback(target);

            if(!watch) document.removeEventListener(evt , handler);
          }
        }
      };

      document.addEventListener(evt , handler);
    //});
  }

  function open(url){
    open_direct(url);
  }

  function open_direct(url){
    var link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
    link.href = url;
    link.click();
  }

  nw.c = create;
  nw.m = monitor;
  nw.o = open;

  nw.$ = $;
  nw.$$ = $$;
  nw.r = replace;

  nw.init = init;
  nw.noop = noop;

  nw.addStyle = page.addStyle;
  nw.addScript = page.addScript;
  nw.addScriptLink = page.addScriptLink;
}(this));

/**
 * hostloc.com
 *
 * fix image upload
 */

nw.c([
  /hostloc\.com\/thread/,
  /hostloc\.com\/forum\.php\?mod=post/,
  /hostloc\.com\/forum\.php\?mod=viewthread/,
  ] , function(){

    nw.addScriptLink({
      'src' : 'https://imgchr.com/sdk/pup.js',
      'id' : 'chevereto-pup-src',
      'data-url':'https://imgchr.com/upload',
      'data-auto-insert':'bbcode-embed-medium'
    });

    nw.addStyle('a.chevereto-pup-button--discuz,body .b1r a.chevereto-pup-button--discuz{background: none !important;color: #8e44ad !important;border:none !important;}');
});

//==================================
nw.init();<commit_msg>fix image quality<commit_after>// ==UserScript==
// @name         hostloc_image
// @namespace    https://github.com/reruin
// @version      0.3
// @license      MIT
// @description  hostloc_image
// @author       reruin@gmail.com
// @grant        none
// @include      http://www.hostloc.com/*
// @include      https://hostloc.com/*
// @connect      *
// @run-at       document-start
// ==/UserScript==

(function(root){
  var nw = root.nw = {};
  var stack = [];
  var ArrayProto = Array.prototype, ObjProto = Object.prototype;
  var hasOwnProperty   = ObjProto.hasOwnProperty;

  var page  = {
    addStyle : function(css){
        var el = document.createElement("style");
        el.innerHTML = css;
        document.getElementsByTagName('head')[0].appendChild(el);
    },
    addScript : function(script , pos){
      var el = document.createElement("script");
      el.textContent = script;
      if(typeof pos == 'object'){
        pos.appendChild(el);
      }
      else if(pos == 'head'){
        document.getElementsByTagName('head')[0].appendChild(el);
      }else{
        document.getElementsByTagName('body')[0].appendChild(el);
      }
    },
    addScriptLink : function( data , pos){
      var el = document.createElement("script");
      for(var i in data){
        el.setAttribute(i , data[i]);
      }

      if(typeof pos == 'object'){
        pos.appendChild(el);
      }
      else if(pos == 'head'){
        document.getElementsByTagName('head')[0].appendChild(el);
      }else{
        document.getElementsByTagName('body')[0].appendChild(el);
      }
    },
    addHtml : function(dom){
      var el = document.createElement("dom");
      el.innerHTML = dom;
      document.getElementsByTagName('body')[0].appendChild(el);
    }
  };

  function $(e){
    return document.querySelector(e);
  }
  function $$(e){
    return document.querySelectorAll(e);
  }

  function noop(){

  }

  function has(obj, key) {
      return obj != null && hasOwnProperty.call(obj, key);
  }

  function key(obj){
      var k = [];
      for(var i in obj){
          if(has(obj , i)) k.push(i);
      }
      return k;
  }

  function isString(v){
    return typeof v === 'string';
  }

  function is(v , b){
    return ObjProto.toString.call(v) === "[object "+b+"]";
  }

  function isArray(v){
    return is(v , 'Array');
  }

  function isRegExp(v){
    return is(v , 'RegExp');
  }

  function isObject(v){
    return is(v , 'Object');
  }

  function isFunction(v){
    return is(v , 'Function');
  }

  function create(expr , handler){
    if(expr && handler){
      stack.push({rule:expr , post:handler});
    }
    else{
      stack.push(expr);
    }
  }

  function replace(str,obj , format){
      return str.replace(RegExp('(?:' + key(obj).join('|').replace(/([\:\'\)\(\{\}])/g,'\\$1') + ')','g') , function(match){
          return format ? format(obj[match]) : obj[match];
      });
  }

  function toArray(a){
    return Array.prototype.slice.call(a);
  }

  function formatLink(newurl , m){
    return newurl.replace(/\$(\d+)/g , function($0,$1){
      return m[$1];
    });
  }

  function hit(obj){
    var ret = [];
    for(var i in stack){
        var rule = stack[i].rule;
        if( isRegExp(rule) ){
          var m = obj.url.match(rule);
            // console.log(stack[i].post,m)
          if( m ){
            if(isString(stack[i].post)){
              ret.push({
                redirect : formatLink(stack[i].post , toArray(m))
              });
            }else{
              ret.push({
                pre : stack[i].pre || noop,
                post : stack[i].post || noop,
                args : toArray(m)
              });

            }
          }

        }
        else if(isObject(rule)){
          var flag = true;
          var m = null, ret_t = {};
          for(var key in rule){
            m = obj[key].match(rule[key]);
            if(!m){
              flag = false;
              break;
            }else{
              if(m.length>1){
                ret_t[key] = toArray(m);
              }
            }
          }
          if(flag){
            ret.push({
              pre : stack[i].pre || noop,
              post : stack[i].post || noop,
              args : ret_t
            });
          }
        }
        else if(isFunction(rule)){
          if( rule() ){
            ret.push({
              pre : stack[i].pre || noop,
              post : stack[i].post || noop,
              args : {}
            });
          }
        }
        else if(isArray(rule)){
          var flag = false;
          for (var j = rule.length - 1; j >= 0; j--) {
            if(obj.url.match(rule[j])){
              flag = true;
              break;
            }
          }
          if(flag){
            ret.push({
              pre : stack[i].pre || noop,
              post : stack[i].post || noop,
              args : {}
            });
          }
        }
    }
    return ret;
  }

  function init(){
    var loc = window.location;

    var obj = {
      url : loc.href,
      scheme: loc.protocol.slice(0, -1),
      host: loc.hostname,
      port: loc.port,
      path: loc.pathname,
      search: loc.search,
      hash: loc.hash
    };

    var handlers = hit(obj);
    if(handlers.length){
      handlers.forEach(function(handler){
        if(handler.redirect){
          open(handler.redirect);
        }
        else if(handler.pre) handler.pre(handler.args);
      });
    }

    document.addEventListener('DOMContentLoaded' , function(){
      if(handlers.length){
        handlers.forEach(function(handler){
          if(handler.post) {
            console.log(handler.post)
            handler.post(handler.args);
          }
        });
      }
    })
  }

  function monitor(tag , expr , callback){
    var d = tag.split(':');
    var evts = {
      'removed':'DOMNodeRemoved',
      'inserted':'DOMNodeInserted',
      'modified':'DOMSubtreeModified'
    };

    tag = d[0];

    var evt = evts[d[1] || 'modified'];

    var watch = d[2] === undefined ? false : true;

    if(isFunction(expr))  {
      callback = expr;
      expr =  null ;
    }

    var matchSpan = function(target , t){
      var k = document.createElement('div');
      k.appendChild(target.cloneNode(false));
      var ret = k.querySelector(t);
      k = null;
      return ret;
    }

    //return new promise(function(resolve, reject){
      var handler = function(event){
        var target = event.target;
        if(matchSpan(target , tag)){
          if(expr){
            var m = target.textContent.match(expr);
            if(m){
              if(callback) callback(m);
              if(!watch) document.removeEventListener(evt , handler);
            }
          }else{
            if(callback) callback(target);

            if(!watch) document.removeEventListener(evt , handler);
          }
        }
      };

      document.addEventListener(evt , handler);
    //});
  }

  function open(url){
    open_direct(url);
  }

  function open_direct(url){
    var link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
    link.href = url;
    link.click();
  }

  nw.c = create;
  nw.m = monitor;
  nw.o = open;

  nw.$ = $;
  nw.$$ = $$;
  nw.r = replace;

  nw.init = init;
  nw.noop = noop;

  nw.addStyle = page.addStyle;
  nw.addScript = page.addScript;
  nw.addScriptLink = page.addScriptLink;
}(this));

/**
 * hostloc.com
 *
 * fix image upload
 */

nw.c([
  /hostloc\.com\/thread/,
  /hostloc\.com\/forum\.php\?mod=post/,
  /hostloc\.com\/forum\.php\?mod=viewthread/,
  ] , function(){

    nw.addScriptLink({
      'src' : 'https://imgchr.com/sdk/pup.js',
      'id' : 'chevereto-pup-src',
      'data-url':'https://imgchr.com/upload',
      'data-auto-insert':'bbcode-embed'
    });

    nw.addStyle('a.chevereto-pup-button--discuz,body .b1r a.chevereto-pup-button--discuz{background: none !important;color: #8e44ad !important;border:none !important;}');
});

//==================================
nw.init();<|endoftext|>


<commit_before>var gamejs = require('../gamejs');

/**
 * @fileoverview Playing sounds with the html5 audio tag. Audio files must be preloaded
 * with the usual `gamejs.preload()` function. Ogg, wav and webm supported.
 *
 * Sounds & Images are loaded relative to './'. You can change that, by setting
 * $g.resourceBaseHref in your page *before* loading the GameJs modules:
 *
 *     <script>
 *     var $g = {
 *        resourceBaseHref: 'http://example.com/resources/'
 *     }
 *     </script>
 *     <script src="./gamejs-wrapped.js"></script>
 *     ....
 *
 * **Note**: sound doesn't work very well across browsers yet. Firefox is best, but all still have
 * bugs.
 */

var CACHE = {};

/**
 * need to export preloading status for require
 * @ignore
 */
var _PRELOADING = false;

/**
 * put all audios on page in cache
 * if same domain as current page, remove common href-prefix
 * @ignore
 */
exports.init = function() {
   var audios = Array.prototype.slice.call(document.getElementsByTagName("audio"), 0);
   addToCache(audios);
   return;
};

/**
 * Preload the audios into cache
 * @param {String[]} List of audio URIs to load
 * @returns {Function} which returns 0-1 for preload progress
 * @ignore
 */
exports.preload = function(audioUrls, showProgressOrImage) {
   var countTotal = 0;
   var countLoaded = 0;

   function incrementLoaded() {
      countLoaded++;
      if (countLoaded == countTotal) {
         _PRELOADING = false;
      }
   }

   function getProgress() {
      return countTotal > 0 ? countLoaded / countTotal : 1;
   }

   function successHandler() {
      addToCache(this);
      incrementLoaded();
   }
   function errorHandler() {
      incrementLoaded();
      throw new Error('Error loading ' + this.src);
   }

   for (var key in audioUrls) {
      if (key.indexOf('wav') == -1 && key.indexOf('ogg') == -1 && key.indexOf('webm') == -1) {
         continue;
      }
      countTotal++;
      var audio = new Audio();
      audio.addEventListener('canplay', successHandler, true);
      audio.addEventListener('error', errorHandler, true);
      audio.src = audioUrls[key];
      audio.gamejsKey = key;
      audio.load();
   }
   if (countTotal > 0) {
      _PRELOADING = true;
   }
   return getProgress;
};

/**
 * @ignore
 */
exports.isPreloading = function() {
   return _PRELOADING;
};

/**
 * @param {dom.ImgElement} audios the <audio> elements to put into cache
 * @ignore
 */
function addToCache(audios) {
   if (!(audios instanceof Array)) {
      audios = [audios];
   }

   var docLoc = document.location.href;
   audios.forEach(function(audio) {
      CACHE[audio.gamejsKey] = audio;
   });
   return;
}

/**
 * Sounds can be played back.
 * @constructor
 * @param {String|dom.AudioElement} uriOrAudio the uri of <audio> dom element
 *                of the sound
 */
exports.Sound = function Sound(uriOrAudio) {
   var cachedAudio;
   if (typeof uriOrAudio === 'string') {
      cachedAudio = CACHE[uriOrAudio];
   } else {
      cachedAudio = uriOrAudio;
   }
   if (!cachedAudio) {
      // TODO sync audio loading
      throw new Error('Missing "' + uriOrAudio + '", gamejs.preload() all audio files before loading');
   }

   var audio = new Audio();
   audio.preload = "auto";
   audio.loop = false;
   audio.src = cachedAudio.src;
   /**
    * start the sound
    */
   this.play = function() {
      if (audio.ended || audio.paused) {
         audio.play();
      }
   };

   /**
    * Stop the sound
    */
   this.stop = function() {
      audio.pause();
   };

   /**
    * Set volume of this sound
    * @param {Number} value volume from 0 to 1
    */
   this.setVolume = function(value) {
      audio.volume = value;
   };

   /**
    * @returns {Number} the sound's volume from 0 to 1
    */
   this.getVolume = function() {
      return audio.volume;
   };

   /**
    * @returns {Number} Duration of this sound in seconds
    */
   this.getLength = function() {
      return audio.duration;
   };

   return this;
};
<commit_msg>experimental channels for gamejs.mixer.<commit_after>var gamejs = require('../gamejs');

/**
 * @fileoverview Playing sounds with the html5 audio tag. Audio files must be preloaded
 * with the usual `gamejs.preload()` function. Ogg, wav and webm supported.
 *
 * Sounds & Images are loaded relative to './'. You can change that, by setting
 * $g.resourceBaseHref in your page *before* loading the GameJs modules:
 *
 *     <script>
 *     var $g = {
 *        resourceBaseHref: 'http://example.com/resources/'
 *     }
 *     </script>
 *     <script src="./gamejs-wrapped.js"></script>
 *     ....
 *
 * **Note**: sound doesn't work very well across browsers yet. Firefox is best, but all still have
 * bugs.
 */

var CACHE = {};

/**
 * need to export preloading status for require
 * @ignore
 */
var _PRELOADING = false;

/**
 * @ignore
 */
var NUM_CHANNELS = 8;

/**
 * Sets the number of available channels for the mixer. The default value is 8.
 */
exports.setNumChannels = function(count) {
   NUM_CHANNELS = parseInt(count, 10) || NUM_CHANNELS;
};

exports.getNumChannels = function() {
   return NUM_CHANNELS;
};

/**
 * put all audios on page in cache
 * if same domain as current page, remove common href-prefix
 * @ignore
 */
exports.init = function() {
   var audios = Array.prototype.slice.call(document.getElementsByTagName("audio"), 0);
   addToCache(audios);
   return;
};

/**
 * Preload the audios into cache
 * @param {String[]} List of audio URIs to load
 * @returns {Function} which returns 0-1 for preload progress
 * @ignore
 */
exports.preload = function(audioUrls, showProgressOrImage) {
   var countTotal = 0;
   var countLoaded = 0;

   function incrementLoaded() {
      countLoaded++;
      if (countLoaded == countTotal) {
         _PRELOADING = false;
      }
   }

   function getProgress() {
      return countTotal > 0 ? countLoaded / countTotal : 1;
   }

   function successHandler() {
      addToCache(this);
      incrementLoaded();
   }
   function errorHandler() {
      incrementLoaded();
      throw new Error('Error loading ' + this.src);
   }

   for (var key in audioUrls) {
      if (key.indexOf('wav') == -1 && key.indexOf('ogg') == -1 && key.indexOf('webm') == -1) {
         continue;
      }
      countTotal++;
      var audio = new Audio();
      audio.addEventListener('canplay', successHandler, true);
      audio.addEventListener('error', errorHandler, true);
      audio.src = audioUrls[key];
      audio.gamejsKey = key;
      audio.load();
   }
   if (countTotal > 0) {
      _PRELOADING = true;
   }
   return getProgress;
};

/**
 * @ignore
 */
exports.isPreloading = function() {
   return _PRELOADING;
};

/**
 * @param {dom.ImgElement} audios the <audio> elements to put into cache
 * @ignore
 */
function addToCache(audios) {
   if (!(audios instanceof Array)) {
      audios = [audios];
   }

   var docLoc = document.location.href;
   audios.forEach(function(audio) {
      CACHE[audio.gamejsKey] = audio;
   });
   return;
}

/**
 * Sounds can be played back.
 * @constructor
 * @param {String|dom.AudioElement} uriOrAudio the uri of <audio> dom element
 *                of the sound
 */
exports.Sound = function Sound(uriOrAudio) {
   var cachedAudio;
   if (typeof uriOrAudio === 'string') {
      cachedAudio = CACHE[uriOrAudio];
   } else {
      cachedAudio = uriOrAudio;
   }
   if (!cachedAudio) {
      // TODO sync audio loading
      throw new Error('Missing "' + uriOrAudio + '", gamejs.preload() all audio files before loading');
   }

   var channels = [];
   var i = NUM_CHANNELS;
   while (i-->0) {
      var audio = new Audio();
      audio.preload = "auto";
      audio.loop = false;
      audio.src = cachedAudio.src;
      channels.push(audio);
   }
   /**
    * start the sound
    * @param {Boolean} loop whether the audio should loop for ever or not
    */
   this.play = function(loop) {
      audio.loop = !!loop;
      channels.some(function(audio) {
         if (audio.ended || audio.paused) {
            audio.play();
            return true;
         }
         return false;
      });
   };

   /**
    * Stop the sound.
    * This will stop the playback of this Sound on any active Channels.
    */
   this.stop = function() {
      channels.forEach(function(audio) {
         audio.stop();
      });
   };

   /**
    * Set volume of this sound
    * @param {Number} value volume from 0 to 1
    */
   this.setVolume = function(value) {
      channels.forEach(function(audio) {
         audio.volume = value;
      });
   };

   /**
    * @returns {Number} the sound's volume from 0 to 1
    */
   this.getVolume = function() {
      return channels[0].volume;
   };

   /**
    * @returns {Number} Duration of this sound in seconds
    */
   this.getLength = function() {
      return channels[0].duration;
   };

   return this;
};
<|endoftext|>


<commit_before><commit_msg>Browser history<commit_after><|endoftext|>


<commit_before>var should = require('should'),
    sinon = require('sinon'),
    rewire = require('rewire'),
    nock = require('nock'),

    // Stuff we are testing
    request = rewire('../../../server/utils/request'),

    sandbox = sinon.sandbox.create();

describe('Request', function () {
    var result,
        requestMock,
        secondRequestMock;

    afterEach(function () {
        sandbox.restore();
    });

    it('[success] should return response for http request', function (done) {
        var url = 'http://some-website.com/endpoint/',
            expectedResponse =
            {
                body: 'Response body',
                url: 'http://some-website.com/endpoint/',
                statusCode: 200
            },
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                }
            };

        requestMock = nock('http://some-website.com')
            .get('/endpoint/')
            .reply(200, 'Response body');

        result = request(url, options).then(function (res) {
            requestMock.isDone().should.be.true();
            should.exist(res);
            should.exist(res.body);
            res.body.should.be.equal(expectedResponse.body);
            should.exist(res.url);
            res.statusCode.should.be.equal(expectedResponse.statusCode);
            should.exist(res.statusCode);
            res.url.should.be.equal(expectedResponse.url);
            done();
        }).catch(done);
    });

    it('[success] can handle redirect', function (done) {
        var url = 'http://some-website.com/endpoint/',
            expectedResponse =
            {
                body: 'Redirected response',
                url: 'http://someredirectedurl.com/files/',
                statusCode: 200
            },
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                }
            };

        requestMock = nock('http://some-website.com')
            .get('/endpoint/')
            .reply(301, 'Oops, got redirected',
            {
                location: 'http://someredirectedurl.com/files/'
            });

        secondRequestMock = nock('http://someredirectedurl.com')
            .get('/files/')
            .reply(200, 'Redirected response');

        result = request(url, options).then(function (res) {
            requestMock.isDone().should.be.true();
            secondRequestMock.isDone().should.be.true();
            should.exist(res);
            should.exist(res.body);
            res.body.should.be.equal(expectedResponse.body);
            should.exist(res.url);
            res.statusCode.should.be.equal(expectedResponse.statusCode);
            should.exist(res.statusCode);
            res.url.should.be.equal(expectedResponse.url);
            done();
        }).catch(done);
    });

    it('[failure] can handle invalid url', function (done) {
        var url = 'test',
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                }
            };

        result = request(url, options)
            .catch(function (err) {
                should.exist(err);
                err.message.should.be.equal('URL empty or invalid.');
                done();
            });
    });

    it('[failure] can handle empty url', function (done) {
        var url = '',
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                }
            };

        result = request(url, options)
            .catch(function (err) {
                should.exist(err);
                err.message.should.be.equal('URL empty or invalid.');
                done();
            });
    });

    it('[failure] can handle an error with statuscode not 200', function (done) {
        var url = 'http://nofilehere.com/files/test.txt',
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                }
            };

        requestMock = nock('http://nofilehere.com')
            .get('/files/test.txt')
            .reply(404);

        result = request(url, options)
            .catch(function (err) {
                requestMock.isDone().should.be.true();
                should.exist(err);
                err.statusMessage.should.be.equal('Not Found');
                done();
            });
    });

    it('[failure] will timeout', function (done) {
        var url = 'http://nofilehere.com/files/test.txt',
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                },
                timeout: 10
            };

        requestMock = nock('http://nofilehere.com')
            .get('/files/test.txt')
            .socketDelay(11)
            .reply(408);

        result = request(url, options)
            .catch(function (err) {
                requestMock.isDone().should.be.true();
                should.exist(err);
                err.statusMessage.should.be.equal('Request Timeout');
                done();
            });
    });

    it('[failure] returns error if request errors', function (done) {
        var url = 'http://nofilehere.com/files/test.txt',
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                }
            };

        requestMock = nock('http://nofilehere.com')
            .get('/files/test.txt')
            .reply(500, {message: 'something aweful happend', code: 'AWFUL_ERROR'});

        result = request(url, options)
            .catch(function (err) {
                requestMock.isDone().should.be.true();
                should.exist(err);
                err.statusMessage.should.be.equal('Internal Server Error');
                done();
            });
    });
});
<commit_msg>Decrease chance of random test failure in core/test/unit/utils/request_spec.js<commit_after>var should = require('should'),
    sinon = require('sinon'),
    rewire = require('rewire'),
    nock = require('nock'),

    // Stuff we are testing
    request = rewire('../../../server/utils/request'),

    sandbox = sinon.sandbox.create();

describe('Request', function () {
    var result,
        requestMock,
        secondRequestMock;

    afterEach(function () {
        sandbox.restore();
    });

    it('[success] should return response for http request', function (done) {
        var url = 'http://some-website.com/endpoint/',
            expectedResponse =
            {
                body: 'Response body',
                url: 'http://some-website.com/endpoint/',
                statusCode: 200
            },
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                }
            };

        requestMock = nock('http://some-website.com')
            .get('/endpoint/')
            .reply(200, 'Response body');

        result = request(url, options).then(function (res) {
            requestMock.isDone().should.be.true();
            should.exist(res);
            should.exist(res.body);
            res.body.should.be.equal(expectedResponse.body);
            should.exist(res.url);
            res.statusCode.should.be.equal(expectedResponse.statusCode);
            should.exist(res.statusCode);
            res.url.should.be.equal(expectedResponse.url);
            done();
        }).catch(done);
    });

    it('[success] can handle redirect', function (done) {
        var url = 'http://some-website.com/endpoint/',
            expectedResponse =
            {
                body: 'Redirected response',
                url: 'http://someredirectedurl.com/files/',
                statusCode: 200
            },
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                }
            };

        requestMock = nock('http://some-website.com')
            .get('/endpoint/')
            .reply(301, 'Oops, got redirected',
            {
                location: 'http://someredirectedurl.com/files/'
            });

        secondRequestMock = nock('http://someredirectedurl.com')
            .get('/files/')
            .reply(200, 'Redirected response');

        result = request(url, options).then(function (res) {
            requestMock.isDone().should.be.true();
            secondRequestMock.isDone().should.be.true();
            should.exist(res);
            should.exist(res.body);
            res.body.should.be.equal(expectedResponse.body);
            should.exist(res.url);
            res.statusCode.should.be.equal(expectedResponse.statusCode);
            should.exist(res.statusCode);
            res.url.should.be.equal(expectedResponse.url);
            done();
        }).catch(done);
    });

    it('[failure] can handle invalid url', function (done) {
        var url = 'test',
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                }
            };

        result = request(url, options)
            .catch(function (err) {
                should.exist(err);
                err.message.should.be.equal('URL empty or invalid.');
                done();
            });
    });

    it('[failure] can handle empty url', function (done) {
        var url = '',
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                }
            };

        result = request(url, options)
            .catch(function (err) {
                should.exist(err);
                err.message.should.be.equal('URL empty or invalid.');
                done();
            });
    });

    it('[failure] can handle an error with statuscode not 200', function (done) {
        var url = 'http://nofilehere.com/files/test.txt',
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                }
            };

        requestMock = nock('http://nofilehere.com')
            .get('/files/test.txt')
            .reply(404);

        result = request(url, options)
            .catch(function (err) {
                requestMock.isDone().should.be.true();
                should.exist(err);
                err.statusMessage.should.be.equal('Not Found');
                done();
            });
    });

    it('[failure] will timeout', function (done) {
        var url = 'http://nofilehere.com/files/test.txt',
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                },
                timeout: 10
            };

        requestMock = nock('http://nofilehere.com')
            .get('/files/test.txt')
            .socketDelay(15)
            .reply(408);

        result = request(url, options)
            .catch(function (err) {
                requestMock.isDone().should.be.true();
                should.exist(err);
                err.statusMessage.should.be.equal('Request Timeout');
                done();
            });
    });

    it('[failure] returns error if request errors', function (done) {
        var url = 'http://nofilehere.com/files/test.txt',
            options = {
                headers: {
                    'User-Agent': 'Mozilla/5.0'
                }
            };

        requestMock = nock('http://nofilehere.com')
            .get('/files/test.txt')
            .reply(500, {message: 'something aweful happend', code: 'AWFUL_ERROR'});

        result = request(url, options)
            .catch(function (err) {
                requestMock.isDone().should.be.true();
                should.exist(err);
                err.statusMessage.should.be.equal('Internal Server Error');
                done();
            });
    });
});
<|endoftext|>


<commit_before>'use strict';

var restify = require('restify');

var server = restify.createServer();

var applications = require('./../controllers/static/applications');
var leaderboard = require('./../controllers/static/leaderboard');
var users = require('./../controllers/static/users');

//var hdl = require('./default_handler'); // default handler

server.listen(8080, function () {
  console.log('%s listening at %s', server.name, server.url);
});

// TODO this is needed for your tests to pass.....
exports.awesome = function () {
	return 'awesome';
};

////////////////////////////////////////////////////////////////////////////////////
// Applications
////////////////////////////////////////////////////////////////////////////////////

// get
server.get('/applications', applications.findAll);
server.get('/applications/:appid', applications.findById);

// post
server.post('/applications', applications.create);

////////////////////////////////////////////////////////////////////////////////////
// Leaderboard
////////////////////////////////////////////////////////////////////////////////////

// get
server.get('/applications/:appid/leaderboard', leaderboard.findAll);

////////////////////////////////////////////////////////////////////////////////////
// Users
////////////////////////////////////////////////////////////////////////////////////

// get
server.get('/applications/:appid/users', users.findAll);
server.get('/applications/:appid/users/:userid', users.findById);
server.get('/applications/:appid/users/:userid/badges', users.findBadgesById);

// post
server.post('/applications/:appid/users', users.create);

// put
// server.put('/applications/:appid/users/:userid', putMessage);

// delete
// server.delete('/applications/:appid/users/:userid', deleteMessage);

////////////////////////////////////////////////////////////////////////////////////
// Events
////////////////////////////////////////////////////////////////////////////////////

// get
// server.get('/applications/:appid/events', hdl.getMessages);
// server.get('/applications/:appid/events/:eventid', hdl.getMessages);

// post
// server.post('/applications/:appid/events', hdl.postMessage);

////////////////////////////////////////////////////////////////////////////////////
// Event Types
////////////////////////////////////////////////////////////////////////////////////

// get
// server.get('/applications/:appid/events/types', hdl.getMessages);
// server.get('/applications/:appid/events/types/:typeid', hdl.getMessages);

// post
// server.post('/applications/:appid/events/types', hdl.postMessage);

////////////////////////////////////////////////////////////////////////////////////
// Rules
////////////////////////////////////////////////////////////////////////////////////

// get
// server.get('/applications/:appid/rules', hdl.getMessages);
// server.get('/applications/:appid/rules/:ruleid', hdl.getMessages);

// post
// server.post('/applications/:appid/rules', hdl.postMessage);

// put
// server.put('/applications/:appid/rules/:ruleid', putMessage);

// delete
// server.delete('/applications/:appid/rules/:ruleid', deleteMessage);

////////////////////////////////////////////////////////////////////////////////////
// Badges
////////////////////////////////////////////////////////////////////////////////////

// get
// server.get('/applications/:appid/badges', hdl.getMessages);
// server.get('/applications/:appid/badges/:badgeid', hdl.getMessages);

// post
// server.post('/applications/:appid/badges', hdl.postMessage);

// put
// server.put('/applications/:appid/badges/:badgeid', putMessage);

////////////////////////////////////////////////////////////////////////////////////
// Badge Categories
////////////////////////////////////////////////////////////////////////////////////

// get
// server.get('/applications/:appid/badges/categories', hdl.getMessages);
// TODO duplicate query in apiaryio server.get('/applications/:appid/badges', hdl.getMessages);

// post
// server.post('/applications/:appid/badges/categories/', hdl.postMessage);

// put
// server.put('/applications/:appid/badges/categories/:categoryid', putMessage);

<commit_msg>added routes to last static handlers<commit_after>'use strict';

var restify = require('restify');

var server = restify.createServer();

// set static controllers for now...
var controller_path = './../controllers/static/';

// load controllers
var applications	= require(controller_path + 'applications');
var leaderboard	= require(controller_path + 'leaderboard');
var users			= require(controller_path + 'users');
var events		= require(controller_path + 'events');
var event_types	= require(controller_path + 'event_types');
var rules			= require(controller_path + 'rules');
var badges		= require(controller_path + 'badges');
var badge_cats		= require(controller_path + 'badge_categories');

//var hdl = require('./default_handler'); // default handler

server.listen(8080, function () {
	console.log('%s listening at %s', server.name, server.url);
});

// TODO this is needed for your tests to pass.....
exports.awesome = function () {
	return 'awesome';
};

////////////////////////////////////////////////////////////////////////////////////
// Applications
////////////////////////////////////////////////////////////////////////////////////

// get
server.get('/applications', applications.findAll);
server.get('/applications/:appid', applications.findById);

// post
server.post('/applications', applications.create);

////////////////////////////////////////////////////////////////////////////////////
// Leaderboard
////////////////////////////////////////////////////////////////////////////////////

// get
server.get('/applications/:appid/leaderboard', leaderboard.findAll);

////////////////////////////////////////////////////////////////////////////////////
// Users
////////////////////////////////////////////////////////////////////////////////////

// get
server.get('/applications/:appid/users', users.findAll);
server.get('/applications/:appid/users/:userid', users.findById);
server.get('/applications/:appid/users/:userid/badges', users.findBadgesById);

// post
server.post('/applications/:appid/users', users.create);

// put
server.put('/applications/:appid/users/:userid', users.update);

// delete
server.del('/applications/:appid/users/:userid', users.remove);

////////////////////////////////////////////////////////////////////////////////////
// Events
////////////////////////////////////////////////////////////////////////////////////

// get
server.get('/applications/:appid/events', events.findAll);
server.get('/applications/:appid/events/:eventid', events.findById);

// post
server.post('/applications/:appid/events', events.create);

////////////////////////////////////////////////////////////////////////////////////
// Event Types
////////////////////////////////////////////////////////////////////////////////////

// get
server.get('/applications/:appid/events/types', event_types.findAll);
server.get('/applications/:appid/events/types/:typeid', event_types.findById);

// post
server.post('/applications/:appid/events/types', event_types.create);

////////////////////////////////////////////////////////////////////////////////////
// Rules
////////////////////////////////////////////////////////////////////////////////////

// get
server.get('/applications/:appid/rules', rules.findAll);
server.get('/applications/:appid/rules/:ruleid', rules.findById);

// post
server.post('/applications/:appid/rules', rules.create);

// put
server.put('/applications/:appid/rules/:ruleid', rules.update);

// delete
server.del('/applications/:appid/rules/:ruleid', rules.remove);

////////////////////////////////////////////////////////////////////////////////////
// Badges
////////////////////////////////////////////////////////////////////////////////////

// get
server.get('/applications/:appid/badges', badges.findAll);
server.get('/applications/:appid/badges/:badgeid', badges.findById);

// post
server.post('/applications/:appid/badges', badges.create);

// put
server.put('/applications/:appid/badges/:badgeid', badges.update);

////////////////////////////////////////////////////////////////////////////////////
// Badge Categories
////////////////////////////////////////////////////////////////////////////////////

// get
server.get('/applications/:appid/badges/categories', badge_cats.findAll);
server.get('/applications/:appid/badges/categories', badge_cats.findById);

// post
server.post('/applications/:appid/badges/categories/', badge_cats.create);

// put
server.put('/applications/:appid/badges/categories/:categoryid', badge_cats.update);

<|endoftext|>


<commit_before>/**
 * @author mflux / http://minmax.design
 * Based on @mattdesl three-orbit-viewer
 */
import h from 'hyperscript';
import emitter from 'mitt';

import * as THREE from './lib/three';
import Stats from './lib/stats';
import { tempVector } from './utils/three';
import settings from './settings';
import Room from './room';
import * as Shadow from './shadow';
import feature from './utils/feature';

require('./lib/VREffect')(THREE);
require('./lib/VRControls')(THREE);
require('./lib/ViveController')(THREE);

const getWindowAspect = () => window.innerWidth / window.innerHeight;
const events = emitter();
const orthographicDistance = 4;

const showStats = !(window.location.hash.indexOf('fps') === -1);

const cameras = (function () {
  const aspect = getWindowAspect();

  const perspective = new THREE.PerspectiveCamera(70, aspect, 0.1, 1000);
  perspective.lookAt(tempVector(0, 0, 1));
  perspective.position.y = settings.holeHeight;

  const orthographic = new THREE.OrthographicCamera(
    -orthographicDistance * aspect,
    orthographicDistance * aspect,
    orthographicDistance,
    -orthographicDistance,
    -100,
    1000,
  );
  orthographic.position.set(0.06, 0.08, 0.08);
  orthographic.lookAt(tempVector());

  return { default: perspective, orthographic };
}());

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setClearColor(0x000000);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.sortObjects = false;
Shadow.configureRenderer(renderer);

const containerEl = h('div.viewer', renderer.domElement);
document.body.appendChild(containerEl);

const vrEffect = new THREE.VREffect(renderer);

const controls = new THREE.VRControls(cameras.default);
controls.standing = true;

const controller1 = new THREE.ViveController(0);
const controller2 = new THREE.ViveController(1);

// Use controllers:
controller1.standingMatrix = controls.getStandingMatrix();
controller2.standingMatrix = controls.getStandingMatrix();

const createScene = () => {
  const scene = new THREE.Scene();
  const light = new THREE.DirectionalLight(0xffffff);
  light.position.set(-1, 0.6, -1).normalize();

  const ambientLight = new THREE.AmbientLight(0x444444, 0.7);
  const hemisphereLight = new THREE.HemisphereLight(0x606060, 0x404040);

  scene.add(hemisphereLight);
  scene.add(light, ambientLight);
  scene.add(Shadow.shadowLight, Shadow.shadowTarget);
  //  Uncomment to see shadow volume
  // scene.add( Shadow.helper );
  scene.fog = new THREE.Fog(0x000000, 0, 75);
  return scene;
};

window.addEventListener('resize', () => {
  const aspect = getWindowAspect();
  const { orthographic } = cameras;
  Object.assign(
    orthographic,
    {
      left: -orthographicDistance * aspect,
      right: orthographicDistance * aspect,
    },
  );

  const { innerWidth, innerHeight } = window;
  vrEffect.setSize(innerWidth, innerHeight);
  Object
    .values(cameras)
    .forEach((camera) => {
      camera.aspect = aspect;
      camera.updateProjectionMatrix();
    });
}, false);

const scene = createScene();
scene.add(controller1, controller2);

let stats;
const statsMeshOffsetPosition = new THREE.Vector3(0.3, 0.15, 1);

if (showStats) {
  stats = new Stats();
  document.body.appendChild(stats.dom);

  scene.add(stats.mesh);
  stats.mesh.scale.set(2.5, 2.5, 2.5);
  stats.mesh.rotation.set(0.0, -Math.PI, 0);
}

const viewer = {
  camera: cameras.default,
  cameras,
  scene,
  renderScene: scene,
  controllers: [controller1, controller2],
  controls,
  createScene,
  events,
  renderer,
  switchCamera: (name) => {
    Room.switchModel(
      name === 'orthographic'
        ? 'orthographic'
        : 'default',
    );
    viewer.camera = cameras[name];
    Shadow.setShadowProfile(name);
  },
  vrEffect,
};

const clock = new THREE.Clock();
clock.start();

const animate = () => {
  if (showStats) stats.begin();
  const dt = clock.getDelta();
  vrEffect.requestAnimationFrame(animate);
  controller1.update();
  controller2.update();
  controls.update();
  events.emit('tick', dt);
  Shadow.updateFollow(viewer.camera);
  if (showStats) stats.mesh.position.copy(viewer.camera.position).add(statsMeshOffsetPosition);
  vrEffect.render(viewer.renderScene, viewer.camera);
  if (vrEffect.isPresenting && feature.hasExternalDisplay) {
    renderer.render(viewer.renderScene, viewer.camera);
  }
  events.emit('render', dt);
  if (showStats) stats.end();
};

animate();

export default viewer;
<commit_msg>Repositioned Directional Light<commit_after>/**
 * @author mflux / http://minmax.design
 * Based on @mattdesl three-orbit-viewer
 */
import h from 'hyperscript';
import emitter from 'mitt';

import * as THREE from './lib/three';
import Stats from './lib/stats';
import { tempVector } from './utils/three';
import settings from './settings';
import Room from './room';
import * as Shadow from './shadow';
import feature from './utils/feature';

require('./lib/VREffect')(THREE);
require('./lib/VRControls')(THREE);
require('./lib/ViveController')(THREE);

const getWindowAspect = () => window.innerWidth / window.innerHeight;
const events = emitter();
const orthographicDistance = 4;

const showStats = !(window.location.hash.indexOf('fps') === -1);

const cameras = (function () {
  const aspect = getWindowAspect();

  const perspective = new THREE.PerspectiveCamera(70, aspect, 0.1, 1000);
  perspective.lookAt(tempVector(0, 0, 1));
  perspective.position.y = settings.holeHeight;

  const orthographic = new THREE.OrthographicCamera(
    -orthographicDistance * aspect,
    orthographicDistance * aspect,
    orthographicDistance,
    -orthographicDistance,
    -100,
    1000,
  );
  orthographic.position.set(0.06, 0.08, 0.08);
  orthographic.lookAt(tempVector());

  return { default: perspective, orthographic };
}());

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setClearColor(0x000000);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.sortObjects = false;
Shadow.configureRenderer(renderer);

const containerEl = h('div.viewer', renderer.domElement);
document.body.appendChild(containerEl);

const vrEffect = new THREE.VREffect(renderer);

const controls = new THREE.VRControls(cameras.default);
controls.standing = true;

const controller1 = new THREE.ViveController(0);
const controller2 = new THREE.ViveController(1);

// Use controllers:
controller1.standingMatrix = controls.getStandingMatrix();
controller2.standingMatrix = controls.getStandingMatrix();

const createScene = () => {
  const scene = new THREE.Scene();
  const light = new THREE.DirectionalLight(0xffffff);
  light.position.set(-1.42, 2.26, 0.74).normalize();

  const ambientLight = new THREE.AmbientLight(0x444444, 0.7);
  const hemisphereLight = new THREE.HemisphereLight(0x606060, 0x404040);

  scene.add(hemisphereLight);
  scene.add(light, ambientLight);
  scene.add(Shadow.shadowLight, Shadow.shadowTarget);
  //  Uncomment to see shadow volume
  // scene.add( Shadow.helper );
  scene.fog = new THREE.Fog(0x000000, 0, 75);
  return scene;
};

window.addEventListener('resize', () => {
  const aspect = getWindowAspect();
  const { orthographic } = cameras;
  Object.assign(
    orthographic,
    {
      left: -orthographicDistance * aspect,
      right: orthographicDistance * aspect,
    },
  );

  const { innerWidth, innerHeight } = window;
  vrEffect.setSize(innerWidth, innerHeight);
  Object
    .values(cameras)
    .forEach((camera) => {
      camera.aspect = aspect;
      camera.updateProjectionMatrix();
    });
}, false);

const scene = createScene();
scene.add(controller1, controller2);

let stats;
const statsMeshOffsetPosition = new THREE.Vector3(0.3, 0.15, 1);

if (showStats) {
  stats = new Stats();
  document.body.appendChild(stats.dom);

  scene.add(stats.mesh);
  stats.mesh.scale.set(2.5, 2.5, 2.5);
  stats.mesh.rotation.set(0.0, -Math.PI, 0);
}

const viewer = {
  camera: cameras.default,
  cameras,
  scene,
  renderScene: scene,
  controllers: [controller1, controller2],
  controls,
  createScene,
  events,
  renderer,
  switchCamera: (name) => {
    Room.switchModel(
      name === 'orthographic'
        ? 'orthographic'
        : 'default',
    );
    viewer.camera = cameras[name];
    Shadow.setShadowProfile(name);
  },
  vrEffect,
};

const clock = new THREE.Clock();
clock.start();

const animate = () => {
  if (showStats) stats.begin();
  const dt = clock.getDelta();
  vrEffect.requestAnimationFrame(animate);
  controller1.update();
  controller2.update();
  controls.update();
  events.emit('tick', dt);
  Shadow.updateFollow(viewer.camera);
  if (showStats) stats.mesh.position.copy(viewer.camera.position).add(statsMeshOffsetPosition);
  vrEffect.render(viewer.renderScene, viewer.camera);
  if (vrEffect.isPresenting && feature.hasExternalDisplay) {
    renderer.render(viewer.renderScene, viewer.camera);
  }
  events.emit('render', dt);
  if (showStats) stats.end();
};

animate();

export default viewer;
<|endoftext|>


<commit_before>/* global require:false */
const fs = require('fs-extra');
const path = require('path');

fs.copySync(
   path.resolve('packages', 'envision-docs', 'public'),
   path.resolve('docs')
);
<commit_msg>Copy dist to docs (#237)<commit_after>/* global require:false */
const fs = require('fs-extra');
const path = require('path');

fs.copySync(
   path.resolve('packages', 'envision-docs', 'public'),
   path.resolve('docs')
);

fs.copySync(
   path.resolve('packages', 'envision', 'dist'),
   path.resolve('docs', 'dist')
);
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// 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.
'use strict';

var metrics = require('metrics');
var sendPing = require('./ping-sender.js');
var sendPingReq = require('./ping-req-sender.js');

function Gossip(options) {
    this.ringpop = options.ringpop;
    this.minProtocolPeriod = options.minProtocolPeriod ||
        Gossip.Defaults.minProtocolPeriod;

    this.isStopped = true;
    this.lastProtocolPeriod = Date.now();
    this.lastProtocolRate = 0;
    this.numProtocolPeriods = 0;
    this.protocolPeriodTimer = null;
    this.protocolRateTimer = null;
    this.protocolTiming = new metrics.Histogram();

    this.protocolTiming.update(this.minProtocolPeriod);
}

Gossip.prototype.computeProtocolDelay = function computeProtocolDelay() {
    if (this.numProtocolPeriods) {
        var target = this.lastProtocolPeriod + this.lastProtocolRate;
        return Math.max(target - Date.now(), this.minProtocolPeriod);
    } else {
        // Delay for first tick will be staggered from 0 to `minProtocolPeriod` ms.
        return Math.floor(Math.random() * (this.minProtocolPeriod + 1));
    }
};

Gossip.prototype.computeProtocolRate = function computeProtocolRate() {
    var observed = this.protocolTiming.percentiles([0.5])['0.5'] * 2;
    return Math.max(observed, this.minProtocolPeriod);
};

Gossip.prototype.getStatus = function getStatus() {
    return this.isStopped ? Gossip.Status.Stopped : Gossip.Status.Started;
};

Gossip.prototype.run = function run() {
    var self = this;

    var protocolDelay = this.computeProtocolDelay();
    this.ringpop.stat('timing', 'protocol.delay', protocolDelay);

    var startTime = new Date();
    this.protocolPeriodTimer = setTimeout(function onGossipTimer() {
        var pingStartTime = Date.now();

        self.tick(function onMemberPinged() {
            self.lastProtocolPeriod = Date.now();
            self.numProtocolPeriods++;
            self.ringpop.stat('timing', 'protocol.frequency', startTime);
            self.protocolTiming.update(Date.now() - pingStartTime); // This keeps the protocol rate in check

            if (self.isStopped) {
                self.ringpop.logger.debug('stopped recurring gossip loop', {
                    local: self.ringpop.whoami()
                });
                return;
            }

            self.run();
        });
    }, protocolDelay);
};

Gossip.prototype.start = function start() {
    if (!this.isStopped) {
        this.ringpop.logger.debug('gossip has already started', {
            local: this.ringpop.whoami()
        });
        return;
    }

    this.ringpop.membership.shuffle();
    this.run();
    this.startProtocolRateTimer();
    this.isStopped = false;

    this.ringpop.logger.debug('started gossip protocol', {
        local: this.ringpop.whoami()
    });
};

Gossip.prototype.startProtocolRateTimer = function startProtocolRateTimer() {
    var self = this;
    this.protocolRateTimer = setInterval(function () {
        self.lastProtocolRate = self.computeProtocolRate();
    }, 1000);
};

Gossip.prototype.stop = function stop() {
    if (this.isStopped) {
        this.ringpop.logger.warn('gossip is already stopped', {
            local: this.ringpop.whoami()
        });
        return;
    }

    clearInterval(this.protocolRateTimer);
    this.protocolRateTimer = null;

    clearTimeout(this.protocolPeriodTimer);
    this.protocolPeriodTimer = null;

    this.isStopped = true;

    this.ringpop.logger.debug('stopped gossip protocol', {
        local: this.ringpop.whoami()
    });
};

Gossip.prototype.tick = function tick(callback) {
    callback = callback || function() {};

    if (this.isPinging) {
        this.ringpop.logger.warn('aborting ping because one is in progress');
        return callback();
    }

    if (!this.ringpop.isReady) {
        this.ringpop.logger.warn('ping started before ring initialized');
        return callback();
    }

    var member = this.ringpop.memberIterator.next();

    if (! member) {
        this.ringpop.logger.warn('no usable nodes at protocol period');
        return callback();
    }

    var self = this;
    this.isPinging = true;
    var start = new Date();
    sendPing({
        ringpop: self.ringpop,
        target: member
    }, function(isOk, body) {
        self.ringpop.stat('timing', 'ping', start);
        if (isOk) {
            self.isPinging = false;
            self.ringpop.membership.update(body.changes);
            return callback();
        }

        if (self.ringpop.destroyed) {
            return callback(new Error('destroyed whilst pinging'));
        }

        var pingReqStartTime = new Date();
        // TODO The pinged member's status could have changed to
        // faulty by the time we received and processed the ping
        // response. There are no ill effects to membership state
        // by sending a ping-req to the faulty member (and processing
        // the response), though it does delay the protocol period
        // unnecessarily. We may want to bypass the ping-req here
        // if the member's status is faulty.
        sendPingReq({
            ringpop: self.ringpop,
            unreachableMember: member,
            pingReqSize: self.ringpop.pingReqSize
        }, function onPingReq() {
            self.ringpop.stat('timing', 'ping-req', pingReqStartTime);
            self.isPinging = false;

            callback.apply(null, Array.prototype.splice.call(arguments, 0));
        });
    });
};

Gossip.Defaults = {
    minProtocolPeriod: 200
};

Gossip.Status = {
    Started: 'started',
    Stopped: 'stopped'
};

module.exports = Gossip;
<commit_msg>Address Nils' PR feedback; initialize isPinging<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// 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.
'use strict';

var metrics = require('metrics');
var sendPing = require('./ping-sender.js');
var sendPingReq = require('./ping-req-sender.js');

function Gossip(options) {
    this.ringpop = options.ringpop;
    this.minProtocolPeriod = options.minProtocolPeriod ||
        Gossip.Defaults.minProtocolPeriod;

    this.isPinging = false;
    this.isStopped = true;
    this.lastProtocolPeriod = Date.now();
    this.lastProtocolRate = 0;
    this.numProtocolPeriods = 0;
    this.protocolPeriodTimer = null;
    this.protocolRateTimer = null;
    this.protocolTiming = new metrics.Histogram();
    this.protocolTiming.update(this.minProtocolPeriod);
}

Gossip.prototype.computeProtocolDelay = function computeProtocolDelay() {
    if (this.numProtocolPeriods) {
        var target = this.lastProtocolPeriod + this.lastProtocolRate;
        return Math.max(target - Date.now(), this.minProtocolPeriod);
    } else {
        // Delay for first tick will be staggered from 0 to `minProtocolPeriod` ms.
        return Math.floor(Math.random() * (this.minProtocolPeriod + 1));
    }
};

Gossip.prototype.computeProtocolRate = function computeProtocolRate() {
    var observed = this.protocolTiming.percentiles([0.5])['0.5'] * 2;
    return Math.max(observed, this.minProtocolPeriod);
};

Gossip.prototype.getStatus = function getStatus() {
    return this.isStopped ? Gossip.Status.Stopped : Gossip.Status.Started;
};

Gossip.prototype.run = function run() {
    var self = this;

    var protocolDelay = this.computeProtocolDelay();
    this.ringpop.stat('timing', 'protocol.delay', protocolDelay);

    var startTime = new Date();
    this.protocolPeriodTimer = setTimeout(function onGossipTimer() {
        var pingStartTime = Date.now();

        self.tick(function onMemberPinged() {
            self.lastProtocolPeriod = Date.now();
            self.numProtocolPeriods++;
            self.ringpop.stat('timing', 'protocol.frequency', startTime);
            self.protocolTiming.update(Date.now() - pingStartTime); // This keeps the protocol rate in check

            if (self.isStopped) {
                self.ringpop.logger.debug('stopped recurring gossip loop', {
                    local: self.ringpop.whoami()
                });
                return;
            }

            self.run();
        });
    }, protocolDelay);
};

Gossip.prototype.start = function start() {
    if (!this.isStopped) {
        this.ringpop.logger.debug('gossip has already started', {
            local: this.ringpop.whoami()
        });
        return;
    }

    this.ringpop.membership.shuffle();
    this.run();
    this.startProtocolRateTimer();
    this.isStopped = false;

    this.ringpop.logger.debug('started gossip protocol', {
        local: this.ringpop.whoami()
    });
};

Gossip.prototype.startProtocolRateTimer = function startProtocolRateTimer() {
    var self = this;
    this.protocolRateTimer = setInterval(function () {
        self.lastProtocolRate = self.computeProtocolRate();
    }, 1000);
};

Gossip.prototype.stop = function stop() {
    if (this.isStopped) {
        this.ringpop.logger.warn('gossip is already stopped', {
            local: this.ringpop.whoami()
        });
        return;
    }

    clearInterval(this.protocolRateTimer);
    this.protocolRateTimer = null;

    clearTimeout(this.protocolPeriodTimer);
    this.protocolPeriodTimer = null;

    this.isStopped = true;

    this.ringpop.logger.debug('stopped gossip protocol', {
        local: this.ringpop.whoami()
    });
};

Gossip.prototype.tick = function tick(callback) {
    callback = callback || function() {};

    if (this.isPinging) {
        this.ringpop.logger.warn('aborting ping because one is in progress');
        return callback();
    }

    if (!this.ringpop.isReady) {
        this.ringpop.logger.warn('ping started before ring initialized');
        return callback();
    }

    var member = this.ringpop.memberIterator.next();

    if (! member) {
        this.ringpop.logger.warn('no usable nodes at protocol period');
        return callback();
    }

    var self = this;
    this.isPinging = true;
    var start = new Date();
    sendPing({
        ringpop: self.ringpop,
        target: member
    }, function(isOk, body) {
        self.ringpop.stat('timing', 'ping', start);
        if (isOk) {
            self.isPinging = false;
            self.ringpop.membership.update(body.changes);
            return callback();
        }

        if (self.ringpop.destroyed) {
            return callback(new Error('destroyed whilst pinging'));
        }

        var pingReqStartTime = new Date();
        // TODO The pinged member's status could have changed to
        // faulty by the time we received and processed the ping
        // response. There are no ill effects to membership state
        // by sending a ping-req to the faulty member (and processing
        // the response), though it does delay the protocol period
        // unnecessarily. We may want to bypass the ping-req here
        // if the member's status is faulty.
        sendPingReq({
            ringpop: self.ringpop,
            unreachableMember: member,
            pingReqSize: self.ringpop.pingReqSize
        }, function onPingReq() {
            self.ringpop.stat('timing', 'ping-req', pingReqStartTime);
            self.isPinging = false;

            callback.apply(null, Array.prototype.splice.call(arguments, 0));
        });
    });
};

Gossip.Defaults = {
    minProtocolPeriod: 200
};

Gossip.Status = {
    Started: 'started',
    Stopped: 'stopped'
};

module.exports = Gossip;
<|endoftext|>


<commit_before><commit_msg>Update map.js<commit_after><|endoftext|>


<commit_before>define([
	"@loader",
	"module",
	"can/view/stache/mustache_core",
	"can/view/parser/parser"
], function(loader, module, mustacheCore, parser){

	function parse(source){
		var template = mustacheCore.cleanLineEndings(source),
			tags = {
				"can-component": true,
				"style": true,
				"template": true,
				"view-model": true,
				"events": true,
				"helpers": true,
				"script": true,
				"can-import": true
			},
			areIn = {},
			texts = {
				style: "",
				"view-model": "",
				events: "",
				helpers: ""
			},
			froms = {};
			types = {},
			attrs = {},
			values = {},
			imports = [],
			ases = {},
			currentTag = "",
			currentAttr = "",
			tagName = "",
			keepToken = function(){
				// We only want to keep the template's tokens.
				return !!areIn.template;
			};

		var intermediate = parser(template, {
			start: function(tagName){
				// Mark when we are inside one of the tags.
				if(tags[tagName]) {
					currentTag = tagName;
					areIn[tagName] = true;
				}
				return keepToken();
			},
			attrStart: function(attrName){
				currentAttr = attrName;
				return keepToken();
			},
			attrEnd: function(attrName){
				currentAttr = "";
				return keepToken();
			},
			attrValue: function(value){
				if(areIn["can-component"] && currentAttr === "tag") {
					tagName = value;
				}
				if(areIn["can-import"] && currentAttr === "from") {
					imports.push(value);
				}
				if(currentAttr === "type" && tags[currentTag]) {
					types[currentTag] = (value+"").replace("text/", "");

					// <script type="events">
					if(currentTag === "script" && tags[value]) {
						currentTag = value;
					}
				} else if(currentAttr === "from" && tags[currentTag]) {
					froms[currentTag] = value;
				}
				attrs[currentAttr] = value;
				return keepToken();
			},
			end: function(tagName){
				if(tagName === "can-import") {
					if(attrs.as) {
						ases[attrs.as] = attrs.from;
					}

					attrs.as = false;
					attrs.from = false;
					areIn["can-import"] = false;
				}
				return keepToken();
			},
			close: function(tagName){
				if(tagName === "can-import") {
					imports.pop();
				}
				if(tags[tagName]) {
					areIn[tagName] = false;
				}
				return keepToken();
			},
			special: keepToken,
			chars: function(char){
				if(texts[currentTag] != null) {
					texts[currentTag] += char;
				}
				return keepToken();
			},
			done: function(){}
		}, true);

		// Remove the leading template noise.
		var idx = 0, cur = intermediate[0];
		while(cur.tokenType !== "end" || (cur.args ? cur.args[0] !== "template" : true)) {
			intermediate.shift();
			cur = intermediate[0];
		}
		// Remove the template end
		intermediate.shift();

		return {
			froms: froms,
			intermediate: intermediate,
			imports: imports,
			tagName: tagName,
			texts: texts,
			types: types
		};
	}

	// Make functions that will define virtual modules
	function makeDefineVirtualModule(loader, load, addDep, args){

		function namer(loadName){
			var baseName = loadName.substr(0, loadName.indexOf("!"));

			return function(part, plugin){
				return baseName + "/" + part + (plugin ? ("." + plugin) : "");
			};
		}

		function addresser(loadAddress){
			return function(part, plugin){
				var base = loadAddress + "." + part;
				return base + (plugin ? ("." + plugin) : "");
			};
		}

		var name = namer(load.name);
		var address = addresser(load.address);

		// A function for disposing of modules during live-reload
		var disposeModule = function(moduleName){
			if(loader.has(moduleName))
				loader["delete"](moduleName);
		};
		if(loader.liveReloadInstalled || loader.has("live-reload")) {
			loader.import("live-reload", { name: module.id }).then(function(reload){
				disposeModule = reload.disposeModule || disposeModule;
			});
		}
		return function(defn){
			if(defn.condition) {
				if(defn.arg) {
					// viewModel
					args.push(defn.arg);
				}

				var moduleName = typeof defn.name === "function" ?
					defn.name(name) : name(defn.name);
				var moduleAddress = typeof defn.address === "function" ?
					defn.address(address) : address(defn.address);

				// from="something.js"
				if(defn.from) {
					addDep(defn.from, false);
				}

				else if(defn.getLoad) {
					var moduleSource = defn.source();
					return defn.getLoad(moduleName).then(function(newLoad){
						moduleName = newLoad.name || moduleName;

						// For live-reload
						disposeModule(moduleName);

						loader.componentSources[moduleName] = moduleSource;
						addDep(moduleName);
					});
				}

				else if(defn.source) {
					addDep(moduleName);

					if(loader.has(moduleName))
						loader["delete"](moduleName);

					loader.componentSources[moduleName] = defn.source;
				}
			}
		}
	}

	function templateDefine(intermediateAndImports){
		var intermediate = intermediateAndImports.intermediate;
		var imports = intermediateAndImports.imports;
		imports.unshift("can/component/component");
		imports.unshift("can/view/stache/stache");

		return "def" + "ine(" + JSON.stringify(imports) + ", function(stache){\n" +
			"\treturn stache(" + JSON.stringify(intermediate) + ");\n" +
			"});";
	}

	function translate(load){
		var result = parse(load.source),
			tagName = result.tagName,
			texts = result.texts,
			types = result.types,
			froms = result.froms,
			deps = ["can/component/component"],
			ases = ["Component"],
			stylePromise,
			addDep = function(moduleName, isVirtual){
				deps.push(moduleName);
				if(isVirtual !== false) {
					load.metadata.virtualDeps.push(moduleName);
				}
			};

		var localLoader = loader.localLoader || loader;

		load.metadata.virtualDeps = [];
		var defineVirtualModule = makeDefineVirtualModule(localLoader, load,
														  addDep, ases);

		// Define the template
		defineVirtualModule({
			condition: froms.template || result.intermediate.length,
			arg: "template",
			name: "template",
			from: froms.template,
			source: templateDefine(result)
		});

		// Define the viewModel
		defineVirtualModule({
			condition: froms["view-model"] || texts["view-model"],
			arg: "viewModel",
			name: "view-model",
			from: froms["view-model"],
			source: texts["view-model"]
		});

		// Define events
		defineVirtualModule({
			condition: froms.events || texts.events,
			arg: "events",
			name: "events",
			from: froms.events,
			source: texts.events
		});

		// Define helpers
		defineVirtualModule({
			condition: froms.events || texts.events,
			arg: "helpers",
			name: "helpers",
			from: froms.helpers,
			source: texts.helpers
		});

		// Define the styles
		stylePromise = defineVirtualModule({
			condition: froms.style || texts.style,
			name: function(name){
				return name("style", types.style || "css") + "!"
			},
			address: function(address){
				return address("style", types.style);
			},
			source: function(){
				var styleText = texts.style;
				if(types.style === "less") {
					var styleText = tagName + " {\n" + texts.style + "}\n";
				}
				return styleText;
			},
			getLoad: function(styleName){
				var styleLoad = {};
				var normalizePromise = localLoader.normalize(styleName, load.name);
				var locatePromise = normalizePromise.then(function(name){
					styleName = name;
					styleLoad = { name: name, metadata: {} };
					return localLoader.locate(styleLoad);
				});

				return locatePromise.then(function(){
					return {
						name: styleName,
						metadata: styleLoad.metadata
					};
				});
			}
		}) || Promise.resolve();

		return stylePromise.then(function(){
			return "def" + "ine(" + JSON.stringify(deps) + ", function(" +
				ases.join(", ") + "){\n" +
				"\tvar __interop = function(m){if(m && m['default']) {return m['default'];}else if(m) return m;};\n\n" +
				"\tvar viewModel = __interop(typeof viewModel !== 'undefined' ? viewModel : undefined);\n" +
				"\tvar ComponentConstructor = Component.extend({\n" +
				"\t\ttag: '" + tagName + "',\n" +
				"\t\ttemplate: __interop(typeof template !== 'undefined' ? template : undefined),\n" +
				"\t\tviewModel: viewModel,\n" +
				"\t\tevents: __interop(typeof events !== 'undefined' ? events : undefined),\n" +
				"\t\thelpers: __interop(typeof helpers !== 'undefined' ? helpers : undefined)\n" +
				"\t});\n\n" +
				"\treturn {\n" +
				"\t\tComponent: ComponentConstructor,\n" +
				"\t\tViewModel: ComponentConstructor.Map,\n" +
				"\t\tviewModel: viewModel\n" +
				"\t};\n" +
				"});";
		});

	}

	// Add a fetch hook for component virtual modules
	if(!loader.componentSources) {
		loader.componentSources = {};
	}

	var oldFetch = loader.fetch;
	loader.fetch = function(load){
		var source = loader.componentSources[load.name];
		if(source) {
			return source;
		}
		return oldFetch.apply(this, arguments);
	};

	return {
		translate: translate
	};

});
<commit_msg>Define fetch hook on both loaders<commit_after>define([
	"@loader",
	"module",
	"can/view/stache/mustache_core",
	"can/view/parser/parser"
], function(loader, module, mustacheCore, parser){

	function parse(source){
		var template = mustacheCore.cleanLineEndings(source),
			tags = {
				"can-component": true,
				"style": true,
				"template": true,
				"view-model": true,
				"events": true,
				"helpers": true,
				"script": true,
				"can-import": true
			},
			areIn = {},
			texts = {
				style: "",
				"view-model": "",
				events: "",
				helpers: ""
			},
			froms = {};
			types = {},
			attrs = {},
			values = {},
			imports = [],
			ases = {},
			currentTag = "",
			currentAttr = "",
			tagName = "",
			keepToken = function(){
				// We only want to keep the template's tokens.
				return !!areIn.template;
			};

		var intermediate = parser(template, {
			start: function(tagName){
				// Mark when we are inside one of the tags.
				if(tags[tagName]) {
					currentTag = tagName;
					areIn[tagName] = true;
				}
				return keepToken();
			},
			attrStart: function(attrName){
				currentAttr = attrName;
				return keepToken();
			},
			attrEnd: function(attrName){
				currentAttr = "";
				return keepToken();
			},
			attrValue: function(value){
				if(areIn["can-component"] && currentAttr === "tag") {
					tagName = value;
				}
				if(areIn["can-import"] && currentAttr === "from") {
					imports.push(value);
				}
				if(currentAttr === "type" && tags[currentTag]) {
					types[currentTag] = (value+"").replace("text/", "");

					// <script type="events">
					if(currentTag === "script" && tags[value]) {
						currentTag = value;
					}
				} else if(currentAttr === "from" && tags[currentTag]) {
					froms[currentTag] = value;
				}
				attrs[currentAttr] = value;
				return keepToken();
			},
			end: function(tagName){
				if(tagName === "can-import") {
					if(attrs.as) {
						ases[attrs.as] = attrs.from;
					}

					attrs.as = false;
					attrs.from = false;
					areIn["can-import"] = false;
				}
				return keepToken();
			},
			close: function(tagName){
				if(tagName === "can-import") {
					imports.pop();
				}
				if(tags[tagName]) {
					areIn[tagName] = false;
				}
				return keepToken();
			},
			special: keepToken,
			chars: function(char){
				if(texts[currentTag] != null) {
					texts[currentTag] += char;
				}
				return keepToken();
			},
			done: function(){}
		}, true);

		// Remove the leading template noise.
		var idx = 0, cur = intermediate[0];
		while(cur.tokenType !== "end" || (cur.args ? cur.args[0] !== "template" : true)) {
			intermediate.shift();
			cur = intermediate[0];
		}
		// Remove the template end
		intermediate.shift();

		return {
			froms: froms,
			intermediate: intermediate,
			imports: imports,
			tagName: tagName,
			texts: texts,
			types: types
		};
	}

	// Make functions that will define virtual modules
	function makeDefineVirtualModule(loader, load, register, addDep, args){

		function namer(loadName){
			var baseName = loadName.substr(0, loadName.indexOf("!"));

			return function(part, plugin){
				return baseName + "/" + part + (plugin ? ("." + plugin) : "");
			};
		}

		function addresser(loadAddress){
			return function(part, plugin){
				var base = loadAddress + "." + part;
				return base + (plugin ? ("." + plugin) : "");
			};
		}

		var name = namer(load.name);
		var address = addresser(load.address);

		// A function for disposing of modules during live-reload
		var disposeModule = function(moduleName){
			if(loader.has(moduleName))
				loader["delete"](moduleName);
		};
		if(loader.liveReloadInstalled || loader.has("live-reload")) {
			loader.import("live-reload", { name: module.id }).then(function(reload){
				disposeModule = reload.disposeModule || disposeModule;
			});
		}
		return function(defn){
			if(defn.condition) {
				if(defn.arg) {
					// viewModel
					args.push(defn.arg);
				}

				var moduleName = typeof defn.name === "function" ?
					defn.name(name) : name(defn.name);
				var moduleAddress = typeof defn.address === "function" ?
					defn.address(address) : address(defn.address);

				// from="something.js"
				if(defn.from) {
					addDep(defn.from, false);
				}

				else if(defn.getLoad) {
					var moduleSource = defn.source();
					return defn.getLoad(moduleName).then(function(newLoad){
						moduleName = newLoad.name || moduleName;

						// For live-reload
						disposeModule(moduleName);

						register(moduleName, moduleSource);
					});
				}

				else if(defn.source) {
					if(loader.has(moduleName))
						loader["delete"](moduleName);

					register(moduleName, defn.source);
				}
			}
		}
	}

	function templateDefine(intermediateAndImports){
		var intermediate = intermediateAndImports.intermediate;
		var imports = intermediateAndImports.imports;
		imports.unshift("can/component/component");
		imports.unshift("can/view/stache/stache");

		return "def" + "ine(" + JSON.stringify(imports) + ", function(stache){\n" +
			"\treturn stache(" + JSON.stringify(intermediate) + ");\n" +
			"});";
	}

	function translate(load){
		var result = parse(load.source),
			tagName = result.tagName,
			texts = result.texts,
			types = result.types,
			froms = result.froms,
			deps = ["can/component/component"],
			ases = ["Component"],
			thisLoader = this,
			stylePromise,
			addDep = function(moduleName, isVirtual){
				deps.push(moduleName);
				if(isVirtual !== false) {
					load.metadata.virtualDeps.push(moduleName);
				}
			},
			register = function(moduleName, source){
				thisLoader.componentSources[moduleName] = source;
				localLoader.componentSources[moduleName] = source;
				addDep(moduleName);
			};

		var localLoader = loader.localLoader || loader;

		load.metadata.virtualDeps = [];
		var defineVirtualModule = makeDefineVirtualModule(localLoader, load,
														  register, addDep, ases);

		// Define the template
		defineVirtualModule({
			condition: froms.template || result.intermediate.length,
			arg: "template",
			name: "template",
			from: froms.template,
			source: templateDefine(result)
		});

		// Define the viewModel
		defineVirtualModule({
			condition: froms["view-model"] || texts["view-model"],
			arg: "viewModel",
			name: "view-model",
			from: froms["view-model"],
			source: texts["view-model"]
		});

		// Define events
		defineVirtualModule({
			condition: froms.events || texts.events,
			arg: "events",
			name: "events",
			from: froms.events,
			source: texts.events
		});

		// Define helpers
		defineVirtualModule({
			condition: froms.events || texts.events,
			arg: "helpers",
			name: "helpers",
			from: froms.helpers,
			source: texts.helpers
		});

		// Define the styles
		stylePromise = defineVirtualModule({
			condition: froms.style || texts.style,
			name: function(name){
				return name("style", types.style || "css") + "!"
			},
			address: function(address){
				return address("style", types.style);
			},
			source: function(){
				var styleText = texts.style;
				if(types.style === "less") {
					var styleText = tagName + " {\n" + texts.style + "}\n";
				}
				return styleText;
			},
			getLoad: function(styleName){
				var styleLoad = {};
				var normalizePromise = localLoader.normalize(styleName, load.name);
				var locatePromise = normalizePromise.then(function(name){
					styleName = name;
					styleLoad = { name: name, metadata: {} };
					return localLoader.locate(styleLoad);
				});

				return locatePromise.then(function(){
					return {
						name: styleName,
						metadata: styleLoad.metadata
					};
				});
			}
		}) || Promise.resolve();

		return stylePromise.then(function(){
			return "def" + "ine(" + JSON.stringify(deps) + ", function(" +
				ases.join(", ") + "){\n" +
				"\tvar __interop = function(m){if(m && m['default']) {return m['default'];}else if(m) return m;};\n\n" +
				"\tvar viewModel = __interop(typeof viewModel !== 'undefined' ? viewModel : undefined);\n" +
				"\tvar ComponentConstructor = Component.extend({\n" +
				"\t\ttag: '" + tagName + "',\n" +
				"\t\ttemplate: __interop(typeof template !== 'undefined' ? template : undefined),\n" +
				"\t\tviewModel: viewModel,\n" +
				"\t\tevents: __interop(typeof events !== 'undefined' ? events : undefined),\n" +
				"\t\thelpers: __interop(typeof helpers !== 'undefined' ? helpers : undefined)\n" +
				"\t});\n\n" +
				"\treturn {\n" +
				"\t\tComponent: ComponentConstructor,\n" +
				"\t\tViewModel: ComponentConstructor.Map,\n" +
				"\t\tviewModel: viewModel\n" +
				"\t};\n" +
				"});";
		});

	}

	function addFetch(loader){
		// Add a fetch hook for component virtual modules
		if(!loader.componentSources) {
			loader.componentSources = {};
		}

		var oldFetch = loader.fetch;
		loader.fetch = function(load){
			var source = this.componentSources[load.name];
			if(source) {
				return source;
			}
			return oldFetch.apply(this, arguments);
		};
	}
	addFetch(loader);
	if(loader.localLoader) addFetch(loader.localLoader);

	return {
		translate: translate
	};

});
<|endoftext|>