<commit_before>var torque = require('../');
var cartocss = require('./cartocss_render');
var Profiler = require('../profiler');
var carto = global.carto || require('carto');
var filters = require('./torque_filters');

  var TAU = Math.PI * 2;
  var DEFAULT_CARTOCSS = [
    '#layer {',
    '  marker-fill: #662506;',
    '  marker-width: 4;',
    '  [value > 1] { marker-fill: #FEE391; }',
    '  [value > 2] { marker-fill: #FEC44F; }',
    '  [value > 3] { marker-fill: #FE9929; }',
    '  [value > 4] { marker-fill: #EC7014; }',
    '  [value > 5] { marker-fill: #CC4C02; }',
    '  [value > 6] { marker-fill: #993404; }',
    '  [value > 7] { marker-fill: #662506; }',
    '}'
  ].join('\n');

  var COMP_OP_TO_CANVAS = {
    "src": 'source-over',
    "src-over": 'source-over',
    "dst-over": 'destination-over',
    "src-in": 'source-in',
    "dst-in": 'destination-in',
    "src-out": 'source-out',
    "dst-out": 'destination-out',
    "src-atop": 'source-atop',
    "dst-atop": 'destination-atop',
    "xor": 'xor',
    "darken": 'darken',
    "lighten": 'lighten'
  }

  function compop2canvas(compop) {
    return COMP_OP_TO_CANVAS[compop] || compop;
  }

  //
  // this renderer just render points depending of the value
  //
  function PointRenderer(canvas, options) {
    if (!canvas) {
      throw new Error("canvas can't be undefined");
    }
    this.options = options;
    this._canvas = canvas;
    this._ctx = canvas.getContext('2d');
    this._sprites = []; // sprites per layer
    this._shader = null;
    this._icons = {};
    this._filters = filters(this._canvas);
    this.setCartoCSS(this.options.cartocss || DEFAULT_CARTOCSS);
    this.TILE_SIZE = 256;
    this._style = null;
    this._gradients = {};

    this._forcePoints = false;
  }

  torque.extend(PointRenderer.prototype, torque.Event, {

    clearCanvas: function() {
      var canvas = this._canvas;
      var color = this._Map['-torque-clear-color']
      // shortcut for the default value
      if (color  === "rgba(255, 255, 255, 0)" || !color) {
        this._canvas.width = this._canvas.width;
      } else {
        var ctx = this._ctx;
        ctx.setTransform(1, 0, 0, 1, 0, 0);
        var compop = this._Map['comp-op']
        ctx.globalCompositeOperation = compop2canvas(compop);
        ctx.fillStyle = color;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
      }
    },

    setCanvas: function(canvas) {
      this._canvas = canvas;
      this._ctx = canvas.getContext('2d');
    },

    //
    // sets the cartocss style to render stuff
    //
    setCartoCSS: function(cartocss) {
      // clean sprites
      this.setShader(new carto.RendererJS().render(cartocss));
    },

    setShader: function(shader) {
      // clean sprites
      this._sprites = [];
      this._shader = shader;
      this._Map = this._shader.getDefault().getStyle({}, { zoom: 0 });
      var img_names = this._shader.getImageURLs();
      this._preloadIcons(img_names);
    },

    clearSpriteCache: function() {
      this._sprites = [];
    },

    //
    // generate sprite based on cartocss style
    //
    generateSprite: function(shader, value, shaderVars) {
      var self = this;
      var prof = Profiler.metric('torque.renderer.point.generateSprite').start();
      var st = shader.getStyle({
        value: value
      }, shaderVars);
      if(this._style === null || this._style !== st){
        this._style = st;
      }

      var pointSize = st['marker-width'];
      if (!pointSize) {
        return null;
      }

      if (st['marker-opacity'] === 0 && !st['marker-line-opacity']) {
        return null;
      }

      var canvas = this._createCanvas();
      // take into account the exterior ring to calculate the size
      var canvasSize = (st['marker-line-width'] || 0) + pointSize*2;
      var ctx = canvas.getContext('2d');
      var w = ctx.width = canvas.width = ctx.height = canvas.height = Math.ceil(canvasSize);
      ctx.translate(w/2, w/2);

      function qualifyURL(url) {
            var a = document.createElement('a');
              a.href = url;
              return a.href;
          };
      var img_name = qualifyURL(st["marker-file"] || st["point-file"]);
      if (img_name && this._icons.itemsToLoad === 0) {
          var img = this._icons[img_name];
          img.w = st['marker-width'] || img.width;
          img.h = st['marker-width'] || st['marker-height'];
          cartocss.renderSprite(ctx, img, st);
      }
      else {
        var mt = st['marker-type'];
        if (mt && mt === 'rectangle') {
          cartocss.renderRectangle(ctx, st);
        } else {
          cartocss.renderPoint(ctx, st);
        }
      }
      prof.end(true);
      if (torque.flags.sprites_to_images) {
        var i = this._createImage();
        i.src = canvas.toDataURL();
        return i;
      }

      return canvas;
    },

    //
    // renders all the layers (and frames for each layer) from cartocss
    //
    renderTile: function(tile, key) {
      var prof = Profiler.metric('torque.renderer.point.renderLayers').start();
      var layers = this._shader.getLayers();
      for(var i = 0, n = layers.length; i < n; ++i ) {
        var layer = layers[i];
        if (layer.name() !== "Map") {
          var sprites = this._sprites[i] || (this._sprites[i] = {});
          // frames for each layer
          for(var fr = 0; fr < layer.frames().length; ++fr) {
            var frame = layer.frames()[fr];
            var fr_sprites = sprites[frame] || (sprites[frame] = []);
            this._renderTile(tile, key - frame, frame, fr_sprites, layer);
          }
        }
      }

      prof.end(true);
    },

    _createCanvas: function() {
      return this.options.canvasClass
        ? new this.options.canvasClass()
        : document.createElement('canvas');
    },

    _createImage: function() {
      return this.options.imageClass
        ? new this.options.imageClass()
        : new Image();
    },

    //
    // renders a tile in the canvas for key defined in
    // the torque tile
    //
    _renderTile: function(tile, key, frame_offset, sprites, shader, shaderVars) {
      if (!this._canvas) return;

      var prof = Profiler.metric('torque.renderer.point.renderTile').start();
      var ctx = this._ctx;
      var blendMode = compop2canvas(shader.eval('comp-op')) || this.options.blendmode;
      if (blendMode) {
        ctx.globalCompositeOperation = blendMode;
      }
      if (this.options.cumulative && key > tile.maxDate) {
        //TODO: precache because this tile is not going to change
        key = tile.maxDate;
      }
      var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1)
      var activePixels = tile.timeCount[key];
      if (activePixels) {
        var pixelIndex = tile.timeIndex[key];
        for(var p = 0; p < activePixels; ++p) {
          var posIdx = tile.renderDataPos[pixelIndex + p];
          var c = tile.renderData[pixelIndex + p];
          if (c) {
           var sp = sprites[c];
           if (sp === undefined) {
             sp = sprites[c] = this.generateSprite(shader, c, torque.extend({ zoom: tile.z, 'frame-offset': frame_offset }, shaderVars));
           }
           if (sp) {
             var x = tile.x[posIdx]- (sp.width >> 1);
             var y = tileMax - tile.y[posIdx]; // flip mercator
             ctx.drawImage(sp, x, y - (sp.height >> 1));
           }
          }
        }
      }

      prof.end(true);
    },

    setBlendMode: function(b) {
      this.options.blendmode = b;
    },

    /**
     * get active points for a step in active zoom
     * returns a list of bounding boxes [[sw, ne] , [], []] where ne is a {lat: .., lon: ...} obj
     * empty list if there is no active pixels
     */
    getActivePointsBBox: function(tile, step) {
      var positions = [];
      var mercator = new torque.Mercator();

      var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1);
      //this.renderer.renderTile(tile, this.key, pos.x, pos.y);
      var activePixels = tile.timeCount[step];
      var pixelIndex = tile.timeIndex[step];
      for(var p = 0; p < activePixels; ++p) {
        var posIdx = tile.renderDataPos[pixelIndex + p];
        var c = tile.renderData[pixelIndex + p];
        if (c) {
         var x = tile.x[posIdx];
         var y = tileMax - tile.y[posIdx]; // flip mercator
         positions.push(mercator.tilePixelBBox(
           tile.coord.x,
           tile.coord.y,
           tile.coord.z,
           x, y
         ));
        }
      }
      return positions;
    },

    // return the value for x, y (tile coordinates)
    // null for no value
    getValueFor: function(tile, step, px, py) {
      var mercator = new torque.Mercator();
      var res = this.options.resolution;
      var res2 = res >> 1;

      var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1);
      //this.renderer.renderTile(tile, this.key, pos.x, pos.y);
      var activePixels = tile.timeCount[step];
      var pixelIndex = tile.timeIndex[step];
      for(var p = 0; p < activePixels; ++p) {
        var posIdx = tile.renderDataPos[pixelIndex + p];
        var c = tile.renderData[pixelIndex + p];
        if (c) {
         var x = tile.x[posIdx];
         var y = tileMax - tile.y[posIdx];
         var dx = px + res2 - x;
         var dy = py + res2 - y;
         if (dx >= 0 && dx < res && dy >= 0 && dy < res) {
           return {
             value: c,
             bbox: mercator.tilePixelBBox(
               tile.coord.x,
               tile.coord.y,
               tile.coord.z,
               x - res2, y - res2, res
             )
           }
         }
        }
      }
      return null;
    },
    _preloadIcons: function(img_names){
      var self = this;
      this._icons = {};
      if (img_names.length > 0 && !this._forcePoints){
        for (var i = 0; i<img_names.length; i++){
          var new_img = this._createImage();
          function qualifyURL(url) {
            var a = document.createElement('a');
              a.href = url;
              return a.href;
          }
          this._icons[qualifyURL(img_names[i])] = null;
          if (typeof self._icons.itemsToLoad === 'undefined'){
            this._icons.itemsToLoad = img_names.length;
          }
          new_img.crossOrigin = "Anonymous";
          new_img.onload = function(e){
            self._icons[this.src] = this;
            if (Object.keys(self._icons).length === img_names.length + 1){
              self._icons.itemsToLoad--;
              if (self._icons.itemsToLoad === 0){
                self.clearSpriteCache();
                self.fire("allIconsLoaded");
              }
            }
          };
          new_img.onerror = function(){
            self._forcePoints = true;
            self.clearSpriteCache();
            console.error("Couldn't get marker-file " + this.src);
          };
          new_img.src = img_names[i];
        }
      }

  },
  applyFilters: function(){
    if(this._style){
      if(this._style['image-filters']){
        function gradientKey(imf){
          var hash = ""
          for(var i = 0; i < imf.args.length; i++){
            var rgb = imf.args[i].rgb;
            hash += rgb[0] + ":" + rgb[1] + ":" + rgb[2];
          }
          return hash;
        }
        var gradient = this._gradients[gradientKey(this._style['image-filters'])];
        if(!gradient){
          function componentToHex(c) {
            var hex = c.toString(16);
            return hex.length == 1 ? "0" + hex : hex;
          }

          function rgbToHex(r, g, b) {
            return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
          }
          gradient = {};
          var colorize = this._style['image-filters'].args;

          var increment = 1/colorize.length;
          for (var i = 0; i < colorize.length; i++){
            var key = increment * i + increment;
            var rgb = colorize[i].rgb;
            var formattedColor = rgbToHex(rgb[0], rgb[1], rgb[2]);
            gradient[key] = formattedColor;
          }
          this._gradients[gradientKey(this._style['image-filters'])] = gradient;
        }
        this._filters.gradient(gradient);
        this._filters.draw();
      }
    }
  }
});

  // exports public api
module.exports = PointRenderer;
<commit_msg>sums 1 to itemstoload previous to load trigger<commit_after>var torque = require('../');
var cartocss = require('./cartocss_render');
var Profiler = require('../profiler');
var carto = global.carto || require('carto');
var filters = require('./torque_filters');

  var TAU = Math.PI * 2;
  var DEFAULT_CARTOCSS = [
    '#layer {',
    '  marker-fill: #662506;',
    '  marker-width: 4;',
    '  [value > 1] { marker-fill: #FEE391; }',
    '  [value > 2] { marker-fill: #FEC44F; }',
    '  [value > 3] { marker-fill: #FE9929; }',
    '  [value > 4] { marker-fill: #EC7014; }',
    '  [value > 5] { marker-fill: #CC4C02; }',
    '  [value > 6] { marker-fill: #993404; }',
    '  [value > 7] { marker-fill: #662506; }',
    '}'
  ].join('\n');

  var COMP_OP_TO_CANVAS = {
    "src": 'source-over',
    "src-over": 'source-over',
    "dst-over": 'destination-over',
    "src-in": 'source-in',
    "dst-in": 'destination-in',
    "src-out": 'source-out',
    "dst-out": 'destination-out',
    "src-atop": 'source-atop',
    "dst-atop": 'destination-atop',
    "xor": 'xor',
    "darken": 'darken',
    "lighten": 'lighten'
  }

  function compop2canvas(compop) {
    return COMP_OP_TO_CANVAS[compop] || compop;
  }

  //
  // this renderer just render points depending of the value
  //
  function PointRenderer(canvas, options) {
    if (!canvas) {
      throw new Error("canvas can't be undefined");
    }
    this.options = options;
    this._canvas = canvas;
    this._ctx = canvas.getContext('2d');
    this._sprites = []; // sprites per layer
    this._shader = null;
    this._icons = {};
    this._filters = filters(this._canvas);
    this.setCartoCSS(this.options.cartocss || DEFAULT_CARTOCSS);
    this.TILE_SIZE = 256;
    this._style = null;
    this._gradients = {};

    this._forcePoints = false;
  }

  torque.extend(PointRenderer.prototype, torque.Event, {

    clearCanvas: function() {
      var canvas = this._canvas;
      var color = this._Map['-torque-clear-color']
      // shortcut for the default value
      if (color  === "rgba(255, 255, 255, 0)" || !color) {
        this._canvas.width = this._canvas.width;
      } else {
        var ctx = this._ctx;
        ctx.setTransform(1, 0, 0, 1, 0, 0);
        var compop = this._Map['comp-op']
        ctx.globalCompositeOperation = compop2canvas(compop);
        ctx.fillStyle = color;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
      }
    },

    setCanvas: function(canvas) {
      this._canvas = canvas;
      this._ctx = canvas.getContext('2d');
    },

    //
    // sets the cartocss style to render stuff
    //
    setCartoCSS: function(cartocss) {
      // clean sprites
      this.setShader(new carto.RendererJS().render(cartocss));
    },

    setShader: function(shader) {
      // clean sprites
      this._sprites = [];
      this._shader = shader;
      this._Map = this._shader.getDefault().getStyle({}, { zoom: 0 });
      var img_names = this._shader.getImageURLs();
      this._preloadIcons(img_names);
    },

    clearSpriteCache: function() {
      this._sprites = [];
    },

    //
    // generate sprite based on cartocss style
    //
    generateSprite: function(shader, value, shaderVars) {
      var self = this;
      var prof = Profiler.metric('torque.renderer.point.generateSprite').start();
      var st = shader.getStyle({
        value: value
      }, shaderVars);
      if(this._style === null || this._style !== st){
        this._style = st;
      }

      var pointSize = st['marker-width'];
      if (!pointSize) {
        return null;
      }

      if (st['marker-opacity'] === 0 && !st['marker-line-opacity']) {
        return null;
      }

      var canvas = this._createCanvas();
      // take into account the exterior ring to calculate the size
      var canvasSize = (st['marker-line-width'] || 0) + pointSize*2;
      var ctx = canvas.getContext('2d');
      var w = ctx.width = canvas.width = ctx.height = canvas.height = Math.ceil(canvasSize);
      ctx.translate(w/2, w/2);

      function qualifyURL(url) {
            var a = document.createElement('a');
              a.href = url;
              return a.href;
          };
      var img_name = qualifyURL(st["marker-file"] || st["point-file"]);
      if (img_name && this._icons.itemsToLoad === 0) {
          var img = this._icons[img_name];
          img.w = st['marker-width'] || img.width;
          img.h = st['marker-width'] || st['marker-height'];
          cartocss.renderSprite(ctx, img, st);
      }
      else {
        var mt = st['marker-type'];
        if (mt && mt === 'rectangle') {
          cartocss.renderRectangle(ctx, st);
        } else {
          cartocss.renderPoint(ctx, st);
        }
      }
      prof.end(true);
      if (torque.flags.sprites_to_images) {
        var i = this._createImage();
        i.src = canvas.toDataURL();
        return i;
      }

      return canvas;
    },

    //
    // renders all the layers (and frames for each layer) from cartocss
    //
    renderTile: function(tile, key) {
      var prof = Profiler.metric('torque.renderer.point.renderLayers').start();
      var layers = this._shader.getLayers();
      for(var i = 0, n = layers.length; i < n; ++i ) {
        var layer = layers[i];
        if (layer.name() !== "Map") {
          var sprites = this._sprites[i] || (this._sprites[i] = {});
          // frames for each layer
          for(var fr = 0; fr < layer.frames().length; ++fr) {
            var frame = layer.frames()[fr];
            var fr_sprites = sprites[frame] || (sprites[frame] = []);
            this._renderTile(tile, key - frame, frame, fr_sprites, layer);
          }
        }
      }

      prof.end(true);
    },

    _createCanvas: function() {
      return this.options.canvasClass
        ? new this.options.canvasClass()
        : document.createElement('canvas');
    },

    _createImage: function() {
      return this.options.imageClass
        ? new this.options.imageClass()
        : new Image();
    },

    //
    // renders a tile in the canvas for key defined in
    // the torque tile
    //
    _renderTile: function(tile, key, frame_offset, sprites, shader, shaderVars) {
      if (!this._canvas) return;

      var prof = Profiler.metric('torque.renderer.point.renderTile').start();
      var ctx = this._ctx;
      var blendMode = compop2canvas(shader.eval('comp-op')) || this.options.blendmode;
      if (blendMode) {
        ctx.globalCompositeOperation = blendMode;
      }
      if (this.options.cumulative && key > tile.maxDate) {
        //TODO: precache because this tile is not going to change
        key = tile.maxDate;
      }
      var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1)
      var activePixels = tile.timeCount[key];
      if (activePixels) {
        var pixelIndex = tile.timeIndex[key];
        for(var p = 0; p < activePixels; ++p) {
          var posIdx = tile.renderDataPos[pixelIndex + p];
          var c = tile.renderData[pixelIndex + p];
          if (c) {
           var sp = sprites[c];
           if (sp === undefined) {
             sp = sprites[c] = this.generateSprite(shader, c, torque.extend({ zoom: tile.z, 'frame-offset': frame_offset }, shaderVars));
           }
           if (sp) {
             var x = tile.x[posIdx]- (sp.width >> 1);
             var y = tileMax - tile.y[posIdx]; // flip mercator
             ctx.drawImage(sp, x, y - (sp.height >> 1));
           }
          }
        }
      }

      prof.end(true);
    },

    setBlendMode: function(b) {
      this.options.blendmode = b;
    },

    /**
     * get active points for a step in active zoom
     * returns a list of bounding boxes [[sw, ne] , [], []] where ne is a {lat: .., lon: ...} obj
     * empty list if there is no active pixels
     */
    getActivePointsBBox: function(tile, step) {
      var positions = [];
      var mercator = new torque.Mercator();

      var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1);
      //this.renderer.renderTile(tile, this.key, pos.x, pos.y);
      var activePixels = tile.timeCount[step];
      var pixelIndex = tile.timeIndex[step];
      for(var p = 0; p < activePixels; ++p) {
        var posIdx = tile.renderDataPos[pixelIndex + p];
        var c = tile.renderData[pixelIndex + p];
        if (c) {
         var x = tile.x[posIdx];
         var y = tileMax - tile.y[posIdx]; // flip mercator
         positions.push(mercator.tilePixelBBox(
           tile.coord.x,
           tile.coord.y,
           tile.coord.z,
           x, y
         ));
        }
      }
      return positions;
    },

    // return the value for x, y (tile coordinates)
    // null for no value
    getValueFor: function(tile, step, px, py) {
      var mercator = new torque.Mercator();
      var res = this.options.resolution;
      var res2 = res >> 1;

      var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1);
      //this.renderer.renderTile(tile, this.key, pos.x, pos.y);
      var activePixels = tile.timeCount[step];
      var pixelIndex = tile.timeIndex[step];
      for(var p = 0; p < activePixels; ++p) {
        var posIdx = tile.renderDataPos[pixelIndex + p];
        var c = tile.renderData[pixelIndex + p];
        if (c) {
         var x = tile.x[posIdx];
         var y = tileMax - tile.y[posIdx];
         var dx = px + res2 - x;
         var dy = py + res2 - y;
         if (dx >= 0 && dx < res && dy >= 0 && dy < res) {
           return {
             value: c,
             bbox: mercator.tilePixelBBox(
               tile.coord.x,
               tile.coord.y,
               tile.coord.z,
               x - res2, y - res2, res
             )
           }
         }
        }
      }
      return null;
    },
    _preloadIcons: function(img_names){
      var self = this;
      this._icons = {};
      if (img_names.length > 0 && !this._forcePoints){
        for (var i = 0; i<img_names.length; i++){
          var new_img = this._createImage();
          function qualifyURL(url) {
            var a = document.createElement('a');
              a.href = url;
              return a.href;
          }
          this._icons[qualifyURL(img_names[i])] = null;
          if (typeof self._icons.itemsToLoad === 'undefined'){
            this._icons.itemsToLoad = img_names.length;
          }
          new_img.crossOrigin = "Anonymous";
          new_img.onload = function(e){
            self._icons[this.src] = this;
            if (Object.keys(self._icons).length === img_names.length + 1){
              self._icons.itemsToLoad--;
              if (self._icons.itemsToLoad === 0){
                self.clearSpriteCache();
                self.fire("allIconsLoaded");
              }
            }
          };
          new_img.onerror = function(){
            self._forcePoints = true;
            self.clearSpriteCache();
            console.error("Couldn't get marker-file " + this.src);
          };
          this.itemsToLoad++;
          new_img.src = img_names[i];
        }
      }

  },
  applyFilters: function(){
    if(this._style){
      if(this._style['image-filters']){
        function gradientKey(imf){
          var hash = ""
          for(var i = 0; i < imf.args.length; i++){
            var rgb = imf.args[i].rgb;
            hash += rgb[0] + ":" + rgb[1] + ":" + rgb[2];
          }
          return hash;
        }
        var gradient = this._gradients[gradientKey(this._style['image-filters'])];
        if(!gradient){
          function componentToHex(c) {
            var hex = c.toString(16);
            return hex.length == 1 ? "0" + hex : hex;
          }

          function rgbToHex(r, g, b) {
            return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
          }
          gradient = {};
          var colorize = this._style['image-filters'].args;

          var increment = 1/colorize.length;
          for (var i = 0; i < colorize.length; i++){
            var key = increment * i + increment;
            var rgb = colorize[i].rgb;
            var formattedColor = rgbToHex(rgb[0], rgb[1], rgb[2]);
            gradient[key] = formattedColor;
          }
          this._gradients[gradientKey(this._style['image-filters'])] = gradient;
        }
        this._filters.gradient(gradient);
        this._filters.draw();
      }
    }
  }
});

  // exports public api
module.exports = PointRenderer;
<|endoftext|>


<commit_before>var _ = require('lodash');
var Promise = require('bluebird');
var urlTools = require('urltools');
var glob = require('glob');
var pathModule = require('path');

// Takes assetConfigs, urls or root-relative paths or arrays of these
module.exports = function () { // ...
    var assetConfigs = _.flatten(arguments);
    return function loadAssets(assetGraph) {
        return Promise.map(assetConfigs, function (assetConfig) {
            if (typeof assetConfig === 'string' && !/^[a-zA-Z-\+]+:/.test(assetConfig) && assetConfig.indexOf('*') !== -1) {
                assetConfig = pathModule.resolve(assetGraph.root ? urlTools.fileUrlToFsPath(assetGraph.root) : process.cwd(), assetConfig);
                return Promise.fromNode(function (cb) {
                    glob(assetConfig, cb);
                }).then(function (files) {
                    return files.map(function (path) {
                        return encodeURI('file://' + path);
                    });
                });
            } else {
                return assetConfig;
            }
        }).then(function (assetConfigs) {
            return Promise.map(_.flatten(assetConfigs), function (assetConfig) {
                var resolvedAssetConfig = assetGraph.resolveAssetConfig(assetConfig, assetGraph.root);
                if (typeof resolvedAssetConfig.isInitial === 'undefined') {
                    resolvedAssetConfig.isInitial = true;
                }
                return assetGraph.ensureAssetConfigHasType(resolvedAssetConfig);
            });
        }).then(function (resolvedAssetConfigs) {
            return Promise.map(resolvedAssetConfigs, function (resolvedAssetConfig) {
                var asset = assetGraph.createAsset(resolvedAssetConfig);
                if (asset.keepUnloaded) {
                    return asset;
                } else {
                    return asset.load().catch(function (err) {
                        assetGraph.emit('warn', err);
                        return asset;
                    });
                }
            }, {concurrency: 10});
        }).then(function (assets) {
            assets.forEach(function (asset) {
                if (asset) {
                    assetGraph.addAsset(asset);
                }
            });
        });
    };
};
<commit_msg>loadAssets: Don't proceed to add assets that weren't loaded.<commit_after>var _ = require('lodash');
var Promise = require('bluebird');
var urlTools = require('urltools');
var glob = require('glob');
var pathModule = require('path');

// Takes assetConfigs, urls or root-relative paths or arrays of these
module.exports = function () { // ...
    var assetConfigs = _.flatten(arguments);
    return function loadAssets(assetGraph) {
        return Promise.map(assetConfigs, function (assetConfig) {
            if (typeof assetConfig === 'string' && !/^[a-zA-Z-\+]+:/.test(assetConfig) && assetConfig.indexOf('*') !== -1) {
                assetConfig = pathModule.resolve(assetGraph.root ? urlTools.fileUrlToFsPath(assetGraph.root) : process.cwd(), assetConfig);
                return Promise.fromNode(function (cb) {
                    glob(assetConfig, cb);
                }).then(function (files) {
                    return files.map(function (path) {
                        return encodeURI('file://' + path);
                    });
                });
            } else {
                return assetConfig;
            }
        }).then(function (assetConfigs) {
            return Promise.map(_.flatten(assetConfigs), function (assetConfig) {
                var resolvedAssetConfig = assetGraph.resolveAssetConfig(assetConfig, assetGraph.root);
                if (typeof resolvedAssetConfig.isInitial === 'undefined') {
                    resolvedAssetConfig.isInitial = true;
                }
                return assetGraph.ensureAssetConfigHasType(resolvedAssetConfig);
            });
        }).then(function (resolvedAssetConfigs) {
            return Promise.map(resolvedAssetConfigs, function (resolvedAssetConfig) {
                var asset = assetGraph.createAsset(resolvedAssetConfig);
                if (asset.keepUnloaded) {
                    return asset;
                } else {
                    return asset.load().catch(function (err) {
                        assetGraph.emit('warn', err);
                        return asset;
                    });
                }
            }, {concurrency: 10});
        }).then(function (assets) {
            assets.forEach(function (asset) {
                if (asset && asset.isLoaded) {
                    assetGraph.addAsset(asset);
                }
            });
        });
    };
};
<|endoftext|>


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

var errorMethodBlacklist = ['message', 'line', 'sourceId', 'sourceURL', 'stack', 'stackArray'].reduce(function (result, prop) {
    result[prop] = true;
    return result;
}, {});

function UnexpectedError(expect, assertion, parent) {
    var base = Error.call(this, '');

    if (Error.captureStackTrace) {
        Error.captureStackTrace(this, UnexpectedError);
    } else {
        // Throw the error to make sure it has its stack serialized:
        try { throw base; } catch (err) {}
        this.stack = base.stack;
    }

    this.expect = expect;
    this.assertion = assertion || null;
    this.parent = parent || null;
    this.name = 'UnexpectedError';
}

UnexpectedError.prototype = Object.create(Error.prototype);

UnexpectedError.prototype._isUnexpected = true;
UnexpectedError.prototype.isUnexpected = true;
UnexpectedError.prototype.buildDiff = function () {
    var expect = this.expect;
    return this.createDiff && this.createDiff(expect.output.clone(), function (actual, expected) {
        return expect.diff(actual, expected);
    }, function (v, depth) {
        return expect.inspect(v, depth || Infinity);
    }, function (actual, expected) {
        return expect.equal(actual, expected);
    });
};

UnexpectedError.prototype.getDefaultErrorMessage = function (options) {
    var message = this.expect.output.clone();
    if (this.assertion) {
        message.append(this.assertion.standardErrorMessage(options));
    } else {
        message.append(this.output);
    }
    var errorWithDiff = this;
    while (!errorWithDiff.createDiff && errorWithDiff.parent) {
        errorWithDiff = errorWithDiff.parent;
    }

    if (errorWithDiff && errorWithDiff.createDiff) {
        var comparison = errorWithDiff.buildDiff();
        if (comparison) {
            message.nl(2).append(comparison.diff);
        }
    }

    return message;
};

UnexpectedError.prototype.getNestedErrorMessage = function (options) {
    var message = this.expect.output.clone();
    if (this.assertion) {
        message.append(this.assertion.standardErrorMessage(options));
    } else {
        message.append(this.output);
    }

    var parent = this.parent;
    while (parent.getErrorMode() === 'bubble') {
        parent = parent.parent;
    }

    message.nl()
        .indentLines()
        .i().block(parent.getErrorMessage(utils.extend({}, options || {}, {
            compact: this.assertion && parent.assertion &&
                this.assertion.subject === parent.assertion.subject
        })));
    return message;
};

UnexpectedError.prototype.getDiffMethod = function () {
    var errorWithDiff = this;
    while (!errorWithDiff.createDiff && errorWithDiff.parent) {
        errorWithDiff = errorWithDiff.parent;
    }

    return errorWithDiff && errorWithDiff.createDiff || null;
};

UnexpectedError.prototype.getDiff = function () {
    var errorWithDiff = this;
    while (!errorWithDiff.createDiff && errorWithDiff.parent) {
        errorWithDiff = errorWithDiff.parent;
    }

    if (errorWithDiff) {
        var diffResult = errorWithDiff.buildDiff();
        if (diffResult && diffResult.diff) {
            return diffResult;
        } else {
            return null;
        }
    } else {
        return null;
    }
};

UnexpectedError.prototype.getDiffMessage = function () {
    var message = this.expect.output.clone();
    var comparison = this.getDiff();
    if (comparison) {
        message.append(comparison.diff);
    } else if (this.assertion) {
        message.append(this.assertion.standardErrorMessage());
    } else {
        message.append(this.output);
    }
    return message;
};

UnexpectedError.prototype.getErrorMode = function () {
    var errorMode = this.errorMode ||
        (this.assertion && this.assertion.errorMode) ||
        'default';

    if (!this.parent) {
        switch (errorMode) {
        case 'default':
        case 'bubbleThrough':
            return errorMode;
        default:
            return 'default';
        }
    } else {
        return errorMode;
    }
};

UnexpectedError.prototype.getErrorMessage = function (options) {
    // Search for any parent error that has mode bubble through on the
    // error these should be bubbled to the top
    var errorWithBubbleThough = this.parent;
    while (errorWithBubbleThough && errorWithBubbleThough.getErrorMode() !== 'bubbleThrough') {
        errorWithBubbleThough = errorWithBubbleThough.parent;
    }
    if (errorWithBubbleThough) {
        return errorWithBubbleThough.getErrorMessage();
    }

    var errorMode = this.getErrorMode();
    switch (errorMode) {
    case 'nested': return this.getNestedErrorMessage(options);
    case 'default': return this.getDefaultErrorMessage(options);
    case 'bubbleThrough': return this.getDefaultErrorMessage();
    case 'bubble': return this.parent.getErrorMessage(options);
    case 'diff': return this.getDiffMessage();
    default: throw new Error("Unknown error mode: '" + errorMode + "'");
    }
};

UnexpectedError.prototype.serializeMessage = function (outputFormat) {
    if (!this._hasSerializedErrorMessage) {
        var message = this.getErrorMessage();
        if (outputFormat === 'html') {
            outputFormat = 'text';
            this.htmlMessage = message.toString('html');
        }
        this.message = '\n' + message.toString(outputFormat);
        this._hasSerializedErrorMessage = true;
    }
};

UnexpectedError.prototype.clone = function () {
    var that = this;
    var newError = new UnexpectedError(this.expect);
    Object.keys(that).forEach(function (key) {
        if (!errorMethodBlacklist[key]) {
            newError[key] = that[key];
        }
    });
    return newError;
};

UnexpectedError.prototype.getLabel = function () {
    var currentError = this;
    while (currentError && !currentError.label) {
        currentError = currentError.parent;
    }
    return (currentError && currentError.label) || null;
};

UnexpectedError.prototype.getParents = function () {
    var result = [];
    var parent = this.parent;
    while (parent) {
        result.push(parent);
        parent = parent.parent;
    }
    return result;
};

UnexpectedError.prototype.getAllErrors = function () {
    var result = this.getParents();
    result.unshift(this);
    return result;
};

module.exports = UnexpectedError;
<commit_msg>UnexpectedError: Capture the error mode of the assertion at creation time.<commit_after>var utils = require('./utils');

var errorMethodBlacklist = ['message', 'line', 'sourceId', 'sourceURL', 'stack', 'stackArray'].reduce(function (result, prop) {
    result[prop] = true;
    return result;
}, {});

function UnexpectedError(expect, assertion, parent) {
    this.errorMode = (assertion && assertion.errorMode) || 'default';
    var base = Error.call(this, '');

    if (Error.captureStackTrace) {
        Error.captureStackTrace(this, UnexpectedError);
    } else {
        // Throw the error to make sure it has its stack serialized:
        try { throw base; } catch (err) {}
        this.stack = base.stack;
    }

    this.expect = expect;
    this.assertion = assertion || null;
    this.parent = parent || null;
    this.name = 'UnexpectedError';
}

UnexpectedError.prototype = Object.create(Error.prototype);

UnexpectedError.prototype._isUnexpected = true;
UnexpectedError.prototype.isUnexpected = true;
UnexpectedError.prototype.buildDiff = function () {
    var expect = this.expect;
    return this.createDiff && this.createDiff(expect.output.clone(), function (actual, expected) {
        return expect.diff(actual, expected);
    }, function (v, depth) {
        return expect.inspect(v, depth || Infinity);
    }, function (actual, expected) {
        return expect.equal(actual, expected);
    });
};

UnexpectedError.prototype.getDefaultErrorMessage = function (options) {
    var message = this.expect.output.clone();
    if (this.assertion) {
        message.append(this.assertion.standardErrorMessage(options));
    } else {
        message.append(this.output);
    }
    var errorWithDiff = this;
    while (!errorWithDiff.createDiff && errorWithDiff.parent) {
        errorWithDiff = errorWithDiff.parent;
    }

    if (errorWithDiff && errorWithDiff.createDiff) {
        var comparison = errorWithDiff.buildDiff();
        if (comparison) {
            message.nl(2).append(comparison.diff);
        }
    }

    return message;
};

UnexpectedError.prototype.getNestedErrorMessage = function (options) {
    var message = this.expect.output.clone();
    if (this.assertion) {
        message.append(this.assertion.standardErrorMessage(options));
    } else {
        message.append(this.output);
    }

    var parent = this.parent;
    while (parent.getErrorMode() === 'bubble') {
        parent = parent.parent;
    }

    message.nl()
        .indentLines()
        .i().block(parent.getErrorMessage(utils.extend({}, options || {}, {
            compact: this.assertion && parent.assertion &&
                this.assertion.subject === parent.assertion.subject
        })));
    return message;
};

UnexpectedError.prototype.getDiffMethod = function () {
    var errorWithDiff = this;
    while (!errorWithDiff.createDiff && errorWithDiff.parent) {
        errorWithDiff = errorWithDiff.parent;
    }

    return errorWithDiff && errorWithDiff.createDiff || null;
};

UnexpectedError.prototype.getDiff = function () {
    var errorWithDiff = this;
    while (!errorWithDiff.createDiff && errorWithDiff.parent) {
        errorWithDiff = errorWithDiff.parent;
    }

    if (errorWithDiff) {
        var diffResult = errorWithDiff.buildDiff();
        if (diffResult && diffResult.diff) {
            return diffResult;
        } else {
            return null;
        }
    } else {
        return null;
    }
};

UnexpectedError.prototype.getDiffMessage = function () {
    var message = this.expect.output.clone();
    var comparison = this.getDiff();
    if (comparison) {
        message.append(comparison.diff);
    } else if (this.assertion) {
        message.append(this.assertion.standardErrorMessage());
    } else {
        message.append(this.output);
    }
    return message;
};

UnexpectedError.prototype.getErrorMode = function () {
    if (!this.parent) {
        switch (this.errorMode) {
        case 'default':
        case 'bubbleThrough':
            return this.errorMode;
        default:
            return 'default';
        }
    } else {
        return this.errorMode;
    }
};

UnexpectedError.prototype.getErrorMessage = function (options) {
    // Search for any parent error that has mode bubble through on the
    // error these should be bubbled to the top
    var errorWithBubbleThough = this.parent;
    while (errorWithBubbleThough && errorWithBubbleThough.getErrorMode() !== 'bubbleThrough') {
        errorWithBubbleThough = errorWithBubbleThough.parent;
    }
    if (errorWithBubbleThough) {
        return errorWithBubbleThough.getErrorMessage();
    }

    var errorMode = this.getErrorMode();
    switch (errorMode) {
    case 'nested': return this.getNestedErrorMessage(options);
    case 'default': return this.getDefaultErrorMessage(options);
    case 'bubbleThrough': return this.getDefaultErrorMessage();
    case 'bubble': return this.parent.getErrorMessage(options);
    case 'diff': return this.getDiffMessage();
    default: throw new Error("Unknown error mode: '" + errorMode + "'");
    }
};

UnexpectedError.prototype.serializeMessage = function (outputFormat) {
    if (!this._hasSerializedErrorMessage) {
        var message = this.getErrorMessage();
        if (outputFormat === 'html') {
            outputFormat = 'text';
            this.htmlMessage = message.toString('html');
        }
        this.message = '\n' + message.toString(outputFormat);
        this._hasSerializedErrorMessage = true;
    }
};

UnexpectedError.prototype.clone = function () {
    var that = this;
    var newError = new UnexpectedError(this.expect);
    Object.keys(that).forEach(function (key) {
        if (!errorMethodBlacklist[key]) {
            newError[key] = that[key];
        }
    });
    return newError;
};

UnexpectedError.prototype.getLabel = function () {
    var currentError = this;
    while (currentError && !currentError.label) {
        currentError = currentError.parent;
    }
    return (currentError && currentError.label) || null;
};

UnexpectedError.prototype.getParents = function () {
    var result = [];
    var parent = this.parent;
    while (parent) {
        result.push(parent);
        parent = parent.parent;
    }
    return result;
};

UnexpectedError.prototype.getAllErrors = function () {
    var result = this.getParents();
    result.unshift(this);
    return result;
};

module.exports = UnexpectedError;
<|endoftext|>


<commit_before>'use strict'

const array_stream = require('../array_stream');
const resolve = require('path').resolve;
const readFile = require('fs').readFile;

module.exports = (entrypoint) => {

    entrypoint.module_root = entrypoint.base = '/node_modules/';

    return {
        mic: (name, options, cb) => {

            // TODO access check

            readFile(resolve('./instance.nq'), (err, data) => {

                if (err) {
                    return cb(err);
                }

                data = data.toString().split('\n');
                data.forEach((triple, index) => {
                    if (triple[0] === '#') {
                        return; //console.log('Comment:', triple);
                    }
                    data[index] = triple.replace(/<([^<>]*)>/g, '$1').split(' ', 3);
                });

                cb(null, array_stream(data));
            });
            //cb(null, require(entrypoint.network + '/' + name));
        },
        mod: (name, options, cb) => {
            cb(null, require(entrypoint.module_root + name));
        }
    };
};
<commit_msg>test with triple as an object, instead of array<commit_after>'use strict'

const array_stream = require('../array_stream');
const resolve = require('path').resolve;
const readFile = require('fs').readFile;

module.exports = (entrypoint) => {

    entrypoint.module_root = entrypoint.base = '/node_modules/';

    return {
        stdin: process.stdin,
        stdout: process.stdout,
        stderr: process.stderr,
        modules: {},
        instances: {},
        events: {},
        streams: {},
        read: (name, options, cb) => {

            // TODO access check

            readFile(resolve('./instance.nq'), (err, data) => {

                if (err) {
                    return cb(err);
                }

                let triples = [];
                data = data.toString().split('\n');
                data.forEach((triple, index) => {
                    if (triple[0] === '#' || !triple) {
                        return;
                    }
                    triple = triple.replace(/<([^<>]*)>/g, '$1').split(' ', 3);
                    triples.push({
                        subject: triple[0],
                        predicate: triple[1],
                        object: triple[2]
                    });
                });

                cb(null, array_stream(triples));
            });
            //cb(null, require(entrypoint.network + '/' + name));
        },
        mod: (name, options, cb) => {
            cb(null, require(entrypoint.module_root + name));
        }
    };
};
<|endoftext|>


<commit_before>// theme/default js:

var authFrom = (function() {
    var isDesktop = function() {
        var ua = navigator.userAgent.toLowerCase();
        return ua.indexOf('windows nt')>=0 || ua.indexOf('macintosh')>=0;
    };
    return function(provider) {
        var
            url = '/auth/from/' + provider,
            popupId = 'x_id_auth_window';
        if (isDesktop()) {
            var w = window.open(url + '?jscallback=onAuthCallback', popupId, 'top=200,left=400,width=600,height=380,directories=no,menubar=no,toolbar=no,resizable=no');
        }
        else {
            location.assign(url);
        }
    };
})();

var onAuthCallback = function(u) {
    $('.x-user-name').text(u.name);
    $('.x-user-image').attr('src', u.image_url);
    $('.x-auth-signed').show();
    $('.x-auth-not-signed').hide();
}

function makeSmartDate() {
    $('.x-smartdate').each(function() {
        $(this).removeClass('x-smartdate').text(toSmartDate($(this).attr('date')));
    });
}

$(function() {
    // set user image:
    $('img.x-user-image').attr('src', g_user_image);

    // active nav bar:
    var xnav = $('meta[property="x-nav"]').attr('content');
    $('#main-nav-bar li a[href="' + xnav + '"]').parent().addClass('active');

    // init scroll:
    var $window = $(window);
    var $header = $('#header');
    var $navbar = $('#navbar');
    var $autodisplay = $('.x-auto-display');
    $window.scroll(function() {
        if ($window.scrollTop() >= 100) {
            if ( ! $navbar.hasClass('navbar-fixed-top')) {
                $navbar.addClass('navbar-fixed-top');
                $header.css('margin-top', '40px');
                $autodisplay.css('display', '');
            }
        }
        else {
            if ($navbar.hasClass('navbar-fixed-top')) {
                $navbar.removeClass('navbar-fixed-top');
                $header.css('margin-top', '0px');
                $autodisplay.css('display', 'none');
            }
        }

        if ($(window).scrollTop() > 1000) {
            $('div.x-goto-top').show();
        }
        else {
            $('div.x-goto-top').hide();
        }
    });

    // goto-top:
    $('div.x-goto-top').click(function() {
        $('html, body').animate({scrollTop: 0}, 1000);
    });

    // start carousel:
    $('.carousel').carousel();

    // smart date:
    makeSmartDate();

    // add '_blank' for all external links:
    $('.x-content a[href^="http://"]').attr('target', '_blank');
    $('.x-content a[href^="https://"]').attr('target', '_blank');

    // search query:
    var input_search = $('input.search-query');
    var old_width = input_search.css('width');
    input_search.bind('focusin', function() {
        input_search.animate({'width': '160px'}, 500);
    }).bind('focusout', function() {
        input_search.animate({'width': old_width}, 500);
    });

    // smart video:
    var bSupportVideo = !!document.createElement('video').canPlayType;
    if (bSupportVideo) {
        var v = document.createElement('video');
        bSupportVideo = v.canPlayType('video/mp4')!='';
    }
    $('div[data-type=video]').each(function() {
        var d = $(this);
        d.addClass('x-video');
        if (! bSupportVideo) {
            d.html('
您的浏览器不支持播放该MP4视频
');
        }
        else {
            var src = d.attr('data-src');
            var w = d.attr('data-width');
            var h = d.attr('data-height');
            d.addClass('x-video-active');
            d.html('

');
            var s = '<video width="' + w + '" height="' + h + '" controls="controls" preload="auto" autoplay style="border:solid 1px #ccc"><source src="' + src + '" /></video>'
            d.click(function() {
                d.css('display', 'none');
                d.after(s);
            });
        }
    });

    // END
});

function toSmartDate(timestamp) {
    if (typeof(timestamp)==='string') {
        timestamp = parseInt(timestamp);
    }
    if (isNaN(timestamp)) {
        return '';
    }

    var
        today = new Date(g_time),
        now = today.getTime(),
        s = '1分钟前',
        t = now - timestamp;
    if (t > 604800000) {
        // 1 week ago:
        var that = new Date(timestamp);
        var
            y = that.getFullYear(),
            m = that.getMonth() + 1,
            d = that.getDate(),
            hh = that.getHours(),
            mm = that.getMinutes();
        s = y===today.getFullYear() ? '' : y + '年';
        s = s + m + '月' + d + '日 ' + hh + ':' + (mm < 10 ? '0' : '') + mm;
    }
    else if (t >= 86400000) {
        // 1-6 days ago:
        s = Math.floor(t / 86400000) + '天前';
    }
    else if (t >= 3600000) {
        // 1-23 hours ago:
        s = Math.floor(t / 3600000) + '小时前';
    }
    else if (t >= 60000) {
        s = Math.floor(t / 60000) + '分钟前';
    }
    return s;
}

function search(keyword) {
    location.assign('http://www.baidu.com/s?ie=utf-8&wd=' + encodeURIComponent(keyword) + '+site%3A' + location.hostname);
    return false;
}

function tryPython() {
    var name = 'iTranswarp_try_python_online';
    var opt = 'width=656,height=420,left=400,top=200,toolbar=no,directories=no,menubar=no,scrollbars=no,resizable=no,location=no,status=no';
    var py = window.open('/static/embed/pyconsole.html#0', name, opt);
    py && py.focus();
}

// create comment by ajax:

function setCommentError($form, s) {
    s = s || '';
    $form.find('span.x-comment-error').text(s);
}

var _comment_template = '' +
    '
' +
    '
' +
    '        ' +
    '
' +
    '
' +
    '
' +
    '             ：' +
    '
' +
    '

' +
    '
' +
    '            ' +
    '                回复' +
    '                Delete' +
    '            ' +
    '
' +
    '
' +
    '
';

function replyComment(a) {
    var p = $(a);
    while (! p.hasClass('x-comment-li')) {
        if (p.get(0)===document) {
            return;
        }
        p = p.parent();
    }
    var u = '@' + p.find('.x-comment-username').text();
    var $textarea = $('form.x-comment-form').find('textarea[name=content]');
    $textarea.val(u + '\n' + $textarea.val());
    $('html, body').animate({scrollTop: $('form.x-comment-form').position().top - 20});
    $textarea.focus();
    $textarea.get(0).setSelectionRange(u.length + 1, u.length + 1);
}

function comment2html(s) {
    var ss = s.split('\n');
    var L = [];
    $.each(ss, function(index, value) {
        L.push('
' + value.replace(/  /g, '  ') + '
');
    });
    return L.join('');
}

function addComment(c) {
    var $dom = $(_comment_template.replace('$ID', c.id));
    $dom.find('a.x-comment-user').attr('href', '/user/' + c.user_id);
    $dom.find('span.x-comment-username').text(c.user_name);
    $dom.find('span.x-comment-date').text(toSmartDate(c.created_at));
    $dom.find('div.x-comment-img img').attr('src', c.user_image_url);
    $dom.find('div.x-comment-content').html(comment2html(c.content));
    $dom.attr('id', 'comment-' + c.id);
    return $dom;
}

function create_comment(form) {
    try {
        var $form = $(form);
        var $btn = $form.find('button[type=submit]');
        var $textarea = $form.find('textarea[name=content]');
        var s = $textarea.val();
        if (s.trim().length===0) {
            setCommentError($form, '请输入评论内容！');
            return false;
        }

        setCommentError($form, '');
        showLoading(true);

        postJSON($form.attr('url'), $form.serialize(), function(err, result) {
            showLoading(false);
            if (err) {
                setCommentError($form, err.message || err.error);
                return;
            }
            $textarea.val('');
            var $dom = addComment(result);
            $('div.x-comments-list').prepend($dom);
            $dom.css('display', 'none');
            $dom.slideDown();
        });
    }
    catch (e) {}
    return false;
}

function deleteComment(cid) {
    if (confirm('delete this comment?')) {
        postJSON('/api/comments/' + cid + '/delete', function(err, result) {
            if (err) {
                return alert('Error: ' + (err.message || err.error));
            }
            $('#comment-' + cid).remove();
        });
    }
}

// END create comment by ajax.
<commit_msg>add functions for discuss<commit_after>// theme/default js:

var authFrom = (function() {
    var isDesktop = function() {
        var ua = navigator.userAgent.toLowerCase();
        return ua.indexOf('windows nt')>=0 || ua.indexOf('macintosh')>=0;
    };
    return function(provider) {
        var
            url = '/auth/from/' + provider,
            popupId = 'x_id_auth_window';
        if (isDesktop()) {
            var w = window.open(url + '?jscallback=onAuthCallback', popupId, 'top=200,left=400,width=600,height=380,directories=no,menubar=no,toolbar=no,resizable=no');
        }
        else {
            location.assign(url);
        }
    };
})();

var onAuthCallback = function(u) {
    $('.x-user-name').text(u.name);
    $('.x-user-image').attr('src', u.image_url);
    $('.x-auth-signed').show();
    $('.x-auth-not-signed').hide();
}

function makeSmartDate() {
    $('.x-smartdate').each(function() {
        $(this).removeClass('x-smartdate').text(toSmartDate($(this).attr('date')));
    });
}

$(function() {
    // set user image:
    $('img.x-user-image').attr('src', g_user_image);

    // active nav bar:
    var xnav = $('meta[property="x-nav"]').attr('content');
    $('#main-nav-bar li a[href="' + xnav + '"]').parent().addClass('active');

    // init scroll:
    var $window = $(window);
    var $header = $('#header');
    var $navbar = $('#navbar');
    var $autodisplay = $('.x-auto-display');
    $window.scroll(function() {
        if ($window.scrollTop() >= 100) {
            if ( ! $navbar.hasClass('navbar-fixed-top')) {
                $navbar.addClass('navbar-fixed-top');
                $header.css('margin-top', '40px');
                $autodisplay.css('display', '');
            }
        }
        else {
            if ($navbar.hasClass('navbar-fixed-top')) {
                $navbar.removeClass('navbar-fixed-top');
                $header.css('margin-top', '0px');
                $autodisplay.css('display', 'none');
            }
        }

        if ($(window).scrollTop() > 1000) {
            $('div.x-goto-top').show();
        }
        else {
            $('div.x-goto-top').hide();
        }
    });

    // goto-top:
    $('div.x-goto-top').click(function() {
        $('html, body').animate({scrollTop: 0}, 1000);
    });

    // start carousel:
    $('.carousel').carousel();

    // smart date:
    makeSmartDate();

    // add '_blank' for all external links:
    $('.x-content a[href^="http://"]').attr('target', '_blank');
    $('.x-content a[href^="https://"]').attr('target', '_blank');

    // search query:
    var input_search = $('input.search-query');
    var old_width = input_search.css('width');
    input_search.bind('focusin', function() {
        input_search.animate({'width': '160px'}, 500);
    }).bind('focusout', function() {
        input_search.animate({'width': old_width}, 500);
    });

    // smart video:
    var bSupportVideo = !!document.createElement('video').canPlayType;
    if (bSupportVideo) {
        var v = document.createElement('video');
        bSupportVideo = v.canPlayType('video/mp4')!='';
    }
    $('div[data-type=video]').each(function() {
        var d = $(this);
        d.addClass('x-video');
        if (! bSupportVideo) {
            d.html('
您的浏览器不支持播放该MP4视频
');
        }
        else {
            var src = d.attr('data-src');
            var w = d.attr('data-width');
            var h = d.attr('data-height');
            d.addClass('x-video-active');
            d.html('

');
            var s = '<video width="' + w + '" height="' + h + '" controls="controls" preload="auto" autoplay style="border:solid 1px #ccc"><source src="' + src + '" /></video>'
            d.click(function() {
                d.css('display', 'none');
                d.after(s);
            });
        }
    });

    // END
});

function toSmartDate(timestamp) {
    if (typeof(timestamp)==='string') {
        timestamp = parseInt(timestamp);
    }
    if (isNaN(timestamp)) {
        return '';
    }

    var
        today = new Date(g_time),
        now = today.getTime(),
        s = '1分钟前',
        t = now - timestamp;
    if (t > 604800000) {
        // 1 week ago:
        var that = new Date(timestamp);
        var
            y = that.getFullYear(),
            m = that.getMonth() + 1,
            d = that.getDate(),
            hh = that.getHours(),
            mm = that.getMinutes();
        s = y===today.getFullYear() ? '' : y + '年';
        s = s + m + '月' + d + '日 ' + hh + ':' + (mm < 10 ? '0' : '') + mm;
    }
    else if (t >= 86400000) {
        // 1-6 days ago:
        s = Math.floor(t / 86400000) + '天前';
    }
    else if (t >= 3600000) {
        // 1-23 hours ago:
        s = Math.floor(t / 3600000) + '小时前';
    }
    else if (t >= 60000) {
        s = Math.floor(t / 60000) + '分钟前';
    }
    return s;
}

function search(keyword) {
    location.assign('http://www.baidu.com/s?ie=utf-8&wd=' + encodeURIComponent(keyword) + '+site%3A' + location.hostname);
    return false;
}

function tryPython() {
    var name = 'iTranswarp_try_python_online';
    var opt = 'width=656,height=420,left=400,top=200,toolbar=no,directories=no,menubar=no,scrollbars=no,resizable=no,location=no,status=no';
    var py = window.open('/static/embed/pyconsole.html#0', name, opt);
    py && py.focus();
}

function setFormError($form, name, text) {
    if (arguments.length === 2) {
        text = name;
        name = undefined;
    }
    $form.find('.control-group').removeClass('error');
    var msg = $form.find('.alert-error');
    if (text) {
        msg.text(text).show();
        name && $form.find('.field-' + name).addClass('error');
    }
    else {
        msg.text('').hide();
        name && $form.find('.field-' + name).removeClass('error');
    }
}

function create_topic(form) {
    try {
        var
            $form = $(form),
            $btn = $form.find('button[type=submit]'),
            $name = $form.find('input[name=name]'),
            $tags = $form.find('input[name=tags]'),
            $textarea = $form.find('textarea[name=content]');
        if ($name.val().trim().length === 0) {
            setFormError($form, 'name', '请输入话题！');
            return false;
        }
        if ($textarea.val().trim().length===0) {
            setFormError($form, 'content', '请输入话题内容！');
            return false;
        }

        setFormError($form, '');
        showLoading(true);

        postJSON($form.attr('url'), $form.serialize(), function(err, result) {
            if (err) {
                showLoading(false);
                setFormError($form, err.data, err.message || err.error);
                return;
            }
            location.assign('/discuss/' + result.board_id + '/' + result.id);
        });
    }
    catch (e) {}
    return false;
}

// create comment by ajax:

function setCommentError($form, s) {
    s = s || '';
    $form.find('span.x-comment-error').text(s);
}

var _comment_template = '' +
    '
' +
    '
' +
    '        ' +
    '
' +
    '
' +
    '
' +
    '             ：' +
    '
' +
    '

' +
    '
' +
    '            ' +
    '                回复' +
    '                Delete' +
    '            ' +
    '
' +
    '
' +
    '
';

function replyComment(a) {
    var p = $(a);
    while (! p.hasClass('x-comment-li')) {
        if (p.get(0)===document) {
            return;
        }
        p = p.parent();
    }
    var u = '@' + p.find('.x-comment-username').text();
    var $textarea = $('form.x-comment-form').find('textarea[name=content]');
    $textarea.val(u + '\n' + $textarea.val());
    $('html, body').animate({scrollTop: $('form.x-comment-form').position().top - 20});
    $textarea.focus();
    $textarea.get(0).setSelectionRange(u.length + 1, u.length + 1);
}

function comment2html(s) {
    var ss = s.split('\n');
    var L = [];
    $.each(ss, function(index, value) {
        L.push('
' + value.replace(/  /g, '  ') + '
');
    });
    return L.join('');
}

function addComment(c) {
    var $dom = $(_comment_template.replace('$ID', c.id));
    $dom.find('a.x-comment-user').attr('href', '/user/' + c.user_id);
    $dom.find('span.x-comment-username').text(c.user_name);
    $dom.find('span.x-comment-date').text(toSmartDate(c.created_at));
    $dom.find('div.x-comment-img img').attr('src', c.user_image_url);
    $dom.find('div.x-comment-content').html(comment2html(c.content));
    $dom.attr('id', 'comment-' + c.id);
    return $dom;
}

function create_comment(form) {
    try {
        var $form = $(form);
        var $btn = $form.find('button[type=submit]');
        var $textarea = $form.find('textarea[name=content]');
        var s = $textarea.val();
        if (s.trim().length===0) {
            setCommentError($form, '请输入评论内容！');
            return false;
        }

        setCommentError($form, '');
        showLoading(true);

        postJSON($form.attr('url'), $form.serialize(), function(err, result) {
            showLoading(false);
            if (err) {
                setCommentError($form, err.message || err.error);
                return;
            }
            $textarea.val('');
            var $dom = addComment(result);
            $('div.x-comments-list').prepend($dom);
            $dom.css('display', 'none');
            $dom.slideDown();
        });
    }
    catch (e) {}
    return false;
}

function deleteComment(cid) {
    if (confirm('delete this comment?')) {
        postJSON('/api/comments/' + cid + '/delete', function(err, result) {
            if (err) {
                return alert('Error: ' + (err.message || err.error));
            }
            $('#comment-' + cid).remove();
        });
    }
}

// END create comment by ajax.
<|endoftext|>


<commit_before>var _ = require('lodash'),
    aws4 = require('aws4'),
    crypto = require('crypto'),
    querystring = require('querystring'),
    RequestBody = require('postman-collection').RequestBody,
    urlencodedBodyBuilder = require('../requester/core-body-builder').urlencoded,

    BODY_HASH_HEADER = 'X-Amz-Content-Sha256',

    /**
     * Encodes characters not encoded by querystring.stringify() according to RFC3986.
     * REFER: https://github.com/postmanlabs/postman-request/blob/master/lib/querystring.js#L42
     *
     * @param {String} str Partially encoded string by querystring.stringify()
     * @returns {String} Fully encoded string
     */
    rfc3986 = function (str) {
        return str.replace(/[!'()*]/g, function (c) {
            return '%' + c.charCodeAt(0).toString(16).toUpperCase();
        });
    },

    /**
     * Calculates body hash with given algorithm and digestEncoding.
     *
     * @todo This function can also be used in Digest auth so that it works correctly for urlencoded and file body types
     *
     * @param {RequestBody} body
     * @param {String} algorithm
     * @param {String} digestEncoding
     * @param {Function} callback
     */
    computeBodyHash = function (body, algorithm, digestEncoding, callback) {
        if (!(body && algorithm && digestEncoding)) { return callback(); }

        var hash = crypto.createHash(algorithm),
            originalReadStream,
            urlencodedBody;

        if (body.mode === RequestBody.MODES.raw) {
            hash.update(body.toString());

            return callback(hash.digest(digestEncoding));
        }

        if (body.mode === RequestBody.MODES.urlencoded) {
            urlencodedBody = rfc3986(querystring.stringify(urlencodedBodyBuilder(body.urlencoded).form));
            hash.update(urlencodedBody);

            return callback(hash.digest(digestEncoding));
        }

        if (body.mode === RequestBody.MODES.formdata) {
            // @todo: This requires adding new data to form instead of setting headers for AWS auth

            return callback();
        }

        if (body.mode === RequestBody.MODES.file) {
            originalReadStream = _.get(body, 'file.content');

            if (!originalReadStream) {
                return callback();
            }

            originalReadStream.cloneReadStream(function (err, clonedStream) {
                if (err) { return callback(); }

                clonedStream.on('data', function (chunk) {
                    hash.update(chunk);
                });

                clonedStream.on('end', function () {
                    callback(hash.digest(digestEncoding));
                });
            });
        }
    };

/**
 * @implements {AuthHandlerInterface}
 */
module.exports = {
    /**
     * @property {AuthHandlerInterface~AuthManifest}
     */
    manifest: {
        info: {
            name: 'awsv4',
            version: '1.0.0'
        },
        updates: [
            {
                property: 'Authorization',
                type: 'header'
            },
            {
                property: 'X-Amz-Date',
                type: 'header'
            },
            {
                property: 'X-Amz-Security-Token',
                type: 'header'
            },
            {
                property: 'Content-Length',
                type: 'header'
            },
            {
                property: 'Content-Type',
                type: 'header'
            },
            {
                property: 'Host',
                type: 'header'
            }
        ]
    },

    /**
     * Initializes a item (fetches all required parameters, etc) before the actual authorization step.
     *
     * @param {AuthInterface} auth
     * @param {Response} response
     * @param {AuthHandlerInterface~authInitHookCallback} done
     */
    init: function (auth, response, done) {
        done(null);
    },

    /**
     * Checks the item, and fetches any parameters that are not already provided.
     *
     * @param {AuthInterface} auth
     * @param {AuthHandlerInterface~authPreHookCallback} done
     */
    pre: function (auth, done) {
        done(null, true);
    },

    /**
     * Verifies whether the request was successful after being sent.
     *
     * @param {AuthInterface} auth
     * @param {Requester} response
     * @param {AuthHandlerInterface~authPostHookCallback} done
     */
    post: function (auth, response, done) {
        done(null, true);
    },

    /**
     * Generates the signature, and returns the Authorization, X-Amz-Date and Content-Type headers.
     * AWS v4 auth mandates that a content type header be present in each request.
     *
     * @param {Object} params
     * @param {Object} params.credentials Should contain the AWS credentials, "accessKeyId" and "secretAccessKey"
     * @param {String} params.host Contains the host name for the request
     * @param {String} params.path Contains the complete path, with query string as well, e.g: /something/kane?hi=ho
     * @param {String} params.service The name of the AWS service
     * @param {String} params.region AWS region
     * @param {String} params.method Request method
     * @param {String} params.body Stringified request body
     * @param {Object} params.headers Each key should be a header key, and the value should be a header value
     */
    computeHeader: function (params) {
        return aws4.sign(params, params.credentials);
    },

    /**
     * Signs a request.
     *
     * @param {AuthInterface} auth
     * @param {Request} request
     * @param {AuthHandlerInterface~authSignHookCallback} done
     */
    sign: function (auth, request, done) {
        var signedData,
            params = auth.get([
                'accessKey',
                'secretKey',
                'sessionToken',
                'service',
                'region'
            ]),
            self = this;

        // Clean up the request (if needed)
        request.removeHeader('Authorization', {ignoreCase: true});
        request.removeHeader('X-Amz-Date', {ignoreCase: true});
        request.removeHeader('X-Amz-Security-Token', {ignoreCase: true});

        // Removed the code which was adding content-type header if it is not there in the request. Because
        // aws4 does not require content-type header. It is only mandatory to include content-type header in signature
        // calculation if it is there in the request.
        // Refer: https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html#canonical-request

        // aws4 module can't calculate body hash for body with ReadStream.
        // So we calculate it our self and set 'X-Amz-Content-Sha256' header which will be used by aws4 module
        // to calculate the signature.
        computeBodyHash(request.body, 'sha256', 'hex', function (bodyHash) {
            bodyHash && request.upsertHeader({
                key: BODY_HASH_HEADER,
                value: bodyHash,
                system: true
            });

            signedData = self.computeHeader({
                credentials: {
                    accessKeyId: params.accessKey,
                    secretAccessKey: params.secretKey,
                    sessionToken: params.sessionToken || undefined
                },
                host: request.url.getRemote(),
                path: request.url.getPathWithQuery(),
                service: params.service || 'execute-api', // AWS API Gateway is the default service.
                region: params.region || 'us-east-1',
                method: request.method,
                body: undefined, // no need to give body since we are setting 'X-Amz-Content-Sha256' header
                headers: _.transform(request.getHeaders({enabled: true}), function (accumulator, value, key) {
                    accumulator[key] = value;
                }, {})
            });

            _.forEach(signedData.headers, function (value, key) {
                request.upsertHeader({
                    key: key,
                    value: value,
                    system: true
                });
            });

            return done();
        });
    }
};
<commit_msg>Fixed bug for AWS auth where execution will hang up if request has no body<commit_after>var _ = require('lodash'),
    aws4 = require('aws4'),
    crypto = require('crypto'),
    querystring = require('querystring'),
    RequestBody = require('postman-collection').RequestBody,
    urlencodedBodyBuilder = require('../requester/core-body-builder').urlencoded,

    BODY_HASH_HEADER = 'X-Amz-Content-Sha256',

    /**
     * Encodes characters not encoded by querystring.stringify() according to RFC3986.
     * REFER: https://github.com/postmanlabs/postman-request/blob/master/lib/querystring.js#L42
     *
     * @param {String} str Partially encoded string by querystring.stringify()
     * @returns {String} Fully encoded string
     */
    rfc3986 = function (str) {
        return str.replace(/[!'()*]/g, function (c) {
            return '%' + c.charCodeAt(0).toString(16).toUpperCase();
        });
    },

    /**
     * Calculates body hash with given algorithm and digestEncoding.
     *
     * @todo This function can also be used in Digest auth so that it works correctly for urlencoded and file body types
     *
     * @param {RequestBody} body
     * @param {String} algorithm
     * @param {String} digestEncoding
     * @param {Function} callback
     */
    computeBodyHash = function (body, algorithm, digestEncoding, callback) {
        if (!(body && algorithm && digestEncoding) || body.isEmpty()) { return callback(); }

        var hash = crypto.createHash(algorithm),
            originalReadStream,
            urlencodedBody;

        if (body.mode === RequestBody.MODES.raw) {
            hash.update(body.toString());

            return callback(hash.digest(digestEncoding));
        }

        if (body.mode === RequestBody.MODES.urlencoded) {
            urlencodedBody = rfc3986(querystring.stringify(urlencodedBodyBuilder(body.urlencoded).form));
            hash.update(urlencodedBody);

            return callback(hash.digest(digestEncoding));
        }

        if (body.mode === RequestBody.MODES.formdata) {
            // @todo: This requires adding new data to form instead of setting headers for AWS auth

            return callback();
        }

        if (body.mode === RequestBody.MODES.file) {
            originalReadStream = _.get(body, 'file.content');

            if (!originalReadStream) {
                return callback();
            }

            originalReadStream.cloneReadStream(function (err, clonedStream) {
                if (err) { return callback(); }

                clonedStream.on('data', function (chunk) {
                    hash.update(chunk);
                });

                clonedStream.on('end', function () {
                    callback(hash.digest(digestEncoding));
                });
            });
        }
    };

/**
 * @implements {AuthHandlerInterface}
 */
module.exports = {
    /**
     * @property {AuthHandlerInterface~AuthManifest}
     */
    manifest: {
        info: {
            name: 'awsv4',
            version: '1.0.0'
        },
        updates: [
            {
                property: 'Authorization',
                type: 'header'
            },
            {
                property: 'X-Amz-Date',
                type: 'header'
            },
            {
                property: 'X-Amz-Security-Token',
                type: 'header'
            },
            {
                property: 'Content-Length',
                type: 'header'
            },
            {
                property: 'Content-Type',
                type: 'header'
            },
            {
                property: 'Host',
                type: 'header'
            }
        ]
    },

    /**
     * Initializes a item (fetches all required parameters, etc) before the actual authorization step.
     *
     * @param {AuthInterface} auth
     * @param {Response} response
     * @param {AuthHandlerInterface~authInitHookCallback} done
     */
    init: function (auth, response, done) {
        done(null);
    },

    /**
     * Checks the item, and fetches any parameters that are not already provided.
     *
     * @param {AuthInterface} auth
     * @param {AuthHandlerInterface~authPreHookCallback} done
     */
    pre: function (auth, done) {
        done(null, true);
    },

    /**
     * Verifies whether the request was successful after being sent.
     *
     * @param {AuthInterface} auth
     * @param {Requester} response
     * @param {AuthHandlerInterface~authPostHookCallback} done
     */
    post: function (auth, response, done) {
        done(null, true);
    },

    /**
     * Generates the signature, and returns the Authorization, X-Amz-Date and Content-Type headers.
     * AWS v4 auth mandates that a content type header be present in each request.
     *
     * @param {Object} params
     * @param {Object} params.credentials Should contain the AWS credentials, "accessKeyId" and "secretAccessKey"
     * @param {String} params.host Contains the host name for the request
     * @param {String} params.path Contains the complete path, with query string as well, e.g: /something/kane?hi=ho
     * @param {String} params.service The name of the AWS service
     * @param {String} params.region AWS region
     * @param {String} params.method Request method
     * @param {String} params.body Stringified request body
     * @param {Object} params.headers Each key should be a header key, and the value should be a header value
     */
    computeHeader: function (params) {
        return aws4.sign(params, params.credentials);
    },

    /**
     * Signs a request.
     *
     * @param {AuthInterface} auth
     * @param {Request} request
     * @param {AuthHandlerInterface~authSignHookCallback} done
     */
    sign: function (auth, request, done) {
        var signedData,
            params = auth.get([
                'accessKey',
                'secretKey',
                'sessionToken',
                'service',
                'region'
            ]),
            self = this;

        // Clean up the request (if needed)
        request.removeHeader('Authorization', {ignoreCase: true});
        request.removeHeader('X-Amz-Date', {ignoreCase: true});
        request.removeHeader('X-Amz-Security-Token', {ignoreCase: true});

        // Removed the code which was adding content-type header if it is not there in the request. Because
        // aws4 does not require content-type header. It is only mandatory to include content-type header in signature
        // calculation if it is there in the request.
        // Refer: https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html#canonical-request

        // aws4 module can't calculate body hash for body with ReadStream.
        // So we calculate it our self and set 'X-Amz-Content-Sha256' header which will be used by aws4 module
        // to calculate the signature.
        computeBodyHash(request.body, 'sha256', 'hex', function (bodyHash) {
            bodyHash && request.upsertHeader({
                key: BODY_HASH_HEADER,
                value: bodyHash,
                system: true
            });

            signedData = self.computeHeader({
                credentials: {
                    accessKeyId: params.accessKey,
                    secretAccessKey: params.secretKey,
                    sessionToken: params.sessionToken || undefined
                },
                host: request.url.getRemote(),
                path: request.url.getPathWithQuery(),
                service: params.service || 'execute-api', // AWS API Gateway is the default service.
                region: params.region || 'us-east-1',
                method: request.method,
                body: undefined, // no need to give body since we are setting 'X-Amz-Content-Sha256' header
                headers: _.transform(request.getHeaders({enabled: true}), function (accumulator, value, key) {
                    accumulator[key] = value;
                }, {})
            });

            _.forEach(signedData.headers, function (value, key) {
                request.upsertHeader({
                    key: key,
                    value: value,
                    system: true
                });
            });

            return done();
        });
    }
};
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */
var uri = require('url');

/**
 * Component-ized boot phase that connects to the service registry.
 *
 * To utilize this component within an application, configure the IoC loader
 * to use service discovery components.
 *
 *     IoC.loader(require('bixby-sd'));
 *
 * @param {Settings} settings
 * @param {Logger} logger
 * @return {Function}
 */
exports = module.exports = function(registry, settings, logger) {

  return function connection(done) {
    var config = settings.get('sd') || {};
    if (!config.url) { throw new Error('Misconfigured service discovery: missing URL'); }

    var url = uri.parse(config.url);

    config.connect = url.host;
    delete config.url;

    logger.info('Connecting to service registry %s', uri.format(url));
    registry.connect(config, function() {
      logger.debug('Connected to service registry %s', uri.format(url));
      done();
    });

    // NOTE: By default, if the connection to the service registry is closed,
    //       the process will exit.  In accordance with a microservices
    //       architecture, it is expected that a higher-level monitor will
    //       detect process termination and restart as necessary.
    registry.on('close', function() {
      logger.error('Service registry connection closed');
      process.exit(-1);
    });

    // NOTE: By default, if an error is encountered from the service registry it
    //       will be rethrown.  This will cause an `uncaughtException` within
    //       Node and the process will exit.  In accordance with a microservices
    //       architecture, it is expected that a higher-level monitor will
    //       detect process failures and restart as necessary.
    registry.on('error', function(err) {
      logger.error('Unexpected error from service registry: %s', err.message);
      logger.error(err.stack);
      throw err;
    });
  }
}

/**
 * Component annotations.
 */
exports['@require'] = [ '../registry', 'settings', 'logger' ];
<commit_msg>Improve logging.<commit_after>/**
 * Module dependencies.
 */
var uri = require('url');

/**
 * Default port constants.
 */
var DEFAULT_PORT = {
  'zk:': 2181
};

/**
 * Component-ized boot phase that connects to the service registry.
 *
 * To utilize this component within an application, configure the IoC loader
 * to use service discovery components.
 *
 *     IoC.loader(require('bixby-sd'));
 *
 * @param {Settings} settings
 * @param {Logger} logger
 * @return {Function}
 */
exports = module.exports = function(registry, settings, logger) {

  return function connection(done) {
    var config = settings.get('sd') || {};
    if (!config.url) { throw new Error('Misconfigured service discovery: missing URL'); }

    var url = uri.parse(config.url);
    var host = url.hostname;
    var port = url.port || DEFAULT_PORT[url.protocol];

    config.connect = url.host;
    delete config.url;

    logger.info('Connecting to service registry %s:%d', host, port);
    registry.connect(config, function() {
      logger.debug('Connected to service registry %s:%d', host, port);
      done();
    });

    // NOTE: By default, if the connection to the service registry is closed,
    //       the process will exit.  In accordance with a microservices
    //       architecture, it is expected that a higher-level monitor will
    //       detect process termination and restart as necessary.
    registry.on('close', function() {
      logger.error('Service registry connection closed');
      process.exit(-1);
    });

    // NOTE: By default, if an error is encountered from the service registry it
    //       will be rethrown.  This will cause an `uncaughtException` within
    //       Node and the process will exit.  In accordance with a microservices
    //       architecture, it is expected that a higher-level monitor will
    //       detect process failures and restart as necessary.
    registry.on('error', function(err) {
      logger.error('Unexpected error from service registry: %s', err.message);
      logger.error(err.stack);
      throw err;
    });
  }
}

/**
 * Component annotations.
 */
exports['@require'] = [ '../registry', 'settings', 'logger' ];
<|endoftext|>


<commit_before>function Tag(impl, conf, innerHTML) {

  var self = riot.observable(this),
      opts = inherit(conf.opts) || {},
      dom = mkdom(impl.tmpl),
      item = conf.item,
      parent = conf.parent,
      frag = conf.frag,
      expressions = [],
      childTags = [],
      root = conf.root,
      fn = impl.fn,
      tagName = root.tagName.toLowerCase(),
      attr = {},
      loopDom,
      TAG_ATTRIBUTES = /([\w\-]+)\s?=\s?['"]([^'"]+)["']/gim

  if (fn && root._tag) {
    root._tag.unmount(true)
  }

  if(impl.attrs) {
    var attrs = impl.attrs.match(TAG_ATTRIBUTES)

    each(attrs, function(a) {
      var kv = a.split(/\s?=\s?/)
      root.setAttribute(kv[0], kv[1].replace(/['"]/g, ''))
    })

  }
  // keep a reference to the tag just created
  // so we will be able to mount this tag multiple times
  root._tag = this

  // create a unique id to this tag
  // it could be handy to use it also to improve the virtual dom rendering speed
  this._id = fastAbs(~~(new Date().getTime() * Math.random()))

  extend(this, { parent: parent, root: root, opts: opts, tags: {} }, item)

  // grab attributes
  each(root.attributes, function(el) {
    var val = el.value
    // remember attributes with expressions only
    if (brackets(/\{.*\}/).test(val)) attr[el.name] = val
  })

  if (dom.innerHTML && !/select/.test(tagName) && !/tbody/.test(tagName) && !/tr/.test(tagName))
    // replace all the yield tags with the tag inner html
    dom.innerHTML = replaceYield(dom.innerHTML, innerHTML)

  // options
  function updateOpts() {
    // update opts from current DOM attributes
    each(root.attributes, function(el) {
      opts[el.name] = tmpl(el.value, parent || self)
    })
    // recover those with expressions
    each(Object.keys(attr), function(name) {
      opts[name] = tmpl(attr[name], parent || self)
    })
  }

  this.update = function(data) {
    extend(self, data, item)
    updateOpts()
    self.trigger('update', item)
    update(expressions, self, item)
    self.trigger('updated')
  }

  this.mixin = function() {
    each(arguments, function(mix) {
      mix = 'string' == typeof mix ? riot.mixin(mix) : mix
      each(Object.keys(mix), function(key) {
        // bind methods to self
        if ('init' != key)
          self[key] = 'function' == typeof mix[key] ? mix[key].bind(self) : mix[key]
      })
      // init method will be called automatically
      if (mix.init) mix.init.bind(self)()
    })
  }

  this.mount = function() {

    updateOpts()

    // initialiation
    fn && fn.call(self, opts)

    toggle(true)

    // parse layout after init. fn may calculate args for nested custom tags
    parseExpressions(dom, self, expressions)

    if (!self.parent) self.update()

    // internal use only, fixes #403
    self.trigger('premount')

    if (fn) {
      while (dom.firstChild) root.appendChild(dom.firstChild)
    } else {
      loopDom = dom.firstChild
      frag.appendChild(loopDom)
    }

    if (root.stub) self.root = root = parent.root

    // if it's not a child tag we can trigger its mount event
    if (!self.parent) self.trigger('mount')
    // otherwise we need to wait that the parent event gets triggered
    else self.parent.one('mount', function() { self.trigger('mount') })
  }

  this.unmount = function(keepRootTag) {
    var el = loopDom || root,
        p = el.parentNode

    if (p) {

      if (parent) {
        // remove this tag from the parent tags object
        // if there are multiple nested tags with same name..
        // remove this element form the array
        if (Array.isArray(parent.tags[tagName])) {
          each(parent.tags[tagName], function(tag, i) {
            if (tag._id == self._id)
              parent.tags[tagName].splice(i, 1)
          })
        } else
          // otherwise just delete the tag instance
          parent.tags[tagName] = undefined
      } else {
        while (el.firstChild) el.removeChild(el.firstChild)
      }

      if (!keepRootTag)
        p.removeChild(el)

    }

    self.trigger('unmount')
    toggle()
    self.off('*')
    // somehow ie8 does not like `delete root._tag`
    root._tag = null

  }

  function toggle(isMount) {

    // mount/unmount children
    each(childTags, function(child) { child[isMount ? 'mount' : 'unmount']() })

    // listen/unlisten parent (events flow one way from parent to children)
    if (parent) {
      var evt = isMount ? 'on' : 'off'
      parent[evt]('update', self.update)[evt]('unmount', self.unmount)
    }
  }

  // named elements available for fn
  parseNamedElements(dom, this, childTags)

}
<commit_msg>Dont replace yield if tag is optgroup<commit_after>function Tag(impl, conf, innerHTML) {

  var self = riot.observable(this),
      opts = inherit(conf.opts) || {},
      dom = mkdom(impl.tmpl),
      item = conf.item,
      parent = conf.parent,
      frag = conf.frag,
      expressions = [],
      childTags = [],
      root = conf.root,
      fn = impl.fn,
      tagName = root.tagName.toLowerCase(),
      attr = {},
      loopDom,
      TAG_ATTRIBUTES = /([\w\-]+)\s?=\s?['"]([^'"]+)["']/gim

  if (fn && root._tag) {
    root._tag.unmount(true)
  }

  if(impl.attrs) {
    var attrs = impl.attrs.match(TAG_ATTRIBUTES)

    each(attrs, function(a) {
      var kv = a.split(/\s?=\s?/)
      root.setAttribute(kv[0], kv[1].replace(/['"]/g, ''))
    })

  }
  // keep a reference to the tag just created
  // so we will be able to mount this tag multiple times
  root._tag = this

  // create a unique id to this tag
  // it could be handy to use it also to improve the virtual dom rendering speed
  this._id = fastAbs(~~(new Date().getTime() * Math.random()))

  extend(this, { parent: parent, root: root, opts: opts, tags: {} }, item)

  // grab attributes
  each(root.attributes, function(el) {
    var val = el.value
    // remember attributes with expressions only
    if (brackets(/\{.*\}/).test(val)) attr[el.name] = val
  })

  if (dom.innerHTML && !/select/.test(tagName) && !/optgroup/.test(tagName) && !/tbody/.test(tagName) && !/tr/.test(tagName))
    // replace all the yield tags with the tag inner html
    dom.innerHTML = replaceYield(dom.innerHTML, innerHTML)

  // options
  function updateOpts() {
    // update opts from current DOM attributes
    each(root.attributes, function(el) {
      opts[el.name] = tmpl(el.value, parent || self)
    })
    // recover those with expressions
    each(Object.keys(attr), function(name) {
      opts[name] = tmpl(attr[name], parent || self)
    })
  }

  this.update = function(data) {
    extend(self, data, item)
    updateOpts()
    self.trigger('update', item)
    update(expressions, self, item)
    self.trigger('updated')
  }

  this.mixin = function() {
    each(arguments, function(mix) {
      mix = 'string' == typeof mix ? riot.mixin(mix) : mix
      each(Object.keys(mix), function(key) {
        // bind methods to self
        if ('init' != key)
          self[key] = 'function' == typeof mix[key] ? mix[key].bind(self) : mix[key]
      })
      // init method will be called automatically
      if (mix.init) mix.init.bind(self)()
    })
  }

  this.mount = function() {

    updateOpts()

    // initialiation
    fn && fn.call(self, opts)

    toggle(true)

    // parse layout after init. fn may calculate args for nested custom tags
    parseExpressions(dom, self, expressions)

    if (!self.parent) self.update()

    // internal use only, fixes #403
    self.trigger('premount')

    if (fn) {
      while (dom.firstChild) root.appendChild(dom.firstChild)
    } else {
      loopDom = dom.firstChild
      frag.appendChild(loopDom)
    }

    if (root.stub) self.root = root = parent.root

    // if it's not a child tag we can trigger its mount event
    if (!self.parent) self.trigger('mount')
    // otherwise we need to wait that the parent event gets triggered
    else self.parent.one('mount', function() { self.trigger('mount') })
  }

  this.unmount = function(keepRootTag) {
    var el = loopDom || root,
        p = el.parentNode

    if (p) {

      if (parent) {
        // remove this tag from the parent tags object
        // if there are multiple nested tags with same name..
        // remove this element form the array
        if (Array.isArray(parent.tags[tagName])) {
          each(parent.tags[tagName], function(tag, i) {
            if (tag._id == self._id)
              parent.tags[tagName].splice(i, 1)
          })
        } else
          // otherwise just delete the tag instance
          parent.tags[tagName] = undefined
      } else {
        while (el.firstChild) el.removeChild(el.firstChild)
      }

      if (!keepRootTag)
        p.removeChild(el)

    }

    self.trigger('unmount')
    toggle()
    self.off('*')
    // somehow ie8 does not like `delete root._tag`
    root._tag = null

  }

  function toggle(isMount) {

    // mount/unmount children
    each(childTags, function(child) { child[isMount ? 'mount' : 'unmount']() })

    // listen/unlisten parent (events flow one way from parent to children)
    if (parent) {
      var evt = isMount ? 'on' : 'off'
      parent[evt]('update', self.update)[evt]('unmount', self.unmount)
    }
  }

  // named elements available for fn
  parseNamedElements(dom, this, childTags)

}
<|endoftext|>


<commit_before>var buster = require("buster-core");
buster.defineVersionGetter(module.exports, __dirname);
<commit_msg>Expose cli APIs from exported module<commit_after>var buster = require("buster-core");
buster.defineVersionGetter(module.exports, __dirname);

module.exports.cli = {
    test: require("buster-test-cli/cli/test"),
    server: require("buster-test-cli/cli/server")
};
<|endoftext|>