<commit_before>const path = require('path')
const _ = require('lodash')
const clone = require('clone')
const traverse = require('traverse')
const DAG = require('dag-map')
const md5 = require('md5')
const utils = require('./utils')
const fileLoader = require('./loaders/file')

const defaults = {
  baseFolder: process.cwd()
}

let cache = {}

const loaders = {
  file: fileLoader
}

/**
 * Returns the reference schema that refVal points to.
 * If the ref val points to a ref within a file, the file is loaded and fully derefed, before we get the
 * pointing property. Derefed files are cached.
 *
 * @param refVal
 * @param refType
 * @param parent
 * @param options
 * @param state
 * @private
 */
function getRefSchema (refVal, refType, parent, options, state) {
  if (refType && loaders[refType]) {
    let newVal
    let oldBasePath
    let loaderValue
    let filePath
    let fullRefFilePath

    if (refType === 'file') {
      filePath = utils.getRefFilePath(refVal)
      fullRefFilePath = utils.isAbsolute(filePath) ? filePath : path.resolve(state.cwd, filePath)

      if (cache[fullRefFilePath]) {
        loaderValue = cache[fullRefFilePath]
      }
    }

    if (!loaderValue) {
      loaderValue = loaders[refType](refVal, options)
      if (loaderValue) {
        // adjust base folder if needed so that we can handle paths in nested folders
        if (refType === 'file') {
          let dirname = path.dirname(filePath)
          if (dirname === '.') {
            dirname = ''
          }

          if (dirname) {
            oldBasePath = state.cwd
            const newBasePath = path.resolve(state.cwd, dirname)
            options.baseFolder = state.cwd = newBasePath
          }
        }

        loaderValue = derefSchema(loaderValue, options, state)

        // reset
        if (oldBasePath) {
          options.baseFolder = state.cwd = oldBasePath
        }
      }
    }

    if (loaderValue) {
      if (refType === 'file' && fullRefFilePath && !cache[fullRefFilePath]) {
        cache[fullRefFilePath] = loaderValue
      }

      if (refVal.indexOf('#') >= 0) {
        const refPaths = refVal.split('#')
        const refPath = refPaths[1]
        const refNewVal = utils.getRefPathValue(loaderValue, refPath)
        if (refNewVal) {
          newVal = refNewVal
        }
      } else {
        newVal = loaderValue
      }
    }

    return newVal
  } else if (refType === 'local') {
    return utils.getRefPathValue(parent, refVal)
  }
}

/**
 * Add to state history
 * @param {Object} state the state
 * @param {String} type ref type
 * @param {String} value ref value
 * @private
 */
function addToHistory (state, type, value) {
  let dest

  if (type === 'file') {
    dest = utils.getRefFilePath(value)
  } else {
    if (value === '#') {
      return false
    }
    dest = state.current.concat(`:${value}`)
  }

  if (dest) {
    dest = dest.toLowerCase()
    if (state.history.indexOf(dest) >= 0) {
      return false
    }

    state.history.push(dest)
  }
  return true
}

/**
 * Set the current into state
 * @param {Object} state the state
 * @param {String} type ref type
 * @param {String} value ref value
 * @private
 */
function setCurrent (state, type, value) {
  let dest
  if (type === 'file') {
    dest = utils.getRefFilePath(value)
  }

  if (dest) {
    state.current = dest
  }
}

/**
 * Check the schema for local circular refs using DAG
 * @param {Object} schema the schema
 * @return {Error|undefined} Error if circular ref, undefined otherwise if OK
 * @private
 */
function checkLocalCircular (schema) {
  const dag = new DAG()
  const locals = traverse(schema).reduce(function (acc, node) {
    if (!_.isNull(node) && !_.isUndefined(null) && typeof node.$ref === 'string') {
      const refType = utils.getRefType(node)
      if (refType === 'local') {
        const value = utils.getRefValue(node)
        if (value) {
          const path = this.path.join('/')
          acc.push({
            from: path,
            to: value
          })
        }
      }
    }
    return acc
  }, [])

  if (!locals || !locals.length) {
    return
  }

  if (_.some(locals, elem => elem.to === '#')) {
    return new Error('Circular self reference')
  }

  const check = _.find(locals, elem => {
    const fromEdge = elem.from.concat('/')
    const dest = elem.to.substring(2).concat('/')
    try {
      dag.addEdge(fromEdge, dest)
    } catch (e) {
      return elem
    }

    if (fromEdge.indexOf(dest) >= 0) {
      return elem
    }
  })

  if (check) {
    return new Error(`Circular self reference from ${check.from} to ${check.to}`)
  }
}

/**
 * Derefs $ref types in a schema
 * @param schema
 * @param options
 * @param state
 * @param type
 * @private
 */
function derefSchema (schema, options, state) {
  const check = checkLocalCircular(schema)
  if (check instanceof Error) {
    return check
  }

  if (state.circular) {
    return new Error(`circular references found: ${state.circularRefs.toString()}`)
  } else if (state.error) {
    return state.error
  }

  return traverse(schema).forEach(function (node) {
    if (!_.isNull(node) && !_.isUndefined(null) && typeof node.$ref === 'string') {
      const refType = utils.getRefType(node)
      const refVal = utils.getRefValue(node)

      const addOk = addToHistory(state, refType, refVal)
      if (!addOk) {
        state.circular = true
        state.circularRefs.push(refVal)
        state.error = new Error(`circular references found: ${state.circularRefs.toString()}`)
        this.update(node, true)
      } else {
        setCurrent(state, refType, refVal)
        const newValue = getRefSchema(refVal, refType, schema, options, state)
        state.history.pop()
        if (newValue === undefined) {
          if (state.missing.indexOf(refVal) === -1) {
            state.missing.push(refVal)
          }
          if (options.failOnMissing) {
            state.error = new Error(`Missing $ref: ${refVal}`)
          }
          this.update(node, options.failOnMissing)
        } else {
          this.update(newValue)
          if (state.missing.indexOf(refVal) !== -1) {
            state.missing.splice(state.missing.indexOf(refVal), 1)
          }
        }
      }
    }
  })
}

/**
 * Derefs $ref's in JSON Schema to actual resolved values. Supports local, and file refs.
 * @param {Object} schema - The JSON schema
 * @param {Object} options - options
 * @param {String} options.baseFolder - the base folder to get relative path files from. Default is process.cwd()
 * @param {Boolean} options.failOnMissing - By default missing / unresolved refs will be left as is with their ref value intact.
 *                                        If set to true we will error out on first missing ref that we cannot
 *                                        resolve. Default: false.
 * @return {Object|Error} the deref schema oran instance of Error if error.
 */
function deref (schema, options) {
  options = _.defaults(options, defaults)

  const bf = options.baseFolder
  let cwd = bf
  if (!utils.isAbsolute(bf)) {
    cwd = path.resolve(process.cwd(), bf)
  }

  const state = {
    graph: new DAG(),
    circular: false,
    circularRefs: [],
    cwd: cwd,
    missing: [],
    history: []
  }

  try {
    const str = JSON.stringify(schema)
    state.current = md5(str)
  } catch (e) {
    return e
  }

  const baseSchema = clone(schema)

  cache = {}

  let ret = derefSchema(baseSchema, options, state)
  if ((ret instanceof Error === false) && state.error) {
    return state.error
  }
  return ret
}

module.exports = deref
<commit_msg>Add mergeAdditionalProperties property<commit_after>const path = require('path')
const _ = require('lodash')
const clone = require('clone')
const traverse = require('traverse')
const DAG = require('dag-map')
const md5 = require('md5')
const utils = require('./utils')
const fileLoader = require('./loaders/file')

const defaults = {
  baseFolder: process.cwd()
}

let cache = {}

const loaders = {
  file: fileLoader
}

/**
 * Returns the reference schema that refVal points to.
 * If the ref val points to a ref within a file, the file is loaded and fully derefed, before we get the
 * pointing property. Derefed files are cached.
 *
 * @param refVal
 * @param refType
 * @param parent
 * @param options
 * @param state
 * @private
 */
function getRefSchema (refVal, refType, parent, options, state) {
  if (refType && loaders[refType]) {
    let newVal
    let oldBasePath
    let loaderValue
    let filePath
    let fullRefFilePath

    if (refType === 'file') {
      filePath = utils.getRefFilePath(refVal)
      fullRefFilePath = utils.isAbsolute(filePath) ? filePath : path.resolve(state.cwd, filePath)

      if (cache[fullRefFilePath]) {
        loaderValue = cache[fullRefFilePath]
      }
    }

    if (!loaderValue) {
      loaderValue = loaders[refType](refVal, options)
      if (loaderValue) {
        // adjust base folder if needed so that we can handle paths in nested folders
        if (refType === 'file') {
          let dirname = path.dirname(filePath)
          if (dirname === '.') {
            dirname = ''
          }

          if (dirname) {
            oldBasePath = state.cwd
            const newBasePath = path.resolve(state.cwd, dirname)
            options.baseFolder = state.cwd = newBasePath
          }
        }

        loaderValue = derefSchema(loaderValue, options, state)

        // reset
        if (oldBasePath) {
          options.baseFolder = state.cwd = oldBasePath
        }
      }
    }

    if (loaderValue) {
      if (refType === 'file' && fullRefFilePath && !cache[fullRefFilePath]) {
        cache[fullRefFilePath] = loaderValue
      }

      if (refVal.indexOf('#') >= 0) {
        const refPaths = refVal.split('#')
        const refPath = refPaths[1]
        const refNewVal = utils.getRefPathValue(loaderValue, refPath)
        if (refNewVal) {
          newVal = refNewVal
        }
      } else {
        newVal = loaderValue
      }
    }

    return newVal
  } else if (refType === 'local') {
    return utils.getRefPathValue(parent, refVal)
  }
}

/**
 * Add to state history
 * @param {Object} state the state
 * @param {String} type ref type
 * @param {String} value ref value
 * @private
 */
function addToHistory (state, type, value) {
  let dest

  if (type === 'file') {
    dest = utils.getRefFilePath(value)
  } else {
    if (value === '#') {
      return false
    }
    dest = state.current.concat(`:${value}`)
  }

  if (dest) {
    dest = dest.toLowerCase()
    if (state.history.indexOf(dest) >= 0) {
      return false
    }

    state.history.push(dest)
  }
  return true
}

/**
 * Set the current into state
 * @param {Object} state the state
 * @param {String} type ref type
 * @param {String} value ref value
 * @private
 */
function setCurrent (state, type, value) {
  let dest
  if (type === 'file') {
    dest = utils.getRefFilePath(value)
  }

  if (dest) {
    state.current = dest
  }
}

/**
 * Check the schema for local circular refs using DAG
 * @param {Object} schema the schema
 * @return {Error|undefined} Error if circular ref, undefined otherwise if OK
 * @private
 */
function checkLocalCircular (schema) {
  const dag = new DAG()
  const locals = traverse(schema).reduce(function (acc, node) {
    if (!_.isNull(node) && !_.isUndefined(null) && typeof node.$ref === 'string') {
      const refType = utils.getRefType(node)
      if (refType === 'local') {
        const value = utils.getRefValue(node)
        if (value) {
          const path = this.path.join('/')
          acc.push({
            from: path,
            to: value
          })
        }
      }
    }
    return acc
  }, [])

  if (!locals || !locals.length) {
    return
  }

  if (_.some(locals, elem => elem.to === '#')) {
    return new Error('Circular self reference')
  }

  const check = _.find(locals, elem => {
    const fromEdge = elem.from.concat('/')
    const dest = elem.to.substring(2).concat('/')
    try {
      dag.addEdge(fromEdge, dest)
    } catch (e) {
      return elem
    }

    if (fromEdge.indexOf(dest) >= 0) {
      return elem
    }
  })

  if (check) {
    return new Error(`Circular self reference from ${check.from} to ${check.to}`)
  }
}

/**
 * Derefs $ref types in a schema
 * @param schema
 * @param options
 * @param state
 * @param type
 * @private
 */
function derefSchema (schema, options, state) {
  const check = checkLocalCircular(schema)
  if (check instanceof Error) {
    return check
  }

  if (state.circular) {
    return new Error(`circular references found: ${state.circularRefs.toString()}`)
  } else if (state.error) {
    return state.error
  }

  return traverse(schema).forEach(function (node) {
    if (!_.isNull(node) && !_.isUndefined(null) && typeof node.$ref === 'string') {
      const refType = utils.getRefType(node)
      const refVal = utils.getRefValue(node)

      const addOk = addToHistory(state, refType, refVal)
      if (!addOk) {
        state.circular = true
        state.circularRefs.push(refVal)
        state.error = new Error(`circular references found: ${state.circularRefs.toString()}`)
        this.update(node, true)
      } else {
        setCurrent(state, refType, refVal)
        let newValue = getRefSchema(refVal, refType, schema, options, state)
        state.history.pop()
        if (newValue === undefined) {
          if (state.missing.indexOf(refVal) === -1) {
            state.missing.push(refVal)
          }
          if (options.failOnMissing) {
            state.error = new Error(`Missing $ref: ${refVal}`)
          }
          this.update(node, options.failOnMissing)
        } else {
          if (options.mergeAdditionalProperties) {
            delete node.$ref;
            newValue = Object.assign({}, newValue, node)
          }
          this.update(newValue);
          if (state.missing.indexOf(refVal) !== -1) {
            state.missing.splice(state.missing.indexOf(refVal), 1)
          }
        }
      }
    }
  })
}

/**
 * Derefs $ref's in JSON Schema to actual resolved values. Supports local, and file refs.
 * @param {Object} schema - The JSON schema
 * @param {Object} options - options
 * @param {String} options.baseFolder - the base folder to get relative path files from. Default is process.cwd()
 * @param {Boolean} options.failOnMissing - By default missing / unresolved refs will be left as is with their ref value intact.
 *                                        If set to true we will error out on first missing ref that we cannot
 *                                        resolve. Default: false.
 * @return {Object|Error} the deref schema oran instance of Error if error.
 */
function deref (schema, options) {
  options = _.defaults(options, defaults)

  const bf = options.baseFolder
  let cwd = bf
  if (!utils.isAbsolute(bf)) {
    cwd = path.resolve(process.cwd(), bf)
  }

  const state = {
    graph: new DAG(),
    circular: false,
    circularRefs: [],
    cwd: cwd,
    missing: [],
    history: []
  }

  try {
    const str = JSON.stringify(schema)
    state.current = md5(str)
  } catch (e) {
    return e
  }

  const baseSchema = clone(schema)

  cache = {}

  let ret = derefSchema(baseSchema, options, state)
  if ((ret instanceof Error === false) && state.error) {
    return state.error
  }
  return ret
}

module.exports = deref
<|endoftext|>


<commit_before>/**
 * sivart-ci v0.1.0
 *
 * A simple interactive CI Dashboard built on MEAN stack.
 *
 * Author: Kushal Pandya <kushalspandya@gmail.com> (https://doublslash.com)
 * Date: 27 November, 2015
 *
 * Sivart CI Angular App.
 */

(function() {
    var sivartCI = angular.module('sivartCI', []);

    /*
     * Declare App Controllers
     */
    sivartCI.controller("MainController", ["$scope", "$http", "$sce", MainController]);

    /*
     * Main Controller
     */
    MainController.$inject = ["$scope"];
    function MainController($scope, $http, $sce) {

        // Load Data
        $http.get('/api/changelists')
        .success(function(data) {
            $scope.changelistItems = data;
        })
        .error(function(data) {
            console.log('Error Loading Changelists');
        });

        // Item Preprocessors.
        $scope.getTimeStarted = function(timeStarted) {
            var timeStartedObj = new Date(timeStarted),
                hh = timeStartedObj.getHours(),
                mm = timeStartedObj.getMinutes(),
                ampm = hh >= 12 ? 'pm' : 'am',
                formattedString;

            hh = hh % 12;
            hh = hh ? hh : 12;
            mm = mm < 10 ? '0' + mm : mm;

            formattedString = timeStartedObj.getMonth() + '/' +
                              timeStartedObj.getDate() + '/' +
                              timeStartedObj.getUTCFullYear() + ' ' +
                              '' +
                              hh + ':' + mm + ' ' + ampm;

            return $sce.trustAsHtml(formattedString);
        };

        $scope.getStatus = function(status) {
            var statusEl = {
                "-1": "Failed",
                "0": "Pending",
                "1": "Passed",
                "2": "Running"
            };

            switch (status) {
                case -1:
                    statusEl = 'Failed';
                    break;
                case 0:
                    statusEl = 'Pending';
                    break;
                case 1:
                    statusEl = 'Passed';
                    break;
                default:
                    statusEl = 'Running';
            }

            return $sce.trustAsHtml(statusEl);
        };

        $scope.getInitialStatusClass = function(status) {
            var statusMap = {
                "-1": "item-fail",
                "0": "item-pending",
                "1": "item-pass",
                "2": "item-active"
            };

            return statusMap[status];
        };
    }
})();
<commit_msg>This commit includes lots of changes. See desc.<commit_after>/**
 * sivart-ci v0.1.0
 *
 * A simple interactive CI Dashboard built on MEAN stack.
 *
 * Author: Kushal Pandya <kushalspandya@gmail.com> (https://doublslash.com)
 * Date: 27 November, 2015
 *
 * Sivart CI Angular App.
 */

(function() {
    var sivartCI = angular.module('sivartCI', []),
        pageLocation = window.location,
        socketListenerPort = 3000,
        socket;

    /*
     * Declare App Controllers
     */
    sivartCI.controller("MainController", ["$scope", "$http", "$sce", '$timeout', MainController]);

    /*
     * Create Directives
     */
    sivartCI.directive('onFinishRender', ['$timeout', '$parse', function($timeout, $parse) {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                if (scope.$last)
                {
                    scope.$eval(attrs.onFinishRender);
                }
            }
        };
    }]);

    /*
     * Main Controller
     */
    MainController.$inject = ["$scope"];
    function MainController($scope, $http, $sce, $timeout) {

        // Load Data
        $http.get('/api/changelists')
        .success(function(data) {
            $scope.changelistItems = data;
            $scope.changelistItems.findChangelist = function(fieldName, lookupValue) {
                var matchedChangelist,
                    i;

                for (i = 0; i < $scope.changelistItems.length; i++)
                {
                    if ($scope.changelistItems[i][fieldName] === lookupValue)
                    {
                        matchedChangelist = $scope.changelistItems[i];
                        break;
                    }
                }

                return matchedChangelist;
            };
        })
        .error(function(data) {
            console.log('Error Loading Changelists');
        });

        // Event Listeners
        $scope.onChangelistReady = function(val) {
            $timeout(function() {
                $scope.initSocket();
            }, 1);
        };

        $scope.onChangelistItemClick = function(changelistId) {
            var changelistEl = $('#' + changelistId),
                changelistDetailsEl = $('#' + changelistId + '-details').find('.changelist-details');

            if (changelistEl.hasClass('item-pass') ||
                changelistEl.hasClass('item-fail'))
            {
                if (!changelistDetailsEl.is(':visible'))
                {
                    changelistEl.addClass('expanded');
                    changelistEl.find('.changelist-status').attr('rowspan', 2);
                    changelistDetailsEl.slideDown('fast');
                }
                else
                {
                    changelistEl.removeClass('expanded');
                    changelistEl.find('.changelist-status').removeAttr('rowspan');
                    changelistDetailsEl.slideUp('fast');
                }
            }
        };

        // Item Preprocessors.
        $scope.getTimeStarted = function(timeStarted) {
            var timeStartedObj = new Date(timeStarted),
                formattedString;

            formattedString = timeStartedObj.getMonth() + '/' +
                              timeStartedObj.getDate() + '/' +
                              timeStartedObj.getUTCFullYear() + ' ' +
                              '' +
                              this.formatTime(timeStartedObj);

            return $sce.trustAsHtml(formattedString);
        };

        $scope.getStatus = function(status) {
            var statusEl = {
                "-1": "Failed",
                "0": "Pending",
                "1": "Passed",
                "2": "Running"
            };

            switch (status) {
                case -1:
                    statusEl =  '' +
                                    'Failed' +
                                '' +
                                '' +
                                    'Build Failure' +
                                '';
                    break;
                case 0:
                    statusEl = 'Pending';
                    break;
                case 1:
                statusEl =  '' +
                                'Passed' +
                            '' +
                            '' +
                                'Build Passed' +
                            '';
                    break;
                default:
                    statusEl = 'Running';
            }

            return $sce.trustAsHtml(statusEl);
        };

        $scope.getBuildStatus = function(status, timeCompleted) {
            var timeCompletedObj = new Date(timeCompleted),
                buildIconEl = status === 1 ? '' : '',
                buildStatusEl;

            buildStatusEl = 'Build ' + buildIconEl + '' +
                            '' +
                                '' +
                                this.formatTime(timeCompletedObj) +
                            '';

            return $sce.trustAsHtml(buildStatusEl);
        };

        $scope.getInitialStatusClass = function(status) {
            var statusMap = {
                "-1": "item-fail",
                "0": "item-pending",
                "1": "item-pass",
                "2": "item-active"
            };

            return statusMap[status];
        };

        // Utility Functions.
        $scope.formatTime = function(dateObj) {
            var hh = dateObj.getHours(),
                mm = dateObj.getMinutes(),
                ampm = hh >= 12 ? 'pm' : 'am';

            return hh + ':' + mm + ' ' + ampm;
        };

        $scope.initSocket = function() {
            var i;

            socket = io.connect(pageLocation.protocol + '//' + pageLocation.hostname + ':' + socketListenerPort);

            // Invokes build on Server.
            for (i = 1; i <=  $scope.changelistItems.length; i++)
            {
                $timeout(function(changelistId) {
                    socket.emit('triggerbuild', changelistId);
                }, i * 1000, true, $scope.changelistItems[i - 1]._id);
            }

            socket.on('buildstart', function(changelistId) {
                var changeListItemEl = $('tr#' + changelistId),
                    buildStepEl = $('tr#' + changelistId).find('.progress-steps .buildStep');
                console.log('Build started for Changelist ', $scope.changelistItems.findChangelist('_id', changelistId).changeListName);

                $scope.changelistItems.findChangelist('_id', changelistId).activity.status = 2;
                buildStepEl.removeClass('step-pending').addClass('step-active');
                buildStepEl.find('.step-icon').removeClass('step-icon-pending').addClass('step-icon-active');
            });

            socket.on('buildfinished', function(changelistId, status) {
                var changeListItemEl = $('tr#' + changelistId),
                    buildStepEl = changeListItemEl.find('.progress-steps .buildStep');
                console.log('Build finished for Changelist ', $scope.changelistItems.findChangelist('_id', changelistId).changeListName, ' with status ', status);

                if (status === 1)
                    buildStepEl.find('.step-icon').removeClass('step-icon-active').addClass('step-icon-pass');
                else
                {
                    $scope.changelistItems.findChangelist('_id', changelistId).activity.status = status;
                    buildStepEl.removeClass('step-active').addClass('step-fail');
                    buildStepEl.find('.step-icon').removeClass('step-icon-active').addClass('step-icon-fail');
                }
            });

            socket.on('unitteststart', function(changelistId) {
                var changeListItemEl = $('tr#' + changelistId),
                    buildStepEl = changeListItemEl.find('.progress-steps .buildStep'),
                    utStepEl = changeListItemEl.find('.progress-steps .utStep');

                console.log('Unit Tests started for Changelist ', $scope.changelistItems.findChangelist('_id', changelistId).changeListName);

                buildStepEl.addClass('fill-step-progress');
                $timeout(function() {
                    utStepEl.removeClass('step-empty').addClass('step-active');
                    utStepEl.find('.step-icon').addClass('step-icon-active');
                }, 1000);
            });

            socket.on('unittestfinished', function(changelistId, status) {
                var changeListItemEl = $('tr#' + changelistId),
                    buildStepEl = changeListItemEl.find('.progress-steps .buildStep'),
                    utStepEl = changeListItemEl.find('.progress-steps .utStep');

                if (status === 1)
                    utStepEl.find('.step-icon').removeClass('step-icon-active').addClass('step-icon-pass');
                else
                {
                    $scope.changelistItems.findChangelist('_id', changelistId).activity.status = status;
                    utStepEl.removeClass('step-active').addClass('step-fail');
                    buildStepEl.removeClass('step-active fill-step-progress').addClass('step-fail fill-step-progress');
                    $timeout(function() {
                        utStepEl.find('.step-icon').removeClass('step-icon-active').addClass('step-icon-fail');
                    }, 1000);
                }
            });

            socket.on('functionalteststart', function(changelistId) {
                var changeListItemEl = $('tr#' + changelistId),
                    buildStepEl = changeListItemEl.find('.progress-steps .buildStep'),
                    utStepEl = changeListItemEl.find('.progress-steps .utStep'),
                    ftStepEl = changeListItemEl.find('.progress-steps .ftStep');

                utStepEl.addClass('fill-step-progress');
                $timeout(function() {
                    ftStepEl.removeClass('step-empty').addClass('step-active');
                    ftStepEl.find('.step-icon').addClass('step-icon-active');
                }, 1000);
            });

            socket.on('functionaltestfinished', function(changelistId, status) {
                var changeListItemEl = $('tr#' + changelistId),
                    buildStepEl = changeListItemEl.find('.progress-steps .buildStep'),
                    utStepEl = changeListItemEl.find('.progress-steps .utStep'),
                    ftStepEl = changeListItemEl.find('.progress-steps .ftStep');

                if (status === 1)
                {
                    $scope.changelistItems.findChangelist('_id', changelistId).activity.status = status;
                    buildStepEl.removeClass('step-active fill-step-progress').addClass('step-pass fill-step-progress');
                    utStepEl.removeClass('step-active fill-step-progress').addClass('step-pass fill-step-progress');
                    ftStepEl.addClass('step-pass');
                    $timeout(function() {
                        ftStepEl.find('.step-icon').removeClass('step-icon-active').addClass('step-icon-pass');
                    }, 1000);
                }
                else
                {
                    $scope.changelistItems.findChangelist('_id', changelistId).activity.status = status;
                    buildStepEl.removeClass('step-active fill-step-progress').addClass('step-fail fill-step-progress');
                    utStepEl.removeClass('step-active fill-step-progress').addClass('step-fail fill-step-progress');
                    ftStepEl.addClass('step-fail');
                    $timeout(function() {
                        ftStepEl.find('.step-icon').removeClass('step-icon-active').addClass('step-icon-fail');
                    }, 1000);
                }
            });
        };
    }
})();
<|endoftext|>


<commit_before>var
	cheerio = require('cheerio'),
	request = require('./request'),

	baseHost = '.craigslist.org',
	defaultRequestOptions = {
		hostname : '',
		path : '',
	    secure : true
	},
	searchMaxAsk = '&maxAsk=',
	searchMinAsk = '&minAsk=';
	// searchPath = '/search/sss?sort=rel&query=';

    var initialize = (function (self) {
	'use strict';

	self = self || {};
	self.options = {};
	/*
		Accepts string of HTML and parses that string to find all pertinent listings.
	*/
	function getRssListings (options, html) {
		var
			$ = cheerio.load(html),
			listing = {},
			listings = [];

        var category = $('channel').find('title').text()

		$('item').each(function (i, element) {
			var children = $(element).children()

            var url = $(element).attr('rdf:about')
			var idx = url.lastIndexOf('/')
			var idx1 = url.indexOf('.', idx)
			var listing = { category : category, url: url, pid: url.substring(idx + 1, idx1) }

			for (var i=0; i<children.length; i++) {
				var t, child = children[i]
				var name = child.name

				if (name == 'title') {
					t = child.children[0].data.trim()
					if (t.indexOf('[CDATA[') != -1)
						t = t.substring(7, t.length - 2).trim().replace(/^\&\#x0024\;/g, '').replace(/&\#x0024\;/g, '$')

					var priceIdx = t.indexOf('$')
					if (priceIdx != -1)  {
						var sidx = t.indexOf(' ', priceIdx)
						listing.price = sidx == -1 ? t.substring(priceIdx) : t.substring(priceIdx, sidx)
					}
					var idx = t.lastIndexOf('(')
				    if (idx == -1)
				    	listing.title = t
				    else {
				    	var idx1 = t.indexOf(')', idx)
				    	listing.location = t.substring(idx + 1, idx1).trim()
				    	listing.title = t.substring(0, idx).trim()
				    }

				}
				else if (name == 'description') {
					t = child.children[0].data.trim()
					if (t.indexOf('[CDATA[') != -1)
						t = t.substring(7, t.length - 2)
					listing.description = t.replace(/&\#x0024\;/g, '$').trim()
				}
				else if (name == 'dc:date')
					listing.date = $(child).text().trim()
				else if (name == 'enc:enclosure') {
					listing.hasPic = true
					listing.img = $(child).attr('resource')
				}
			}

					// coordinates : {
					// 	lat : $(element).attr('data-latitude'),
					// 	lon : $(element).attr('data-longitude')
					// },

				// make sure lat / lon is valid
				// if (typeof listing.coordinates.lat === 'undefined' ||
				// 	typeof listing.coordinates.lon === 'undefined') {
				// 	delete listing.coordinates;
				// }
			listings.push(listing);
		});

		return listings;
	}

	/*
		Accepts string of HTML and parses that string to find all pertinent listings.
	*/
	function getListings (options, html) {
		var
			$ = cheerio.load(html),
			listing = {},
			listings = [];

		$('div.content').find('p.row').each(function (i, element) {
			listing = {
				category : $(element)
					.find('span.l2 a.gc')
					.text(),
				coordinates : {
					lat : $(element).attr('data-latitude'),
					lon : $(element).attr('data-longitude')
				},
				date : $(element)
					.find('span.date')
					.text(),
				hasPic : ($(element)
					.find('span.l2 span.p')
					.text()
					.trim()) !== '',
				location : $(element)
					.find('span.pnr small')
					.text()
					.replace(/[\(,\)]/g, '').trim(), // santize
				pid : $(element)
					.attr('data-pid'),
				price : $(element)
					.find('span.l2 span.price')
					.text()
					.replace(/^\&\#x0024\;/g, ''), // sanitize
				title : $(element)
					.find('span.pl a')
					.text().trim()
				// url :
				// 	(options.secure ? 'https://' : 'http://') +
				// 	options.hostname + $(element).find('span.pl a').attr('href')
			}
			var rurl = $(element).find('span.pl a').attr('href');
			if (rurl) {
			  if (rurl.indexOf('http') == -1)
			    rurl = (options.secure ? 'https://' : 'http://') + options.hostname + rurl
			  listing.url = rurl;
		    }
		    if (options.cityName)
		      listing.cityName = options.cityName

			if (listing.hasPic) {
				var dId = $(element).find('a.i').attr('data-id')
				if (dId)
				  listing.pic = 'http://images.craigslist.org/' + dId.substring(2) + '_300x300.jpg'
			}
			var d = $(element).find('span.date')
			if (!d  ||  d.text().length == 0) {
				d = $(element).find('time').attr('datetime')
				listing.date = d;
			}

			// make sure lat / lon is valid
			if (typeof listing.coordinates.lat === 'undefined' ||
				typeof listing.coordinates.lon === 'undefined') {
				delete listing.coordinates;
			}

			listings.push(listing);
		});

		return listings;
	}

	function getCities(options, html) {
		var
			$ = cheerio.load(html),
			listing = {},
			listings = [];

		$('div.colmask').find('a').each(function (i, element) {
           var href = $(element).attr('href')
           var idx = href.indexOf('//'), idx1 = href.indexOf('.');

           listing = { city: href.substring(idx + 2, idx1),
           			   href: href,
                       cityName: $(element).text().replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()})
                     }

           listings.push(listing)
		})
		return listings
	}

	function getCategories(options, html) {
		var
			$ = cheerio.load(html),
			listing = {},
			listings = [];

        var city = $('h2.no-mobile').html();
        var idx = city.indexOf('<');
        if (idx != -1)
          city = city.substring(0, idx)

		$('div#center').find('a').each(function (i, element) {
           var href = $(element).attr('href')
           if (href.indexOf('/search/') != 0)
           	return;
           var idx = href.indexOf('//'), idx1 = href.indexOf('.');

           listing = { categoryName: $(element).text(),
           			   categoryHref: href,
                       city: city
                     }

           listings.push(listing)
		})
		return listings
	}
	function getSubCities(options, html) {
		var
			$ = cheerio.load(html),
			listing = {},
			listings = [];

        var city = $('h2.no-mobile').html();
        var idx = city.indexOf('<');
        if (idx != -1)
          city = city.substring(0, idx)

		$('ul.sublinks').find('a').each(function (i, element) {
       var href = $(element).attr('href')

       listing = { subCityHref: options.hostname + href,
                   subCity: $(element).attr('title')
                 }

       listings.push(listing)
		})
		// nearby cities
		var rightPanelElms = $('div#rightbar').find('.menu .collapsible').find('li');
		for (var i=0; i<rightPanelElms; i++) {
			var li = rightPaneElms.get(i);
			if ($(li).find('h5').get(0).text() != 'nearby cl')
				continue;
			$(li).find('a').each(function(i, element) {
				listing = { city: $(element).text(),
					        href: $(element).attr('href')
				          }
			})

		}
		return listings
	}

    // Extracting full description for the listing
	function getDescription(options, html) {
		var
			$ = cheerio.load(html);

		var description = $('section#postingbody').html()
		var listing = {}
		if (description)
	  	  listing.description = description.trim()
		var attr = $('p.attrgroup')
        if (!attr)
          return listing
    	attr.find('span').each(function(i, p) {
    	  if ($(p).attr('class'))
    	  	listing.date = $(p).find('a').text()
    	  else {
    	  	var pVal, pName = $(p).text().trim()

    	  	var idx = pName.indexOf(':')
    	  	if (idx == -1) {
    	  	  pVal = pName
    	  	  pName = 'p' + i
    	  	}
    	  	else {
    	  	  pName = pName.substring(0, idx).trim()
    	  	  if (pName.charAt(0) == '#')
    	  	    pName = ('Number of' + pName.substring(1))
    	  	  pVal = $(p).find('b');
    	  	}

    	  	listing[pName] = pVal
    	  }
        })
        return listing
	}
	/*
		Accepts options, iterates through the known acceptable keys from defaultOptions
		and if found in input options, uses that. If not found in input options to method,
		falls back to the options specified when the module was initialized. If not found
		in initialization options, uses the default options setting. All keys provided in
		the input options variable are retained.
	*/
	function getRequestOptions (options, query) {
		var requestOptions = JSON.parse(JSON.stringify(defaultRequestOptions));
		if (options.fullListing  &&  options.path) {
			requestOptions.path = options.path
			requestOptions.hostname = options.hostname
			return requestOptions
		}

		// ensure default options are set, even if omitted from input options
		requestOptions.hostname = options.allCities? 'www' + baseHost : (options.city || self.options.city || '') + baseHost;

		// preserve any extraneous input option keys (may have addition instructions for underlying request object)
		Object.keys(options).forEach(function (key) {
			if (
				// key !== 'maxAsk'   &&
				// key !== 'minAsk'   &&
				// key !== 'category' &&
				// key !== 'hasPic'   &&
				// key !== 's'        &&
				typeof requestOptions[key] === 'undefined' &&
				typeof defaultRequestOptions[key] === 'undefined') {
				requestOptions[key] = options[key];
			}
		});

		// set path
		if (options.allCities)
		  requestOptions.path = '/about/sites'
		else if (options.categoriesOnly)
		  requestOptions.path = ''
		else
		  requestOptions.path = '/search/' + (options.category ? options.category : 'sss') + '?sort=rel' +
  		                                     (options.s ? '&s=' + options.s : '') +
		                                     (options.hasPic && (options.hasPic == '1' || options.hasPic == 'true') ? '&hasPic=1' : '') +
		                                     (options.rss ? '&format=rss' : '') +
		                                     (options.query ? '&query=' + encodeURIComponent(options.query) : '');

		// add min and max asking price
		if (typeof options.minAsk !== 'undefined') {
			requestOptions.path += searchMinAsk + options.minAsk;
		}

		if (typeof options.maxAsk !== 'undefined') {
			requestOptions.path += searchMaxAsk + options.maxAsk;
		}

		return requestOptions;
	}

	/*
		options = {
			city : '',
			maxAsk : '',
			minAsk : '',
		}
	*/
	self.search = function (options, query, callback) {
		if (typeof query === 'function' && typeof callback === 'undefined') {
			callback = query;
			query = options;
			options = {};
		}

        // The original set of options will have something like
        //
        //  options = {
		//   city: 'newyork',
		//   category: 'tia',
		//   hasPic: 1,
		//   fullListing: true,
		//   offset: 100,
		//   query: 'concert'
		// }
		//
		// only if particular listing's url is known then we can request the listing's page and description
		//
        var isFullDescriptionRequest = options.fullListing  &&  options.path
		options = getRequestOptions(options, query);

		self.request.get(options, function (err, data) {
			if (err)
			  return callback(err)

   //          if (options.allCities)
   //            return callback(null, getCities(options, data))
   //          if (options.rss)
   //            return callback(null, getRssListings(options, data))
   //          if (isFullDescriptionRequest)
   //            return callback(null, getDescription(options, data))
   //          if (options.categoriesOnly)
   //            return callback(null, getCategories(options, data))

			// return callback(null, getListings(options, data))
            if (options.allCities)
              return callback(null, data)
            if (options.rss)
              return callback(null, data)
            if (isFullDescriptionRequest)
              return callback(null, data)
            if (options.categoriesOnly)
              return callback(null, data)

			return callback(null, getListings(options, data))
		});
	};

	/*
		the module
	*/
	return function (options) {
		options = options || {};

		self.options = options;
		self.request = request.initialize();
		return self;
	};
}({}));

exports = module.exports = initialize;
exports.initialize = initialize;
<commit_msg>getting all craigslist categories<commit_after>var
	cheerio = require('cheerio'),
	request = require('./request'),

	baseHost = '.craigslist.org',
	defaultRequestOptions = {
		hostname : '',
		path : '',
	    secure : true
	},
	searchMaxAsk = '&maxAsk=',
	searchMinAsk = '&minAsk=';
	// searchPath = '/search/sss?sort=rel&query=';

    var initialize = (function (self) {
	'use strict';

	self = self || {};
	self.options = {};
	/*
		Accepts string of HTML and parses that string to find all pertinent listings.
	*/
	function getRssListings (options, html) {
		var
			$ = cheerio.load(html),
			listing = {},
			listings = [];

        var category = $('channel').find('title').text()

		$('item').each(function (i, element) {
			var children = $(element).children()

            var url = $(element).attr('rdf:about')
			var idx = url.lastIndexOf('/')
			var idx1 = url.indexOf('.', idx)
			var listing = { category : category, url: url, pid: url.substring(idx + 1, idx1) }

			for (var i=0; i<children.length; i++) {
				var t, child = children[i]
				var name = child.name

				if (name == 'title') {
					t = child.children[0].data.trim()
					if (t.indexOf('[CDATA[') != -1)
						t = t.substring(7, t.length - 2).trim().replace(/^\&\#x0024\;/g, '').replace(/&\#x0024\;/g, '$')

					var priceIdx = t.indexOf('$')
					if (priceIdx != -1)  {
						var sidx = t.indexOf(' ', priceIdx)
						listing.price = sidx == -1 ? t.substring(priceIdx) : t.substring(priceIdx, sidx)
					}
					var idx = t.lastIndexOf('(')
				    if (idx == -1)
				    	listing.title = t
				    else {
				    	var idx1 = t.indexOf(')', idx)
				    	listing.location = t.substring(idx + 1, idx1).trim()
				    	listing.title = t.substring(0, idx).trim()
				    }

				}
				else if (name == 'description') {
					t = child.children[0].data.trim()
					if (t.indexOf('[CDATA[') != -1)
						t = t.substring(7, t.length - 2)
					listing.description = t.replace(/&\#x0024\;/g, '$').trim()
				}
				else if (name == 'dc:date')
					listing.date = $(child).text().trim()
				else if (name == 'enc:enclosure') {
					listing.hasPic = true
					listing.img = $(child).attr('resource')
				}
			}

					// coordinates : {
					// 	lat : $(element).attr('data-latitude'),
					// 	lon : $(element).attr('data-longitude')
					// },

				// make sure lat / lon is valid
				// if (typeof listing.coordinates.lat === 'undefined' ||
				// 	typeof listing.coordinates.lon === 'undefined') {
				// 	delete listing.coordinates;
				// }
			listings.push(listing);
		});

		return listings;
	}

	/*
		Accepts string of HTML and parses that string to find all pertinent listings.
	*/
	self.getListings = function getListings (options, html) {
		var
			$ = cheerio.load(html),
			listing = {},
			listings = [];

		$('div.content').find('p.row').each(function (i, element) {
			listing = {
				category : $(element)
					.find('span.l2 a.gc')
					.text(),
				coordinates : {
					lat : $(element).attr('data-latitude'),
					lon : $(element).attr('data-longitude')
				},
				date : $(element)
					.find('span.date')
					.text(),
				hasPic : ($(element)
					.find('span.l2 span.p')
					.text()
					.trim()) !== '',
				location : $(element)
					.find('span.pnr small')
					.text()
					.replace(/[\(,\)]/g, '').trim(), // santize
				pid : $(element)
					.attr('data-pid'),
				price : $(element)
					.find('span.l2 span.price')
					.text()
					.replace(/^\&\#x0024\;/g, ''), // sanitize
				title : $(element)
					.find('span.pl a')
					.text().trim()
				// url :
				// 	(options.secure ? 'https://' : 'http://') +
				// 	options.hostname + $(element).find('span.pl a').attr('href')
			}
			var rurl = $(element).find('span.pl a').attr('href');
			if (rurl) {
			  if (rurl.indexOf('http') == -1)
			    rurl = (options.secure ? 'https://' : 'http://') + options.hostname + rurl
			  listing.url = rurl;
		    }
		    if (options.cityName)
		      listing.cityName = options.cityName

			if (listing.hasPic) {
				var dId = $(element).find('a.i').attr('data-id')
				if (dId)
				  listing.pic = 'http://images.craigslist.org/' + dId.substring(2) + '_300x300.jpg'
			}
			var d = $(element).find('span.date')
			if (!d  ||  d.text().length == 0) {
				d = $(element).find('time').attr('datetime')
				listing.date = d;
			}

			// make sure lat / lon is valid
			if (typeof listing.coordinates.lat === 'undefined' ||
				typeof listing.coordinates.lon === 'undefined') {
				delete listing.coordinates;
			}

			listings.push(listing);
		});

		return listings;
	}

	function getCities(options, html) {
		var
			$ = cheerio.load(html),
			listing = {},
			listings = [];

		$('div.colmask').find('a').each(function (i, element) {
           var href = $(element).attr('href')
           var idx = href.indexOf('//'), idx1 = href.indexOf('.');

           listing = { city: href.substring(idx + 2, idx1),
           			   href: href,
                       cityName: $(element).text().replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()})
                     }

           listings.push(listing)
		})
		return listings
	}

	function getCategories(options, html) {
		var
			$ = cheerio.load(html),
			listing = {},
			listings = [];

        var city = $('h2.no-mobile').html();
        var idx = city.indexOf('<');
        if (idx != -1)
          city = city.substring(0, idx)

		$('div#center').find('a').each(function (i, element) {
           var href = $(element).attr('href')
           if (href.indexOf('/search/') != 0)
           	return;
           var idx = href.indexOf('//'), idx1 = href.indexOf('.');

           listing = { categoryName: $(element).text(),
           			   categoryHref: href,
                       city: city
                     }

           listings.push(listing)
		})
		return listings
	}
	function getSubCities(options, html) {
		var
			$ = cheerio.load(html),
			listing = {},
			listings = [];

        var city = $('h2.no-mobile').html();
        var idx = city.indexOf('<');
        if (idx != -1)
          city = city.substring(0, idx)

		$('ul.sublinks').find('a').each(function (i, element) {
       var href = $(element).attr('href')

       listing = { subCityHref: options.hostname + href,
                   subCity: $(element).attr('title')
                 }

       listings.push(listing)
		})
		// nearby cities
		var rightPanelElms = $('div#rightbar').find('.menu .collapsible').find('li');
		for (var i=0; i<rightPanelElms; i++) {
			var li = rightPaneElms.get(i);
			if ($(li).find('h5').get(0).text() != 'nearby cl')
				continue;
			$(li).find('a').each(function(i, element) {
				listing = { city: $(element).text(),
					        href: $(element).attr('href')
				          }
			})

		}
		return listings
	}

    // Extracting full description for the listing
	function getDescription(options, html) {
		var
			$ = cheerio.load(html);

		var description = $('section#postingbody').html()
		var listing = {}
		if (description)
	  	  listing.description = description.trim()
		var attr = $('p.attrgroup')
        if (!attr)
          return listing
    	attr.find('span').each(function(i, p) {
    	  if ($(p).attr('class'))
    	  	listing.date = $(p).find('a').text()
    	  else {
    	  	var pVal, pName = $(p).text().trim()

    	  	var idx = pName.indexOf(':')
    	  	if (idx == -1) {
    	  	  pVal = pName
    	  	  pName = 'p' + i
    	  	}
    	  	else {
    	  	  pName = pName.substring(0, idx).trim()
    	  	  if (pName.charAt(0) == '#')
    	  	    pName = ('Number of' + pName.substring(1))
    	  	  pVal = $(p).find('b');
    	  	}

    	  	listing[pName] = pVal
    	  }
        })
        return listing
	}
	/*
		Accepts options, iterates through the known acceptable keys from defaultOptions
		and if found in input options, uses that. If not found in input options to method,
		falls back to the options specified when the module was initialized. If not found
		in initialization options, uses the default options setting. All keys provided in
		the input options variable are retained.
	*/
	function getRequestOptions (options, query) {
		var requestOptions = JSON.parse(JSON.stringify(defaultRequestOptions));
		if (options.fullListing  &&  options.path) {
			requestOptions.path = options.path
			requestOptions.hostname = options.hostname
			return requestOptions
		}

		// ensure default options are set, even if omitted from input options
		requestOptions.hostname = options.allCities? 'www' + baseHost : (options.city || self.options.city || '') + baseHost;

		// preserve any extraneous input option keys (may have addition instructions for underlying request object)
		Object.keys(options).forEach(function (key) {
			if (
				// key !== 'maxAsk'   &&
				// key !== 'minAsk'   &&
				// key !== 'category' &&
				// key !== 'hasPic'   &&
				// key !== 's'        &&
				typeof requestOptions[key] === 'undefined' &&
				typeof defaultRequestOptions[key] === 'undefined') {
				requestOptions[key] = options[key];
			}
		});

		// set path
		if (options.allCities)
		  requestOptions.path = '/about/sites'
		else if (options.categoriesOnly)
		  requestOptions.path = ''
		else
		  requestOptions.path = '/search/' + (options.category ? options.category : 'sss') + '?sort=rel' +
  		                                     (options.s ? '&s=' + options.s : '') +
		                                     (options.hasPic && (options.hasPic == '1' || options.hasPic == 'true') ? '&hasPic=1' : '') +
		                                     (options.rss ? '&format=rss' : '') +
		                                     (options.query ? '&query=' + encodeURIComponent(options.query) : '');

		// add min and max asking price
		if (typeof options.minAsk !== 'undefined') {
			requestOptions.path += searchMinAsk + options.minAsk;
		}

		if (typeof options.maxAsk !== 'undefined') {
			requestOptions.path += searchMaxAsk + options.maxAsk;
		}

		return requestOptions;
	}

	/*
		options = {
			city : '',
			maxAsk : '',
			minAsk : '',
		}
	*/
	self.search = function (options, query, callback) {
		if (typeof query === 'function' && typeof callback === 'undefined') {
			callback = query;
			query = options;
			options = {};
		}

        // The original set of options will have something like
        //
        //  options = {
		//   city: 'newyork',
		//   category: 'tia',
		//   hasPic: 1,
		//   fullListing: true,
		//   offset: 100,
		//   query: 'concert'
		// }
		//
		// only if particular listing's url is known then we can request the listing's page and description
		//
        var isFullDescriptionRequest = options.fullListing  &&  options.path
		options = getRequestOptions(options, query);

		self.request.get(options, function (err, data) {
			if (err)
			  return callback(err)

   //          if (options.allCities)
   //            return callback(null, getCities(options, data))
   //          if (options.rss)
   //            return callback(null, getRssListings(options, data))
   //          if (isFullDescriptionRequest)
   //            return callback(null, getDescription(options, data))
   //          if (options.categoriesOnly)
   //            return callback(null, getCategories(options, data))

			// return callback(null, getListings(options, data))
            if (options.allCities)
              return callback(null, data)
            if (options.rss)
              return callback(null, data)
            if (isFullDescriptionRequest)
              return callback(null, data)
            if (options.categoriesOnly)
              return callback(null, data))

			return callback(null, getListings(options, data))
		});
	};

	/*
		the module
	*/
	return function (options) {
		options = options || {};

		self.options = options;
		self.request = request.initialize();
		return self;
	};
}({}));

exports = module.exports = initialize;
exports.initialize = initialize;
<|endoftext|>


<commit_before>// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

/* toolbar settings */
wn.provide('erpnext.toolbar');

erpnext.toolbar.setup = function() {
	// modules
	erpnext.toolbar.add_modules();

	// profile
	$('#toolbar-user').append('
My Settings...
');

	$('.navbar .pull-right').append('\

');

	// help
	$('.navbar .pull-right').prepend('
\
		Help\

\

')

	$('#toolbar-help').append('
\
		Documentation
')

	$('#toolbar-help').append('
\
		Forum
')

	$('#toolbar-help').append('
\
		Live Chat (Office Hours)
')

	erpnext.toolbar.set_new_comments();
}

erpnext.toolbar.add_modules = function() {
	$('
\
		Modules\

\

\

').prependTo('.navbar .nav:first');

	// if no modules list then show all
	if(wn.boot.modules_list && typeof(wn.boot.modules_list) == 'string') {
		wn.boot.modules_list = JSON.parse(wn.boot.modules_list);
	}
	else
		wn.boot.modules_list = keys(wn.modules).sort();

	// add to dropdown
	for(var i in wn.boot.modules_list) {
		var m = wn.boot.modules_list[i]

		if(m!='Setup' && wn.boot.profile.allow_modules.indexOf(m)!=-1) {
			args = {
				module: m,
				module_page: wn.modules[m].link,
				module_label: wn.modules[m].label || m
			}

			$('.navbar .modules').append(repl('
%(module_label)s
', args));
		}
	}

	// setup for system manager
	if(user_roles.indexOf("System Manager")!=-1) {
		$('.navbar .modules').append('

\

Setup
');
	}

}

erpnext.toolbar.set_new_comments = function(new_comments) {
	var navbar_nc = $('.navbar-new-comments');
	if(cint(new_comments)) {
		navbar_nc.addClass('navbar-new-comments-true')
		navbar_nc.text(new_comments);
	} else {
		navbar_nc.removeClass('navbar-new-comments-true');
		navbar_nc.text(0);
	}
}

<commit_msg>fix in module addition in toolbar<commit_after>// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

/* toolbar settings */
wn.provide('erpnext.toolbar');

erpnext.toolbar.setup = function() {
	// modules
	erpnext.toolbar.add_modules();

	// profile
	$('#toolbar-user').append('
My Settings...
');

	$('.navbar .pull-right').append('\

');

	// help
	$('.navbar .pull-right').prepend('
\
		Help\

\

')

	$('#toolbar-help').append('
\
		Documentation
')

	$('#toolbar-help').append('
\
		Forum
')

	$('#toolbar-help').append('
\
		Live Chat (Office Hours)
')

	erpnext.toolbar.set_new_comments();
}

erpnext.toolbar.add_modules = function() {
	$('
\
		Modules\

\

\

').prependTo('.navbar .nav:first');

	// if no modules list then show all
	if(wn.boot.modules_list && typeof(wn.boot.modules_list) == 'string') {
		wn.boot.modules_list = JSON.parse(wn.boot.modules_list);
	}
	else
		wn.boot.modules_list = keys(wn.modules).sort();

	// add to dropdown
	for(var i in wn.boot.modules_list) {
		var m = wn.boot.modules_list[i]

		if(m!='Setup' && wn.boot.profile.allow_modules.indexOf(m)!=-1 && wn.modules[m]) {
			args = {
				module: m,
				module_page: wn.modules[m].link,
				module_label: wn.modules[m].label || m
			}

			$('.navbar .modules').append(repl('
%(module_label)s
', args));
		}
	}

	// setup for system manager
	if(user_roles.indexOf("System Manager")!=-1) {
		$('.navbar .modules').append('

\

Setup
');
	}

}

erpnext.toolbar.set_new_comments = function(new_comments) {
	var navbar_nc = $('.navbar-new-comments');
	if(cint(new_comments)) {
		navbar_nc.addClass('navbar-new-comments-true')
		navbar_nc.text(new_comments);
	} else {
		navbar_nc.removeClass('navbar-new-comments-true');
		navbar_nc.text(0);
	}
}

<|endoftext|>


<commit_before>let micro = require('micro'),
  urlencodedBodyParser = require('urlencoded-body-parser'),
  url = require('url'),
  qs = require('querystring'),
  serve = require('./serve');

/**
 * Handles the mix of single and array of middlewares
 * @method parseMiddlewares
 * @param  {Function|Array}         middlewares     // Middleware or array of middlewares
 * @param  {Array}                  [array=[]]      // The array to store the final list of middlewares
 * @return {Array}                                  // The final list of middlewares
 */
let parseMiddlewares = (middlewares, array = []) => {
  if (typeof middlewares === 'function') {
    array.push(middlewares);
    return array;
  }

  let i = 0,
    l = middlewares.length;
  for (; i < l; i++) {
    if (Array.isArray(middlewares[i])) {
      parseMiddlewares(middlewares[i], array);
      continue;
    }

    array.push(middlewares[i]);
  }
  return array;
};

/**
 * Adds a path to a router
 * @method addPath
 * @param  {Router} router              The router in which to add the path
 * @param  {String} method              The method that will handle this path
 * @param  {Array} args                The mixed params (String|Function|Array)
 * @returns {Object} router
 */
let addPath = (router, method, args) => {
  let path, middlewares;

  // Get the first argument
  if (typeof args[0] === 'string') {
    path = args.shift();
  }

  // Handle subrouters
  // If the seccond argument is a function and has paths
  // and regexpList properties then
  // Treat it as a subrouter
  if (
    typeof args[0] === 'function' &&
    args[0].paths !== undefined &&
    args[0].regexpList !== undefined
  ) {
    let subrouter = args.shift(),
      i = 0,
      l = subrouter.paths.length;

    // For each path of the subrouter
    for (; i < l; i++) {
      let submiddlewares = subrouter.paths[i].middlewares;
      let subpath = subrouter.paths[i].path;

      // If there is a path add it as prefix to the subpath
      if (path !== undefined) {
        subpath = path + (subpath || '*');
      }

      // If there are a subpath set it as the first element
      // on the submiddlewares array
      if (subpath !== undefined) {
        submiddlewares.unshift(subpath);
      }

      // Add the path to the router
      router = addPath(router, subrouter.paths[i].method, submiddlewares);
    }
  }

  // Parse middlwares to handle mixed arrays of middlwares and sequenced middlwares
  middlewares = parseMiddlewares(args);

  // Add the path only if there are middlewares passed
  if (middlewares.length > 0) {
    // If the path wasn't set before, set the regexp and params list
    if (path !== undefined && router.regexpList[path] === undefined) {
      // Remove the last slash
      path = path.replace(/\/(\?.*)?$/gi, '$1');

      // Find the params like express params
      let params = path.match(/:(\w+)?/gi) || [];

      // Set the names of the params found
      for (let i in params) {
        params[i] = params[i].replace(':', '');
      }

      let regexpPath = path
        // Catch params
        .replace(/:(\w+)/gi, '([^\\s\\/|\\?]+)')
        // To set to any url with the path as prefix
        .replace(/\*/g, '.*')
        // Remove the last slash
        .replace(/\/(\?.*)?$/gi, '$1');

      // Set the object to the path
      router.regexpList[path] = {
        regexp: new RegExp('^' + regexpPath + '/?(\\?.*)?$', 'gi'),
        params: params
      };
    }

    // Add the path to the paths list
    router.paths.push({
      method: method,
      path: path,
      middlewares: middlewares
    });
  }

  return router;
};

/**
 * Parses the body according with its content-type
 * @method parseBody
 * @param  {Request}    req // The request object
 * @param  {Object}     opt // Additional options to parse the body
 * @return {Void} void
 */
let parseBody = async (req, opt) => {
  /**
   * Set the params property to an empty object
   * @type {Object}
   */
  req.params = req.params || {};

  /**
   * Set the body property to undefined
   * @type {Undefined}
   */
  req.body = undefined;

  /**
   * Set the query object
   * The object returned by the querystring.parse() method does not prototypically inherit from the JavaScript Object.
   * So we create a new object and merge its properties
   * @type {Object}
   */
  req.query = Object.assign({}, qs.parse(url.parse(req.url).query));

  /**
   * If the method is other than get try to parse the body
   * @method if
   * @param  {Request} req
   */
  if (req.method.toLowerCase() !== 'get' && opt.parseBody) {
    let type = req.headers['content-type'],
      parsed = false,
      options = {
        limit: opt.limit,
        encoding: opt.encoding
      };

    try {
      if (type === 'application/json') {
        parsed = true;
        req.body = await micro.json(req, options);
      }

      if (type === 'application/x-www-form-urlencoded' && !parsed) {
        parsed = true;
        req.body = await urlencodedBodyParser(req, options);
      }

      if (/^text/gi.test(type) && !parsed) {
        parsed = true;
        req.body = await micro.text(req, options);
      }
    } catch (e) {}
  }
};

let getMiddlewaresAndParams = (Router, req) => {
  let method = req.method.toLowerCase(),
    params = {},
    middlewares = [],
    i = 0,
    l = Router.paths.length;

  for (; i < l; i++) {
    let path = Router.paths[i];
    if (method !== path.method && path.method !== 'use') {
      continue;
    }

    if (
      (path.method === 'use' || method === path.method) &&
      path.path === undefined
    ) {
      middlewares = parseMiddlewares(path.middlewares, middlewares);
      continue;
    }

    let matches = Router.regexpList[path.path].regexp.exec(req.url);
    Router.regexpList[path.path].regexp.lastIndex = -1;
    if (Array.isArray(matches)) {
      matches.shift();
      let l = Router.regexpList[path.path].params.length;
      while (l--) {
        if (params[Router.regexpList[path.path].params[l]] === undefined) {
          params[Router.regexpList[path.path].params[l]] = matches[l];
        }
      }
      middlewares = parseMiddlewares(path.middlewares, middlewares);
    }
  }

  return { middlewares, params };
};

let RouterFactory = (options = {}) => {
  let opt = Object.assign(
    {},
    {
      parseBody: true, // Tells the router to parse the body by default
      // How much data is aggregated before parsing at max. It can be a Number of bytes or a string like '1mb'.
      limit: '1mb',
      encoding: 'utf8',
      acceptedMethods: [
        'get',
        'post',
        'put',
        'patch',
        'delete',
        'head',
        'options',
        'use'
      ] // The methods that will be handled by the router
    },
    options
  );

  /**
   * new Rotuer
   * @param  {Request}    req     NodeJs Request object
   * @param  {Response}   res     NodeJs Response object
   * @return {Function}           The async function to be passed to micro
   */
  let Router = async function (req, res) {
    let method = req.method.toLowerCase(),
      response,
      i = 0,
      l = Router.paths.length;

    let { middlewares, params } = getMiddlewaresAndParams(Router, req);

    if (middlewares.length > 0) {
      await parseBody(req, opt);
      req.params = params;

      let i = 0,
        l = middlewares.length;
      // call sequentially every middleware
      for (; i < l; i++) {
        response = await middlewares[i](req, res);
        // If there is a response or a response was sent to the client
        // break the for block
        if (response !== undefined || res.headersSent) {
          break;
        }
      }

      // If there is a response and no other response was sent to the client
      // return the response
      if (response !== undefined && !res.headersSent) {
        return response;
      }
    }

    // If no response was sent to the client throw an error
    if (!res.headersSent) {
      throw new Error(
        `The url ${req.url} requested by ${method}, wasn't found`
      );
    }
  };

  /**
   * Where to store the paths and its middlewares
   * @type {Object}
   */
  Router.paths = [];

  /**
   * Where to store the regexp and params list for the paths
   * @type {[type]}
   */
  Router.regexpList = {};

  /**
   * For each accepted method, add the method to the router
   * @type {Array}
   */
  opt.acceptedMethods.map((method) => {
    Router[method] = (...args) => addPath(Router, method, args);
  });

  /**
   * Return the new router
   * @type {Router}
   */
  return Router;
};

RouterFactory.serveDir = serve.serveDir;
RouterFactory.serveFile = serve.serveFile;
RouterFactory.render = serve.render;

module.exports = RouterFactory;
<commit_msg>Update content-type check of parseBody function<commit_after>let micro = require('micro'),
  urlencodedBodyParser = require('urlencoded-body-parser'),
  url = require('url'),
  qs = require('querystring'),
  serve = require('./serve');

/**
 * Handles the mix of single and array of middlewares
 * @method parseMiddlewares
 * @param  {Function|Array}         middlewares     // Middleware or array of middlewares
 * @param  {Array}                  [array=[]]      // The array to store the final list of middlewares
 * @return {Array}                                  // The final list of middlewares
 */
let parseMiddlewares = (middlewares, array = []) => {
  if (typeof middlewares === 'function') {
    array.push(middlewares);
    return array;
  }

  let i = 0,
    l = middlewares.length;
  for (; i < l; i++) {
    if (Array.isArray(middlewares[i])) {
      parseMiddlewares(middlewares[i], array);
      continue;
    }

    array.push(middlewares[i]);
  }
  return array;
};

/**
 * Adds a path to a router
 * @method addPath
 * @param  {Router} router              The router in which to add the path
 * @param  {String} method              The method that will handle this path
 * @param  {Array} args                The mixed params (String|Function|Array)
 * @returns {Object} router
 */
let addPath = (router, method, args) => {
  let path, middlewares;

  // Get the first argument
  if (typeof args[0] === 'string') {
    path = args.shift();
  }

  // Handle subrouters
  // If the seccond argument is a function and has paths
  // and regexpList properties then
  // Treat it as a subrouter
  if (
    typeof args[0] === 'function' &&
    args[0].paths !== undefined &&
    args[0].regexpList !== undefined
  ) {
    let subrouter = args.shift(),
      i = 0,
      l = subrouter.paths.length;

    // For each path of the subrouter
    for (; i < l; i++) {
      let submiddlewares = subrouter.paths[i].middlewares;
      let subpath = subrouter.paths[i].path;

      // If there is a path add it as prefix to the subpath
      if (path !== undefined) {
        subpath = path + (subpath || '*');
      }

      // If there are a subpath set it as the first element
      // on the submiddlewares array
      if (subpath !== undefined) {
        submiddlewares.unshift(subpath);
      }

      // Add the path to the router
      router = addPath(router, subrouter.paths[i].method, submiddlewares);
    }
  }

  // Parse middlwares to handle mixed arrays of middlwares and sequenced middlwares
  middlewares = parseMiddlewares(args);

  // Add the path only if there are middlewares passed
  if (middlewares.length > 0) {
    // If the path wasn't set before, set the regexp and params list
    if (path !== undefined && router.regexpList[path] === undefined) {
      // Remove the last slash
      path = path.replace(/\/(\?.*)?$/gi, '$1');

      // Find the params like express params
      let params = path.match(/:(\w+)?/gi) || [];

      // Set the names of the params found
      for (let i in params) {
        params[i] = params[i].replace(':', '');
      }

      let regexpPath = path
        // Catch params
        .replace(/:(\w+)/gi, '([^\\s\\/|\\?]+)')
        // To set to any url with the path as prefix
        .replace(/\*/g, '.*')
        // Remove the last slash
        .replace(/\/(\?.*)?$/gi, '$1');

      // Set the object to the path
      router.regexpList[path] = {
        regexp: new RegExp('^' + regexpPath + '/?(\\?.*)?$', 'gi'),
        params: params
      };
    }

    // Add the path to the paths list
    router.paths.push({
      method: method,
      path: path,
      middlewares: middlewares
    });
  }

  return router;
};

/**
 * Parses the body according with its content-type
 * @method parseBody
 * @param  {Request}    req // The request object
 * @param  {Object}     opt // Additional options to parse the body
 * @return {Void} void
 */
let parseBody = async (req, opt) => {
  /**
   * Set the params property to an empty object
   * @type {Object}
   */
  req.params = req.params || {};

  /**
   * Set the body property to undefined
   * @type {Undefined}
   */
  req.body = undefined;

  /**
   * Set the query object
   * The object returned by the querystring.parse() method does not prototypically inherit from the JavaScript Object.
   * So we create a new object and merge its properties
   * @type {Object}
   */
  req.query = Object.assign({}, qs.parse(url.parse(req.url).query));

  /**
   * If the method is other than get try to parse the body
   * @method if
   * @param  {Request} req
   */
  if (req.method.toLowerCase() !== 'get' && opt.parseBody) {
    let type = req.headers['content-type'],
      parsed = false,
      options = {
        limit: opt.limit,
        encoding: opt.encoding
      };

    try {
      if (type.includes('application/json')) {
        parsed = true;
        req.body = await micro.json(req, options);
      }

      if (type.includes('application/x-www-form-urlencoded') && !parsed) {
        parsed = true;
        req.body = await urlencodedBodyParser(req, options);
      }

      if (/^text/gi.test(type) && !parsed) {
        parsed = true;
        req.body = await micro.text(req, options);
      }
    } catch (e) {}
  }
};

let getMiddlewaresAndParams = (Router, req) => {
  let method = req.method.toLowerCase(),
    params = {},
    middlewares = [],
    i = 0,
    l = Router.paths.length;

  for (; i < l; i++) {
    let path = Router.paths[i];
    if (method !== path.method && path.method !== 'use') {
      continue;
    }

    if (
      (path.method === 'use' || method === path.method) &&
      path.path === undefined
    ) {
      middlewares = parseMiddlewares(path.middlewares, middlewares);
      continue;
    }

    let matches = Router.regexpList[path.path].regexp.exec(req.url);
    Router.regexpList[path.path].regexp.lastIndex = -1;
    if (Array.isArray(matches)) {
      matches.shift();
      let l = Router.regexpList[path.path].params.length;
      while (l--) {
        if (params[Router.regexpList[path.path].params[l]] === undefined) {
          params[Router.regexpList[path.path].params[l]] = matches[l];
        }
      }
      middlewares = parseMiddlewares(path.middlewares, middlewares);
    }
  }

  return { middlewares, params };
};

let RouterFactory = (options = {}) => {
  let opt = Object.assign(
    {},
    {
      parseBody: true, // Tells the router to parse the body by default
      // How much data is aggregated before parsing at max. It can be a Number of bytes or a string like '1mb'.
      limit: '1mb',
      encoding: 'utf8',
      acceptedMethods: [
        'get',
        'post',
        'put',
        'patch',
        'delete',
        'head',
        'options',
        'use'
      ] // The methods that will be handled by the router
    },
    options
  );

  /**
   * new Rotuer
   * @param  {Request}    req     NodeJs Request object
   * @param  {Response}   res     NodeJs Response object
   * @return {Function}           The async function to be passed to micro
   */
  let Router = async function (req, res) {
    let method = req.method.toLowerCase(),
      response,
      i = 0,
      l = Router.paths.length;

    let { middlewares, params } = getMiddlewaresAndParams(Router, req);

    if (middlewares.length > 0) {
      await parseBody(req, opt);
      req.params = params;

      let i = 0,
        l = middlewares.length;
      // call sequentially every middleware
      for (; i < l; i++) {
        response = await middlewares[i](req, res);
        // If there is a response or a response was sent to the client
        // break the for block
        if (response !== undefined || res.headersSent) {
          break;
        }
      }

      // If there is a response and no other response was sent to the client
      // return the response
      if (response !== undefined && !res.headersSent) {
        return response;
      }
    }

    // If no response was sent to the client throw an error
    if (!res.headersSent) {
      throw new Error(
        `The url ${req.url} requested by ${method}, wasn't found`
      );
    }
  };

  /**
   * Where to store the paths and its middlewares
   * @type {Object}
   */
  Router.paths = [];

  /**
   * Where to store the regexp and params list for the paths
   * @type {[type]}
   */
  Router.regexpList = {};

  /**
   * For each accepted method, add the method to the router
   * @type {Array}
   */
  opt.acceptedMethods.map((method) => {
    Router[method] = (...args) => addPath(Router, method, args);
  });

  /**
   * Return the new router
   * @type {Router}
   */
  return Router;
};

RouterFactory.serveDir = serve.serveDir;
RouterFactory.serveFile = serve.serveFile;
RouterFactory.render = serve.render;

module.exports = RouterFactory;
<|endoftext|>


<commit_before>
/**
 * Defines Mocha test cases for each given parameter.
 * @param {(string|function)} testName - A prefix of each test case name.
 *     When it is a function, its return value is used for each test case name.
 * @param {Array} parameters - An array of values. Each of this
 *     will be passed to testBody function.
 * @param {function} testBody - A function which contains test code.
 * @param {function} it - The 'it' function used in this function.
 *     This is mainly used in unit tests.
 */
export default function itEach(
  testName, parameters, testBody, it = global.it
) {
  if (typeof it !== 'function') {
    throw new Error('itEach: Mocha is not found');
  }

  // When the testName is omitted.
  if (typeof parameters === 'function') {
    it = testBody || it;
    testBody = parameters;
    parameters = testName;
    testName = `handles`;
  }

  const makeTestName = (typeof testName === 'function')
    ? testName
    : param => `${testName} ${JSON.stringify(param)}`;

  parameters.forEach(param => {
    const args = Array.isArray(param) ? param : [param];
    it(makeTestName(...args), () => testBody(...args));
  });
}

<commit_msg>:bug: Normalize arguments first<commit_after>
/**
 * Defines Mocha test cases for each given parameter.
 * @param {(string|function)} testName - A prefix of each test case name.
 *     When it is a function, its return value is used for each test case name.
 * @param {Array} parameters - An array of values. Each of this
 *     will be passed to testBody function.
 * @param {function} testBody - A function which contains test code.
 * @param {function} it - The 'it' function used in this function.
 *     This is mainly used in unit tests.
 */
export default function itEach(
  testName, parameters, testBody, it = global.it
) {
  // When the testName is omitted.
  if (typeof parameters === 'function') {
    it = testBody || it;
    testBody = parameters;
    parameters = testName;
    testName = `handles`;
  }

  if (typeof it !== 'function') {
    throw new Error('itEach: Mocha is not found');
  }

  const makeTestName = (typeof testName === 'function')
    ? testName
    : param => `${testName} ${JSON.stringify(param)}`;

  parameters.forEach(param => {
    const args = Array.isArray(param) ? param : [param];
    it(makeTestName(...args), () => testBody(...args));
  });
}

<|endoftext|>


<commit_before>'use strict';

// MODULES //

var isPositiveInteger = require( 'validate.io-positive-integer' );

// INCREMENTAL MOVING SUM //

/**
* FUNCTION: incrmsum( W )
*	Returns a method to compute a moving sum incrementally.
*
* @param {Number} W - window size
* @returns {Function} method to compute a moving sum incrementally
*/
function incrmsum( W ) {
	if ( !isPositiveInteger( W ) ) {
		throw new TypeError( 'incrmsum()::invalid input argument. Window size must be a positive integer.' );
	}
	var arr = new Array( W ),
		sum = 0,
		N = 0,
		i = -1,
		tmp;
	/**
	* FUNCTION: incrmsum( [value] )
	*	If a `value` is provided, updates and returns the updated sum. If no `value` is provided, returns the current sum.
	*
	* @param {Number} [value] - value used to update the moving sum
	* @returns {Number} sum
	*/
	return function incrmsum( x ) {
		if ( !arguments.length ) {
			if ( N === 0 ) {
				return null;
			}
			return sum;
		}
		// Update the index for managing the circular buffer...
		i = (i+1) % W;

		// Fill up the initial window; else, update the existing window...
		if ( N < W ) {
			arr[ i ] = x;
			N += 1;
			sum += x;
		} else {
			tmp = arr[ i ];
			arr[ i ] = x;
			sum += x - tmp;
		}
		return sum;
	};
} // end FUNCTION incrmsum()

// EXPORTS //

module.exports = incrmsum;
<commit_msg>[UPDATE] error msg<commit_after>'use strict';

// MODULES //

var isPositiveInteger = require( 'validate.io-positive-integer' );

// INCREMENTAL MOVING SUM //

/**
* FUNCTION: incrmsum( W )
*	Returns a method to compute a moving sum incrementally.
*
* @param {Number} W - window size
* @returns {Function} method to compute a moving sum incrementally
*/
function incrmsum( W ) {
	if ( !isPositiveInteger( W ) ) {
		throw new TypeError( 'incrmsum()::invalid input argument. Window size must be a positive integer. Value: `' + W + '`.' );
	}
	var arr = new Array( W ),
		sum = 0,
		N = 0,
		i = -1,
		tmp;
	/**
	* FUNCTION: incrmsum( [value] )
	*	If a `value` is provided, updates and returns the updated sum. If no `value` is provided, returns the current sum.
	*
	* @param {Number} [value] - value used to update the moving sum
	* @returns {Number} sum
	*/
	return function incrmsum( x ) {
		if ( !arguments.length ) {
			if ( N === 0 ) {
				return null;
			}
			return sum;
		}
		// Update the index for managing the circular buffer...
		i = (i+1) % W;

		// Fill up the initial window; else, update the existing window...
		if ( N < W ) {
			arr[ i ] = x;
			N += 1;
			sum += x;
		} else {
			tmp = arr[ i ];
			arr[ i ] = x;
			sum += x - tmp;
		}
		return sum;
	};
} // end FUNCTION incrmsum()

// EXPORTS //

module.exports = incrmsum;
<|endoftext|>


<commit_before>"use strict";

class Bundle {
  constructor(name, options, main) {
    Object.defineProperties(this, {
      "isMain": {
        value: !!main,
        writable: false
      }
    });

    options = options || {};
    Object.assign(this, options, { name: name, dest: options.dest === false ? false : (options.dest || name) });
  }

  configure(options) {
    return !options || options === this ? this : new Bundle(this.name, Object.assign({}, this, options), this.isMain);
  }

  clear() {
    return this.configure({ content: null });
  }

  setDest(dest) {
    this.dest = dest;
    return this;
  }

  setName(name) {
    this.name = name;
    return this;
  }

  setContent(content) {
    this.content = content;
    return this;
  }

  setEntries(entires) {
    this.entries = entires;
    return this;
  }

  setModules(modules) {
    this.modules = modules;
    return this;
  }
}

module.exports = Bundle;
<commit_msg>Adding logic to be a lil bit smarter about determining if the name of a bundle can be used as the destination of the bundle<commit_after>"use strict";

class Bundle {
  constructor(name, options, main) {
    Object.defineProperties(this, {
      "isMain": {
        value: !!main,
        writable: false
      }
    });

    options = options || {};
    var dest = options.dest;

    // Try to see if we need to use the bundle as the dest. This
    // helps simplify the syntax for creating bundles.
    if (!dest) {
      dest = dest !== false && looksLikeFileName(name) ? name : false;
    }

    Object.assign(this, options, { name: name, dest: dest });
  }

  configure(options) {
    return !options || options === this ? this : new Bundle(this.name, Object.assign({}, this, options), this.isMain);
  }

  clear() {
    return this.configure({ content: null });
  }

  setDest(dest) {
    this.dest = dest;
    return this;
  }

  setName(name) {
    this.name = name;
    return this;
  }

  setContent(content) {
    this.content = content;
    return this;
  }

  setEntries(entires) {
    this.entries = entires;
    return this;
  }

  setModules(modules) {
    this.modules = modules;
    return this;
  }
}

function looksLikeFileName(name) {
  return /[\w]+[\.][\w]+$/.test(name);
}

module.exports = Bundle;
<|endoftext|>


<commit_before>// import necessary libraries
const acorn = require('acorn/dist/acorn');
const acorn_loose = require('acorn/dist/acorn_loose');
const aux = require('./aux');
import * as types from './domains/types'
import * as context from './domains/context'
// const status = require('./domains/status');
import * as status from './domains/status'
import * as varBlock from './varBlock'
const cGen = require('./constraint/cGen');
const varRefs = require('./varrefs');
const retOccur = require('./retOccur');
const thisOccur = require('./thisOccur');
import * as myWalker from './util/myWalker'
import * as getTypeData from './getTypeData'
import * as defaultOption from '../defaultOption'

function analyze(input, retAll, option) {
    // the Scope object for global scope
    // scope.Scope.globalScope = new scope.Scope(null);

    if (option === undefined) {
        // if no option is given, use the default option
        option = defaultOption.options;
    }
    // parsing input program
    var ast;
    try {
        ast = acorn.parse(input, option.acornOption);
    } catch (e) {
        ast = acorn_loose.parse_dammit(input, option.acornOption);
    }

    var nodeArrayIndexedByList = aux.getNodeList(ast);

    // Show AST before scope resolution
    // aux.showUnfolded(ast);

    var gVarBlock = new varBlock.VarBlock(
        null,
        ast,
        varBlock.VarBlock.blockTypes.globalBlock,
        // 'use strict' directive is checked in annotateBlockInfo.
        option.acornOption.sourceType === 'module'
    );

    varBlock.annotateBlockInfo(ast, gVarBlock);

    // Setting up the sensitivity parameter
    // It is possible to compute the parameter by examining the code.
    context.changeSensitivityParameter(option.sensitivityParameter);

    var gBlock = ast['@block'];
    var initialContext = context.CallSiteContext.epsilonContext;
    var gScope = gBlock.getScopeInstance(null, initialContext);
    var gObject = types.mkObjFromGlobalScope(gScope);
    var initStatus = new status.Status(
        gObject,
        types.AValNull,
        types.AValNull,
        initialContext,
        gScope);
    // the prototype object of Object
    var ObjProto = new types.ObjType(null, 'Object.prototype');
    var rtCX = {
        globalObject: gObject,
        // temporal
        protos: {
            Object: ObjProto,
            Function: new types.ObjType(new types.AVal(ObjProto), 'Function.prototype'),
            Array: new types.ObjType(new types.AVal(ObjProto), 'Array.prototype'),
            RegExp: new types.ObjType(new types.AVal(ObjProto), 'RegExp.prototype'),
            String: new types.ObjType(new types.AVal(ObjProto), 'String.prototype'),
            Number: new types.ObjType(new types.AVal(ObjProto), 'Number.prototype'),
            Boolean: new types.ObjType(new types.AVal(ObjProto), 'Boolean.prototype')
        },
        Ĉ: new types.AbsCache(),
        option: option
    };
    cGen.addConstraints(ast, initStatus, rtCX);
    //aux.showUnfolded(gBlockAndAnnotatedAST.ast);
    // aux.showUnfolded(constraints);
    // aux.showUnfolded(gBlock);
    // console.log(util.inspect(gBlock, {depth: 10}));
    if (retAll) {
        return {
            gObject: gObject,
            AST: ast,
            gBlock: gBlock,
            gScope: gScope,
            Ĉ: rtCX.Ĉ
        };
    } else {
        return gObject;
    }
}

exports.analyze = analyze;
exports.findIdentifierAt = myWalker.findIdentifierAt;
exports.findVarRefsAt = varRefs.findVarRefsAt;
exports.onEscapingStatement = retOccur.onEscapingStatement;
exports.findEscapingStatements = retOccur.findEscapingStatements;
exports.onThisKeyword = thisOccur.onThisKeyword;
exports.findThisExpressions = thisOccur.findThisExpressions;
exports.findSurroundingNode = myWalker.findSurroundingNode;
exports.findMemberOrVariableAt = myWalker.findMemberOrVariableAt;
exports.getTypeData = getTypeData.getTypeAtRange;
exports.getCompletionAtPos = getTypeData.getCompletionAtPos;
exports.getFnTypeStructuresAt = getTypeData.getFnTypeStructuresAt;
exports.getDefinitionSitesAt = getTypeData.getDefinitionSitesAt;
<commit_msg>[BUGFIX] Should be AVal instead of Type<commit_after>// import necessary libraries
const acorn = require('acorn/dist/acorn');
const acorn_loose = require('acorn/dist/acorn_loose');
const aux = require('./aux');
import * as types from './domains/types'
import * as context from './domains/context'
// const status = require('./domains/status');
import * as status from './domains/status'
import * as varBlock from './varBlock'
const cGen = require('./constraint/cGen');
const varRefs = require('./varrefs');
const retOccur = require('./retOccur');
const thisOccur = require('./thisOccur');
import * as myWalker from './util/myWalker'
import * as getTypeData from './getTypeData'
import * as defaultOption from '../defaultOption'

function analyze(input, retAll, option) {
    // the Scope object for global scope
    // scope.Scope.globalScope = new scope.Scope(null);

    if (option === undefined) {
        // if no option is given, use the default option
        option = defaultOption.options;
    }
    // parsing input program
    var ast;
    try {
        ast = acorn.parse(input, option.acornOption);
    } catch (e) {
        ast = acorn_loose.parse_dammit(input, option.acornOption);
    }

    var nodeArrayIndexedByList = aux.getNodeList(ast);

    // Show AST before scope resolution
    // aux.showUnfolded(ast);

    var gVarBlock = new varBlock.VarBlock(
        null,
        ast,
        varBlock.VarBlock.blockTypes.globalBlock,
        // 'use strict' directive is checked in annotateBlockInfo.
        option.acornOption.sourceType === 'module'
    );

    varBlock.annotateBlockInfo(ast, gVarBlock);

    // Setting up the sensitivity parameter
    // It is possible to compute the parameter by examining the code.
    context.changeSensitivityParameter(option.sensitivityParameter);

    var gBlock = ast['@block'];
    var initialContext = context.CallSiteContext.epsilonContext;
    var gScope = gBlock.getScopeInstance(null, initialContext);
    var gObject = types.mkObjFromGlobalScope(gScope);
    var initStatus = new status.Status(
        new types.AVal(gObject),
        types.AValNull,
        types.AValNull,
        initialContext,
        gScope);
    // the prototype object of Object
    var ObjProto = new types.ObjType(null, 'Object.prototype');
    var rtCX = {
        globalObject: gObject,
        // temporal
        protos: {
            Object: ObjProto,
            Function: new types.ObjType(new types.AVal(ObjProto), 'Function.prototype'),
            Array: new types.ObjType(new types.AVal(ObjProto), 'Array.prototype'),
            RegExp: new types.ObjType(new types.AVal(ObjProto), 'RegExp.prototype'),
            String: new types.ObjType(new types.AVal(ObjProto), 'String.prototype'),
            Number: new types.ObjType(new types.AVal(ObjProto), 'Number.prototype'),
            Boolean: new types.ObjType(new types.AVal(ObjProto), 'Boolean.prototype')
        },
        Ĉ: new types.AbsCache(),
        option: option
    };
    cGen.addConstraints(ast, initStatus, rtCX);
    //aux.showUnfolded(gBlockAndAnnotatedAST.ast);
    // aux.showUnfolded(constraints);
    // aux.showUnfolded(gBlock);
    // console.log(util.inspect(gBlock, {depth: 10}));
    if (retAll) {
        return {
            gObject: gObject,
            AST: ast,
            gBlock: gBlock,
            gScope: gScope,
            Ĉ: rtCX.Ĉ
        };
    } else {
        return gObject;
    }
}

exports.analyze = analyze;
exports.findIdentifierAt = myWalker.findIdentifierAt;
exports.findVarRefsAt = varRefs.findVarRefsAt;
exports.onEscapingStatement = retOccur.onEscapingStatement;
exports.findEscapingStatements = retOccur.findEscapingStatements;
exports.onThisKeyword = thisOccur.onThisKeyword;
exports.findThisExpressions = thisOccur.findThisExpressions;
exports.findSurroundingNode = myWalker.findSurroundingNode;
exports.findMemberOrVariableAt = myWalker.findMemberOrVariableAt;
exports.getTypeData = getTypeData.getTypeAtRange;
exports.getCompletionAtPos = getTypeData.getCompletionAtPos;
exports.getFnTypeStructuresAt = getTypeData.getFnTypeStructuresAt;
exports.getDefinitionSitesAt = getTypeData.getDefinitionSitesAt;
<|endoftext|>