<commit_before>var path = require('path');
var fs = require('fs-extra');
var exec = require('child_process').exec;
var runSeries = require('run-series');

var common = require('./util/common');
var constants = require('./util/constants');
var pkg = require('../package.json');

var packagesSpecs = constants.partialBundlePaths
    .map(function(d) {
        return {
            name: 'plotly.js-' + d.name + '-dist',
            index: d.index,
            main: 'plotly-' + d.name + '.js',
            dist: d.dist,
            desc: 'Ready-to-use plotly.js ' + d.name + ' distributed bundle.',
        };
    })
    .concat([{
        name: 'plotly.js-dist',
        index: path.join(constants.pathToLib, 'index.js'),
        main: 'plotly.js',
        dist: constants.pathToPlotlyDist,
        desc: 'Ready-to-use plotly.js distributed bundle.',
    }]);

packagesSpecs.forEach(function(d) {
    var pkgPath = path.join(constants.pathToBuild, d.name);

    function initDirectory(cb) {
        if(common.doesDirExist(pkgPath)) {
            cb();
        } else {
            fs.mkdir(pkgPath, cb);
        }
    }

    function writePackageJSON(cb) {
        var cnt = {
            name: d.name,
            version: pkg.version,
            description: d.desc,
            license: pkg.license,
            main: d.main,
            repository: pkg.repository,
            bugs: pkg.bugs,
            author: pkg.author,
            keywords: pkg.keywords
        };

        fs.writeFile(
            path.join(pkgPath, 'package.json'),
            JSON.stringify(cnt, null, 2) + '\n',
            cb
        );
    }

    function writeREADME(cb) {
        var moduleList = common.findModuleList(d.index);

        var cnt = [
            '# ' + d.name,
            '',
            d.desc,
            '',
            'Contains trace modules ' + common.formatEnumeration(moduleList) + '.',
            '',
            'For more info on plotly.js, go to https://github.com/plotly/plotly.js',
            '',
            '## Installation',
            '',
            '```',
            'npm install ' + d.name,
            '```',
            '## Usage',
            '',
            '```js',
            '// ES6 module',
            'import Plotly from \'' + d.name + '\';',
            '',
            '// CommonJS',
            'var Plotly = require(\'' + d.name + '\');',
            '```',
            '',
            '## Copyright and license',
            '',
            'Code and documentation copyright 2018 Plotly, Inc.',
            '',
            'Code released under the [MIT license](https://github.com/plotly/plotly.js/blob/master/LICENSE).',
            '',
            'Docs released under the [Creative Commons license](https://github.com/plotly/documentation/blob/source/LICENSE).',
            ''
        ];

        fs.writeFile(
            path.join(pkgPath, 'README.md'),
            cnt.join('\n'),
            cb
        );
    }

    function copyMain(cb) {
        fs.copy(d.dist, path.join(pkgPath, d.main), cb);
    }

    function copyLicense(cb) {
        fs.copy(
            path.join(constants.pathToRoot, 'LICENSE'),
            path.join(pkgPath, 'LICENSE'),
            cb
        );
    }

    function publishToNPM(cb) {
        if(process.env.DRYRUN) {
            console.log('dry run, did not publish ' + d.name);
            cb();
            return;
        }
        exec('npm publish', {cwd: pkgPath}, cb).stdout.pipe(process.stdout);
    }

    runSeries([
        initDirectory,
        writePackageJSON,
        writeREADME,
        copyMain,
        copyLicense,
        publishToNPM
    ], function(err) {
        if(err) throw err;
    });
});
<commit_msg>list pkg files (to make sure npm doesn't grab them from repo root)<commit_after>var path = require('path');
var fs = require('fs-extra');
var exec = require('child_process').exec;
var runSeries = require('run-series');

var common = require('./util/common');
var constants = require('./util/constants');
var pkg = require('../package.json');

var packagesSpecs = constants.partialBundlePaths
    .map(function(d) {
        return {
            name: 'plotly.js-' + d.name + '-dist',
            index: d.index,
            main: 'plotly-' + d.name + '.js',
            dist: d.dist,
            desc: 'Ready-to-use plotly.js ' + d.name + ' distributed bundle.',
        };
    })
    .concat([{
        name: 'plotly.js-dist',
        index: path.join(constants.pathToLib, 'index.js'),
        main: 'plotly.js',
        dist: constants.pathToPlotlyDist,
        desc: 'Ready-to-use plotly.js distributed bundle.',
    }]);

packagesSpecs.forEach(function(d) {
    var pkgPath = path.join(constants.pathToBuild, d.name);

    function initDirectory(cb) {
        if(common.doesDirExist(pkgPath)) {
            cb();
        } else {
            fs.mkdir(pkgPath, cb);
        }
    }

    function writePackageJSON(cb) {
        var cnt = {
            name: d.name,
            version: pkg.version,
            description: d.desc,
            license: pkg.license,
            main: d.main,
            repository: pkg.repository,
            bugs: pkg.bugs,
            author: pkg.author,
            keywords: pkg.keywords,
            files: [
                'LICENSE',
                'README.md',
                d.main
            ]
        };

        fs.writeFile(
            path.join(pkgPath, 'package.json'),
            JSON.stringify(cnt, null, 2) + '\n',
            cb
        );
    }

    function writeREADME(cb) {
        var moduleList = common.findModuleList(d.index);

        var cnt = [
            '# ' + d.name,
            '',
            d.desc,
            '',
            'Contains trace modules ' + common.formatEnumeration(moduleList) + '.',
            '',
            'For more info on plotly.js, go to https://github.com/plotly/plotly.js',
            '',
            '## Installation',
            '',
            '```',
            'npm install ' + d.name,
            '```',
            '## Usage',
            '',
            '```js',
            '// ES6 module',
            'import Plotly from \'' + d.name + '\';',
            '',
            '// CommonJS',
            'var Plotly = require(\'' + d.name + '\');',
            '```',
            '',
            '## Copyright and license',
            '',
            'Code and documentation copyright 2018 Plotly, Inc.',
            '',
            'Code released under the [MIT license](https://github.com/plotly/plotly.js/blob/master/LICENSE).',
            '',
            'Docs released under the [Creative Commons license](https://github.com/plotly/documentation/blob/source/LICENSE).',
            ''
        ];

        fs.writeFile(
            path.join(pkgPath, 'README.md'),
            cnt.join('\n'),
            cb
        );
    }

    function copyMain(cb) {
        fs.copy(d.dist, path.join(pkgPath, d.main), cb);
    }

    function copyLicense(cb) {
        fs.copy(
            path.join(constants.pathToRoot, 'LICENSE'),
            path.join(pkgPath, 'LICENSE'),
            cb
        );
    }

    function publishToNPM(cb) {
        if(process.env.DRYRUN) {
            console.log('dry run, did not publish ' + d.name);
            cb();
            return;
        }
        exec('npm publish', {cwd: pkgPath}, cb).stdout.pipe(process.stdout);
    }

    runSeries([
        initDirectory,
        writePackageJSON,
        writeREADME,
        copyMain,
        copyLicense,
        publishToNPM
    ], function(err) {
        if(err) throw err;
    });
});
<|endoftext|>


<commit_before>/*
 * Namespace: lb.core.events.publisher
 * Core Events Publisher
 *
 * The publisher manages a list of subscribers, which get all notified of
 * every event published until they get removed from the list.
 *
 * Authors:
 * o Eric Bréchemier <legalbox@eric.brechemier.name>
 * o Marc Delhommeau <marc.delhommeau@legalbox.com>
 *
 * Copyright:
 * Legal-Box SAS (c) 2010-2011, All Rights Reserved
 *
 * License:
 * BSD License
 * http://creativecommons.org/licenses/BSD/
 *
 * Version:
 * 2011-06-29
 */
/*jslint white:false, plusplus:false */
/*global define */
define(["./lb.core.events","./lb.base.log","./lb.base.array"],
  (function(lbCoreEvents,   logModule,      array) {
    // Builder of
    // Closure for lb.core.events.publisher module

    // Define aliases
    var log = logModule.print,
        copy = array.copy,
        addOne = array.addOne,
        removeOne = array.removeOne,

    // Private members

    // array, the list of subscribers (lb.core.events.Subscriber) subscribed to
    // event notifications
        subscribers = [];

    function getSubscribers(){
      // Function: getSubscribers(): array
      // Get the list of subscribers.
      //
      // Returns:
      //   array, the list of subscribers (<lb.core.events.Subscriber>)

      return subscribers;
    }

    function addSubscriber(subscriber){
      // Function: addSubscriber(subscriber)
      // Add a new subscriber to the list.
      //
      // Parameter:
      //   subscriber - object, the new subscriber (<lb.core.events.Subscriber>)
      //
      // Note:
      // Nothing happens in case the subscriber is already present.

      addOne(subscribers, subscriber);
    }

    function removeSubscriber(subscriber){
      // Function: removeSubscriber(subscriber)
      // Remove an existing subscriber from the list.
      //
      // Parameter:
      //   subscriber - object, the old subscriber (<lb.core.events.Subscriber>)
      //
      // Note:
      // Nothing happens in case the subscriber is not present.

      removeOne(subscribers, subscriber);
    }

    function publish(event){
      // Function: publish(event)
      // Publish an event to be broadcast to all subscribers.
      //
      // Parameter:
      //   event - object, the event object
      //
      // Note:
      //   All subscribers present at the start of the call will get notified.
      //   Adding or removing a subscriber during the publication of an event
      //   will only have effect for subsequent events.

      // take a snapshot of the list of subscribers to avoid running into
      // infinite loops or skipping subscribers in case the list is modified.
      var currentSubscribers = copy(subscribers),
          i;
      for (i=0; i<currentSubscribers.length; i++){
        try {
          currentSubscribers[i].notify(event);
        } catch(e) {
          log('ERROR: Failed to notify subscriber "'+currentSubscribers[i]+
              '", "'+e+'"');
        }
      }
    }

    // Assign to lb.core.events.publisher
    // for backward-compatibility in browser environment
    lbCoreEvents.publisher = { // Facade API
      getSubscribers: getSubscribers,
      addSubscriber: addSubscriber,
      removeSubscriber: removeSubscriber,
      publish: publish
    };
    return lbCoreEvents.publisher;
  }
);
<commit_msg>Removed extra parenthesis<commit_after>/*
 * Namespace: lb.core.events.publisher
 * Core Events Publisher
 *
 * The publisher manages a list of subscribers, which get all notified of
 * every event published until they get removed from the list.
 *
 * Authors:
 * o Eric Bréchemier <legalbox@eric.brechemier.name>
 * o Marc Delhommeau <marc.delhommeau@legalbox.com>
 *
 * Copyright:
 * Legal-Box SAS (c) 2010-2011, All Rights Reserved
 *
 * License:
 * BSD License
 * http://creativecommons.org/licenses/BSD/
 *
 * Version:
 * 2011-07-01
 */
/*jslint white:false, plusplus:false */
/*global define */
define(["./lb.core.events","./lb.base.log","./lb.base.array"],
  function(lbCoreEvents,   logModule,      array) {
    // Builder of
    // Closure for lb.core.events.publisher module

    // Define aliases
    var log = logModule.print,
        copy = array.copy,
        addOne = array.addOne,
        removeOne = array.removeOne,

    // Private members

    // array, the list of subscribers (lb.core.events.Subscriber) subscribed to
    // event notifications
        subscribers = [];

    function getSubscribers(){
      // Function: getSubscribers(): array
      // Get the list of subscribers.
      //
      // Returns:
      //   array, the list of subscribers (<lb.core.events.Subscriber>)

      return subscribers;
    }

    function addSubscriber(subscriber){
      // Function: addSubscriber(subscriber)
      // Add a new subscriber to the list.
      //
      // Parameter:
      //   subscriber - object, the new subscriber (<lb.core.events.Subscriber>)
      //
      // Note:
      // Nothing happens in case the subscriber is already present.

      addOne(subscribers, subscriber);
    }

    function removeSubscriber(subscriber){
      // Function: removeSubscriber(subscriber)
      // Remove an existing subscriber from the list.
      //
      // Parameter:
      //   subscriber - object, the old subscriber (<lb.core.events.Subscriber>)
      //
      // Note:
      // Nothing happens in case the subscriber is not present.

      removeOne(subscribers, subscriber);
    }

    function publish(event){
      // Function: publish(event)
      // Publish an event to be broadcast to all subscribers.
      //
      // Parameter:
      //   event - object, the event object
      //
      // Note:
      //   All subscribers present at the start of the call will get notified.
      //   Adding or removing a subscriber during the publication of an event
      //   will only have effect for subsequent events.

      // take a snapshot of the list of subscribers to avoid running into
      // infinite loops or skipping subscribers in case the list is modified.
      var currentSubscribers = copy(subscribers),
          i;
      for (i=0; i<currentSubscribers.length; i++){
        try {
          currentSubscribers[i].notify(event);
        } catch(e) {
          log('ERROR: Failed to notify subscriber "'+currentSubscribers[i]+
              '", "'+e+'"');
        }
      }
    }

    // Assign to lb.core.events.publisher
    // for backward-compatibility in browser environment
    lbCoreEvents.publisher = { // Facade API
      getSubscribers: getSubscribers,
      addSubscriber: addSubscriber,
      removeSubscriber: removeSubscriber,
      publish: publish
    };
    return lbCoreEvents.publisher;
  }
);
<|endoftext|>


<commit_before>const base = require('./karma.base.conf')
const pack = require('../package.json')

/**
 * Having too many tests running concurrently on saucelabs
 * causes timeouts and errors, so we have to run them in
 * smaller batches.
 */

const batches = [
  // the coolkids
  {
    sl_chrome: {
      base: 'SauceLabs',
      browserName: 'chrome',
      platform: 'Windows 7'
    },
    sl_firefox: {
      base: 'SauceLabs',
      browserName: 'firefox'
    },
    sl_mac_safari: {
      base: 'SauceLabs',
      browserName: 'safari',
      platform: 'OS X 10.10'
    }
  },
  // ie family
  {
    sl_ie_9: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 7',
      version: '9'
    },
    sl_ie_10: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 8',
      version: '10'
    },
    sl_ie_11: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 8.1',
      version: '11'
    }
    /*
    sl_edge: {
      base: 'SauceLabs',
      platform: 'Windows 10',
      browserName: 'microsoftedge'
    }
    */
  },
  // mobile
  {
    sl_ios_safari: {
      base: 'SauceLabs',
      browserName: 'iphone',
      platform: 'OS X 10.9',
      version: '7.1'
    },
    sl_android: {
      base: 'SauceLabs',
      browserName: 'android',
      platform: 'Linux',
      version: '4.2'
    }
  }
]

module.exports = config => {
  const batch = batches[process.argv[5] || 0]

  config.set(Object.assign(base, {
    browsers: Object.keys(batch),
    customLaunchers: batch,
    reporters: ['progress', 'saucelabs'],
    reporters: process.env.CI
      ? ['dots', 'saucelabs'] // avoid spamming CI output
      : ['progress', 'saucelabs'],
    sauceLabs: {
      testName: `${pack.name} unit tests`,
      recordScreenshots: false,
      build: process.env.CIRCLE_BUILD_NUM || process.env.SAUCE_BUILD_ID || Date.now()
    },
    captureTimeout: 300000,
    browserNoActivityTimeout: 300000
  }))
}
<commit_msg>:zap: improvement(sauce): enable microsoft edge<commit_after>const base = require('./karma.base.conf')
const pack = require('../package.json')

/**
 * Having too many tests running concurrently on saucelabs
 * causes timeouts and errors, so we have to run them in
 * smaller batches.
 */

const batches = [
  // the coolkids
  {
    sl_chrome: {
      base: 'SauceLabs',
      browserName: 'chrome',
      platform: 'Windows 7'
    },
    sl_firefox: {
      base: 'SauceLabs',
      browserName: 'firefox'
    },
    sl_mac_safari: {
      base: 'SauceLabs',
      browserName: 'safari',
      platform: 'OS X 10.10'
    }
  },
  // ie family
  {
    sl_ie_9: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 7',
      version: '9'
    },
    sl_ie_10: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 8',
      version: '10'
    },
    sl_ie_11: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 8.1',
      version: '11'
    },
    sl_edge: {
      base: 'SauceLabs',
      platform: 'Windows 10',
      browserName: 'MicrosoftEdge'
    }
  },
  // mobile
  {
    sl_ios_safari: {
      base: 'SauceLabs',
      browserName: 'iphone',
      platform: 'OS X 10.9',
      version: '7.1'
    },
    sl_android: {
      base: 'SauceLabs',
      browserName: 'android',
      platform: 'Linux',
      version: '4.2'
    }
  }
]

module.exports = config => {
  const batch = batches[process.argv[5] || 0]

  config.set(Object.assign(base, {
    singleRun: true,
    browsers: Object.keys(batch),
    customLaunchers: batch,
    reporters: ['progress', 'saucelabs'],
    reporters: process.env.CI
      ? ['dots', 'saucelabs'] // avoid spamming CI output
      : ['progress', 'saucelabs'],
    sauceLabs: {
      testName: `${pack.name} unit tests`,
      recordScreenshots: false,
      build: process.env.CIRCLE_BUILD_NUM || process.env.SAUCE_BUILD_ID || Date.now()
    },
    captureTimeout: 300000,
    browserNoActivityTimeout: 300000
  }))
}
<|endoftext|>


<commit_before>import Promise from 'bluebird';
import fs from 'fs';

export const DEFAULT_TIMEZONE = 'UTC';
export const DEFAULT_FORMAT = 'pdf';
export const POLL_TIME = 5 * 1000;
export const MAX_TRIES = 5;

/**
* Generates Exports object with methods using passed api
*
* @param {object} api Valid api object
* @param {object} logger Logger
* @returns {object} exports Methods to interact with exports on API
*/
export default function Exports(api, logger) {
  return {
    /**
    * Create an export for an audit
    *
    * @param {string} auditId Audit id
    * @param {string} timezone Timezone of export
    * @param {string} export format
    * @returns {Promise} Resolves to successfully created export,
    *                    Rejects with an error from API.
    */
    create({ auditId, timezone = DEFAULT_TIMEZONE, format = DEFAULT_FORMAT, exportProfile }) {
      logger.info(`Creating export for ${auditId} (${timezone}, ${format}, ${exportProfile})`);
      const qs = { format, timezone };
      if (exportProfile) qs.export_profile = exportProfile;
      return api.post(`/audits/${auditId}/export`, { qs });
    },

    /**
    * Find a promise by audit id and id
    *
    * @param {string} auditId Audit id
    * @param {string} id Export id
    * @returns {Promise} Resolves to requested export,
    *                    Rejects with an error from API.
    */
    findById({ auditId, id }) {
      return api.get(`/audits/${auditId}/exports/${id}`).catch((error) => {
        if (error.statusCode === 404) { // Workaround for ARG-2136
          return api.get(`/audits/${auditId}/exports/${id}`);
        }
      });
    },

    /**
    * Get an export (poll until completed)
    *
    * @param {string} auditId Audit id
    * @param {string} id Export id
    * @returns {Promise} Resolves to requested export,
    *                    Rejects with an error from API.
    */
    get({ auditId, id, poll = POLL_TIME, tries = MAX_TRIES }) {
      let attempts = 1;

      let attempt = () => {
        return this.findById({ auditId, id }).then((response) => {
          if (response.status === 'FAILED') return Promise.reject(response.error);
          if (response.status === 'SUCCESS') return response;
          if (response.status === 'IN PROGRESS' && attempts < tries) {
            return Promise.delay(poll).then(() => {
              attempts += 1;
              return attempt();
            });
          }
          return Promise.reject(new Error(`Request to get export timed out after ${attempts} attempts.`));
        }).catch((error) => Promise.reject(error));
      };

      return attempt();
    },

    /**
     * extract and decode a filename from the end of a URI
     * @param   {string} uri a uri with a filename
     * @returns {string}     a decoded filename
     */
    filenameFromURI(uri) {
      return decodeURIComponent(uri.match(/\/([^/]+)$/)[1]);
    },

    /**
    * Download an export
    *
    * @param {string} uri Export uri
    * @param {string} [dir=.] Directory to save to
    * @param {string} [filename] file to save to
    * @param {stream} [writeStream] stream to write to
    * @returns {Promise} Rejects with an error from API.
    *
    * If no optional arguments are set the downloaded file will be saved to the current
    * directory with the filename extracted from the end of the URI.
    */
    download({ uri, dir = '.', filename, writeStream }) {
      if (writeStream) {
        logger.info(`Downloading export\n   from ${uri}\n   to writeStream`);
        return api.streamGet(uri, { stream: writeStream });
      }
      const targetFilename = filename || this.filenameFromURI(uri);
      logger.info(`Downloading export\n   from ${uri}\n   to ${dir}/${targetFilename}`);
      return api.streamGet(uri, { stream: fs.createWriteStream(`${dir}/${targetFilename}`) });
    }
  };
}
<commit_msg>Bow (conform) to the backtick!<commit_after>import Promise from 'bluebird';
import fs from 'fs';

export const DEFAULT_TIMEZONE = 'UTC';
export const DEFAULT_FORMAT = 'pdf';
export const POLL_TIME = 5 * 1000;
export const MAX_TRIES = 5;

/**
* Generates Exports object with methods using passed api
*
* @param {object} api Valid api object
* @param {object} logger Logger
* @returns {object} exports Methods to interact with exports on API
*/
export default function Exports(api, logger) {
  return {
    /**
    * Create an export for an audit
    *
    * @param {string} auditId Audit id
    * @param {string} timezone Timezone of export
    * @param {string} export format
    * @returns {Promise} Resolves to successfully created export,
    *                    Rejects with an error from API.
    */
    create({ auditId, timezone = DEFAULT_TIMEZONE, format = DEFAULT_FORMAT, exportProfile }) {
      logger.info(`Creating export for ${auditId} (${timezone}, ${format}, ${exportProfile})`);
      const qs = { format, timezone };
      if (exportProfile) qs.export_profile = exportProfile;
      return api.post(`/audits/${auditId}/export`, { qs });
    },

    /**
    * Find a promise by audit id and id
    *
    * @param {string} auditId Audit id
    * @param {string} id Export id
    * @returns {Promise} Resolves to requested export,
    *                    Rejects with an error from API.
    */
    findById({ auditId, id }) {
      return api.get(`/audits/${auditId}/exports/${id}`).catch((error) => {
        if (error.statusCode === 404) { // Workaround for ARG-2136
          return api.get(`/audits/${auditId}/exports/${id}`);
        }
      });
    },

    /**
    * Get an export (poll until completed)
    *
    * @param {string} auditId Audit id
    * @param {string} id Export id
    * @returns {Promise} Resolves to requested export,
    *                    Rejects with an error from API.
    */
    get({ auditId, id, poll = POLL_TIME, tries = MAX_TRIES }) {
      let attempts = 1;

      let attempt = () => {
        return this.findById({ auditId, id }).then((response) => {
          if (response.status === `FAILED`) return Promise.reject(response.error);
          if (response.status === `SUCCESS`) return response;
          if (response.status === `IN PROGRESS` && attempts < tries) {
            return Promise.delay(poll).then(() => {
              attempts += 1;
              return attempt();
            });
          }
          return Promise.reject(new Error(`Request to get export timed out after ${attempts} attempts.`));
        }).catch((error) => Promise.reject(error));
      };

      return attempt();
    },

    /**
     * extract and decode a filename from the end of a URI
     * @param   {string} uri a uri with a filename
     * @returns {string}     a decoded filename
     */
    filenameFromURI(uri) {
      return decodeURIComponent(uri.match(/\/([^/]+)$/)[1]);
    },

    /**
    * Download an export
    *
    * @param {string} uri Export uri
    * @param {string} [dir=.] Directory to save to
    * @param {string} [filename] file to save to
    * @param {stream} [writeStream] stream to write to
    * @returns {Promise} Rejects with an error from API.
    *
    * If no optional arguments are set the downloaded file will be saved to the current
    * directory with the filename extracted from the end of the URI.
    */
    download({ uri, dir = '.', filename, writeStream }) {
      if (writeStream) {
        logger.info(`Downloading export\n   from ${uri}\n   to writeStream`);
        return api.streamGet(uri, { stream: writeStream });
      }
      const targetFilename = filename || this.filenameFromURI(uri);
      logger.info(`Downloading export\n   from ${uri}\n   to ${dir}/${targetFilename}`);
      return api.streamGet(uri, { stream: fs.createWriteStream(`${dir}/${targetFilename}`) });
    }
  };
}
<|endoftext|>


<commit_before>
var esprima = require('esprima');

/**
 * Position in the source file.
 *
 * @see [SpiderMonkey Parser API]
 *   {@link https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API}
 *
 * @typedef {Object} Position
 * @property {number} line - Line number, 1-indexed.
 * @property {?number} column - Column number, 0-indexed.
 */

/**
 * Location - position range.
 *
 * @typedef {Object} Location
 * @property {Position} start
 * @property {Position} end
 */

/**
 * Extract comments from code.
 * Each comment is represented by a string within its usual comment delimiters.
 * Returned location always contains both line and column info.
 *
 * @arg {string} code - JavaScript code.
 * @return {{text: string, loc: Location}[]}
 */
var extract = function (code) {
  return esprima.parse(code, {
    comment: true,
    loc: true
  }).comments.map(function (comment) {
    return {
      text: (comment.type == 'Line')
        ? '//' + comment.value
        : '/*' + comment.value + '*/',
      loc: comment.loc
    };
  });
};

module.exports = extract;
<commit_msg>Make column numbers in Location mandatory<commit_after>var esprima = require('esprima');

/**
 * Position in the source file.
 *
 * @see [SpiderMonkey Parser API]
 *   {@link https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API}
 *
 * @typedef {Object} Position
 * @property {number} line - Line number, 1-indexed.
 * @property {?number} column - Column number, 0-indexed.
 */

/**
 * Location - position range.
 *
 * @typedef {Object} Location
 * @property {Position} start - Column number must be set.
 * @property {Position} end - Column number must be set.
 */

/**
 * Extract comments from code.
 * Each comment is represented by a string within its usual comment delimiters.
 *
 * @arg {string} code - JavaScript code.
 * @return {{text: string, loc: Location}[]}
 */
var extract = function (code) {
  return esprima.parse(code, {
    comment: true,
    loc: true
  }).comments.map(function (comment) {
    return {
      text: (comment.type == 'Line')
        ? '//' + comment.value
        : '/*' + comment.value + '*/',
      loc: comment.loc
    };
  });
};

module.exports = extract;
<|endoftext|>


<commit_before>/*
 * Webpack development server configuration
 *
 * This file is set up for serving the webpak-dev-server, which will watch for changes and recompile as required if
 * the subfolder /webpack-dev-server/ is visited. Visiting the root will not automatically reload.
 */
'use strict';
var webpack = require('webpack');

module.exports = {

  output: {
    filename: 'main.js',
    publicPath: '/assets/'
  },

  cache: true,
  debug: true,
  devtool: false,
  entry: [
      'webpack/hot/only-dev-server',
      './src/scripts/components/<% if (reactRouter) { %>main<% } else { %><%= scriptAppName %><% } %>.jsx'
  ],

  stats: {
    colors: true,
    reasons: true
  },

  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  module: {
    preLoaders: [{
      test: '\\.js$',
      exclude: 'node_modules',
      loader: 'jshint'
    }],
    loaders: [{
      test: /\.jsx$/,
      loader: 'react-hot!jsx-loader?harmony'
    },<% if (stylesLanguage === 'sass') { %> {
      test: /\.sass/,
      loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded'
    },<% } %><% if (stylesLanguage === 'less') { %> {
      test: /\.less/,
      loader: 'style-loader!css-loader!less-loader'
    },<% } %><% if (stylesLanguage === 'stylus') { %> {
      test: /\.styl/,
      loader: 'style-loader!css-loader!stylus-loader'
    },<% } %> {
      test: /\.css$/,
      loader: 'style-loader!css-loader'
    }, {
      test: /\.(png|jpg)$/,
      loader: 'url-loader?limit=8192'
    }]
  },

  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ]

};
<commit_msg>adding 6to5 loader<commit_after>/*
 * Webpack development server configuration
 *
 * This file is set up for serving the webpak-dev-server, which will watch for changes and recompile as required if
 * the subfolder /webpack-dev-server/ is visited. Visiting the root will not automatically reload.
 */
'use strict';
var webpack = require('webpack');

module.exports = {

  output: {
    filename: 'main.js',
    publicPath: '/assets/'
  },

  cache: true,
  debug: true,
  devtool: false,
  entry: [
      'webpack/hot/only-dev-server',
      './src/scripts/components/<% if (reactRouter) { %>main<% } else { %><%= scriptAppName %><% } %>.jsx'
  ],

  stats: {
    colors: true,
    reasons: true
  },

  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  module: {
    preLoaders: [{
      test: '\\.js$',
      exclude: 'node_modules',
      loader: 'jshint'
    }],
    loaders: [{
      test: /\.jsx$/,
      loader: 'react-hot!<% if (es6) { %>6to5!<% }%>jsx-loader?harmony'
    },<% if (stylesLanguage === 'sass') { %> {
      test: /\.sass/,
      loader: 'style-loader!css-loader!sass-loader?outputStyle=expanded'
    },<% } %><% if (stylesLanguage === 'less') { %> {
      test: /\.less/,
      loader: 'style-loader!css-loader!less-loader'
    },<% } %><% if (stylesLanguage === 'stylus') { %> {
      test: /\.styl/,
      loader: 'style-loader!css-loader!stylus-loader'
    },<% } %> {
      test: /\.css$/,
      loader: 'style-loader!css-loader'
    }, {
      test: /\.(png|jpg)$/,
      loader: 'url-loader?limit=8192'
    }]
  },

  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ]

};
<|endoftext|>


<commit_before>// Generated by CoffeeScript 1.7.1
(function() {
  module.exports = function(grunt) {
    return grunt.registerMultiTask('xml_validator', 'Grunt plugin to validate XML files', function() {
      var DOMParser, checkValidity, fail, options, schema, xmllint;
      DOMParser = require('xmldom').DOMParser;
      xmllint = require('xmllint');
      fail = false;
      schema = null;
      checkValidity = function(f) {
        var doc, validation, xml;
        xml = grunt.file.read(f);
        doc = new DOMParser({
          locator: {},
          errorHandler: function(level, msg) {
            fail = true;
            return grunt.log.error(f + "\tnot valid");
          }
        }).parseFromString(xml, 'text/xml');
        if (!fail && schema) {
          validation = xmllint.validateXML({
            xml: doc,
            schema: schema
          });
          if (validation.errors) {
            fail = true;
            grunt.log.error(f + "\tnot well formed");
            validation.errors.forEach(function(e) {
              return grunt.log.error(f + "\t " + e);
            });
          }
        }
        if (!fail) {
          return doc;
        }
      };
      options = this.options({
        xsd: null
      });
      if (options.xsd) {
        schema = checkValidity(options.xsd);
      }
      this.filesSrc.forEach(checkValidity);
      if (fail) {
        return grunt.fail.warn('Some files are not valid');
      } else {
        return grunt.log.ok(this.filesSrc.length + ' files valid');
      }
    });
  };

}).call(this);
<commit_msg>deleted generated file<commit_after><|endoftext|>


<commit_before>import React, { Component } from 'react'
import { polyfill } from 'react-lifecycles-compat'
import { bool, number, object, string } from 'prop-types'
import { connect } from 'react-redux'

import { DEFAULT_SCOPE } from './loading_bar_ducks'

export const UPDATE_TIME = 200
export const MAX_PROGRESS = 99
export const PROGRESS_INCREASE = 10
export const ANIMATION_DURATION = UPDATE_TIME * 4
export const TERMINATING_ANIMATION_DURATION = UPDATE_TIME / 2

const initialState = {
  percent: 0,
  status: 'hidden',
}

class LoadingBar extends Component {
  static propTypes = {
    className: string,
    loading: number,
    maxProgress: number,
    progressIncrease: number,
    showFastActions: bool,
    updateTime: number,
    scope: string,
    style: object,
  }

  static defaultProps = {
    className: '',
    loading: 0,
    maxProgress: MAX_PROGRESS,
    progressIncrease: PROGRESS_INCREASE,
    showFastActions: false,
    style: {},
    updateTime: UPDATE_TIME,
    scope: DEFAULT_SCOPE,
  }

  static shouldStart(props, state) {
    return (
      props.loading > 0 && ['hidden', 'stopping'].indexOf(state.status) >= 0
    )
  }

  static shouldStop(props, state) {
    return (
      props.loading === 0 && ['starting', 'running'].indexOf(state.status) >= 0
    )
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    if (LoadingBar.shouldStart(nextProps, prevState)) {
      return { status: 'starting' }
    }

    if (LoadingBar.shouldStop(nextProps, prevState)) {
      return { status: 'stopping' }
    }

    return null
  }

  state = { ...initialState }

  componentDidMount() {
    if (this.state.status === 'starting') {
      this.start()
    }
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevState.status !== this.state.status) {
      if (this.state.status === 'starting') {
        this.start()
      }

      if (this.state.status === 'stopping') {
        this.stop()
      }
    }
  }

  componentWillUnmount() {
    clearInterval(this.progressIntervalId)
    clearTimeout(this.terminatingAnimationTimeoutId)
  }

  start() {
    this.progressIntervalId = setInterval(
      this.simulateProgress,
      this.props.updateTime,
    )
    this.setState({ status: 'running' })
  }

  stop() {
    clearInterval(this.progressIntervalId)
    this.progressIntervalId = null

    const terminatingAnimationDuration = (
      this.isShown() || this.props.showFastActions ?
      TERMINATING_ANIMATION_DURATION : 0
    )

    this.terminatingAnimationTimeoutId = setTimeout(
      this.reset,
      terminatingAnimationDuration,
    )

    this.setState({ percent: 100 })
  }

  reset = () => {
    this.terminatingAnimationTimeoutId = null
    this.setState(initialState)
  }

  newPercent = (percent, progressIncrease) => {
    // Use cosine as a smoothing function
    // It could be any function to slow down progress near the ending 100%
    const smoothedProgressIncrease = (
      progressIncrease * Math.cos(percent * (Math.PI / 2 / 100))
    )

    return percent + smoothedProgressIncrease
  }

  simulateProgress = () => {
    this.setState((prevState, { maxProgress, progressIncrease }) => {
      let { percent } = prevState
      const newPercent = this.newPercent(percent, progressIncrease)

      if (newPercent <= maxProgress) {
        percent = newPercent
      }

      return { percent }
    })
  }

  isShown() {
    return this.state.percent > 0 && this.state.percent <= 100
  }

  buildStyle() {
    const animationDuration = (
      this.state.status === 'stopping' ?
        TERMINATING_ANIMATION_DURATION :
        ANIMATION_DURATION
    )

    const style = {
      opacity: '1',
      transform: `scaleX(${this.state.percent / 100})`,
      transformOrigin: 'left',
      transition: `transform ${animationDuration}ms linear`,
      width: '100%',
      willChange: 'transform, opacity',
    }

    // Use default styling if there's no CSS class applied
    if (!this.props.className) {
      style.height = '3px'
      style.backgroundColor = 'red'
      style.position = 'absolute'
    }

    if (this.isShown()) {
      style.opacity = '1'
    } else {
      style.opacity = '0'
    }

    return { ...style, ...this.props.style }
  }

  render() {
    if (this.state.status === 'hidden') {
      return

    }

    return (

    )
  }
}

const mapStateToProps = (state, ownProps) => ({
  loading: state.loadingBar[ownProps.scope || DEFAULT_SCOPE],
})

polyfill(LoadingBar)
const ConnectedLoadingBar = connect(mapStateToProps)(LoadingBar)

export {
  LoadingBar,
  ConnectedLoadingBar as default,
}
<commit_msg>browser css3  animation compatibility<commit_after>import React, { Component } from 'react'
import { polyfill } from 'react-lifecycles-compat'
import { bool, number, object, string } from 'prop-types'
import { connect } from 'react-redux'

import { DEFAULT_SCOPE } from './loading_bar_ducks'

export const UPDATE_TIME = 200
export const MAX_PROGRESS = 99
export const PROGRESS_INCREASE = 10
export const ANIMATION_DURATION = UPDATE_TIME * 4
export const TERMINATING_ANIMATION_DURATION = UPDATE_TIME / 2

const initialState = {
  percent: 0,
  status: 'hidden',
}

class LoadingBar extends Component {
  static propTypes = {
    className: string,
    loading: number,
    maxProgress: number,
    progressIncrease: number,
    showFastActions: bool,
    updateTime: number,
    scope: string,
    style: object,
  }

  static defaultProps = {
    className: '',
    loading: 0,
    maxProgress: MAX_PROGRESS,
    progressIncrease: PROGRESS_INCREASE,
    showFastActions: false,
    style: {},
    updateTime: UPDATE_TIME,
    scope: DEFAULT_SCOPE,
  }

  static shouldStart(props, state) {
    return (
      props.loading > 0 && ['hidden', 'stopping'].indexOf(state.status) >= 0
    )
  }

  static shouldStop(props, state) {
    return (
      props.loading === 0 && ['starting', 'running'].indexOf(state.status) >= 0
    )
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    if (LoadingBar.shouldStart(nextProps, prevState)) {
      return { status: 'starting' }
    }

    if (LoadingBar.shouldStop(nextProps, prevState)) {
      return { status: 'stopping' }
    }

    return null
  }

  state = { ...initialState }

  componentDidMount() {
    if (this.state.status === 'starting') {
      this.start()
    }
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevState.status !== this.state.status) {
      if (this.state.status === 'starting') {
        this.start()
      }

      if (this.state.status === 'stopping') {
        this.stop()
      }
    }
  }

  componentWillUnmount() {
    clearInterval(this.progressIntervalId)
    clearTimeout(this.terminatingAnimationTimeoutId)
  }

  start() {
    this.progressIntervalId = setInterval(
      this.simulateProgress,
      this.props.updateTime,
    )
    this.setState({ status: 'running' })
  }

  stop() {
    clearInterval(this.progressIntervalId)
    this.progressIntervalId = null

    const terminatingAnimationDuration = (
      this.isShown() || this.props.showFastActions ?
      TERMINATING_ANIMATION_DURATION : 0
    )

    this.terminatingAnimationTimeoutId = setTimeout(
      this.reset,
      terminatingAnimationDuration,
    )

    this.setState({ percent: 100 })
  }

  reset = () => {
    this.terminatingAnimationTimeoutId = null
    this.setState(initialState)
  }

  newPercent = (percent, progressIncrease) => {
    // Use cosine as a smoothing function
    // It could be any function to slow down progress near the ending 100%
    const smoothedProgressIncrease = (
      progressIncrease * Math.cos(percent * (Math.PI / 2 / 100))
    )

    return percent + smoothedProgressIncrease
  }

  simulateProgress = () => {
    this.setState((prevState, { maxProgress, progressIncrease }) => {
      let { percent } = prevState
      const newPercent = this.newPercent(percent, progressIncrease)

      if (newPercent <= maxProgress) {
        percent = newPercent
      }

      return { percent }
    })
  }

  isShown() {
    return this.state.percent > 0 && this.state.percent <= 100
  }

  buildStyle() {
    const animationDuration = (
      this.state.status === 'stopping' ?
        TERMINATING_ANIMATION_DURATION :
        ANIMATION_DURATION
    )

    const style = {
      opacity: '1',
      transform: `scaleX(${this.state.percent / 100})`,
      msTransform:`scaleX(${this.state.percent / 100})`,
      webkitTransform:`scaleX(${this.state.percent / 100})`,
      MozTransform:`scaleX(${this.state.percent / 100})`,
      OTransform:`scaleX(${this.state.percent / 100})`,
      transformOrigin: 'left',
      msTransformOrigin: 'left',
      webkitTransformOrigin: 'left',
      MozTransformOrigin: 'left',
      OTransformOrigin: 'left',
      transition: `transform ${animationDuration}ms linear`,
      msTransition: `msTransform ${animationDuration}ms linear`,
      webkitTransition: `webkitTransform ${animationDuration}ms linear`,
      MozTransition: `MozTransform ${animationDuration}ms linear`,
      OTransition: `OTransform ${animationDuration}ms linear`,
      width: '100%',
      willChange: 'transform, opacity',
    }

    // Use default styling if there's no CSS class applied
    if (!this.props.className) {
      style.height = '3px'
      style.backgroundColor = 'red'
      style.position = 'absolute'
    }

    if (this.isShown()) {
      style.opacity = '1'
    } else {
      style.opacity = '0'
    }

    return { ...style, ...this.props.style }
  }

  render() {
    if (this.state.status === 'hidden') {
      return

    }

    return (

    )
  }
}

const mapStateToProps = (state, ownProps) => ({
  loading: state.loadingBar[ownProps.scope || DEFAULT_SCOPE],
})

polyfill(LoadingBar)
const ConnectedLoadingBar = connect(mapStateToProps)(LoadingBar)

export {
  LoadingBar,
  ConnectedLoadingBar as default,
}
<|endoftext|>


<commit_before>import { connect } from 'react-redux'
import hoistStatics from 'hoist-non-react-statics'
import isEmpty from 'lodash.isempty'

const defaults = {
  failureRedirectPath: '/login',
  wrapperDisplayName: 'AuthWrapper',
  predicate: x => !isEmpty(x),
  authenticatingSelector: state => false,
  allowRedirectBack: true
}

export default function factory(React, empty) {

  const { Component, PropTypes } = React;

  return (args) => {
    const {authSelector, authenticatingSelector, failureRedirectPath, wrapperDisplayName, predicate, allowRedirectBack, redirectAction} = {
      ...defaults,
      ...args
    }

    const isAuthorized = (authData) => predicate(authData)

    const ensureAuth = ({location, authData, isAuthenticating}, redirect) => {
      let query
      if (allowRedirectBack) {
        query = {redirect: `${location.pathname}${location.search}`}
      } else {
        query = {}
      }

      if (!isAuthorized(authData)) {
        redirect({
          pathname: failureRedirectPath,
          query
        })
      }
    }

    // Wraps the component that needs the auth enforcement
    function wrapComponent(DecoratedComponent) {
      const displayName = DecoratedComponent.displayName || DecoratedComponent.name || 'Component'

      const mapDispatchToProps = (dispatch) => {
        if (redirectAction !== undefined) {
          return {redirect: (args) => dispatch(redirectAction(args))}
        } else {
          return {}
        }
      }

      @connect(
        (state, ownProps) => {
          return {
            authData: authSelector(state, ownProps, false),
            isAuthenticating: authenticatingSelector(state, ownProps, false),
          }
        },
        mapDispatchToProps,
      )
      class UserAuthWrapper extends Component {

        static displayName = `${wrapperDisplayName}(${displayName})`;

        static propTypes = {
          location: PropTypes.shape({
            pathname: PropTypes.string.isRequired,
            search: PropTypes.string.isRequired
          }).isRequired,
          redirect: PropTypes.func,
          authData: PropTypes.object
        };

        static contextTypes = {
          // Only used if no redirectAction specified
          router: React.PropTypes.object
        };

        componentWillMount() {
          if(!this.props.isAuthenticating) {
            ensureAuth(this.props, this.getRedirectFunc(this.props))
          }
        }

        componentWillReceiveProps(nextProps) {
          if(!nextProps.isAuthenticating) {
            ensureAuth(nextProps, this.getRedirectFunc(nextProps))
          }
        }

        getRedirectFunc = (props) => {
          if (props.redirect) {
            return props.redirect
          } else {
            if (!this.context.router.replace) {
              /* istanbul ignore next sanity */
              throw new Error(`You must provide a router context (or use React-Router 2.x) if not passing a redirectAction to ${wrapperDisplayName}`)
            } else {
              return this.context.router.replace
            }
          }
        };

        render() {
          // Allow everything but the replace aciton creator to be passed down
          // Includes route props from React-Router and authData
          const {redirect, authData, ...otherProps} = this.props

          if (isAuthorized(authData)) {
            return <DecoratedComponent authData={authData} {...otherProps} />
          } else {
            // Don't need to display anything because the user will be redirected
            return React.createElement(empty);
          }
        }
      }

      return hoistStatics(UserAuthWrapper, DecoratedComponent)
    }

    wrapComponent.onEnter = (store, nextState, replace) => {
      const authData = authSelector(store.getState(), null, true)
      ensureAuth({location: nextState.location, authData}, replace)
    }

    return wrapComponent
  }
}
<commit_msg>dont send onEnter bool (always false)<commit_after>import { connect } from 'react-redux'
import hoistStatics from 'hoist-non-react-statics'
import isEmpty from 'lodash.isempty'

const defaults = {
  failureRedirectPath: '/login',
  wrapperDisplayName: 'AuthWrapper',
  predicate: x => !isEmpty(x),
  authenticatingSelector: state => false,
  allowRedirectBack: true
}

export default function factory(React, empty) {

  const { Component, PropTypes } = React;

  return (args) => {
    const {authSelector, authenticatingSelector, failureRedirectPath, wrapperDisplayName, predicate, allowRedirectBack, redirectAction} = {
      ...defaults,
      ...args
    }

    const isAuthorized = (authData) => predicate(authData)

    const ensureAuth = ({location, authData, isAuthenticating}, redirect) => {
      let query
      if (allowRedirectBack) {
        query = {redirect: `${location.pathname}${location.search}`}
      } else {
        query = {}
      }

      if (!isAuthorized(authData)) {
        redirect({
          pathname: failureRedirectPath,
          query
        })
      }
    }

    // Wraps the component that needs the auth enforcement
    function wrapComponent(DecoratedComponent) {
      const displayName = DecoratedComponent.displayName || DecoratedComponent.name || 'Component'

      const mapDispatchToProps = (dispatch) => {
        if (redirectAction !== undefined) {
          return {redirect: (args) => dispatch(redirectAction(args))}
        } else {
          return {}
        }
      }

      @connect(
        (state, ownProps) => {
          return {
            authData: authSelector(state, ownProps, false),
            isAuthenticating: authenticatingSelector(state, ownProps),
          }
        },
        mapDispatchToProps,
      )
      class UserAuthWrapper extends Component {

        static displayName = `${wrapperDisplayName}(${displayName})`;

        static propTypes = {
          location: PropTypes.shape({
            pathname: PropTypes.string.isRequired,
            search: PropTypes.string.isRequired
          }).isRequired,
          redirect: PropTypes.func,
          authData: PropTypes.object
        };

        static contextTypes = {
          // Only used if no redirectAction specified
          router: React.PropTypes.object
        };

        componentWillMount() {
          if(!this.props.isAuthenticating) {
            ensureAuth(this.props, this.getRedirectFunc(this.props))
          }
        }

        componentWillReceiveProps(nextProps) {
          if(!nextProps.isAuthenticating) {
            ensureAuth(nextProps, this.getRedirectFunc(nextProps))
          }
        }

        getRedirectFunc = (props) => {
          if (props.redirect) {
            return props.redirect
          } else {
            if (!this.context.router.replace) {
              /* istanbul ignore next sanity */
              throw new Error(`You must provide a router context (or use React-Router 2.x) if not passing a redirectAction to ${wrapperDisplayName}`)
            } else {
              return this.context.router.replace
            }
          }
        };

        render() {
          // Allow everything but the replace aciton creator to be passed down
          // Includes route props from React-Router and authData
          const {redirect, authData, ...otherProps} = this.props

          if (isAuthorized(authData)) {
            return <DecoratedComponent authData={authData} {...otherProps} />
          } else {
            // Don't need to display anything because the user will be redirected
            return React.createElement(empty);
          }
        }
      }

      return hoistStatics(UserAuthWrapper, DecoratedComponent)
    }

    wrapComponent.onEnter = (store, nextState, replace) => {
      const authData = authSelector(store.getState(), null, true)
      ensureAuth({location: nextState.location, authData}, replace)
    }

    return wrapComponent
  }
}
<|endoftext|>


<commit_before>// The M in MVC
var model = {
    // Server-set constant getters
    // Name of the repository
    repo: function()       { return $("#repository").val(); },
    // Who's the instructor? (i.e., github login)
    instructor: function() { return $("#instructor").val(); },
    // User's login at their machine
    hostLogin: function()  { return $("#host").val(); },
    // User's public key
    publicKey: function()  { return $("#public-key").val(); },

    // Server-initialized variable getters
    // The user's full name
    name: function() {
        // Is the name valid?
        var isValid = function(value) {
            var regex = /[^ ]+( [^ ]+)+/;
            return regex.test(value);
        };
        // Get name from the form element
        if (isValid($("#name").val().trim())) {
            localStorage.setItem("User.name", $("#name").val().trim());
            return $("#name").val().trim();
        }
        // Get name from localStorage (user confirmed value)
        if (localStorage.hasOwnProperty("User.name") && isValid(localStorage.getItem("User.name"))) {
            return localStorage.getItem("User.name");
        }
        // FAIL
        return "";
    },
    // The user's school email address
    email: function() {
        // Is the user's email valid?
        var isValid = function(value) {
            var regex1 = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
            var regex2 = /edu$/;
            return regex1.test(value) && regex2.test(value);
        };
        var theEmail = $("#email").val().toLowerCase().trim();
        // Get email from the form element
        if (isValid(theEmail)) {
            localStorage.setItem("User.email", theEmail);
            return theEmail;
        }
        // Get email from localStorage (user confirmed value)
        if (localStorage.hasOwnProperty("User.email") && isValid(localStorage.getItem("User.email"))) {
            return localStorage.getItem("User.email");
        }
        // FAIL
        return "";
    },
    // Gravatar ID
    gravatarId: function() { return SparkMD5.hash(model.email()); },
};

// The C in MVC :-)
var controller = {
    // Show class and hide its opposite
    update: function(klass, value) {
        $(((value) ? "." : ".no-")+klass).show();
        $(((value) ? ".no-" : ".")+klass).hide();
    },
    // Update name view on change
    name: function() {
        $( "#git-config-name" ).html('git config --global user.name "' + model.name() + '"');
    },
    // Update email view on change
    email: function() {
        $( "#git-config-email" ).html('git config --global user.email ' + model.email());

        $("#visible-gravatar").attr('src', 'http://www.gravatar.com/avatar/' + model.gravatarId() + '?d=retro&s=140');
        $.ajax({
            method: "GET",
            dataType: "jsonp",
            crossDomain: true,
            processData: false,
            url: 'https://en.gravatar.com/' + model.gravatarId() + '.json',
            success: function(response) {
                localStorage.setItem("Gravatar", model.gravatarId());
                controller.update('gravatar-account',true);
            },
            error: function(response) {
                localStorage.removeItem("Gravatar");
                controller.update('gravatar-account',false);
            }
        });
    },
    gravatar: function() {
        controller.update('gravatar-authenticated',false);
    },
    github: function() {
        if (Github.authenticated()) {
            $("#github-login").val(Github.getUsername());
            setupUser();
            setupEmail();
            setupSSH();
            setupRepo();
            setupLocal();
            $(".origin-href").attr("href", "https://github.com/" + Github.getUsername() + "/" + model.repo());
            $("#private-href").attr("href", "https://github.com/" + Github.getUsername() + "/" + model.repo() + "/settings");
            $("#collaborator-href").attr("href", "https://github.com/" + Github.getUsername() + "/" + model.repo() + "/settings/collaboration");
            $("#origin-code").html("git remote add origin git@github.com:" + Github.getUsername() + "/" + model.repo() + ".git");

            controller.update('github-authenticated', true);
        } else {
            controller.update('github-authenticated', false);
        }
    },
};
$( "#name" ).on( "change", function(event) {
    controller.name();
});
$( "#email" ).on( "change", function(event) {
    controller.email();
});
$( "#github-password" ).on( "change", function(event) {
    controller.github();
});
$( "#github-retry" ).on( "click", function(event) {
    controller.github();
});
$("#gravatar-signout").on("click", function(event) {
    controller.gravatar.logout();
});
$("#gravatar-signin").on("click", function(event) {
    controller.gravatar.login();
});
$("#github-signout").on("click", function(event) {
    logout();
});
$("#github-signin").on("click", function(event) {
    $("#github-signin").prop("disabled",true);
    login();
});

$(function() {
    $("#name").val(model.name());
    $("#email").val(model.email());
    $("#manual-github-login").prop('required',false);
    controller.name();
    controller.email();
    controller.gravatar();
    controller.github();
});

function setupLocal() {
    $.ajax({
        method: "POST",
        contentType: "application/json",
        dataType: "json",
        crossDomain: true,
        processData: false,
        url: 'http://localhost:8080/setup',
        processData: false,
        data: JSON.stringify({
            "github.login": Github.getUsername(),
            "user.name": model.name(),
            "user.email": model.email(),
        }),
        success: function(response) {
            if (response.name == model.name()) {
                controller.update('git-name',true);
            }
            if (response.email == model.email()) {
                controller.update('git-email',true);
            }
            controller.update('git-origin', /origin/.test(response.remotes));
            controller.update('git-upstream', /upstream/.test(response.remotes));
            controller.update('git-clone', response.clone);
            controller.update('git-push', response.push);
        },
        error: function(response) {
            console.log(JSON.stringify(response));
            alert("Local server not responding.");
        }
    });

}

function setupUser() {
    // Nag the user if they're not on an upgraded plan
    Github.getUser({
        success: function(response) {
            controller.update('github-upgraded', (response.plan.name.toLowerCase() != "free"));
        }
    });
    Github.setUser({
        data: { name: model.name() },
        success: function(response) {
            controller.update('github-profile',true);
        },
        fail: function(response) {
            controller.update('github-profile',false);
        }
    });
}
function setupEmail() {
    // Setup email
    Github.getEmail({
        email: model.email(),
        verified: function(status) {
            controller.update('github-email-verified',status);
        }
    });
}
function setupSSH() {
    Github.shareKey({
        title: model.hostLogin(),
        key: model.publicKey(),
        success: function() {
            controller.update('github-key',true);
        },
        fail: function() {
            controller.update('github-key',false);
        }
    });
}
function setupRepo() {
    Github.createRepo({
        repo: model.repo(),
        success: function(response) {
            controller.update('github-repository',true);
            Github.addCollaborator({
                repo: model.repo(),
                collaborator: model.instructor(),
                success: function(response) {
                    controller.update('github-collaborator', true);
                },
                fail: function(response) {
                    controller.update('github-collaborator', false);
                }
            });
            // As long as we're not the instructor, ...
            if ($("#instructor").val() != Github.getUsername()) {
                // Make the repository private
                Github.privateRepo({
                    repo: model.repo(),
                    success: function(response) {
                        controller.update('github-private', true);
                    },
                    fail: function(response) {
                        controller.update('github-private', false);
                    }
                });
            }
        },
        fail: function(response) {
            controller.update('github-repository',false);
        }
    });
}
function login() {
    Github.login({
        username: $("#email").val(),
        password: $("#github-password").val(),
        otp: $("#otp").val(),
        authenticated: function(login) {
            controller.github();
        },
        badCredential: function() {
            // Clear the password
            $("#github-signin").prop("disabled",false);
            $("#password").attr('value', '');
            controller.github();
        },
        twoFactor: function() {
            $("#github-signin").prop("disabled",false);
            $("#password").prop("disabled", false);
            $('.github-two-factor').show();
            $('#otp').focus();
        }
    });
}
function logout() {
    Github.logout();
    $("#github-signin").prop("disabled",false);
    $("#otp").attr('value','');
    controller.update('github-authenticated', false);
}<commit_msg>Submit form when password is entered.<commit_after>// The M in MVC
var model = {
    // Server-set constant getters
    // Name of the repository
    repo: function()       { return $("#repository").val(); },
    // Who's the instructor? (i.e., github login)
    instructor: function() { return $("#instructor").val(); },
    // User's login at their machine
    hostLogin: function()  { return $("#host").val(); },
    // User's public key
    publicKey: function()  { return $("#public-key").val(); },

    // Server-initialized variable getters
    // The user's full name
    name: function() {
        // Is the name valid?
        var isValid = function(value) {
            var regex = /[^ ]+( [^ ]+)+/;
            return regex.test(value);
        };
        // Get name from the form element
        if (isValid($("#name").val().trim())) {
            localStorage.setItem("User.name", $("#name").val().trim());
            return $("#name").val().trim();
        }
        // Get name from localStorage (user confirmed value)
        if (localStorage.hasOwnProperty("User.name") && isValid(localStorage.getItem("User.name"))) {
            return localStorage.getItem("User.name");
        }
        // FAIL
        return "";
    },
    // The user's school email address
    email: function() {
        // Is the user's email valid?
        var isValid = function(value) {
            var regex1 = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
            var regex2 = /edu$/;
            return regex1.test(value) && regex2.test(value);
        };
        var theEmail = $("#email").val().toLowerCase().trim();
        // Get email from the form element
        if (isValid(theEmail)) {
            localStorage.setItem("User.email", theEmail);
            return theEmail;
        }
        // Get email from localStorage (user confirmed value)
        if (localStorage.hasOwnProperty("User.email") && isValid(localStorage.getItem("User.email"))) {
            return localStorage.getItem("User.email");
        }
        // FAIL
        return "";
    },
    // Gravatar ID
    gravatarId: function() { return SparkMD5.hash(model.email()); },
};

// The C in MVC :-)
var controller = {
    // Show class and hide its opposite
    update: function(klass, value) {
        $(((value) ? "." : ".no-")+klass).show();
        $(((value) ? ".no-" : ".")+klass).hide();
    },
    // Update name view on change
    name: function() {
        $( "#git-config-name" ).html('git config --global user.name "' + model.name() + '"');
    },
    // Update email view on change
    email: function() {
        $( "#git-config-email" ).html('git config --global user.email ' + model.email());

        $("#visible-gravatar").attr('src', 'http://www.gravatar.com/avatar/' + model.gravatarId() + '?d=retro&s=140');
        $.ajax({
            method: "GET",
            dataType: "jsonp",
            crossDomain: true,
            processData: false,
            url: 'https://en.gravatar.com/' + model.gravatarId() + '.json',
            success: function(response) {
                localStorage.setItem("Gravatar", model.gravatarId());
                controller.update('gravatar-account',true);
            },
            error: function(response) {
                localStorage.removeItem("Gravatar");
                controller.update('gravatar-account',false);
            }
        });
    },
    gravatar: function() {
        controller.update('gravatar-authenticated',false);
    },
    github: function() {
        if (Github.authenticated()) {
            $("#github-login").val(Github.getUsername());
            setupUser();
            setupEmail();
            setupSSH();
            setupRepo();
            setupLocal();
            $(".origin-href").attr("href", "https://github.com/" + Github.getUsername() + "/" + model.repo());
            $("#private-href").attr("href", "https://github.com/" + Github.getUsername() + "/" + model.repo() + "/settings");
            $("#collaborator-href").attr("href", "https://github.com/" + Github.getUsername() + "/" + model.repo() + "/settings/collaboration");
            $("#origin-code").html("git remote add origin git@github.com:" + Github.getUsername() + "/" + model.repo() + ".git");

            controller.update('github-authenticated', true);
        } else {
            controller.update('github-authenticated', false);
        }
    },
};
$( "#name" ).on( "change", function(event) {
    controller.name();
});
$( "#email" ).on( "change", function(event) {
    controller.email();
});
$( "#github-password" ).on( "change", function(event) {
    controller.github();
});
$("#github-password").keyup(function(event){
    if(event.keyCode == 13){
        controller.github();
    }
});
$( "#github-retry" ).on( "click", function(event) {
    controller.github();
});
$("#gravatar-signout").on("click", function(event) {
    controller.gravatar.logout();
});
$("#gravatar-signin").on("click", function(event) {
    controller.gravatar.login();
});
$("#github-signout").on("click", function(event) {
    logout();
});
$("#github-signin").on("click", function(event) {
    $("#github-signin").prop("disabled",true);
    login();
});

$(function() {
    $("#name").val(model.name());
    $("#email").val(model.email());
    $("#manual-github-login").prop('required',false);
    controller.name();
    controller.email();
    controller.gravatar();
    controller.github();
});

function setupLocal() {
    $.ajax({
        method: "POST",
        contentType: "application/json",
        dataType: "json",
        crossDomain: true,
        processData: false,
        url: 'http://localhost:8080/setup',
        processData: false,
        data: JSON.stringify({
            "github.login": Github.getUsername(),
            "user.name": model.name(),
            "user.email": model.email(),
        }),
        success: function(response) {
            if (response.name == model.name()) {
                controller.update('git-name',true);
            }
            if (response.email == model.email()) {
                controller.update('git-email',true);
            }
            controller.update('git-origin', /origin/.test(response.remotes));
            controller.update('git-upstream', /upstream/.test(response.remotes));
            controller.update('git-clone', response.clone);
            controller.update('git-push', response.push);
        },
        error: function(response) {
            console.log(JSON.stringify(response));
            alert("Local server not responding.");
        }
    });

}

function setupUser() {
    // Nag the user if they're not on an upgraded plan
    Github.getUser({
        success: function(response) {
            controller.update('github-upgraded', (response.plan.name.toLowerCase() != "free"));
        }
    });
    Github.setUser({
        data: { name: model.name() },
        success: function(response) {
            controller.update('github-profile',true);
        },
        fail: function(response) {
            controller.update('github-profile',false);
        }
    });
}
function setupEmail() {
    // Setup email
    Github.getEmail({
        email: model.email(),
        verified: function(status) {
            controller.update('github-email-verified',status);
        }
    });
}
function setupSSH() {
    Github.shareKey({
        title: model.hostLogin(),
        key: model.publicKey(),
        success: function() {
            controller.update('github-key',true);
        },
        fail: function() {
            controller.update('github-key',false);
        }
    });
}
function setupRepo() {
    Github.createRepo({
        repo: model.repo(),
        success: function(response) {
            controller.update('github-repository',true);
            Github.addCollaborator({
                repo: model.repo(),
                collaborator: model.instructor(),
                success: function(response) {
                    controller.update('github-collaborator', true);
                },
                fail: function(response) {
                    controller.update('github-collaborator', false);
                }
            });
            // As long as we're not the instructor, ...
            if ($("#instructor").val() != Github.getUsername()) {
                // Make the repository private
                Github.privateRepo({
                    repo: model.repo(),
                    success: function(response) {
                        controller.update('github-private', true);
                    },
                    fail: function(response) {
                        controller.update('github-private', false);
                    }
                });
            }
        },
        fail: function(response) {
            controller.update('github-repository',false);
        }
    });
}
function login() {
    Github.login({
        username: $("#email").val(),
        password: $("#github-password").val(),
        otp: $("#otp").val(),
        authenticated: function(login) {
            controller.github();
        },
        badCredential: function() {
            // Clear the password
            $("#github-signin").prop("disabled",false);
            $("#password").attr('value', '');
            controller.github();
        },
        twoFactor: function() {
            $("#github-signin").prop("disabled",false);
            $("#password").prop("disabled", false);
            $('.github-two-factor').show();
            $('#otp').focus();
        }
    });
}
function logout() {
    Github.logout();
    $("#github-signin").prop("disabled",false);
    $("#otp").attr('value','');
    controller.update('github-authenticated', false);
}<|endoftext|>


<commit_before>import { normalizeObjectUnits } from '../units/aliases';
import { getLocale } from '../locale/locales';
import isDurationValid from './valid.js';

export function Duration (duration) {
    var normalizedInput = normalizeObjectUnits(duration);

    this._isValid = isDurationValid(normalizedInput);
    this.isValid = () => this._isValid;

    var years = this._isValid && normalizedInput.year || 0,
        quarters = this._isValid && normalizedInput.quarter || 0,
        months = this._isValid && normalizedInput.month || 0,
        weeks = this._isValid && normalizedInput.week || 0,
        days = this._isValid && normalizedInput.day || 0,
        hours = this._isValid && normalizedInput.hour || 0,
        minutes = this._isValid && normalizedInput.minute || 0,
        seconds = this._isValid && normalizedInput.second || 0,
        milliseconds = this._isValid && normalizedInput.millisecond || 0;

    // representation for dateAddRemove
    this._milliseconds = +milliseconds +
        seconds * 1e3 + // 1000
        minutes * 6e4 + // 1000 * 60
        hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
    // Because of dateAddRemove treats 24 hours as different from a
    // day when working around DST, we need to store them separately
    this._days = +days +
        weeks * 7;
    // It is impossible translate months into days without knowing
    // which months you are are talking about, so we have to store
    // it separately.
    this._months = +months +
        quarters * 3 +
        years * 12;

    this._data = {};

    this._locale = getLocale();

    this._bubble();
}

export function isDuration (obj) {
    return obj instanceof Duration;
}
<commit_msg>Replace arrow function<commit_after>import { normalizeObjectUnits } from '../units/aliases';
import { getLocale } from '../locale/locales';
import isDurationValid from './valid.js';

export function Duration (duration) {
    var normalizedInput = normalizeObjectUnits(duration);

    this._isValid = isDurationValid(normalizedInput);
    this.isValid = function () {
        return this._isValid;
    };

    var years = this._isValid && normalizedInput.year || 0,
        quarters = this._isValid && normalizedInput.quarter || 0,
        months = this._isValid && normalizedInput.month || 0,
        weeks = this._isValid && normalizedInput.week || 0,
        days = this._isValid && normalizedInput.day || 0,
        hours = this._isValid && normalizedInput.hour || 0,
        minutes = this._isValid && normalizedInput.minute || 0,
        seconds = this._isValid && normalizedInput.second || 0,
        milliseconds = this._isValid && normalizedInput.millisecond || 0;

    // representation for dateAddRemove
    this._milliseconds = +milliseconds +
        seconds * 1e3 + // 1000
        minutes * 6e4 + // 1000 * 60
        hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
    // Because of dateAddRemove treats 24 hours as different from a
    // day when working around DST, we need to store them separately
    this._days = +days +
        weeks * 7;
    // It is impossible translate months into days without knowing
    // which months you are are talking about, so we have to store
    // it separately.
    this._months = +months +
        quarters * 3 +
        years * 12;

    this._data = {};

    this._locale = getLocale();

    this._bubble();
}

export function isDuration (obj) {
    return obj instanceof Duration;
}
<|endoftext|>


<commit_before>var gulp = require('gulp');
var path = require('path');
var devGulpTasks = require('grommet/utils/gulp/gulp-tasks');

var opts = {
  base: '.',
  dist: path.resolve(__dirname, 'dist/'),
  copyAssets: [
    'src/index.html',
    {
      asset: 'src/img/**',
      dist: 'dist/img/'
    }
  ],
  scssAssets: ['src/scss/**/*.scss'],
  jsAssets: ['src/js/**/*.js'],
  mainJs: 'src/js/index.js',
  mainScss: 'src/scss/index.scss',
  webpack: {
    resolve: {
      root: [
        path.resolve(__dirname, 'src/js'),
        path.resolve(__dirname, 'src/scss'),
        path.resolve(__dirname, 'node_modules')
      ]
    }
  },
  devServerPort: 9000
};

devGulpTasks(gulp, opts);
<commit_msg>Removed cto-app-tuner from templates directory.<commit_after><|endoftext|>


<commit_before>
var lib = require('./lib');
var r = require('./runtime');

var filters = {
    abs: function(n) {
        return Math.abs(n);
    },

    batch: function(arr, linecount, fill_with) {
        var res = [];
        var tmp = [];

        for(var i=0; i<arr.length; i++) {
            if(i % linecount === 0 && tmp.length) {
                res.push(tmp);
                tmp = [];
            }

            tmp.push(arr[i]);
        }

        if(tmp.length) {
            if(fill_with) {
                for(var i=tmp.length; i<linecount; i++) {
                    tmp.push(fill_with);
                }
            }

            res.push(tmp);
        }

        return res;
    },

    capitalize: function(str) {
        var ret = str.toLowerCase();
        return r.copySafeness(str, ret[0].toUpperCase() + ret.slice(1));
    },

    center: function(str, width) {
        width = width || 80;

        if(str.length >= width) {
            return str;
        }

        var spaces = width - str.length;
        var pre = lib.repeat(" ", spaces/2 - spaces % 2);
        var post = lib.repeat(" ", spaces/2);
        return r.copySafeness(str, pre + str + post);
    },

    'default': function(val, def) {
        return val ? val : def;
    },

    dictsort: function(val, case_sensitive, by) {
        if (!lib.isObject(val)) {
            throw new lib.TemplateError("dictsort filter: val must be an object");
        }

        var array = [];
        for (var k in val) {
            // deliberately include properties from the object's prototype
            array.push([k,val[k]]);
        }

        var si;
        if (by === undefined || by === "key") {
            si = 0;
        } else if (by === "value") {
            si = 1;
        } else {
            throw new lib.TemplateError(
                "dictsort filter: You can only sort by either key or value");
        }

        array.sort(function(t1, t2) {
            var a = t1[si];
            var b = t2[si];

            if (!case_sensitive) {
                if (lib.isString(a)) {
                    a = a.toUpperCase();
                }
                if (lib.isString(b)) {
                    b = b.toUpperCase();
                }
            }

            return a > b ? 1 : (a == b ? 0 : -1);
        });

        return array;
    },

    escape: function(str) {
        if(typeof str == 'string' ||
           str instanceof r.SafeString) {
            return lib.escape(str);
        }
        return str;
    },

    safe: function(str) {
        return new r.SafeString(str);
    },

    first: function(arr) {
        return arr[0];
    },

    groupby: function(arr, attr) {
        return lib.groupBy(arr, attr);
    },

    indent: function(str, width, indentfirst) {
        width = width || 4;
        var res = '';
        var lines = str.split('\n');
        var sp = lib.repeat(' ', width);

        for(var i=0; i<lines.length; i++) {
            if(i == 0 && !indentfirst) {
                res += lines[i] + '\n';
            }
            else {
                res += sp + lines[i] + '\n';
            }
        }

        return r.copySafeness(str, res);
    },

    join: function(arr, del, attr) {
        del = del || '';

        if(attr) {
            arr = lib.map(arr, function(v) {
                return v[attr];
            });
        }

        return arr.join(del);
    },

    last: function(arr) {
        return arr[arr.length-1];
    },

    length: function(arr) {
        return arr.length;
    },

    list: function(val) {
        if(lib.isString(val)) {
            return val.split('');
        }
        else if(lib.isObject(val)) {
            var keys = [];

            if(Object.keys) {
                keys = Object.keys(val);
            }
            else {
                for(var k in val) {
                    keys.push(k);
                }
            }

            return lib.map(keys, function(k) {
                return { key: k,
                         value: val[k] };
            });
        }
        else {
            throw new lib.TemplateError("list filter: type not iterable");
        }
    },

    lower: function(str) {
        return str.toLowerCase();
    },

    random: function(arr) {
        var i = Math.floor(Math.random() * arr.length);
        if(i == arr.length) {
            i--;
        }

        return arr[i];
    },

    replace: function(str, old, new_, maxCount) {
        var res = str;
        var last = res;
        var count = 1;
        res = res.replace(old, new_);

        while(last != res) {
            if(count >= maxCount) {
                break;
            }

            last = res;
            res = res.replace(old, new_);
            count++;
        }

        return r.copySafeness(str, res);
    },

    reverse: function(val) {
        var arr;
        if(lib.isString(val)) {
            arr = filters.list(val);
        }
        else {
            // Copy it
            arr = lib.map(val, function(v) { return v; });
        }

        arr.reverse();

        if(lib.isString(val)) {
            return r.copySafeness(val, arr.join(''));
        }
        return arr;
    },

    round: function(val, precision, method) {
        precision = precision || 0;
        var factor = Math.pow(10, precision);
        var rounder;

        if(method == 'ceil') {
            rounder = Math.ceil;
        }
        else if(method == 'floor') {
            rounder = Math.floor;
        }
        else {
            rounder = Math.round;
        }

        return rounder(val * factor) / factor;
    },

    slice: function(arr, slices, fillWith) {
        var sliceLength = Math.floor(arr.length / slices);
        var extra = arr.length % slices;
        var offset = 0;
        var res = [];

        for(var i=0; i<slices; i++) {
            var start = offset + i * sliceLength;
            if(i < extra) {
                offset++;
            }
            var end = offset + (i + 1) * sliceLength;

            var slice = arr.slice(start, end);
            if(fillWith && i >= extra) {
                slice.push(fillWith);
            }
            res.push(slice);
        }

        return res;
    },

    sort: function(arr, reverse, caseSens, attr) {
        // Copy it
        arr = lib.map(arr, function(v) { return v; });

        arr.sort(function(a, b) {
            var x, y;

            if(attr) {
                x = a[attr];
                y = b[attr];
            }
            else {
                x = a;
                y = b;
            }

            if(!caseSens && lib.isString(x) && lib.isString(y)) {
                x = x.toLowerCase();
                y = y.toLowerCase();
            }

            if(x < y) {
                return reverse ? 1 : -1;
            }
            else if(x > y) {
                return reverse ? -1: 1;
            }
            else {
                return 0;
            }
        });

        return arr;
    },

    string: function(obj) {
        return r.copySafeness(obj, obj);
    },

    title: function(str) {
        var words = str.split(' ');
        for(var i = 0; i < words.length; i++) {
            words[i] = filters.capitalize(words[i]);
        }
        return r.copySafeness(str, words.join(' '));
    },

    trim: function(str) {
        return r.copySafeness(str, str.replace(/^\s*|\s*$/g, ''));
    },

    truncate: function(input, length, killwords, end) {
        var orig = input;
        length = length || 255;

        if (input.length <= length)
            return input;

        if (killwords) {
            input = input.substring(0, length);
        } else {
            var idx = input.lastIndexOf(' ', length);
            if(idx === -1) {
                idx = length;
            }

            input = input.substring(0, idx);
        }

        input += (end !== undefined && end !== null) ? end : '...';
        return r.copySafeness(orig, input);
    },

    upper: function(str) {
        return str.toUpperCase();
    },

    wordcount: function(str) {
        return str.match(/\w+/g).length;
    },

    'float': function(val, def) {
        var res = parseFloat(val);
        return isNaN(res) ? def : res;
    },

    'int': function(val, def) {
        var res = parseInt(val, 10);
        return isNaN(res) ? def : res;
    }
};

// Aliases
filters.d = filters['default'];
filters.e = filters.escape;

module.exports = filters;
<commit_msg>Converting `safe` filter to use `markAsSafe`<commit_after>
var lib = require('./lib');
var r = require('./runtime');

var filters = {
    abs: function(n) {
        return Math.abs(n);
    },

    batch: function(arr, linecount, fill_with) {
        var res = [];
        var tmp = [];

        for(var i=0; i<arr.length; i++) {
            if(i % linecount === 0 && tmp.length) {
                res.push(tmp);
                tmp = [];
            }

            tmp.push(arr[i]);
        }

        if(tmp.length) {
            if(fill_with) {
                for(var i=tmp.length; i<linecount; i++) {
                    tmp.push(fill_with);
                }
            }

            res.push(tmp);
        }

        return res;
    },

    capitalize: function(str) {
        var ret = str.toLowerCase();
        return r.copySafeness(str, ret[0].toUpperCase() + ret.slice(1));
    },

    center: function(str, width) {
        width = width || 80;

        if(str.length >= width) {
            return str;
        }

        var spaces = width - str.length;
        var pre = lib.repeat(" ", spaces/2 - spaces % 2);
        var post = lib.repeat(" ", spaces/2);
        return r.copySafeness(str, pre + str + post);
    },

    'default': function(val, def) {
        return val ? val : def;
    },

    dictsort: function(val, case_sensitive, by) {
        if (!lib.isObject(val)) {
            throw new lib.TemplateError("dictsort filter: val must be an object");
        }

        var array = [];
        for (var k in val) {
            // deliberately include properties from the object's prototype
            array.push([k,val[k]]);
        }

        var si;
        if (by === undefined || by === "key") {
            si = 0;
        } else if (by === "value") {
            si = 1;
        } else {
            throw new lib.TemplateError(
                "dictsort filter: You can only sort by either key or value");
        }

        array.sort(function(t1, t2) {
            var a = t1[si];
            var b = t2[si];

            if (!case_sensitive) {
                if (lib.isString(a)) {
                    a = a.toUpperCase();
                }
                if (lib.isString(b)) {
                    b = b.toUpperCase();
                }
            }

            return a > b ? 1 : (a == b ? 0 : -1);
        });

        return array;
    },

    escape: function(str) {
        if(typeof str == 'string' ||
           str instanceof r.SafeString) {
            return lib.escape(str);
        }
        return str;
    },

    safe: function(str) {
        return r.markAsSafe(str);
    },

    first: function(arr) {
        return arr[0];
    },

    groupby: function(arr, attr) {
        return lib.groupBy(arr, attr);
    },

    indent: function(str, width, indentfirst) {
        width = width || 4;
        var res = '';
        var lines = str.split('\n');
        var sp = lib.repeat(' ', width);

        for(var i=0; i<lines.length; i++) {
            if(i == 0 && !indentfirst) {
                res += lines[i] + '\n';
            }
            else {
                res += sp + lines[i] + '\n';
            }
        }

        return r.copySafeness(str, res);
    },

    join: function(arr, del, attr) {
        del = del || '';

        if(attr) {
            arr = lib.map(arr, function(v) {
                return v[attr];
            });
        }

        return arr.join(del);
    },

    last: function(arr) {
        return arr[arr.length-1];
    },

    length: function(arr) {
        return arr.length;
    },

    list: function(val) {
        if(lib.isString(val)) {
            return val.split('');
        }
        else if(lib.isObject(val)) {
            var keys = [];

            if(Object.keys) {
                keys = Object.keys(val);
            }
            else {
                for(var k in val) {
                    keys.push(k);
                }
            }

            return lib.map(keys, function(k) {
                return { key: k,
                         value: val[k] };
            });
        }
        else {
            throw new lib.TemplateError("list filter: type not iterable");
        }
    },

    lower: function(str) {
        return str.toLowerCase();
    },

    random: function(arr) {
        var i = Math.floor(Math.random() * arr.length);
        if(i == arr.length) {
            i--;
        }

        return arr[i];
    },

    replace: function(str, old, new_, maxCount) {
        var res = str;
        var last = res;
        var count = 1;
        res = res.replace(old, new_);

        while(last != res) {
            if(count >= maxCount) {
                break;
            }

            last = res;
            res = res.replace(old, new_);
            count++;
        }

        return r.copySafeness(str, res);
    },

    reverse: function(val) {
        var arr;
        if(lib.isString(val)) {
            arr = filters.list(val);
        }
        else {
            // Copy it
            arr = lib.map(val, function(v) { return v; });
        }

        arr.reverse();

        if(lib.isString(val)) {
            return r.copySafeness(val, arr.join(''));
        }
        return arr;
    },

    round: function(val, precision, method) {
        precision = precision || 0;
        var factor = Math.pow(10, precision);
        var rounder;

        if(method == 'ceil') {
            rounder = Math.ceil;
        }
        else if(method == 'floor') {
            rounder = Math.floor;
        }
        else {
            rounder = Math.round;
        }

        return rounder(val * factor) / factor;
    },

    slice: function(arr, slices, fillWith) {
        var sliceLength = Math.floor(arr.length / slices);
        var extra = arr.length % slices;
        var offset = 0;
        var res = [];

        for(var i=0; i<slices; i++) {
            var start = offset + i * sliceLength;
            if(i < extra) {
                offset++;
            }
            var end = offset + (i + 1) * sliceLength;

            var slice = arr.slice(start, end);
            if(fillWith && i >= extra) {
                slice.push(fillWith);
            }
            res.push(slice);
        }

        return res;
    },

    sort: function(arr, reverse, caseSens, attr) {
        // Copy it
        arr = lib.map(arr, function(v) { return v; });

        arr.sort(function(a, b) {
            var x, y;

            if(attr) {
                x = a[attr];
                y = b[attr];
            }
            else {
                x = a;
                y = b;
            }

            if(!caseSens && lib.isString(x) && lib.isString(y)) {
                x = x.toLowerCase();
                y = y.toLowerCase();
            }

            if(x < y) {
                return reverse ? 1 : -1;
            }
            else if(x > y) {
                return reverse ? -1: 1;
            }
            else {
                return 0;
            }
        });

        return arr;
    },

    string: function(obj) {
        return r.copySafeness(obj, obj);
    },

    title: function(str) {
        var words = str.split(' ');
        for(var i = 0; i < words.length; i++) {
            words[i] = filters.capitalize(words[i]);
        }
        return r.copySafeness(str, words.join(' '));
    },

    trim: function(str) {
        return r.copySafeness(str, str.replace(/^\s*|\s*$/g, ''));
    },

    truncate: function(input, length, killwords, end) {
        var orig = input;
        length = length || 255;

        if (input.length <= length)
            return input;

        if (killwords) {
            input = input.substring(0, length);
        } else {
            var idx = input.lastIndexOf(' ', length);
            if(idx === -1) {
                idx = length;
            }

            input = input.substring(0, idx);
        }

        input += (end !== undefined && end !== null) ? end : '...';
        return r.copySafeness(orig, input);
    },

    upper: function(str) {
        return str.toUpperCase();
    },

    wordcount: function(str) {
        return str.match(/\w+/g).length;
    },

    'float': function(val, def) {
        var res = parseFloat(val);
        return isNaN(res) ? def : res;
    },

    'int': function(val, def) {
        var res = parseInt(val, 10);
        return isNaN(res) ? def : res;
    }
};

// Aliases
filters.d = filters['default'];
filters.e = filters.escape;

module.exports = filters;
<|endoftext|>