<commit_before>/**
 * Manages the infowindows for a map. It listens to events triggered by a
 * CartoDBLayerGroupView and updates models accordingly
 */
var InfowindowManager = function (deps, options) {
  deps = deps || {};
  options = options || {};
  if (!deps.visModel) throw new Error('visModel is required');
  if (!deps.mapModel) throw new Error('mapModel is required');
  if (!deps.infowindowModel) throw new Error('infowindowModel is required');
  if (!deps.tooltipModel) throw new Error('tooltipModel is required');

  this._vis = deps.visModel;
  this._mapModel = deps.mapModel;
  this._infowindowModel = deps.infowindowModel;
  this._tooltipModel = deps.tooltipModel;
  this._showEmptyFields = !!options.showEmptyFields;

  this._cartoDBLayerGroupView = null;
  this._cartoDBLayerModel = null;

  this._mapModel.on('change:popupsEnabled', this._onPopupsEnabledChanged, this);
};

InfowindowManager.prototype.start = function (cartoDBLayerGroupView) {
  this._cartoDBLayerGroupView = cartoDBLayerGroupView;
  cartoDBLayerGroupView.on('featureClick', this._onFeatureClicked, this);
};

InfowindowManager.prototype.stop = function () {
  if (this._cartoDBLayerGroupView) {
    this._cartoDBLayerGroupView.off('featureClick', this._onFeatureClicked, this);
    delete this._cartoDBLayerGroupView;
  }
  if (this._cartoDBLayerModel) {
    this._unbindLayerModel();
    delete this._cartoDBLayerModel;
  }
};

InfowindowManager.prototype._onFeatureClicked = function (featureClickEvent) {
  this._unbindLayerModel();

  this._cartoDBLayerModel = featureClickEvent.layer;
  var featureData = featureClickEvent.feature;
  var featureId = featureData.cartodb_id;
  var latLng = featureClickEvent.latlng;

  if (!this._mapModel.arePopupsEnabled() || !this._cartoDBLayerModel.infowindow.hasTemplate()) {
    return;
  }

  this._tooltipModel.hide();
  this._updateInfowindowModel(this._cartoDBLayerModel.infowindow);
  this._infowindowModel.setLatLng(latLng);
  this._showInfowindow(featureId);
  this._fetchAttributes(featureId);
};

InfowindowManager.prototype._showInfowindow = function (featureId) {
  this._bindLayerModel();
  this._infowindowModel.show();
  this._infowindowModel.setCurrentFeatureId(featureId);
};

InfowindowManager.prototype._hideInfowindow = function () {
  this._unbindLayerModel();
  this._infowindowModel.hide();
  this._infowindowModel.unsetCurrentFeatureId();
};

InfowindowManager.prototype._fetchAttributes = function (featureId) {
  this._currentFeatureId = featureId || this._currentFeatureId;
  this._infowindowModel.setLoading();
  var layerIndex = this._cartoDBLayerGroupView.model.getIndexOfLayerInLayerGroup(this._cartoDBLayerModel);

  this._cartoDBLayerGroupView.model.fetchAttributes(layerIndex, this._currentFeatureId, function (attributes) {
    if (attributes) {
      this._infowindowModel.updateContent(attributes, {
        showEmptyFields: this._showEmptyFields
      });
    } else {
      this._infowindowModel.setError();
    }
  }.bind(this));
};

InfowindowManager.prototype._bindLayerModel = function () {
  this._cartoDBLayerModel.on('destroy', this._hideInfowindow, this);
  this._cartoDBLayerModel.on('change:visible', this._hideInfowindow, this);
  this._cartoDBLayerModel.infowindow.on('change', this._updateInfowindowModel, this);
  this._cartoDBLayerModel.infowindow.fields.on('reset', this._onInfowindowTemplateFieldsReset, this);
  this._vis.on('reloaded', this._onVisReloaded, this);
};

InfowindowManager.prototype._unbindLayerModel = function () {
  if (this._cartoDBLayerModel) {
    this._cartoDBLayerModel.off('destroy', this._hideInfowindow, this);
    this._cartoDBLayerModel.off('change:visible', this._hideInfowindow, this);
    this._cartoDBLayerModel.infowindow.off('change', this._updateInfowindowModel, this);
    this._cartoDBLayerModel.infowindow.fields.off('reset', this._onInfowindowTemplateFieldsReset, this);
    this._vis.off('reloaded', this._onVisReloaded, this);
  }
};

InfowindowManager.prototype._updateInfowindowModel = function (infowindowTemplate) {
  this._infowindowModel.setInfowindowTemplate(infowindowTemplate);
};

InfowindowManager.prototype._onInfowindowTemplateFieldsReset = function () {
  if (this._cartoDBLayerModel.infowindow.hasFields()) {
    this._updateInfowindowModel(this._cartoDBLayerModel.infowindow);
  } else {
    this._hideInfowindow();
  }
};

InfowindowManager.prototype._onVisReloaded = function () {
  if (this._cartoDBLayerModel && this._cartoDBLayerModel.infowindow.hasFields()) {
    this._fetchAttributes();
  }
};

InfowindowManager.prototype._onPopupsEnabledChanged = function () {
  if (this._mapModel.arePopupsDisabled()) {
    this._hideInfowindow();
  }
};

module.exports = InfowindowManager;
<commit_msg>Don't update content if layerId and featureId are not the same<commit_after>/**
 * Manages the infowindows for a map. It listens to events triggered by a
 * CartoDBLayerGroupView and updates models accordingly
 */
var InfowindowManager = function (deps, options) {
  deps = deps || {};
  options = options || {};
  if (!deps.visModel) throw new Error('visModel is required');
  if (!deps.mapModel) throw new Error('mapModel is required');
  if (!deps.infowindowModel) throw new Error('infowindowModel is required');
  if (!deps.tooltipModel) throw new Error('tooltipModel is required');

  this._vis = deps.visModel;
  this._mapModel = deps.mapModel;
  this._infowindowModel = deps.infowindowModel;
  this._tooltipModel = deps.tooltipModel;
  this._showEmptyFields = !!options.showEmptyFields;

  this._cartoDBLayerGroupView = null;
  this._cartoDBLayerModel = null;
  this.currentFeatureUniqueId = null;

  this._mapModel.on('change:popupsEnabled', this._onPopupsEnabledChanged, this);
};

InfowindowManager.prototype.start = function (cartoDBLayerGroupView) {
  this._cartoDBLayerGroupView = cartoDBLayerGroupView;
  cartoDBLayerGroupView.on('featureClick', this._onFeatureClicked, this);
};

InfowindowManager.prototype.stop = function () {
  if (this._cartoDBLayerGroupView) {
    this._cartoDBLayerGroupView.off('featureClick', this._onFeatureClicked, this);
    delete this._cartoDBLayerGroupView;
  }
  if (this._cartoDBLayerModel) {
    this._unbindLayerModel();
    delete this._cartoDBLayerModel;
  }
};

InfowindowManager.prototype._onFeatureClicked = function (featureClickEvent) {
  this._unbindLayerModel();

  this._cartoDBLayerModel = featureClickEvent.layer;
  var featureData = featureClickEvent.feature;
  var featureId = featureData.cartodb_id;
  var latLng = featureClickEvent.latlng;

  if (!this._mapModel.arePopupsEnabled() || !this._cartoDBLayerModel.infowindow.hasTemplate()) {
    return;
  }

  this._tooltipModel.hide();
  this._updateInfowindowModel(this._cartoDBLayerModel.infowindow);
  this._infowindowModel.setLatLng(latLng);
  this._showInfowindow(featureId);
  this._fetchAttributes(featureId);
};

InfowindowManager.prototype._showInfowindow = function (featureId) {
  this._bindLayerModel();
  this._infowindowModel.show();
  this._infowindowModel.setCurrentFeatureId(featureId);
};

InfowindowManager.prototype._hideInfowindow = function () {
  this._unbindLayerModel();
  this._infowindowModel.hide();
  this._infowindowModel.unsetCurrentFeatureId();
};

InfowindowManager.prototype._fetchAttributes = function (featureId) {
  var layerIndex = this._cartoDBLayerGroupView.model.getIndexOfLayerInLayerGroup(this._cartoDBLayerModel);
  var currentFeatureUniqueId = this._generateFeatureUniqueId(layerIndex, featureId);

  this._currentFeatureId = featureId || this._currentFeatureId;
  this._infowindowModel.setLoading();
  this.currentFeatureUniqueId = currentFeatureUniqueId;

  this._cartoDBLayerGroupView.model.fetchAttributes(layerIndex, this._currentFeatureId, function (attributes) {
    if (currentFeatureUniqueId !== this.currentFeatureUniqueId) {
      return;
    }

    if (attributes) {
      this._infowindowModel.updateContent(attributes, {
        showEmptyFields: this._showEmptyFields
      });
    } else {
      this._infowindowModel.setError();
    }
  }.bind(this));
};

InfowindowManager.prototype._bindLayerModel = function () {
  this._cartoDBLayerModel.on('destroy', this._hideInfowindow, this);
  this._cartoDBLayerModel.on('change:visible', this._hideInfowindow, this);
  this._cartoDBLayerModel.infowindow.on('change', this._updateInfowindowModel, this);
  this._cartoDBLayerModel.infowindow.fields.on('reset', this._onInfowindowTemplateFieldsReset, this);
  this._vis.on('reloaded', this._onVisReloaded, this);
};

InfowindowManager.prototype._unbindLayerModel = function () {
  if (this._cartoDBLayerModel) {
    this._cartoDBLayerModel.off('destroy', this._hideInfowindow, this);
    this._cartoDBLayerModel.off('change:visible', this._hideInfowindow, this);
    this._cartoDBLayerModel.infowindow.off('change', this._updateInfowindowModel, this);
    this._cartoDBLayerModel.infowindow.fields.off('reset', this._onInfowindowTemplateFieldsReset, this);
    this._vis.off('reloaded', this._onVisReloaded, this);
  }
};

InfowindowManager.prototype._updateInfowindowModel = function (infowindowTemplate) {
  this._infowindowModel.setInfowindowTemplate(infowindowTemplate);
};

InfowindowManager.prototype._onInfowindowTemplateFieldsReset = function () {
  if (this._cartoDBLayerModel.infowindow.hasFields()) {
    this._updateInfowindowModel(this._cartoDBLayerModel.infowindow);
  } else {
    this._hideInfowindow();
  }
};

InfowindowManager.prototype._onVisReloaded = function () {
  if (this._cartoDBLayerModel && this._cartoDBLayerModel.infowindow.hasFields()) {
    this._fetchAttributes();
  }
};

InfowindowManager.prototype._onPopupsEnabledChanged = function () {
  if (this._mapModel.arePopupsDisabled()) {
    this._hideInfowindow();
  }
};

InfowindowManager.prototype._generateFeatureUniqueId = function (layerId, featureId) {
  return [layerId, featureId].join('_');
};

module.exports = InfowindowManager;
<|endoftext|>


<commit_before>;(function(angular) {
  'use strict';

  angular.module('condor.api', ['condor.auth']);

  angular
    .module('condor.api')
    .provider('API', function() {
      var _options = {
        baseUrl: 'http://rock.io/', // base URL to our API
        headerName: 'X-Access-Token', // header name for JWT
        id: {} // a map of model-id key so mutations are handled properly
      };
      var _JWT = {};
      var _headers = {headers: {}};
      var _store = {};

      return {
        config: function(options) {
          _options = angular.extend(_options, options);
        },

        $get: ['$rootScope', '$q', '$http', '$timeout', 'Auth', function($rootScope, $q, $http, $timeout, Auth) {
          var _emitChange = function(p) {
            $timeout(function() {
              p === undefined ? $rootScope.$emit('CHANGE') : $rootScope.$emit('CHANGE', p);
            });
          };

          Auth.subscribe($rootScope, function(e, info) {
            if(info !== null) {
              _JWT = info.jwt;
              _headers.headers[_options.headerName] = _JWT;
            }
          });

          return {
            /**
             * subscribe to changes
             *
             * @param {object} $scope
             * @param {function} callback
             * @return {function} unregister function
             */
            subscribe: function(scope, callback) {
              var handler = $rootScope.$on('CHANGE', callback);
              scope.$on('$destroy', handler);

              return handler;
            },

            /**
             * @param {string} model
             * @param {integer} id
             * @return {object} requested data model
             */
            get: function(model, id) {
              var deferred = $q.defer();

              // running Auth on every REST request makes sure
              // we don't run into those nasty race conditions
              Auth
                .user()
                .then(function(info) {
                  _JWT = info.jwt;
                  _headers.headers[_options.headerName] = _JWT;

                  if(_store.hasOwnProperty(model)) {
                    var found = false;

                    angular.forEach(_store[model], function(value, key) {
                      if(value[_options.id[model]] === id) {
                        found = true;
                        deferred.resolve(value);
                      }
                    });

                    if(!found) {
                      $http
                        .get(_options.baseUrl + model + '/' + id, _headers)
                        .success(function(data) {
                          _store[model].push(data);
                          deferred.resolve(data);
                          _emitChange(_store);
                        })
                        .error(function(data) {
                          deferred.reject(data);
                        });
                    }
                  } else {
                    $http
                      .get(_options.baseUrl + model + '/' + id, _headers)
                      .success(function(data) {
                        deferred.resolve(data);
                        _emitChange(_store);
                      })
                      .error(function(data) {
                        deferred.reject(data);
                      });
                  }
                });

              return deferred.promise;
            },

            /**
             * @param {string} model
             * @return {array} - query result
             */
            query: function(model) {
              var deferred = $q.defer();

              Auth
                .user()
                .then(function(info) {
                  _JWT = info.jwt;
                  _headers.headers[_options.headerName] = _JWT;

                  if(_store.hasOwnProperty(model)) {
                    deferred.resolve(_store[model]);
                  } else {
                    $http
                      .get(_options.baseUrl + model, _headers)
                      .success(function(data) {
                        _store[model] = data;
                        deferred.resolve(data);
                        _emitChange(_store);
                      })
                      .error(function(data) {
                        deferred.reject(data);
                      });
                  }
                });

              return deferred.promise;
            },

            /**
             * @param {string} model
             * @param {string} q
             * @param {integer} limit
             * @return {array} - search query result
             */
            search: function(model, query, limit) {
              var deferred = $q.defer();

              if(limit === undefined) {
                limit = 100;
              }

              Auth
                .user()
                .then(function(info) {
                  _JWT = info.jwt;
                  _headers.headers[_options.headerName] = _JWT;
                  _headers.params = {query: query, limit: limit};

                    $http
                      .get(_options.baseUrl + model, _headers)
                      .success(function(data) {
                        delete _headers.params;
                        _store[model] = data;
                        deferred.resolve(data);
                        _emitChange(_store);
                      })
                      .error(function(data) {
                        deferred.reject(data);
                      });
                })
                .catch(function(error) {
                  deferred.reject(error);
                });

              return deferred.promise;
            },

            /**
             * @param {string} model
             * @param {object} data
             * @return {object} - newly saved model object
             */
            save: function(model, data) {
              var deferred = $q.defer();

              Auth
                .user()
                .then(function(info) {
                  _JWT = info.jwt;
                  _headers.headers[_options.headerName] = _JWT;

                  $http
                    .post(_options.baseUrl + model, data, _headers)
                    .success(function(data) {
                      deferred.resolve(data);

                      if(_store.hasOwnProperty(model)) {
                        _store[model].push(data);
                      }

                      _emitChange(_store);
                    })
                    .error(function(data) {
                      deferred.reject(data);
                    });
                });

              return deferred.promise;
            },

            /**
             * @param {string} model
             * @param {object} data
             * @return {object} - updated data object
             */
            update: function(model, data) {
              var deferred = $q.defer();

              Auth
                .user()
                .then(function(info) {
                  _JWT = info.jwt;
                  _headers.headers[_options.headerName] = _JWT;

                  $http
                    .put(_options.baseUrl + model + '/' + data[_options.id[model]], data, _headers)
                    .success(function(data) {
                      deferred.resolve(data);

                      if(_store.hasOwnProperty(model)) {
                        angular.forEach(_store[model], function(value, index) {
                          if(value[_options.id[model]] === data[_options.id[model]]) {
                            _store[model][index] = data;
                            _emitChange(_store);
                          }
                        });
                      }
                    })
                    .error(function(data) {
                      deferred.reject(data);
                    });
                });

              return deferred.promise;
            },

            /**
             * @param {string} model
             * @param {object} data
             * @return {object} - deleted model object
             */
            delete: function(model, data) {
              var deferred = $q.defer();

              Auth
                .user()
                .then(function(info) {
                  _JWT = info.jwt;
                  _headers.headers[_options.headerName] = _JWT;

                  $http
                    .delete(_options.baseUrl + model + '/' + data[_options.id[model]], _headers)
                    .success(function(data) {
                      deferred.resolve(data);

                      if(_store.hasOwnProperty(model)) {
                        angular.forEach(_store[model], function(value, index) {
                          if(value[_options.id[model]] === data[_options.id[model]]) {
                            _store[model].splice(index, 1);
                            _emitChange(_store);
                          }
                        });
                      }
                    })
                    .error(function(data) {
                      deferred.reject(data);
                    });
                });

              return deferred.promise;
            }
          };
        }]
      };
    });
})(window.angular);
<commit_msg>parameter update `q`<commit_after>;(function(angular) {
  'use strict';

  angular.module('condor.api', ['condor.auth']);

  angular
    .module('condor.api')
    .provider('API', function() {
      var _options = {
        baseUrl: 'http://rock.io/', // base URL to our API
        headerName: 'X-Access-Token', // header name for JWT
        id: {} // a map of model-id key so mutations are handled properly
      };
      var _JWT = {};
      var _headers = {headers: {}};
      var _store = {};

      return {
        config: function(options) {
          _options = angular.extend(_options, options);
        },

        $get: ['$rootScope', '$q', '$http', '$timeout', 'Auth', function($rootScope, $q, $http, $timeout, Auth) {
          var _emitChange = function(p) {
            $timeout(function() {
              p === undefined ? $rootScope.$emit('CHANGE') : $rootScope.$emit('CHANGE', p);
            });
          };

          Auth.subscribe($rootScope, function(e, info) {
            if(info !== null) {
              _JWT = info.jwt;
              _headers.headers[_options.headerName] = _JWT;
            }
          });

          return {
            /**
             * subscribe to changes
             *
             * @param {object} $scope
             * @param {function} callback
             * @return {function} unregister function
             */
            subscribe: function(scope, callback) {
              var handler = $rootScope.$on('CHANGE', callback);
              scope.$on('$destroy', handler);

              return handler;
            },

            /**
             * @param {string} model
             * @param {integer} id
             * @return {object} requested data model
             */
            get: function(model, id) {
              var deferred = $q.defer();

              // running Auth on every REST request makes sure
              // we don't run into those nasty race conditions
              Auth
                .user()
                .then(function(info) {
                  _JWT = info.jwt;
                  _headers.headers[_options.headerName] = _JWT;

                  if(_store.hasOwnProperty(model)) {
                    var found = false;

                    angular.forEach(_store[model], function(value, key) {
                      if(value[_options.id[model]] === id) {
                        found = true;
                        deferred.resolve(value);
                      }
                    });

                    if(!found) {
                      $http
                        .get(_options.baseUrl + model + '/' + id, _headers)
                        .success(function(data) {
                          _store[model].push(data);
                          deferred.resolve(data);
                          _emitChange(_store);
                        })
                        .error(function(data) {
                          deferred.reject(data);
                        });
                    }
                  } else {
                    $http
                      .get(_options.baseUrl + model + '/' + id, _headers)
                      .success(function(data) {
                        deferred.resolve(data);
                        _emitChange(_store);
                      })
                      .error(function(data) {
                        deferred.reject(data);
                      });
                  }
                });

              return deferred.promise;
            },

            /**
             * @param {string} model
             * @return {array} - query result
             */
            query: function(model) {
              var deferred = $q.defer();

              Auth
                .user()
                .then(function(info) {
                  _JWT = info.jwt;
                  _headers.headers[_options.headerName] = _JWT;

                  if(_store.hasOwnProperty(model)) {
                    deferred.resolve(_store[model]);
                  } else {
                    $http
                      .get(_options.baseUrl + model, _headers)
                      .success(function(data) {
                        _store[model] = data;
                        deferred.resolve(data);
                        _emitChange(_store);
                      })
                      .error(function(data) {
                        deferred.reject(data);
                      });
                  }
                });

              return deferred.promise;
            },

            /**
             * @param {string} model
             * @param {string} q
             * @param {integer} limit
             * @return {array} - search query result
             */
            search: function(model, query, limit) {
              var deferred = $q.defer();

              if(limit === undefined) {
                limit = 100;
              }

              Auth
                .user()
                .then(function(info) {
                  _JWT = info.jwt;
                  _headers.headers[_options.headerName] = _JWT;
                  _headers.params = {q: query, limit: limit};

                    $http
                      .get(_options.baseUrl + model, _headers)
                      .success(function(data) {
                        delete _headers.params;
                        _store[model] = data;
                        deferred.resolve(data);
                        _emitChange(_store);
                      })
                      .error(function(data) {
                        deferred.reject(data);
                      });
                })
                .catch(function(error) {
                  deferred.reject(error);
                });

              return deferred.promise;
            },

            /**
             * @param {string} model
             * @param {object} data
             * @return {object} - newly saved model object
             */
            save: function(model, data) {
              var deferred = $q.defer();

              Auth
                .user()
                .then(function(info) {
                  _JWT = info.jwt;
                  _headers.headers[_options.headerName] = _JWT;

                  $http
                    .post(_options.baseUrl + model, data, _headers)
                    .success(function(data) {
                      deferred.resolve(data);

                      if(_store.hasOwnProperty(model)) {
                        _store[model].push(data);
                      }

                      _emitChange(_store);
                    })
                    .error(function(data) {
                      deferred.reject(data);
                    });
                });

              return deferred.promise;
            },

            /**
             * @param {string} model
             * @param {object} data
             * @return {object} - updated data object
             */
            update: function(model, data) {
              var deferred = $q.defer();

              Auth
                .user()
                .then(function(info) {
                  _JWT = info.jwt;
                  _headers.headers[_options.headerName] = _JWT;

                  $http
                    .put(_options.baseUrl + model + '/' + data[_options.id[model]], data, _headers)
                    .success(function(data) {
                      deferred.resolve(data);

                      if(_store.hasOwnProperty(model)) {
                        angular.forEach(_store[model], function(value, index) {
                          if(value[_options.id[model]] === data[_options.id[model]]) {
                            _store[model][index] = data;
                            _emitChange(_store);
                          }
                        });
                      }
                    })
                    .error(function(data) {
                      deferred.reject(data);
                    });
                });

              return deferred.promise;
            },

            /**
             * @param {string} model
             * @param {object} data
             * @return {object} - deleted model object
             */
            delete: function(model, data) {
              var deferred = $q.defer();

              Auth
                .user()
                .then(function(info) {
                  _JWT = info.jwt;
                  _headers.headers[_options.headerName] = _JWT;

                  $http
                    .delete(_options.baseUrl + model + '/' + data[_options.id[model]], _headers)
                    .success(function(data) {
                      deferred.resolve(data);

                      if(_store.hasOwnProperty(model)) {
                        angular.forEach(_store[model], function(value, index) {
                          if(value[_options.id[model]] === data[_options.id[model]]) {
                            _store[model].splice(index, 1);
                            _emitChange(_store);
                          }
                        });
                      }
                    })
                    .error(function(data) {
                      deferred.reject(data);
                    });
                });

              return deferred.promise;
            }
          };
        }]
      };
    });
})(window.angular);
<|endoftext|>


<commit_before>const { execSync } = require('child_process')
const { existsSync } = require('fs')
const { resolve } = require('path')

const builds = [
  {
    os: 'darwin',
    arch: 'amd64',
    filename: 'primitive-darwin-x64'
  },
  {
    os: 'linux',
    arch: 'amd64',
    filename: 'primitive-linux-x64'
  },
  {
    os: 'windows',
    arch: 'amd64',
    filename: 'primitive-win32-x64.exe'
  }
]

// Get primitive
execSync(`go get -u github.com/fogleman/primitive`)

// Build executables
builds.forEach(build => {
  const { os, arch, filename } = build
  const path = resolve(__dirname, '..', 'vendor', filename)
  if (existsSync(path)) {
    console.log(`Primitive executable for ${os} (${arch}) already exists`)
    return
  }
  console.log(`Building primitive executable for ${os} (${arch})`)
  execSync(
    `env GOOS=${os} GOARCH=${arch} go build -o ${path} github.com/fogleman/primitive`
  )
  console.log('done')
})
<commit_msg>feat(sqip-plugin-primitive): help user when go is not installed<commit_after>const { execSync } = require('child_process')
const { existsSync } = require('fs')
const { resolve } = require('path')

const builds = [
  {
    os: 'darwin',
    arch: 'amd64',
    filename: 'primitive-darwin-x64'
  },
  {
    os: 'linux',
    arch: 'amd64',
    filename: 'primitive-linux-x64'
  },
  {
    os: 'windows',
    arch: 'amd64',
    filename: 'primitive-win32-x64.exe'
  }
]

try {
  // Get primitive
  execSync(`go get -u github.com/fogleman/primitive`)
} catch (err) {
  console.log('\n---\n\nUnable to download primitive from https://github.com/fogleman/primitive.\n\nIs go installed? Some users might just want to download it from here:\nhttps://golang.org/dl/\n\n---\n\n')
  process.exit(1)
}

// Build executables
builds.forEach(build => {
  const { os, arch, filename } = build
  const path = resolve(__dirname, '..', 'vendor', filename)
  if (existsSync(path)) {
    console.log(`Primitive executable for ${os} (${arch}) already exists`)
    return
  }
  console.log(`Building primitive executable for ${os} (${arch})`)
  execSync(
    `env GOOS=${os} GOARCH=${arch} go build -o ${path} github.com/fogleman/primitive`
  )
  console.log('done')
})
<|endoftext|>


<commit_before><commit_msg>Alterando menu<commit_after><|endoftext|>


<commit_before>#!/usr/bin/env node

let { readFile, writeFile, unlink, mkdir } = require('fs').promises
let remarkHighlight = require('remark-highlight.js')
let { existsSync } = require('fs')
let { promisify } = require('util')
let childProcess = require('child_process')
let remarkParse = require('remark-parse')
let remarkHtml = require('remark-html')
let { join } = require('path')
let Bundler = require('parcel-bundler')
let { red } = require('colorette')
let unified = require('unified')
let TypeDoc = require('typedoc')
let globby = require('globby')

let exec = promisify(childProcess.exec)

const PROJECTS = join(__dirname, '..', '..')
const DIST = join(__dirname, '..', 'dist')
const SRC = join(__dirname, '..', 'src')

async function buildLayout () {
  let bundler = new Bundler(join(SRC, 'api.pug'), { sourceMaps: false })
  await bundler.bundle()
  let htmlFile = join(DIST, 'api.html')
  let html = await readFile(htmlFile)
  await unlink(htmlFile)
  return html.toString()
}

async function downloadProject (name) {
  let dir = join(PROJECTS, name)
  if (existsSync(dir)) return
  let url = `https://github.com/postcss/${name}.git`
  await exec(`git clone --branch ose --depth 1 ${url} "${dir}"`)
  await exec('yarn install', { cwd: dir })
}

async function readTypedoc () {
  let files = await globby('lib/*.d.ts', {
    absolute: true,
    cwd: join(PROJECTS, 'postcss')
  })

  let app = new TypeDoc.Application()
  app.bootstrap({
    includeDeclarations: true,
    excludeExternals: true,
    esModuleInterop: true
  })
  let { errors, project } = app.converter.convert(files.flat())
  if (errors.length > 0) {
    console.error(`Error during API types generation`)
    throw new Error(errors[0].messageText)
  }
  if (!project.children) {
    throw new Error(JSON.stringify(project))
  }
  let nodes = []
  for (let file of project.children) {
    nodes.push(...file.children)
  }

  return nodes
}

function tag (prefix, attrs, body) {
  if (typeof body === 'undefined') {
    body = attrs
    attrs = {}
  }
  let [tagName, cls] = prefix.split('.')
  if (cls) attrs.class = cls
  if (Array.isArray(body)) body = body.join('')
  let attrsString = Object.keys(attrs)
    .map(i => ` ${i}="${attrs[i]}"`)
    .join('')
  return `<${tagName}${attrsString}>${body}</${tagName}>`
}

function link (cls, hash, text) {
  return tag(`a.${cls}`, { href: `#${hash}` }, text)
}

function generateSidemenu (nodes) {
  let ignore = ['LazyResult', 'Processor', 'Container', 'Node']
  let classes = nodes
    .filter(
      i =>
        (i.kindString === 'Class' && !ignore.includes(i.name)) ||
        i.name === 'postcss'
    )
    .sort((a, b) => {
      if (a.name === 'postcss') {
        return -1
      } else if (b.name === 'postcss') {
        return 1
      } else if (a.name < b.name) {
        return -1
      } else if (b.name < a.name) {
        return 1
      } else {
        return 0
      }
    })
  let html = tag(
    'nav.sidemenu',
    tag(
      'ul',
      classes.map(cls => {
        let clsSlug = cls.name.toLowerCase()
        let name = link('sidemenu_section', clsSlug, cls.name)
        let children = cls.children
        if (cls.name === 'postcss') {
          children = cls.type.reflection.children
        }
        return tag(
          'li',
          name +
            tag(
              'ul',
              children
                .filter(child => child.name !== 'constructor')
                .map(child => {
                  let childName = child.name
                  if (
                    child.kindString === 'Method' ||
                    child.name === 'parse' ||
                    child.name === 'stringify'
                  ) {
                    childName += '()'
                  }
                  let childSlug = clsSlug + '-' + child.name.toLowerCase()
                  return tag('li', link('sidemenu_child', childSlug, childName))
                })
            )
        )
      })
    )
  )
  return html
}

function toHTML (nodes, markdown) {
  if (!markdown) return ''
  let html = unified()
    .use(remarkParse)
    .use(remarkHighlight, { prefix: 'code_' })
    .use(remarkHtml)
    .processSync(markdown).contents
  return html
    .replace(/hljs language-js/g, 'code')
    .replace(/<code>[A-Z]\w+(#\w+)?<\/code>/g, str => {
      let cls = str.match(/[A-Z]\w+/)[0]
      if (nodes.some(i => i.name === cls)) {
        if (str.includes('#')) {
          let method = str.match(/#(\w+)/)[1]
          return tag(
            'code',
            tag(
              'a',
              { href: `#${cls.toLowerCase()}-${method.toLowerCase()}` },
              cls + '#' + method
            )
          )
        } else {
          return tag('code', tag('a', { href: `#${cls.toLowerCase()}` }, cls))
        }
      } else {
        return str
      }
    })
}

function commentHtml (nodes, node) {
  let comment = node.comment
  if (node.signatures && node.signatures[0].comment) {
    comment = node.signatures[0].comment
  }
  if (!comment) return ''
  return toHTML(nodes, comment.shortText + '\n\n' + comment.text)
}

function functionString (node) {
  let signature = node.signatures[0]
  return (
    '(' +
    (signature.parameters || [])
      .map(param => param.name + ': ' + typeString(param.type))
      .join(', ') +
    ') => ' +
    typeString(signature.type)
  )
}

function typeString (type) {
  if (type.type === 'union') {
    return type.types.map(i => typeString(i)).join(' | ')
  }
  let string = type.toString()
  if (string === 'object' && type.declaration) {
    return (
      '{ ' +
      type.declaration.children
        .map(i => {
          if (i.kindString === 'Function') {
            return i.name + ': ' + functionString(i)
          } else {
            return i.name + ': ' + typeString(i.type)
          }
        })
        .join(', ') +
      ' }'
    )
  } else if (string === 'function') {
    return functionString(type.declaration)
  } else {
    return string
  }
}

function typeHtml (nodes, type) {
  return typeString(type)
    .replace(/<>/g, '')
    .replace(
      'DeclarationProps | Declaration | AtRule | Rule | Comment | AtRuleProps' +
        ' | RuleProps | CommentProps',
      'ChildProps | ChildNode'
    )
    .replace(
      /\(DeclarationProps \| At(?:RuleProps \| ){2}CommentProps\)/g,
      'ChildProps'
    )
    .replace(/\(Declaration \| AtRule \| Rule \| Comment\)/g, 'ChildNode')
    .replace(
      /DeclarationProps \| Node \| At(?:RuleProps \| ){2}Com{2}entProps/g,
      'ChildProps | Node'
    )
    .replace(/&/g, '&')
    .replace(/</g, '<')
    .replace(/[A-Z]\w+(?!:)/g, cls => {
      if (nodes.some(i => i.name === cls)) {
        return tag('a', { href: `#${cls.toLowerCase()}` }, cls)
      } else {
        return cls
      }
    })
}

function varHtml (nodes, type) {
  if (!type) return ''
  return tag('p', 'Type: ' + typeHtml(nodes, type) + '.')
}

function tableHtml (nodes, title, values) {
  let comments = values.map((i, index) => {
    let comment = i
    if (!comment.comment && i.parent.parent.signatures) {
      comment = i.parent.parent.signatures[0].parameters[index] || {}
    }
    if (!comment.comment && i.parent.overwrites) {
      comment = i.parent.overwrites.reflection.signatures[0].parameters[index]
    }
    return commentHtml(nodes, comment).replace(/<\/?p>/g, '')
  })
  let hasComment = comments.some(i => i)
  return tag('table', [
    tag('tr', [
      tag('th', title),
      tag('th', 'Type'),
      hasComment ? tag('th', 'Description') : ''
    ]),
    ...values.map((i, index) => {
      let name = i.name
      if (i.flags.isRest) name += '…'
      if (i.isOptional) name += '?'
      return tag('tr', [
        tag('td', tag('code', name)),
        tag('td', typeHtml(nodes, i.type)),
        hasComment ? tag('td', comments[index]) : ''
      ])
    })
  ])
}

function signaturesHtml (nodes, node) {
  if (!node.signatures) return ''
  let comment = node.comment || node.signatures[0].comment || {}
  let returns
  if (node.signatures[0].type.name === 'this') {
    returns = tag('p', 'Returns itself for methods chain.')
  } else if (/^(walk|each)/.test(node.name)) {
    return (
      tableHtml(nodes, 'Argument', node.signatures[0].parameters).replace(
        ' => void',
        ' => void | false'
      ) +
      tag('p', [
        'Returns ',
        tag('code', 'void | false'),
        '. ',
        toHTML(nodes, comment.returns).replace(/<\/?p>/g, '')
      ])
    )
  } else if (node.signatures[0].type.name === 'void') {
    returns = ''
  } else {
    returns = tag('p', [
      'Returns ',
      tag('code', typeHtml(nodes, node.signatures[0].type)),
      '. ',
      toHTML(nodes, comment.returns).replace(/<\/?p>/g, '')
    ])
  }
  return (
    node.signatures
      .filter(signature => signature.parameters)
      .map(signature => {
        return tableHtml(nodes, 'Argument', signature.parameters)
      })
      .join('') + returns
  )
}

function generateBody (nodes) {
  let ignore = [
    'Postcss',
    'List',
    'stringify',
    'space',
    'rule',
    'root',
    'plugin',
    'parse',
    'decl',
    'comma',
    'atRule'
  ]
  return nodes
    .filter(node => !ignore.includes(node.name))
    .sort((a, b) => {
      if (a.name === 'postcss') {
        return -1
      } else if (b.name === 'postcss') {
        return 1
      } else if (a.kindString === 'Class' && b.kindString !== 'Class') {
        return -1
      } else if (b.kindString === 'Class' && a.kindString !== 'Class') {
        return 1
      } else if (a.name < b.name) {
        return -1
      } else if (b.name < a.name) {
        return 1
      } else {
        return 0
      }
    })
    .map(node => {
      let id = node.name.toLowerCase()
      let type = node
      if (node.name === 'postcss' || node.name === 'list') {
        type = node.type.reflection
      }
      let title =
        tag('h1.doc_title', { id }, node.name) + commentHtml(nodes, type)

      if (
        /(Options|Raws|Props|Source|Position|Message|Syntax)$/.test(
          node.name
        ) &&
        node.name !== 'ChildProps'
      ) {
        return tag('section.doc', [
          title,
          tableHtml(nodes, 'Property', type.children)
        ])
      }

      let content = type.type
      let children = type.children || []
      if (type.type && type.type.toString() === 'object') {
        content = false
        children = type.type.declaration.children
      }
      return tag('section.doc', [
        title,
        varHtml(nodes, content),
        signaturesHtml(nodes, type),
        ...children
          .filter(member => member.name !== 'constructor')
          .map(member => {
            let memberId = id + '-' + member.name.toLowerCase()
            let prefix = node.name
            if (node.name === 'postcss' || node.name === 'list') {
              prefix += '.'
            } else {
              prefix += '#'
            }
            let postfix = ''
            if (member.kindString === 'Method') postfix += '()'
            let memberContent
            if (member.type && member.type.toString() === 'object') {
              children = tableHtml(
                nodes,
                'Property',
                member.type.declaration.children
              )
            } else {
              memberContent = varHtml(nodes, member.type)
            }
            return (
              tag(
                'h2.doc_subtitle',
                { id: memberId },
                tag('span.doc_prefix', prefix) + member.name + postfix
              ) +
              commentHtml(nodes, member) +
              memberContent +
              signaturesHtml(nodes, member)
            )
          })
      ])
    })
    .join('')
}

async function saveFile (html) {
  let api = join(DIST, 'api')
  if (!existsSync(api)) await mkdir(api)
  await writeFile(join(api, 'index.html'), html)
}

async function build () {
  await downloadProject('postcss')
  let [nodes, layout] = await Promise.all([readTypedoc(), buildLayout()])
  let submenu = generateSidemenu(nodes)
  let body = generateBody(nodes)
  await saveFile(layout.replace('<main>', submenu + '<main>' + body))
}

build().catch(e => {
  process.stderr.write(red(e.stack) + '\n')
  process.exit(1)
})
<commit_msg>Fix API build script<commit_after>#!/usr/bin/env node

let { readFile, writeFile, unlink, mkdir } = require('fs').promises
let remarkHighlight = require('remark-highlight.js')
let { existsSync } = require('fs')
let { promisify } = require('util')
let childProcess = require('child_process')
let remarkParse = require('remark-parse')
let remarkHtml = require('remark-html')
let { join } = require('path')
let Bundler = require('parcel-bundler')
let { red } = require('colorette')
let unified = require('unified')
let TypeDoc = require('typedoc')
let globby = require('globby')

let exec = promisify(childProcess.exec)

const PROJECTS = join(__dirname, '..', '..')
const DIST = join(__dirname, '..', 'dist')
const SRC = join(__dirname, '..', 'src')

async function buildLayout () {
  let bundler = new Bundler(join(SRC, 'api.pug'), { sourceMaps: false })
  await bundler.bundle()
  let htmlFile = join(DIST, 'api.html')
  let html = await readFile(htmlFile)
  await unlink(htmlFile)
  return html.toString()
}

async function downloadProject (name) {
  let dir = join(PROJECTS, name)
  if (existsSync(dir)) return
  let url = `https://github.com/postcss/${name}.git`
  await exec(`git clone --branch ose --depth 1 ${url} "${dir}"`)
  await exec('yarn install', { cwd: dir })
}

async function readTypedoc () {
  let files = await globby('lib/*.d.ts', {
    absolute: true,
    cwd: join(PROJECTS, 'postcss')
  })

  let app = new TypeDoc.Application()
  app.bootstrap({
    includeDeclarations: true,
    excludeExternals: true,
    esModuleInterop: true
  })
  let { errors, project } = app.converter.convert(files.flat())
  if (errors.length > 0) {
    console.error(`Error during API types generation`)
    throw new Error(errors[0].messageText)
  }
  if (!project.children) {
    throw new Error(JSON.stringify(project))
  }
  let nodes = []
  for (let file of project.children) {
    nodes.push(...file.children)
  }

  return nodes
}

function tag (prefix, attrs, body) {
  if (typeof body === 'undefined') {
    body = attrs
    attrs = {}
  }
  let [tagName, cls] = prefix.split('.')
  if (cls) attrs.class = cls
  if (Array.isArray(body)) body = body.join('')
  let attrsString = Object.keys(attrs)
    .map(i => ` ${i}="${attrs[i]}"`)
    .join('')
  return `<${tagName}${attrsString}>${body}</${tagName}>`
}

function link (cls, hash, text) {
  return tag(`a.${cls}`, { href: `#${hash}` }, text)
}

function generateSidemenu (nodes) {
  let ignore = ['LazyResult', 'Processor', 'Container', 'Node']
  let classes = nodes
    .filter(
      i =>
        (i.kindString === 'Class' && !ignore.includes(i.name)) ||
        i.name === 'postcss'
    )
    .sort((a, b) => {
      if (a.name === 'postcss') {
        return -1
      } else if (b.name === 'postcss') {
        return 1
      } else if (a.name < b.name) {
        return -1
      } else if (b.name < a.name) {
        return 1
      } else {
        return 0
      }
    })
  let html = tag(
    'nav.sidemenu',
    tag(
      'ul',
      classes.map(cls => {
        let clsSlug = cls.name.toLowerCase()
        let name = link('sidemenu_section', clsSlug, cls.name)
        let children = cls.children
        if (cls.name === 'postcss') {
          children = cls.type.reflection.children
        }
        return tag(
          'li',
          name +
            tag(
              'ul',
              children
                .filter(child => child.name !== 'constructor')
                .map(child => {
                  let childName = child.name
                  if (
                    child.kindString === 'Method' ||
                    child.name === 'parse' ||
                    child.name === 'stringify'
                  ) {
                    childName += '()'
                  }
                  let childSlug = clsSlug + '-' + child.name.toLowerCase()
                  return tag('li', link('sidemenu_child', childSlug, childName))
                })
            )
        )
      })
    )
  )
  return html
}

function toHTML (nodes, markdown) {
  if (!markdown) return ''
  let html = unified()
    .use(remarkParse)
    .use(remarkHighlight, { prefix: 'code_' })
    .use(remarkHtml)
    .processSync(markdown).contents
  return html
    .replace(/hljs language-js/g, 'code')
    .replace(/<code>[A-Z]\w+(#\w+)?<\/code>/g, str => {
      let cls = str.match(/[A-Z]\w+/)[0]
      if (nodes.some(i => i.name === cls)) {
        if (str.includes('#')) {
          let method = str.match(/#(\w+)/)[1]
          return tag(
            'code',
            tag(
              'a',
              { href: `#${cls.toLowerCase()}-${method.toLowerCase()}` },
              cls + '#' + method
            )
          )
        } else {
          return tag('code', tag('a', { href: `#${cls.toLowerCase()}` }, cls))
        }
      } else {
        return str
      }
    })
}

function commentHtml (nodes, node) {
  let comment = node.comment
  if (node.signatures && node.signatures[0].comment) {
    comment = node.signatures[0].comment
  }
  if (!comment) return ''
  return toHTML(nodes, comment.shortText + '\n\n' + comment.text)
}

function functionString (node) {
  let signature = node.signatures[0]
  return (
    '(' +
    (signature.parameters || [])
      .map(param => param.name + ': ' + typeString(param.type))
      .join(', ') +
    ') => ' +
    typeString(signature.type)
  )
}

function typeString (type) {
  if (type.type === 'union') {
    return type.types.map(i => typeString(i)).join(' | ')
  }
  let string = type.toString()
  if (string === 'object' && type.declaration) {
    let decl = type.declaration
    if (decl.indexSignature) {
      let param = decl.indexSignature.parameters[0]
      return (
        '{ [' +
        param.name +
        ': ' +
        typeString(param.type) +
        ']: ' +
        typeString(decl.indexSignature.type) +
        '}'
      )
    } else {
      return (
        '{ ' +
        decl.children
          .map(i => {
            if (i.kindString === 'Function') {
              return i.name + ': ' + functionString(i)
            } else {
              return i.name + ': ' + typeString(i.type)
            }
          })
          .join(', ') +
        ' }'
      )
    }
  } else if (string === 'function') {
    return functionString(type.declaration)
  } else {
    return string
  }
}

function typeHtml (nodes, type) {
  return typeString(type)
    .replace(/<>/g, '')
    .replace(
      'DeclarationProps | Declaration | AtRule | Rule | Comment | AtRuleProps' +
        ' | RuleProps | CommentProps',
      'ChildProps | ChildNode'
    )
    .replace(
      /\(DeclarationProps \| At(?:RuleProps \| ){2}CommentProps\)/g,
      'ChildProps'
    )
    .replace(/\(Declaration \| AtRule \| Rule \| Comment\)/g, 'ChildNode')
    .replace(
      /DeclarationProps \| Node \| At(?:RuleProps \| ){2}Com{2}entProps/g,
      'ChildProps | Node'
    )
    .replace(/&/g, '&')
    .replace(/</g, '<')
    .replace(/[A-Z]\w+(?!:)/g, cls => {
      if (nodes.some(i => i.name === cls)) {
        return tag('a', { href: `#${cls.toLowerCase()}` }, cls)
      } else {
        return cls
      }
    })
}

function varHtml (nodes, type) {
  if (!type) return ''
  return tag('p', 'Type: ' + typeHtml(nodes, type) + '.')
}

function tableHtml (nodes, title, values) {
  let comments = values.map((i, index) => {
    let comment = i
    if (!comment.comment && i.parent.parent.signatures) {
      comment = i.parent.parent.signatures[0].parameters[index] || {}
    }
    if (!comment.comment && i.parent.overwrites) {
      comment = i.parent.overwrites.reflection.signatures[0].parameters[index]
    }
    return commentHtml(nodes, comment).replace(/<\/?p>/g, '')
  })
  let hasComment = comments.some(i => i)
  return tag('table', [
    tag('tr', [
      tag('th', title),
      tag('th', 'Type'),
      hasComment ? tag('th', 'Description') : ''
    ]),
    ...values.map((i, index) => {
      let name = i.name
      if (i.flags.isRest) name += '…'
      if (i.isOptional) name += '?'
      return tag('tr', [
        tag('td', tag('code', name)),
        tag('td', typeHtml(nodes, i.type)),
        hasComment ? tag('td', comments[index]) : ''
      ])
    })
  ])
}

function signaturesHtml (nodes, node) {
  if (!node.signatures) return ''
  let comment = node.comment || node.signatures[0].comment || {}
  let returns
  if (node.signatures[0].type.name === 'this') {
    returns = tag('p', 'Returns itself for methods chain.')
  } else if (/^(walk|each)/.test(node.name)) {
    return (
      tableHtml(nodes, 'Argument', node.signatures[0].parameters).replace(
        ' => void',
        ' => void | false'
      ) +
      tag('p', [
        'Returns ',
        tag('code', 'void | false'),
        '. ',
        toHTML(nodes, comment.returns).replace(/<\/?p>/g, '')
      ])
    )
  } else if (node.signatures[0].type.name === 'void') {
    returns = ''
  } else {
    returns = tag('p', [
      'Returns ',
      tag('code', typeHtml(nodes, node.signatures[0].type)),
      '. ',
      toHTML(nodes, comment.returns).replace(/<\/?p>/g, '')
    ])
  }
  return (
    node.signatures
      .filter(signature => signature.parameters)
      .map(signature => {
        return tableHtml(nodes, 'Argument', signature.parameters)
      })
      .join('') + returns
  )
}

function generateBody (nodes) {
  let ignore = [
    'Postcss',
    'List',
    'stringify',
    'space',
    'rule',
    'root',
    'plugin',
    'parse',
    'decl',
    'comma',
    'atRule'
  ]
  return nodes
    .filter(node => !ignore.includes(node.name))
    .sort((a, b) => {
      if (a.name === 'postcss') {
        return -1
      } else if (b.name === 'postcss') {
        return 1
      } else if (a.kindString === 'Class' && b.kindString !== 'Class') {
        return -1
      } else if (b.kindString === 'Class' && a.kindString !== 'Class') {
        return 1
      } else if (a.name < b.name) {
        return -1
      } else if (b.name < a.name) {
        return 1
      } else {
        return 0
      }
    })
    .map(node => {
      let id = node.name.toLowerCase()
      let type = node
      if (node.name === 'postcss' || node.name === 'list') {
        type = node.type.reflection
      }
      let title =
        tag('h1.doc_title', { id }, node.name) + commentHtml(nodes, type)

      if (
        /(Options|Raws|Props|Source|Position|Message|Syntax)$/.test(
          node.name
        ) &&
        node.name !== 'ChildProps'
      ) {
        return tag('section.doc', [
          title,
          tableHtml(nodes, 'Property', type.children)
        ])
      }

      let content = type.type
      let children = type.children || []
      if (type.type && type.type.toString() === 'object') {
        content = false
        children = type.type.declaration.children
      }
      return tag('section.doc', [
        title,
        varHtml(nodes, content),
        signaturesHtml(nodes, type),
        ...children
          .filter(member => member.name !== 'constructor')
          .map(member => {
            let memberId = id + '-' + member.name.toLowerCase()
            let prefix = node.name
            if (node.name === 'postcss' || node.name === 'list') {
              prefix += '.'
            } else {
              prefix += '#'
            }
            let postfix = ''
            if (member.kindString === 'Method') postfix += '()'
            let memberContent
            if (member.type && member.type.toString() === 'object') {
              children = tableHtml(
                nodes,
                'Property',
                member.type.declaration.children
              )
            } else {
              memberContent = varHtml(nodes, member.type)
            }
            return (
              tag(
                'h2.doc_subtitle',
                { id: memberId },
                tag('span.doc_prefix', prefix) + member.name + postfix
              ) +
              commentHtml(nodes, member) +
              memberContent +
              signaturesHtml(nodes, member)
            )
          })
      ])
    })
    .join('')
}

async function saveFile (html) {
  let api = join(DIST, 'api')
  if (!existsSync(api)) await mkdir(api)
  await writeFile(join(api, 'index.html'), html)
}

async function build () {
  await downloadProject('postcss')
  let [nodes, layout] = await Promise.all([readTypedoc(), buildLayout()])
  let submenu = generateSidemenu(nodes)
  let body = generateBody(nodes)
  await saveFile(layout.replace('<main>', submenu + '<main>' + body))
}

build().catch(e => {
  process.stderr.write(red(e.stack) + '\n')
  process.exit(1)
})
<|endoftext|>


<commit_before>var
  ResponseObject = require('../core/models/responseObject');

module.exports = function SecurityController (kuzzle) {

  /**
   * Get a specific role according to the given id
   * @param {RequestObject} requestObject
   * @returns {Promise}
   */
  this.getRole = function (requestObject) {
    kuzzle.pluginsManager.trigger('data:getRole', requestObject);

    return kuzzle.repositories.role.loadRole(
      kuzzle.repositories.role.getRoleFromRequestObject(requestObject)
      )
      .then(role => {
        if (role.closures) {
          delete role.closures;
        }

        return Promise.resolve(new ResponseObject(requestObject, role || {}));
      });
  };

  /**
   * Return a list of roles that specify a right for the given indexes
   * @param {RequestObject} requestObject
   * @returns {Promise}
   */
  this.searchRoles = function (requestObject) {
    kuzzle.pluginsManager.trigger('data:searchRole', requestObject);

    return kuzzle.repositories.role.searchRole(requestObject)
      .then((response) => {
        if (requestObject.data.body.hydrate && response.data.body && response.data.body.hits) {
          response.data.body.hits = response.data.body.hits.map(role => {
            var parsedRole = {};

            parsedRole._id = role._id;
            parsedRole._source = {indexes: role.indexes};

            return parsedRole;
          });
        }

        return Promise.resolve(response);
      });
  };

  /**
   * Create or update a Role
   * @param {RequestObject} requestObject
   * @returns {Promise}
   */
  this.putRole = function (requestObject) {
    kuzzle.pluginsManager.trigger('data:putRole', requestObject);

    return kuzzle.repositories.role.validateAndSaveRole(
      kuzzle.repositories.role.getRoleFromRequestObject(requestObject)
      )
      .then(result => {
        return Promise.resolve(new ResponseObject(requestObject, result));
      });
  };

  /**
   * Remove a role according to the given id
   * @param {RequestObject} requestObject
   * @returns {Promise}
   */
  this.deleteRole = function (requestObject) {
    kuzzle.pluginsManager.trigger('data:deleteRole', requestObject);

    return kuzzle.repositories.role.deleteRole(
      kuzzle.repositories.role.getRoleFromRequestObject(requestObject)
    );
  };
};<commit_msg>fix delete closure in role<commit_after>var
  ResponseObject = require('../core/models/responseObject');

module.exports = function SecurityController (kuzzle) {

  /**
   * Get a specific role according to the given id
   * @param {RequestObject} requestObject
   * @returns {Promise}
   */
  this.getRole = function (requestObject) {
    kuzzle.pluginsManager.trigger('data:getRole', requestObject);

    return kuzzle.repositories.role.loadRole(
      kuzzle.repositories.role.getRoleFromRequestObject(requestObject)
      )
      .then(role => {
        if (role && role.closures) {
          delete role.closures;
        }

        return Promise.resolve(new ResponseObject(requestObject, role || {}));
      });
  };

  /**
   * Return a list of roles that specify a right for the given indexes
   * @param {RequestObject} requestObject
   * @returns {Promise}
   */
  this.searchRoles = function (requestObject) {
    kuzzle.pluginsManager.trigger('data:searchRole', requestObject);

    return kuzzle.repositories.role.searchRole(requestObject)
      .then((response) => {
        if (requestObject.data.body.hydrate && response.data.body && response.data.body.hits) {
          response.data.body.hits = response.data.body.hits.map(role => {
            var parsedRole = {};

            parsedRole._id = role._id;
            parsedRole._source = {indexes: role.indexes};

            return parsedRole;
          });
        }

        return Promise.resolve(response);
      });
  };

  /**
   * Create or update a Role
   * @param {RequestObject} requestObject
   * @returns {Promise}
   */
  this.putRole = function (requestObject) {
    kuzzle.pluginsManager.trigger('data:putRole', requestObject);

    return kuzzle.repositories.role.validateAndSaveRole(
      kuzzle.repositories.role.getRoleFromRequestObject(requestObject)
      )
      .then(result => {
        return Promise.resolve(new ResponseObject(requestObject, result));
      });
  };

  /**
   * Remove a role according to the given id
   * @param {RequestObject} requestObject
   * @returns {Promise}
   */
  this.deleteRole = function (requestObject) {
    kuzzle.pluginsManager.trigger('data:deleteRole', requestObject);

    return kuzzle.repositories.role.deleteRole(
      kuzzle.repositories.role.getRoleFromRequestObject(requestObject)
    );
  };
};<|endoftext|>


<commit_before>(function() {
    Iris.Renderer.extend({
        about: {
            name: "network",
            author: "Paul and Jer-Ming",
            version: "1.0",
            requires: ['d3.js'],
            options: {
                'key': 'value',
                'target': 'test',
                'data': 'exampleData()'
            },
            defaults: {
                key: "value",
                target: "test",
                width: 600,
                height: 600,
                data: []
            },
            classes: [],
            dataFormat: "list of string"
        },

        render: function(options) {
            var target = options.target;
            target.innerHTML = "";

            var data = options.data;

            var nodeHash = {
                ids: {},
                types: {}
            };

            // build hashes for node/edge lookup
            for (var i=0; i<data.nodes.length; i++) {
                var node = data.nodes[i];
                nodeHash.ids[node.id] = node;
                node.edges = [];

                if (typeof(nodeHash.types[node.type]) === 'undefined') {
                    nodeHash.types[node.type] = [];
                }

                nodeHash.types[node.type].push(node);
            }

            for (var i=0; i<data.edges.length; i++) {
                var edge = data.edges[i];
                nodeHash.ids[edge.source].edges.push(['s', edge.id]);
                nodeHash.ids[edge.target].edges.push(['t', edge.id]);
            }

            var svg = d3.select(target)
                .append('svg:svg')
                .attr('width', options.width)
                .attr('height', options.height);

            // lines go first so they are on bottom of svg (lower z-index in html lingo)
            svg.selectAll('line')
                .data(data.edges)
                .enter().append('svg:line')
                .attr('id', function(d) {
                    return 'edge_' + d.id;
                })
                .attr('x1', function(d) {
                    return nodeHash.ids[d.source].x;
                }).attr('x2', function(d) {
                    return nodeHash.ids[d.target].x;
                }).attr('y1', function(d) {
                    return nodeHash.ids[d.source].y;
                }).attr('y2', function(d) {
                    return nodeHash.ids[d.target].y;
                }).style('stroke', 'black');

            // TODO: make sure there are nodes for the type
            for (var type in data.types) {
                var info = data.types[type];
                var g = svg.selectAll('none')
                    .data(nodeHash.types[type])
                    .enter().append('svg:g')
                    .attr('transform', function(d) {
                        return "translate(" + d.x + "," + d.y + ")";
                    })
                    .call(d3.behavior.drag()
                          .origin(Object)
                          .on('drag', drag));

                var shape = g.append('svg:' + info.shape)
                    .attr('id', function(d) {
                        return 'node_' + d.id;
                    });

                for (var attr in info.attrs) {
                    shape.attr(attr, info.attrs[attr]);
                }

                // positioning logic here
                if (info.dx || info.dy) {
                    shape.attr('transform', function(d) {
                        var dx = (typeof info.dx === 'number' ? info.dx : 0);
                        var dy = (typeof info.dy === 'number' ? info.dy : 0);
                        return "translate(" + dx + "," + dy + ")";
                    });
                } else {
                    // try to position based on shape
                    if (info.shape === 'rect') {
                        shape.attr('transform', function(d) {
                            // first ensure width and height
                            var dx = info.attrs.width / 2;
                                var dy = info.attrs.height / 2;
                            return "translate(-" + dx + ",-" + dy + ")";
                        });
                    }
                }

                var text = g.append('svg:text')
                    .attr('text-anchor', 'middle')
                    .attr('pointer-events', 'none')
                    .attr('fill', '#FFFFFF')
                    .attr('opacity', '1')
                    .text(function(d) {
                        return d.id;
                    });
            }

            // prevent text from being selected (probably doesn't work in ie)
            // and set the color (should do this via css eventually)
            $('text').css({
                '-moz-user-select'   : 'none',
                '-khtml-user-select' : 'none',
                '-webkit-user-select': 'none',
                'user-select'        : 'none'
            });

            var padding = 10;
            function drag() {
                d3.select(this)
                    .attr('transform', function(d) {
                        d.x = Math.max(padding, Math.min(options.width  - padding, d3.event.x));
                        d.y = Math.max(padding, Math.min(options.height - padding, d3.event.y));

                        // move the edge
                        for (var i=0; i<d.edges.length; i++) {
                            var edge = d.edges[i];

                            var which = (edge[0] === 's' ? '1' : '2');
                            d3.select($('#edge_' + edge[1])[0])
                                .attr('x' + which, d.x)
                                .attr('y' + which, d.y);
                        }

                        // translate will move the node
                        return "translate(" + d.x + "," + d.y + ")";
                    });
            }
        },

        exampleData: function() {
            return {
                types: {
                    star: {
                        shape: 'polygon',
                        attrs: {
                            points: "30,3 12,54 57,18 3,18 48,54"
                        },
                        dx: -30,
                        dy: -30
                    },
                    rectangle: {
                        shape: 'rect',
                        attrs: {
                            width: 48,
                            height: 30
                        }
                    },
                    ellipse: {
                        shape: 'ellipse',
                        attrs: {
                            rx: 25,
                            ry: 18
                        }
                    }
                },

                nodes: [{ x: 300, y: 100, id: 1, type: 'star'      },
                        { x: 100, y: 500, id: 2, type: 'rectangle' },
                        { x: 500, y: 500, id: 3, type: 'ellipse'   }],

                edges: [{ source: 1, target: 2, id: '1to2' },
                        { source: 2, target: 3, id: '2to3' },
                        { source: 3, target: 1, id: '3to1' }]
            };
        }
    });
})();<commit_msg>Forgot to include renderer js file<commit_after>(function() {
    Iris.Renderer.extend({
        about: {
            name: "network",
            author: "Paul and Jer-Ming",
            version: "1.0",
            requires: ['d3.v2.js'],
            options: {
                'key': 'value',
                'target': 'test',
                'data': 'exampleData()'
            },
            defaults: {
                key: "value",
                target: "test",
                width: 600,
                height: 600,
                data: []
            },
            classes: [],
            dataFormat: "list of string"
        },

        render: function(options) {
            var target = options.target;
            target.innerHTML = "";

            var data = options.data;

            var nodeHash = {
                ids: {},
                types: {}
            };

            // build hashes for node/edge lookup
            for (var i=0; i<data.nodes.length; i++) {
                var node = data.nodes[i];
                nodeHash.ids[node.id] = node;
                node.edges = [];

                if (typeof(nodeHash.types[node.type]) === 'undefined') {
                    nodeHash.types[node.type] = [];
                }

                nodeHash.types[node.type].push(node);
            }

            for (var i=0; i<data.edges.length; i++) {
                var edge = data.edges[i];
                nodeHash.ids[edge.source].edges.push(['s', edge.id]);
                nodeHash.ids[edge.target].edges.push(['t', edge.id]);
            }

            var svg = d3.select(target)
                .append('svg:svg')
                .attr('width', options.width)
                .attr('height', options.height)
                .attr('pointer-events', 'all')
                .append('svg:g')
                .call(d3.behavior.zoom().on('zoom', zoom))
                .append('svg:g');

            svg.append('svg:rect')
                .attr('width', options.width)
                .attr('height', options.height)
                .attr('fill', 'white');

            // lines go first so they are on bottom of svg (lower z-index in html lingo)
            svg.selectAll('line')
                .data(data.edges)
                .enter().append('svg:line')
                .attr('id', function(d) {
                    return 'edge_' + d.id;
                })
                .attr('x1', function(d) {
                    return nodeHash.ids[d.source].x;
                }).attr('x2', function(d) {
                    return nodeHash.ids[d.target].x;
                }).attr('y1', function(d) {
                    return nodeHash.ids[d.source].y;
                }).attr('y2', function(d) {
                    return nodeHash.ids[d.target].y;
                }).style('stroke', 'black');

            // TODO: make sure there are nodes for the type
            for (var type in data.types) {
                var info = data.types[type];
                var g = svg.selectAll('none')
                    .data(nodeHash.types[type])
                    .enter().append('svg:g')
                    .attr('transform', function(d) {
                        return "translate(" + d.x + "," + d.y + ")";
                    })
                    .call(d3.behavior.drag()
                          .origin(Object)
                          .on('drag', drag));

                var shape = g.append('svg:' + info.shape)
                    .attr('id', function(d) {
                        return 'node_' + d.id;
                    });

                for (var attr in info.attrs) {
                    shape.attr(attr, info.attrs[attr]);
                }

                // positioning logic here
                if (info.dx || info.dy) {
                    shape.attr('transform', function(d) {
                        var dx = (typeof info.dx === 'number' ? info.dx : 0);
                        var dy = (typeof info.dy === 'number' ? info.dy : 0);
                        return "translate(" + dx + "," + dy + ")";
                    });
                } else {
                    // try to position based on shape
                    if (info.shape === 'rect') {
                        shape.attr('transform', function(d) {
                            // first ensure width and height
                            var dx = info.attrs.width / 2;
                                var dy = info.attrs.height / 2;
                            return "translate(-" + dx + ",-" + dy + ")";
                        });
                    }
                }

                var text = g.append('svg:text')
                    .attr('text-anchor', 'middle')
                    .attr('pointer-events', 'none')
                    .attr('fill', '#FFFFFF')
                    .attr('opacity', '1')
                    .text(function(d) {
                        return d.id;
                    });
            }

            // prevent text from being selected (probably doesn't work in ie)
            // and set the color (should do this via css eventually)
            $('text').css({
                '-moz-user-select'   : 'none',
                '-khtml-user-select' : 'none',
                '-webkit-user-select': 'none',
                'user-select'        : 'none'
            });

            function zoom() {
                console.log("zoom/pan", d3.event.translate, d3.event.scale);
                svg.attr("transform",
                         "translate(" + d3.event.translate + ")"
                         + " scale(" + d3.event.scale + ")");
            }

            var padding = 10;
            function drag() {
                console.log('drag', d3.event.x, d3.event.y);
                d3.select(this)
                    .attr('transform', function(d) {
                        d.x = Math.max(padding, Math.min(options.width  - padding, d3.event.x));
                        d.y = Math.max(padding, Math.min(options.height - padding, d3.event.y));

                        // move the edge
                        for (var i=0; i<d.edges.length; i++) {
                            var edge = d.edges[i];

                            var which = (edge[0] === 's' ? '1' : '2');
                            d3.select($('#edge_' + edge[1])[0])
                                .attr('x' + which, d.x)
                                .attr('y' + which, d.y);
                        }

                        // translate will move the node
                        return "translate(" + d.x + "," + d.y + ")";
                    });

                return false;
            }
        },

        exampleData: function() {
            return {
                types: {
                    star: {
                        shape: 'polygon',
                        attrs: {
                            points: "30,3 12,54 57,18 3,18 48,54"
                        },
                        dx: -30,
                        dy: -30
                    },
                    rectangle: {
                        shape: 'rect',
                        attrs: {
                            width: 48,
                            height: 30
                        }
                    },
                    ellipse: {
                        shape: 'ellipse',
                        attrs: {
                            rx: 25,
                            ry: 18
                        }
                    }
                },

                nodes: [{ x: 300, y: 100, id: 1, type: 'star'      },
                        { x: 100, y: 500, id: 2, type: 'rectangle' },
                        { x: 500, y: 500, id: 3, type: 'ellipse'   }],

                edges: [{ source: 1, target: 2, id: '1to2' },
                        { source: 2, target: 3, id: '2to3' },
                        { source: 3, target: 1, id: '3to1' }]
            };
        }
    });
})();<|endoftext|>


<commit_before>/* eslint no-unused-vars:0 */
import React, { Component, PropTypes } from 'react';
import { build, getNext, getPrev } from '../engines/carousel';
import { addListener, removeListener } from '../listener';
import { isBlocked, block } from '../clock';
import { isActive } from '../isActive';
import { execCb } from '../funcHandler';
import { addCarouselToStore, _updateBinder } from '../redux/actions';
import { LEFT, RIGHT, DOWN, UP, ENTER } from '../keys';
import { CAROUSEL_TYPE } from '../constants';

class Carousel extends Component {

  static get propTypes() {
    return {
      children: React.PropTypes.oneOfType([
        React.PropTypes.object,
        React.PropTypes.array,
      ]),
      id: PropTypes.string.isRequired,
      active: PropTypes.bool,
      index: PropTypes.number,
      size: PropTypes.number,
      speed: PropTypes.number,
      debounce: PropTypes.number,
      context: PropTypes.object,
      elWidth: PropTypes.number,
      circular: PropTypes.bool,
      className: PropTypes.string,
      childrenClassName: PropTypes.string,
      onChange: PropTypes.func,
      onDownExit: PropTypes.func,
      onUpExit: PropTypes.func,
      onEnter: PropTypes.func,
    };
  }

  static get defaultProps() {
    return {
      index: 0,
      size: 3,
      elWidth: 100,
      context: {},
      circular: true,
      active: true,
      speed: 100,
      debounce: 82,
      className: 'carousel',
      childrenClassName: 'carousel-child',
    };
  }

  constructor(props) {
    super(props);
    this.listenerId = addListener(this.keysHandler, this);
    this.timeout = null;
    this.movingCountDown = () => this.timeout = setTimeout(() =>
      _updateBinder(props.id, { moving: false }), props.speed);
    this.state = { cursor: props.index, elements: [] };
  }

  keysHandler(keyCode) {
    const { children, circular, onDownExit, onUpExit, onEnter } = this.props;
    const { cursor } = this.state;
    if (isActive(this.props) && !isBlocked()) {
      switch (keyCode) {
        case LEFT:
          if (!circular && cursor === 0) return;
          this.performAction(getPrev(children.length, cursor));
          break;
        case RIGHT:
          if (!circular && cursor === children.length - 1) return;
          this.performAction(getNext(children.length, cursor));
          break;
        case DOWN:
          this.performCallback(onDownExit);
          break;
        case UP:
          this.performCallback(onUpExit);
          break;
        case ENTER:
          this.performCallback(onEnter);
          break;
      }
    }
  }

  componentWillMount() {
    addCarouselToStore(this.props, CAROUSEL_TYPE);
    this.updateState(this.state.cursor, this.props.children);
  }

  componentWillUpdate({ children }) {
    if (this.props.children.length === 0) {
      this.updateState(this.state.cursor, children);
    }
  }

  performAction(cursor) {
    const { debounce, onChange, children } = this.props;
    block(debounce);
    clearTimeout(this.timeout);
    this.updateState(cursor, children);
    this.movingCountDown();
    execCb(onChange, this.selectedId, this, this.props.context);
  }

  updateState(cursor, children) {
    if (!children || children.length === 0) return;
    const { id, size, circular } = this.props;
    this.selectedId = children[cursor].props.id;
    _updateBinder(id, { selectedId: this.selectedId, cursor, moving: true });
    this.setState({
      cursor,
      elements: build(children, size + 4, cursor, circular),
    });
  }

  performCallback(callback) {
    if (callback) {
      block();
      execCb(callback, this.selectedId, this, this.props.context);
    }
  }

  render() {
    const { size, elWidth, childrenClassName, className } = this.props;
    const { elements } = this.state;
    return

      {elements.map((element, inc) => {
        if (!element) return;
        const gap = (inc - 2) * elWidth;
        return <div key={element.props.id} className={childrenClassName} style={{
          marginLeft: `${gap}px`,
          position: 'absolute',
          width: `${elWidth}px`,
          display: 'block',
          opacity: (gap === -(2 * elWidth) || gap === (size + 1) * elWidth) ? 0 : 1,
        }}>{element}
;
      })}

;
  }

  componentWillUnmount() {
    removeListener(this.listenerId);
  }

}

export default Carousel;
<commit_msg>Carousel : fix bug with selectedId in current<commit_after>/* eslint no-unused-vars:0 */
import React, { Component, PropTypes } from 'react';
import { build, getNext, getPrev } from '../engines/carousel';
import { addListener, removeListener } from '../listener';
import { isBlocked, block } from '../clock';
import { isActive } from '../isActive';
import { execCb } from '../funcHandler';
import { addCarouselToStore, _updateBinder } from '../redux/actions';
import { LEFT, RIGHT, DOWN, UP, ENTER } from '../keys';
import { CAROUSEL_TYPE } from '../constants';

class Carousel extends Component {

  static get propTypes() {
    return {
      children: React.PropTypes.oneOfType([
        React.PropTypes.object,
        React.PropTypes.array,
      ]),
      id: PropTypes.string.isRequired,
      active: PropTypes.bool,
      index: PropTypes.number,
      size: PropTypes.number,
      speed: PropTypes.number,
      debounce: PropTypes.number,
      context: PropTypes.object,
      elWidth: PropTypes.number,
      circular: PropTypes.bool,
      className: PropTypes.string,
      childrenClassName: PropTypes.string,
      onChange: PropTypes.func,
      onDownExit: PropTypes.func,
      onUpExit: PropTypes.func,
      onEnter: PropTypes.func,
    };
  }

  static get defaultProps() {
    return {
      index: 0,
      size: 3,
      elWidth: 100,
      context: {},
      circular: true,
      active: true,
      speed: 100,
      debounce: 82,
      className: 'carousel',
      childrenClassName: 'carousel-child',
    };
  }

  constructor(props) {
    super(props);
    this.listenerId = addListener(this.keysHandler, this);
    this.timeout = null;
    this.movingCountDown = () => this.timeout = setTimeout(() =>
      _updateBinder(props.id, { moving: false, selectedId: this.selectedId }), props.speed);
    this.state = { cursor: props.index, elements: [] };
  }

  keysHandler(keyCode) {
    const { children, circular, onDownExit, onUpExit, onEnter } = this.props;
    const { cursor } = this.state;
    if (isActive(this.props) && !isBlocked()) {
      switch (keyCode) {
        case LEFT:
          if (!circular && cursor === 0) return;
          this.performAction(getPrev(children.length, cursor));
          break;
        case RIGHT:
          if (!circular && cursor === children.length - 1) return;
          this.performAction(getNext(children.length, cursor));
          break;
        case DOWN:
          this.performCallback(onDownExit);
          break;
        case UP:
          this.performCallback(onUpExit);
          break;
        case ENTER:
          this.performCallback(onEnter);
          break;
      }
    }
  }

  componentWillMount() {
    addCarouselToStore(this.props, CAROUSEL_TYPE);
    this.updateState(this.state.cursor, this.props.children);
  }

  componentWillUpdate({ children }) {
    if (this.props.children.length === 0) {
      this.updateState(this.state.cursor, children);
    }
  }

  performAction(cursor) {
    const { debounce, onChange, children } = this.props;
    block(debounce);
    clearTimeout(this.timeout);
    this.updateState(cursor, children);
    this.movingCountDown();
    execCb(onChange, this.selectedId, this, this.props.context);
  }

  updateState(cursor, children) {
    if (!children || children.length === 0) return;
    const { id, size, circular } = this.props;
    this.selectedId = children[cursor].props.id;
    _updateBinder(id, { selectedId: this.selectedId, cursor, moving: true });
    this.setState({
      cursor,
      elements: build(children, size + 4, cursor, circular),
    });
  }

  performCallback(callback) {
    if (callback) {
      block();
      execCb(callback, this.selectedId, this, this.props.context);
    }
  }

  render() {
    const { size, elWidth, childrenClassName, className } = this.props;
    const { elements } = this.state;
    return

      {elements.map((element, inc) => {
        if (!element) return;
        const gap = (inc - 2) * elWidth;
        return <div key={element.props.id} className={childrenClassName} style={{
          marginLeft: `${gap}px`,
          position: 'absolute',
          width: `${elWidth}px`,
          display: 'block',
          opacity: (gap === -(2 * elWidth) || gap === (size + 1) * elWidth) ? 0 : 1,
        }}>{element}
;
      })}

;
  }

  componentWillUnmount() {
    removeListener(this.listenerId);
  }

}

export default Carousel;
<|endoftext|>


<commit_before>$(function() {
  var calculator_select = $('select#calc_type')
  var original_calc_type = calculator_select.attr('value');
  $('div#calculator-settings-warning').hide();
  calculator_select.change(function() {
    if (calculator_select.attr('value') == original_calc_type) {
      $('div.calculator-settings').show();
      $('div#calculator-settings-warning').hide();
      $('.calculator-settings input').prop("disabled", false);
    } else {
      $('div.calculator-settings').hide();
      $('div#calculator-settings-warning').show();
      $('.calculator-settings input').prop("disabled", true);
    }
  });
})
<commit_msg>When a calculator is using a preference of type :text, a textarea is shown. The calculator.js should disable/enable this textarea the same as the input from a preference of any other type.<commit_after>$(function() {
  var calculator_select = $('select#calc_type')
  var original_calc_type = calculator_select.attr('value');
  $('div#calculator-settings-warning').hide();
  calculator_select.change(function() {
    if (calculator_select.attr('value') == original_calc_type) {
      $('div.calculator-settings').show();
      $('div#calculator-settings-warning').hide();
      $('.calculator-settings').find('input,textarea').prop("disabled", false);
    } else {
      $('div.calculator-settings').hide();
      $('div#calculator-settings-warning').show();
      $('.calculator-settings').find('input,textarea').prop("disabled", true);
    }
  });
})
<|endoftext|>


<commit_before>'use strict';

const Command = require('../../Command.js');

/**
 * Get a role from the matching string
 * @param  {string} string      String to use to search for role
 * @param  {Message} message    originating message
 * @returns {Role|null}         Role
 */
function getRoleForString(string, message) {
  const trimmedString = string.trim();
  const roleFromId = message.guild.roles.get(trimmedString);
  let roleFromName;
  if (typeof roleFromId === 'undefined') {
    roleFromName = message.guild.roles
      .find(item => item.name.toLowerCase() === trimmedString.toLowerCase());
  }
  return roleFromId || roleFromName || null;
}

/**
 * Add a joinable role
 */
class LeaveRole extends Command {
  constructor(bot) {
    super(bot, 'settings.leaveRole', 'leave');
    this.usages = [
      { description: 'Show instructions for leaving roles', parameters: [] },
      { description: 'Leave a role', parameters: ['Role/Role id to leave'] },
    ];
    this.regex = new RegExp(`^${this.call}\\s(.*)?`, 'i');
    this.allowDM = false;
  }

  /**
   * Run the command
   * @param {Message} message Message with a command to handle, reply to,
   *                          or perform an action based on parameters.
   */
  run(message) {
    const stringRole = message.strippedContent.replace(`${this.call} `, '');
    if (!stringRole) {
      this.sendInstructionEmbed(message);
    } else {
      const role = getRoleForString(stringRole, message);
      if (!role) {
        this.sendInstructionEmbed(message);
      } else {
        this.bot.settings.getRolesForGuild(message.guild)
           .then((roles) => {
             const filteredRoles = roles.filter(storedRole => role.id === storedRole.id);
             const roleRemoveable = filteredRoles.length > 0
               && message.member.roles.get(role.id)
               && message.channel.permissionsFor(this.bot.client.user.id).hasPermission('MANAGE_ROLES');
             if (roleRemoveable) {
               message.member.removeRole(role.id)
                .then(() => this.sendLeft(message, role))
                .catch(this.logger.error);
             } else {
               this.sendCantLeave(message);
             }
           })
           .catch(this.logger.error);
      }
    }
  }

  sendLeft(message, role) {
    this.messageManager.embed(message, {
      title: 'Left Role',
      type: 'rich',
      color: 0x779ECB,
      fields: [
        {
          name: '_ _',
          value: role.name,
          inline: true,
        },
      ],
    }, true, true);
  }

  sendCantLeave(message) {
    this.messageManager.embed(message, {
      title: 'Invalid Role',
      type: 'rich',
      color: 0x779ECB,
      fields: [
        {
          name: '_ _',
          value: 'You can\'t leave that role.',
          inline: true,
        },
      ],
    }, true, true);
  }

  sendInstructionEmbed(message) {
    const embed = {
      title: 'Usage',
      type: 'rich',
      color: 0x779ECB,
      fields: [
        {
          name: '_ _',
          value: 'Role or role id to join.',
        },
        {
          name: 'Possible role values:',
          value: '_ _',
        },
      ],
    };
    this.bot.settings.getChannelPrefix(message.channel)
      .then((prefix) => {
        embed.fields[0].name = `${prefix}${this.call} <role or role id>`;
        return this.bot.settings.getRolesForGuild(message.guild);
      })
      .then((roles) => {
        embed.fields[1].value = roles.map(role => role.name).join('; ');
        this.messageManager.embed(message, embed, true, false);
      })
      .catch(this.logger.error);
  }
}

module.exports = LeaveRole;
<commit_msg>Fix incorrect permission resolveable<commit_after>'use strict';

const Command = require('../../Command.js');

/**
 * Get a role from the matching string
 * @param  {string} string      String to use to search for role
 * @param  {Message} message    originating message
 * @returns {Role|null}         Role
 */
function getRoleForString(string, message) {
  const trimmedString = string.trim();
  const roleFromId = message.guild.roles.get(trimmedString);
  let roleFromName;
  if (typeof roleFromId === 'undefined') {
    roleFromName = message.guild.roles
      .find(item => item.name.toLowerCase() === trimmedString.toLowerCase());
  }
  return roleFromId || roleFromName || null;
}

/**
 * Add a joinable role
 */
class LeaveRole extends Command {
  constructor(bot) {
    super(bot, 'settings.leaveRole', 'leave');
    this.usages = [
      { description: 'Show instructions for leaving roles', parameters: [] },
      { description: 'Leave a role', parameters: ['Role/Role id to leave'] },
    ];
    this.regex = new RegExp(`^${this.call}\\s(.*)?`, 'i');
    this.allowDM = false;
  }

  /**
   * Run the command
   * @param {Message} message Message with a command to handle, reply to,
   *                          or perform an action based on parameters.
   */
  run(message) {
    const stringRole = message.strippedContent.replace(`${this.call} `, '');
    if (!stringRole) {
      this.sendInstructionEmbed(message);
    } else {
      const role = getRoleForString(stringRole, message);
      if (!role) {
        this.sendInstructionEmbed(message);
      } else {
        this.bot.settings.getRolesForGuild(message.guild)
           .then((roles) => {
             const filteredRoles = roles.filter(storedRole => role.id === storedRole.id);
             const roleRemoveable = filteredRoles.length > 0
               && message.member.roles.get(role.id)
               && message.channel.permissionsFor(this.bot.client.user.id).hasPermission('MANAGE_ROLES_OR_PERMISSIONS');
             if (roleRemoveable) {
               message.member.removeRole(role.id)
                .then(() => this.sendLeft(message, role))
                .catch(this.logger.error);
             } else {
               this.sendCantLeave(message);
             }
           })
           .catch(this.logger.error);
      }
    }
  }

  sendLeft(message, role) {
    this.messageManager.embed(message, {
      title: 'Left Role',
      type: 'rich',
      color: 0x779ECB,
      fields: [
        {
          name: '_ _',
          value: role.name,
          inline: true,
        },
      ],
    }, true, true);
  }

  sendCantLeave(message) {
    this.messageManager.embed(message, {
      title: 'Invalid Role',
      type: 'rich',
      color: 0x779ECB,
      fields: [
        {
          name: '_ _',
          value: 'You can\'t leave that role.',
          inline: true,
        },
      ],
    }, true, true);
  }

  sendInstructionEmbed(message) {
    const embed = {
      title: 'Usage',
      type: 'rich',
      color: 0x779ECB,
      fields: [
        {
          name: '_ _',
          value: 'Role or role id to join.',
        },
        {
          name: 'Possible role values:',
          value: '_ _',
        },
      ],
    };
    this.bot.settings.getChannelPrefix(message.channel)
      .then((prefix) => {
        embed.fields[0].name = `${prefix}${this.call} <role or role id>`;
        return this.bot.settings.getRolesForGuild(message.guild);
      })
      .then((roles) => {
        embed.fields[1].value = roles.map(role => role.name).join('; ');
        this.messageManager.embed(message, embed, true, false);
      })
      .catch(this.logger.error);
  }
}

module.exports = LeaveRole;
<|endoftext|>


<commit_before>/*
	Block a function from being called by adding and removing any number of blocks.
	Excellent for waiting on parallel asynchronous operations.
	A blocked function starts out with exactly one block

	Example usage:

	http.createServer(function(req, res) {
		var sendResponse = blockFunction(function() {
			res.writeHead(204)
			res.end()
		})
		var queries = parseQueries(req.url)
		for (var i=0; i<queries.length; i++) {
			sendResponse.addBlock()
			handleQuery(queries[i]; function() {
				sendResponse.removeBlock()
			})
		}
	})
*/

module.exports = function blockFunction(fn) {
	var numBlocks = 0
	return {
		addBlock:function() {
			numBlocks++
			return this
		},
		removeBlock:function() {
			if (!fn) { throw new Error("Block removed after function was unblocked") }
			if (!numBlocks) { throw new Error("Tried to remove a block that was never added") }
			if (--numBlocks) { return }
			fn()
			delete fn
			return this
		}
	}
}
<commit_msg>Implement blockFunction.fail<commit_after>/*
	Block a function from being called by adding and removing any number of blocks.
	Excellent for waiting on parallel asynchronous operations.
	A blocked function starts out with exactly one block

	Example usage:

	http.createServer(function(req, res) {
		var sendResponse = blockFunction(function() {
			res.writeHead(204)
			res.end()
		})
		var queries = parseQueries(req.url)
		for (var i=0; i<queries.length; i++) {
			sendResponse.addBlock()
			handleQuery(queries[i]; function() {
				sendResponse.removeBlock()
			})
		}
	})
*/

module.exports = function blockFunction(fn) {
	var numBlocks = 0
	return {
		addBlock:function() {
			numBlocks++
			return this
		},
		removeBlock:function() {
			if (!fn) { throw new Error("Block removed after function was unblocked") }
			if (!numBlocks) { throw new Error("Tried to remove a block that was never added") }
			if (--numBlocks) { return }
			fn(null)
			delete fn
			return this
		},
		fail:function(error) {
			fn(error)
			delete fn
			return this
		}
	}
}
<|endoftext|>