<commit_before>require('colors');

var SpecReporter = function(baseReporterDecorator, logger, formatError) {
  baseReporterDecorator(this);

  // colorize output of BaseReporter functions
  this.USE_COLORS = true;
  this.SPEC_FAILURE = '%s %s FAILED'.red + '\n';
  this.SPEC_SLOW = '%s SLOW %s: %s'.yellow + '\n';
  this.ERROR = '%s ERROR'.red + '\n';
  this.FINISHED_ERROR = ' ERROR'.red;
  this.FINISHED_SUCCESS = ' SUCCESS'.green;
  this.FINISHED_DISCONNECTED = ' DISCONNECTED'.red;
  this.X_FAILED = ' (%d FAILED)'.red;
  this.TOTAL_SUCCESS = 'TOTAL: %d SUCCESS'.green + '\n';
  this.TOTAL_FAILED = 'TOTAL: %d FAILED, %d SUCCESS'.red + '\n';

  this.onRunStart = function(browsers) {
    browsers.forEach(function(browser) {
      // useful properties
      browser.id;
      browser.fullName;
    });
  };

  this.onBrowserComplete = function(browser) {
    // useful properties
    var result = browser.lastResult;
    result.total;
    result.disconnected;
    result.error;
    result.failed;
    result.netTime; // in millieseconds? or microseconds?
  };

  this.onRunComplete = function(browsers, results) {
    // the renderBrowser function is defined in karma/reporters/Base.js
    this.writeCommonMsg(browsers.map(this.renderBrowser).join('\n') + '\n');

    if (browsers.length > 1 && !results.disconnected && !results.error) {
      if (!results.failed) {
        this.write(this.TOTAL_SUCCESS, results.success);
      } else {
        this.write(this.TOTAL_FAILED, results.failed, results.success);
      }
    }

    this.write("\n");
  };

  this.currentSuite = [];
  this.writeSpecMessage = function(status) {
    debugger;
    return (function(browser, result) {
      var suite = result.suite
      var indent = "";
      suite.forEach(
        // beware, this in the context of a foreach loop is not what you expect!
        // To be sure, we bind this explicitly
        (function(value, index) {
          if (index >= this.currentSuite.length || this.currentSuite[index] != value) {
            if (index == 0) {
              this.writeCommonMsg('\n');
            }
            this.writeCommonMsg(indent + value + ':\n');
            this.currentSuite = [];
          }
          indent += "    ";
        }).bind(this)
      );
      this.currentSuite = suite;

      var specName = result.description;
      //TODO: add timing information
      var msg = '  '  + indent + status + " - " + specName, specName

      result.log.forEach(function(log) {
        // TODO: have to find out, what this line exactly does. just copied it from karma's BaseReporter
        msg += formatError(log, '\t');
      });

      this.writeCommonMsg(msg + '\n');

      // other useful properties
      browser.id;
      browser.fullName;
      result.time;
      result.skipped;
      result.success;
    }).bind(this);
  };

  this.specSuccess = this.writeSpecMessage('PASSED '.green);
  this.specSkipped = this.writeSpecMessage('SKIPPED'.gray);
  this.specFailure = this.writeSpecMessage('FAILED '.red);
};

SpecReporter.$inject = ['baseReporterDecorator', 'logger', 'formatError'];

module.exports = {
  'reporter:spec': ['type', SpecReporter]
};
<commit_msg>Remove debugger.<commit_after>require('colors');

var SpecReporter = function(baseReporterDecorator, logger, formatError) {
  baseReporterDecorator(this);

  // colorize output of BaseReporter functions
  this.USE_COLORS = true;
  this.SPEC_FAILURE = '%s %s FAILED'.red + '\n';
  this.SPEC_SLOW = '%s SLOW %s: %s'.yellow + '\n';
  this.ERROR = '%s ERROR'.red + '\n';
  this.FINISHED_ERROR = ' ERROR'.red;
  this.FINISHED_SUCCESS = ' SUCCESS'.green;
  this.FINISHED_DISCONNECTED = ' DISCONNECTED'.red;
  this.X_FAILED = ' (%d FAILED)'.red;
  this.TOTAL_SUCCESS = 'TOTAL: %d SUCCESS'.green + '\n';
  this.TOTAL_FAILED = 'TOTAL: %d FAILED, %d SUCCESS'.red + '\n';

  this.onRunStart = function(browsers) {
    browsers.forEach(function(browser) {
      // useful properties
      browser.id;
      browser.fullName;
    });
  };

  this.onBrowserComplete = function(browser) {
    // useful properties
    var result = browser.lastResult;
    result.total;
    result.disconnected;
    result.error;
    result.failed;
    result.netTime; // in millieseconds? or microseconds?
  };

  this.onRunComplete = function(browsers, results) {
    // the renderBrowser function is defined in karma/reporters/Base.js
    this.writeCommonMsg(browsers.map(this.renderBrowser).join('\n') + '\n');

    if (browsers.length > 1 && !results.disconnected && !results.error) {
      if (!results.failed) {
        this.write(this.TOTAL_SUCCESS, results.success);
      } else {
        this.write(this.TOTAL_FAILED, results.failed, results.success);
      }
    }

    this.write("\n");
  };

  this.currentSuite = [];
  this.writeSpecMessage = function(status) {
    return (function(browser, result) {
      var suite = result.suite
      var indent = "";
      suite.forEach(
        // beware, this in the context of a foreach loop is not what you expect!
        // To be sure, we bind this explicitly
        (function(value, index) {
          if (index >= this.currentSuite.length || this.currentSuite[index] != value) {
            if (index == 0) {
              this.writeCommonMsg('\n');
            }
            this.writeCommonMsg(indent + value + ':\n');
            this.currentSuite = [];
          }
          indent += "    ";
        }).bind(this)
      );
      this.currentSuite = suite;

      var specName = result.description;
      //TODO: add timing information
      var msg = '  '  + indent + status + " - " + specName, specName

      result.log.forEach(function(log) {
        // TODO: have to find out, what this line exactly does. just copied it from karma's BaseReporter
        msg += formatError(log, '\t');
      });

      this.writeCommonMsg(msg + '\n');

      // other useful properties
      browser.id;
      browser.fullName;
      result.time;
      result.skipped;
      result.success;
    }).bind(this);
  };

  this.specSuccess = this.writeSpecMessage('PASSED '.green);
  this.specSkipped = this.writeSpecMessage('SKIPPED'.gray);
  this.specFailure = this.writeSpecMessage('FAILED '.red);
};

SpecReporter.$inject = ['baseReporterDecorator', 'logger', 'formatError'];

module.exports = {
  'reporter:spec': ['type', SpecReporter]
};
<|endoftext|>


<commit_before>// TODO: Build this list programmatically
var expressions = [
  /one \(1\)/,
  /two \(2\)/,
  /three \(3\)/,
  /four \(4\)/,
  /five \(5\)/ ]

function message(form, path, expression, match) {
  var word = match[1]
  return {
    message: "'" + word + "' repeats a written number and numeral, which is redundant and error-prone'",
    level: "info",
    path: path,
    source: 'doubleplus-numbers',
    url: null } }

var annotator = require('commonform-regexp-annotator')(expressions, message)

module.exports = annotator
<commit_msg>Fix RegExp match index<commit_after>// TODO: Build this list programmatically
var expressions = [
  /one \(1\)/,
  /two \(2\)/,
  /three \(3\)/,
  /four \(4\)/,
  /five \(5\)/ ]

function message(form, path, expression, match) {
  var word = match[0]
  return {
    message: "'" + word + "' repeats a written number and numeral, which is redundant and error-prone'",
    level: "info",
    path: path,
    source: 'doubleplus-numbers',
    url: null } }

var annotator = require('commonform-regexp-annotator')(expressions, message)

module.exports = annotator
<|endoftext|>


<commit_before>module.exports = function(url, callbackFunction)
{
	this.bindFunction = function (caller, object) {
		return function() {
			return caller.apply(object, [object]);
		};
	};

	this.stateChange = function (object) {
		if (this.request.readyState==4)
			this.callbackFunction(this.request.responseText);
	};

	this.getRequest = function() {
		if (window.ActiveXObject)
			return new ActiveXObject('Microsoft.XMLHTTP');
		else if (window.XMLHttpRequest)
			return new XMLHttpRequest();
		return false;
	};

	this.postBody = (arguments[2] || "");

	this.callbackFunction=callbackFunction;
	this.url=url;
	this.request = this.getRequest();

	if(this.request) {
		var req = this.request;
		req.onreadystatechange = this.bindFunction(this.stateChange, this);

		if (this.postBody!=="") {
			req.open("POST", url, true);
			req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
		} else {
			req.open("GET", url, true);
		}

    req.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

		req.send(this.postBody);
	}
}
<commit_msg>Clean up code.<commit_after>function newXHR() {
  if (window.ActiveXObject)
    return new ActiveXObject('Microsoft.XMLHTTP');
  else if (window.XMLHttpRequest)
    return new XMLHttpRequest();
  return null;
};

module.exports = function(url, callback, postBody) {
  var xhr = newXHR();

  if (!xhr)
    return;

  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4)
      callback(xhr.responseText);
  };

  if (postBody) {
    xhr.open('POST', url, true);
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  }
  else
    xhr.open('GET', url, true);

  xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
  xhr.send(this.postBody);
};
<|endoftext|>


<commit_before>var fs     = require('fs');
var path   = require('path');
var xml2js = require('xml2js');
var ig     = require('imagemagick');
var colors = require('colors');
var _      = require('underscore');
var Q      = require('q');
var wrench = require('wrench');

/**
 * Check which platforms are added to the project and return their splash screen names and sizes
 *
 * @param  {String} projectName
 * @return {Promise} resolves with an array of platforms
 */
var getPlatforms = function (projectName) {
  var deferred = Q.defer();
  var platforms = [];
  platforms.push({
    name : 'ios',
    // TODO: use async fs.exists
    isAdded : fs.existsSync('platforms/ios'),
    splashPath : 'platforms/ios/' + projectName + '/Images.xcassets/LaunchImage.launchimage/',
    splash : [
      // iPhone
      { name: 'Default~iphone.png',            width: 320,  height: 480  },
      { name: 'Default@2x~iphone.png',         width: 640,  height: 960  },
      { name: 'Default-568h@2x~iphone.png',    width: 640,  height: 1136 },
      { name: 'Default-667h.png',              width: 750,  height: 1334 },
      { name: 'Default-736h.png',              width: 1242, height: 2208 },
      { name: 'Default-Landscape-736h.png',    width: 2208, height: 1242 },
      // iPad
      { name: 'Default-Portrait~ipad.png',     width: 768,  height: 1024 },
      { name: 'Default-Portrait@2x~ipad.png',  width: 1536, height: 2048 },
      { name: 'Default-Landscape~ipad.png',    width: 1024, height: 768  },
      { name: 'Default-Landscape@2x~ipad.png', width: 2048, height: 1536 }
    ]
  });
  platforms.push({
    name : 'android',
    isAdded : fs.existsSync('platforms/android'),
    splashPath : 'platforms/android/res/',
    splash : [
      { name: 'drawable-land-ldpi/screen.png',  width: 320,  height: 200  },
      { name: 'drawable-land-mdpi/screen.png',  width: 480,  height: 320  },
      { name: 'drawable-land-hdpi/screen.png',  width: 800,  height: 480  },
      { name: 'drawable-land-xhdpi/screen.png', width: 1280, height: 720  },
      { name: 'drawable-port-ldpi/screen.png',  width: 200,  height: 320  },
      { name: 'drawable-port-mdpi/screen.png',  width: 320,  height: 480  },
      { name: 'drawable-port-hdpi/screen.png',  width: 480,  height: 800  },
      { name: 'drawable-port-xhdpi/screen.png', width: 720,  height: 1280 }
    ]
  });
  platforms.push({
    name : 'windows',
    isAdded : fs.existsSync('platforms/windows'),
    splashPath : 'platforms/windows/images/',
    splash : [
      { name: 'SplashScreen.scale-100.png', width: 620,  height: 300  },
      { name: 'SplashScreen.scale-125.png', width: 775,  height: 375  },
      { name: 'SplashScreen.scale-150.png', width: 930,  height: 450  },
      { name: 'SplashScreen.scale-200.png', width: 1240, height: 600  },
      { name: 'SplashScreen.scale-400.png', width: 2480, height: 1200 }
    ]
  });
  deferred.resolve(platforms);
  return deferred.promise;
};

/**
 * @var {Object} settings - names of the config file and of the splash image
 * TODO: add option to get these values as CLI params
 */
var settings = {};
settings.CONFIG_FILE = 'config.xml';
settings.SPLASH_FILE   = 'splash.png';

/**
 * @var {Object} console utils
 */
var display = {};
display.success = function (str) {
  str = '✓  '.green + str;
  console.log('  ' + str);
};
display.error = function (str) {
  str = '✗  '.red + str;
  console.log('  ' + str);
};
display.header = function (str) {
  console.log('');
  console.log(' ' + str.cyan.underline);
  console.log('');
};

/**
 * read the config file and get the project name
 *
 * @return {Promise} resolves to a string - the project's name
 */
var getProjectName = function () {
  var deferred = Q.defer();
  var parser = new xml2js.Parser();
  data = fs.readFile(settings.CONFIG_FILE, function (err, data) {
    if (err) {
      deferred.reject(err);
    }
    parser.parseString(data, function (err, result) {
      if (err) {
        deferred.reject(err);
      }
      var projectName = result.widget.name[0];
      deferred.resolve(projectName);
    });
  });
  return deferred.promise;
};

/**
 * Crops and creates a new splash in the platform's folder.
 *
 * @param  {Object} platform
 * @param  {Object} splash
 * @return {Promise}
 */
var generateSplash = function (platform, splash) {
  var deferred = Q.defer();
  var srcPath = settings.SPLASH_FILE;
  var platformPath = srcPath.replace(/\.png$/, '-' + platform.name + '.png');
  if (fs.existsSync(platformPath)) {
    srcPath = platformPath;
  }
  var dstPath = platform.splashPath + splash.name;
  var dst = path.dirname(dstPath);
  if (!fs.existsSync(dst)) {
    wrench.mkdirSyncRecursive(dst);
  }
  ig.crop({
    srcPath: srcPath,
    dstPath: dstPath,
    quality: 1,
    format: 'png',
    width: splash.width,
    height: splash.height
  } , function(err, stdout, stderr){
    if (err) {
      deferred.reject(err);
    } else {
      deferred.resolve();
      display.success(splash.name + ' created');
    }
  });
  return deferred.promise;
};

/**
 * Generates splash based on the platform object
 *
 * @param  {Object} platform
 * @return {Promise}
 */
var generateSplashForPlatform = function (platform) {
  var deferred = Q.defer();
  display.header('Generating splash screen for ' + platform.name);
  var all = [];
  var splashes = platform.splash;
  splashes.forEach(function (splash) {
    all.push(generateSplash(platform, splash));
  });
  Q.all(all).then(function () {
    deferred.resolve();
  }).catch(function (err) {
    console.log(err);
  });
  return deferred.promise;
};

/**
 * Goes over all the platforms and triggers splash screen generation
 *
 * @param  {Array} platforms
 * @return {Promise}
 */
var generateSplashes = function (platforms) {
  var deferred = Q.defer();
  var sequence = Q();
  var all = [];
  _(platforms).where({ isAdded : true }).forEach(function (platform) {
    sequence = sequence.then(function () {
      return generateSplashForPlatform(platform);
    });
    all.push(sequence);
  });
  Q.all(all).then(function () {
    deferred.resolve();
  });
  return deferred.promise;
};

/**
 * Checks if at least one platform was added to the project
 *
 * @return {Promise} resolves if at least one platform was found, rejects otherwise
 */
var atLeastOnePlatformFound = function () {
  var deferred = Q.defer();
  getPlatforms().then(function (platforms) {
    var activePlatforms = _(platforms).where({ isAdded : true });
    if (activePlatforms.length > 0) {
      display.success('platforms found: ' + _(activePlatforms).pluck('name').join(', '));
      deferred.resolve();
    } else {
      display.error('No cordova platforms found. Make sure you are in the root folder of your Cordova project and add platforms with \'cordova platform add\'');
      deferred.reject();
    }
  });
  return deferred.promise;
};

/**
 * Checks if a valid splash file exists
 *
 * @return {Promise} resolves if exists, rejects otherwise
 */
var validSplashExists = function () {
  var deferred = Q.defer();
  fs.exists(settings.SPLASH_FILE, function (exists) {
    if (exists) {
      display.success(settings.SPLASH_FILE + ' exists');
      deferred.resolve();
    } else {
      display.error(settings.SPLASH_FILE + ' does not exist in the root folder');
      deferred.reject();
    }
  });
  return deferred.promise;
};

/**
 * Checks if a config.xml file exists
 *
 * @return {Promise} resolves if exists, rejects otherwise
 */
var configFileExists = function () {
  var deferred = Q.defer();
  fs.exists(settings.CONFIG_FILE, function (exists) {
    if (exists) {
      display.success(settings.CONFIG_FILE + ' exists');
      deferred.resolve();
    } else {
      display.error('cordova\'s ' + settings.CONFIG_FILE + ' does not exist in the root folder');
      deferred.reject();
    }
  });
  return deferred.promise;
};

display.header('Checking Project & Splash');

atLeastOnePlatformFound()
.then(validSplashExists)
.then(configFileExists)
.then(getProjectName)
.then(getPlatforms)
.then(generateSplashes)
.catch(function (err) {
  if (err) {
    console.log(err);
  }
}).then(function () {
  console.log('');
});
<commit_msg>Android: Add xxhdpi & xxxhdpi<commit_after>var fs     = require('fs');
var path   = require('path');
var xml2js = require('xml2js');
var ig     = require('imagemagick');
var colors = require('colors');
var _      = require('underscore');
var Q      = require('q');
var wrench = require('wrench');

/**
 * Check which platforms are added to the project and return their splash screen names and sizes
 *
 * @param  {String} projectName
 * @return {Promise} resolves with an array of platforms
 */
var getPlatforms = function (projectName) {
  var deferred = Q.defer();
  var platforms = [];
  platforms.push({
    name : 'ios',
    // TODO: use async fs.exists
    isAdded : fs.existsSync('platforms/ios'),
    splashPath : 'platforms/ios/' + projectName + '/Images.xcassets/LaunchImage.launchimage/',
    splash : [
      // iPhone
      { name: 'Default~iphone.png',            width: 320,  height: 480  },
      { name: 'Default@2x~iphone.png',         width: 640,  height: 960  },
      { name: 'Default-568h@2x~iphone.png',    width: 640,  height: 1136 },
      { name: 'Default-667h.png',              width: 750,  height: 1334 },
      { name: 'Default-736h.png',              width: 1242, height: 2208 },
      { name: 'Default-Landscape-736h.png',    width: 2208, height: 1242 },
      // iPad
      { name: 'Default-Portrait~ipad.png',     width: 768,  height: 1024 },
      { name: 'Default-Portrait@2x~ipad.png',  width: 1536, height: 2048 },
      { name: 'Default-Landscape~ipad.png',    width: 1024, height: 768  },
      { name: 'Default-Landscape@2x~ipad.png', width: 2048, height: 1536 }
    ]
  });
  platforms.push({
    name : 'android',
    isAdded : fs.existsSync('platforms/android'),
    splashPath : 'platforms/android/res/',
    splash : [
      // Landscape
      { name: 'drawable-land-ldpi/screen.png',  width: 320,  height: 200  },
      { name: 'drawable-land-mdpi/screen.png',  width: 480,  height: 320  },
      { name: 'drawable-land-hdpi/screen.png',  width: 800,  height: 480  },
      { name: 'drawable-land-xhdpi/screen.png', width: 1280, height: 720  },
      { name: 'drawable-land-xxhdpi/screen.png', width: 1600, height: 960  },
      { name: 'drawable-land-xxxhdpi/screen.png', width: 1920, height: 1280  },
      // Portrait
      { name: 'drawable-port-ldpi/screen.png',  width: 200,  height: 320  },
      { name: 'drawable-port-mdpi/screen.png',  width: 320,  height: 480  },
      { name: 'drawable-port-hdpi/screen.png',  width: 480,  height: 800  },
      { name: 'drawable-port-xhdpi/screen.png', width: 720,  height: 1280 },
      { name: 'drawable-port-xxhdpi/screen.png', width: 960, height: 1600  },
      { name: 'drawable-port-xxxhdpi/screen.png', width: 1280, height: 1920  }
    ]
  });
  platforms.push({
    name : 'windows',
    isAdded : fs.existsSync('platforms/windows'),
    splashPath : 'platforms/windows/images/',
    splash : [
      { name: 'SplashScreen.scale-100.png', width: 620,  height: 300  },
      { name: 'SplashScreen.scale-125.png', width: 775,  height: 375  },
      { name: 'SplashScreen.scale-150.png', width: 930,  height: 450  },
      { name: 'SplashScreen.scale-200.png', width: 1240, height: 600  },
      { name: 'SplashScreen.scale-400.png', width: 2480, height: 1200 }
    ]
  });
  deferred.resolve(platforms);
  return deferred.promise;
};

/**
 * @var {Object} settings - names of the config file and of the splash image
 * TODO: add option to get these values as CLI params
 */
var settings = {};
settings.CONFIG_FILE = 'config.xml';
settings.SPLASH_FILE   = 'splash.png';

/**
 * @var {Object} console utils
 */
var display = {};
display.success = function (str) {
  str = '✓  '.green + str;
  console.log('  ' + str);
};
display.error = function (str) {
  str = '✗  '.red + str;
  console.log('  ' + str);
};
display.header = function (str) {
  console.log('');
  console.log(' ' + str.cyan.underline);
  console.log('');
};

/**
 * read the config file and get the project name
 *
 * @return {Promise} resolves to a string - the project's name
 */
var getProjectName = function () {
  var deferred = Q.defer();
  var parser = new xml2js.Parser();
  data = fs.readFile(settings.CONFIG_FILE, function (err, data) {
    if (err) {
      deferred.reject(err);
    }
    parser.parseString(data, function (err, result) {
      if (err) {
        deferred.reject(err);
      }
      var projectName = result.widget.name[0];
      deferred.resolve(projectName);
    });
  });
  return deferred.promise;
};

/**
 * Crops and creates a new splash in the platform's folder.
 *
 * @param  {Object} platform
 * @param  {Object} splash
 * @return {Promise}
 */
var generateSplash = function (platform, splash) {
  var deferred = Q.defer();
  var srcPath = settings.SPLASH_FILE;
  var platformPath = srcPath.replace(/\.png$/, '-' + platform.name + '.png');
  if (fs.existsSync(platformPath)) {
    srcPath = platformPath;
  }
  var dstPath = platform.splashPath + splash.name;
  var dst = path.dirname(dstPath);
  if (!fs.existsSync(dst)) {
    wrench.mkdirSyncRecursive(dst);
  }
  ig.crop({
    srcPath: srcPath,
    dstPath: dstPath,
    quality: 1,
    format: 'png',
    width: splash.width,
    height: splash.height
  } , function(err, stdout, stderr){
    if (err) {
      deferred.reject(err);
    } else {
      deferred.resolve();
      display.success(splash.name + ' created');
    }
  });
  return deferred.promise;
};

/**
 * Generates splash based on the platform object
 *
 * @param  {Object} platform
 * @return {Promise}
 */
var generateSplashForPlatform = function (platform) {
  var deferred = Q.defer();
  display.header('Generating splash screen for ' + platform.name);
  var all = [];
  var splashes = platform.splash;
  splashes.forEach(function (splash) {
    all.push(generateSplash(platform, splash));
  });
  Q.all(all).then(function () {
    deferred.resolve();
  }).catch(function (err) {
    console.log(err);
  });
  return deferred.promise;
};

/**
 * Goes over all the platforms and triggers splash screen generation
 *
 * @param  {Array} platforms
 * @return {Promise}
 */
var generateSplashes = function (platforms) {
  var deferred = Q.defer();
  var sequence = Q();
  var all = [];
  _(platforms).where({ isAdded : true }).forEach(function (platform) {
    sequence = sequence.then(function () {
      return generateSplashForPlatform(platform);
    });
    all.push(sequence);
  });
  Q.all(all).then(function () {
    deferred.resolve();
  });
  return deferred.promise;
};

/**
 * Checks if at least one platform was added to the project
 *
 * @return {Promise} resolves if at least one platform was found, rejects otherwise
 */
var atLeastOnePlatformFound = function () {
  var deferred = Q.defer();
  getPlatforms().then(function (platforms) {
    var activePlatforms = _(platforms).where({ isAdded : true });
    if (activePlatforms.length > 0) {
      display.success('platforms found: ' + _(activePlatforms).pluck('name').join(', '));
      deferred.resolve();
    } else {
      display.error('No cordova platforms found. Make sure you are in the root folder of your Cordova project and add platforms with \'cordova platform add\'');
      deferred.reject();
    }
  });
  return deferred.promise;
};

/**
 * Checks if a valid splash file exists
 *
 * @return {Promise} resolves if exists, rejects otherwise
 */
var validSplashExists = function () {
  var deferred = Q.defer();
  fs.exists(settings.SPLASH_FILE, function (exists) {
    if (exists) {
      display.success(settings.SPLASH_FILE + ' exists');
      deferred.resolve();
    } else {
      display.error(settings.SPLASH_FILE + ' does not exist in the root folder');
      deferred.reject();
    }
  });
  return deferred.promise;
};

/**
 * Checks if a config.xml file exists
 *
 * @return {Promise} resolves if exists, rejects otherwise
 */
var configFileExists = function () {
  var deferred = Q.defer();
  fs.exists(settings.CONFIG_FILE, function (exists) {
    if (exists) {
      display.success(settings.CONFIG_FILE + ' exists');
      deferred.resolve();
    } else {
      display.error('cordova\'s ' + settings.CONFIG_FILE + ' does not exist in the root folder');
      deferred.reject();
    }
  });
  return deferred.promise;
};

display.header('Checking Project & Splash');

atLeastOnePlatformFound()
.then(validSplashExists)
.then(configFileExists)
.then(getProjectName)
.then(getPlatforms)
.then(generateSplashes)
.catch(function (err) {
  if (err) {
    console.log(err);
  }
}).then(function () {
  console.log('');
});
<|endoftext|>


<commit_before>var _ = require("lodash");
var fs = require("fs");
var path = require("path");

var retro = require("./lib/retro");
var block = require("./lib/block");

var QUIZ_WEBSITE_TPL = _.template(fs.readFileSync(path.resolve(__dirname, "./assets/website_quiz.html")));
var QUIZ_EBOOK_TPL = _.template(fs.readFileSync(path.resolve(__dirname, "./assets/ebook_quiz.html")));

module.exports = {
    website: {
        assets: "./assets",
        js: [
            "quizzes.js",
        ],
        css: [
            "quizzes.css"
        ],
    },
    blocks: {
        quiz: {
            process: function(blk) {
                // Extract quiz info
                var context = block(blk.body);

                // Select appropriate template
                var tpl = (this.generator === 'ebook' ? QUIZ_EBOOK_TPL : QUIZ_WEBSITE_TPL);

                return tpl(context);
            }
        }
    },
    hooks: {
        "page:before": function(page) {
            // Skip all non markdown pages
            if(page.type != "markdown") {
                return page;
            }

            // Rewrite content (modernizing old exercises)
            page.content = retro(page.content);

            // Return modified page
            return page;
        }
    }
};
<commit_msg>Fix index.js' template context<commit_after>var _ = require("lodash");
var fs = require("fs");
var path = require("path");

var retro = require("./lib/retro");
var block = require("./lib/block");

var QUIZ_WEBSITE_TPL = _.template(fs.readFileSync(path.resolve(__dirname, "./assets/website_quiz.html")));
var QUIZ_EBOOK_TPL = _.template(fs.readFileSync(path.resolve(__dirname, "./assets/ebook_quiz.html")));

module.exports = {
    website: {
        assets: "./assets",
        js: [
            "quizzes.js",
        ],
        css: [
            "quizzes.css"
        ],
    },
    blocks: {
        quiz: {
            process: function(blk) {
                // Extract quiz info
                var context = block(blk.body);

                // Select appropriate template
                var tpl = (this.generator === 'ebook' ? QUIZ_EBOOK_TPL : QUIZ_WEBSITE_TPL);

                return tpl({
                    quiz: context
                });
            }
        }
    },
    hooks: {
        "page:before": function(page) {
            // Skip all non markdown pages
            if(page.type != "markdown") {
                return page;
            }

            // Rewrite content (modernizing old exercises)
            page.content = retro(page.content);

            // Return modified page
            return page;
        }
    }
};
<|endoftext|>


<commit_before>/**
 * @module index.js
 * @summary: Wires up the cloud library.
 *
 * @description:
 *
 * Author: justin
 * Created On: 2015-03-21.
 * @license Apache-2.0
 */

require('win-common')();

module.exports = function construct(config, logger) {
  var m = {};
  config = config || {};
  config = _.defaults(config, {
    // useGlobals: true
  });

  m.Storage = require('./src/blob/storage');
  m.EventLogger = require('./src/event/event-logger');
  //m.nosql = {};  // TODO: add a nosql provider.
  // m.notification = require('./src/notification/notification-svc')(config);  // TODO: implement email service.
  m.Queue = require('./src/queue/queue');
  m.TaskQueue = require('./src/task/task-queue');

  m.eventLogger = m.EventLogger(config.eventLog, m.Queue(config.eventQueueName), logger);

  return m;
};
<commit_msg>Expose TaskRunner api.<commit_after>/**
 * @module index.js
 * @summary: Wires up the cloud library.
 *
 * @description:
 *
 * Author: justin
 * Created On: 2015-03-21.
 * @license Apache-2.0
 */

require('win-common')();

module.exports = function construct(config, logger) {
  var m = {};
  config = config || {};
  config = _.defaults(config, {
    // useGlobals: true
  });

  m.Storage = require('./src/blob/storage');
  m.EventLogger = require('./src/event/event-logger');
  //m.nosql = {};  // TODO: add a nosql provider.
  // m.notification = require('./src/notification/notification-svc')(config);  // TODO: implement email service.
  m.Queue = require('./src/queue/queue');
  m.TaskQueue = require('./src/task/task-queue');
  m.TaskRunner = require('./src/task/task-runner');

  m.eventLogger = m.EventLogger(config.eventLog, m.Queue(config.eventQueueName), logger);

  return m;
};
<|endoftext|>


<commit_before>/**
 * A Bot for Slack!
 */

/**
 * Define a function for initiating a conversation on installation
 * With custom integrations, we don't have a way to find out who installed us, so we can't message them :(
 */

function onInstallation(bot, installer) {
    if (installer) {
        bot.startPrivateConversation({user: installer}, function (err, convo) {
            if (err) {
                console.log(err);
            } else {
                convo.say('I am a bot that has just joined your team');
                convo.say('You must now /invite me to a channel so that I can be of use!');
            }
        });
    }
}

/**
 * Configure the persistence options
 */

var config = {};
if (process.env.MONGOLAB_URI) {
    var BotkitStorage = require('botkit-storage-mongo');
    config = {
        storage: BotkitStorage({mongoUri: process.env.MONGOLAB_URI}),
    };
} else {
    config = {
        json_file_store: ((process.env.TOKEN)?'./db_slack_bot_ci/':'./db_slack_bot_a/'), //use a different name if an app or CI
    };
}

/**
 * Are being run as an app or a custom integration? The initialization will differ, depending
 */

if (process.env.TOKEN || process.env.SLACK_TOKEN) {
    //Treat this as a custom integration
    var customIntegration = require('./lib/custom_integrations');
    var token = (process.env.TOKEN) ? process.env.TOKEN : process.env.SLACK_TOKEN;
    var controller = customIntegration.configure(token, config, onInstallation);
} else if (process.env.CLIENT_ID && process.env.CLIENT_SECRET && process.env.PORT) {
    //Treat this as an app
    var app = require('./lib/apps');
    var controller = app.configure(process.env.PORT, process.env.CLIENT_ID, process.env.CLIENT_SECRET, config, onInstallation);
} else {
    console.log('Error: If this is a custom integration, please specify TOKEN in the environment. If this is an app, please specify CLIENTID, CLIENTSECRET, and PORT in the environment');
    process.exit(1);
}

/**
 * A demonstration for how to handle websocket events. In this case, just log when we have and have not
 * been disconnected from the websocket. In the future, it would be super awesome to be able to specify
 * a reconnect policy, and do reconnections automatically. In the meantime, we aren't going to attempt reconnects,
 * WHICH IS A B0RKED WAY TO HANDLE BEING DISCONNECTED. So we need to fix this.
 *
 * TODO: fixed b0rked reconnect behavior
 */
// Handle events related to the websocket connection to Slack
controller.on('rtm_open', function (bot) {
    console.log('** The RTM api just connected!');
});

controller.on('rtm_close', function (bot) {
    console.log('** The RTM api just closed');
    // you may want to attempt to re-open
});

/**
 * Core bot logic goes here!
 */
// BEGIN EDITING HERE!

var date = new Date()
console.log(date.toLocaleTimeString());

var schedule = require('node-schedule');
var request = require('request');

controller.on('bot_channel_join', function (bot, message) {
    bot.reply(message, "I'm here!")
});

const botAPI = controller.spawn({
  token: token,
  retry: 'Infinity'
})

var j = schedule.scheduleJob(' */1 9-14 * * 1-5 ', function () {

    var chosen_message;

    controller.on('bot_channel_join', function (bot, message) {
    bot.reply(message, "I'm here!")
});

const botAPI = controller.spawn({
  token: token,
  retry: 'Infinity'
})

request.post(                    //Find the time the last message was posted, set to lastmessagedelay
    'https://slack.com/api/channels.history?channel=C3P05V49W&pretty=1&token=' + process.env.TOKEN,
        function (error, response, body) {
    if (error)
        console.log("Error:", error)
    else
        var time = JSON.parse(response.body);
        var timestamp = time.messages[0].ts     // find Slack timestamp
        var milliseconds = (new Date).getTime(); // find epoch timestamp
        var currenttime = (milliseconds/1000) // convert epoch to seconds
        var lastmessagedelay = currenttime-timestamp; // calculate time since last message
        var timetowait = 60
        var postmessage = (lastmessagedelay > timetowait) ? "Post":"Dont Post";

            console.log('----currenttime-------->'+ currenttime)
            console.log('----slacktimestamp----->'+ timestamp)
            console.log('-----seconds since last message-------->'+ lastmessagedelay)
            console.log('-----time to wait-------->' + timetowait)
            console.log('-----lastmessagedelay - time to wait -------->' + lastmessagedelay-timetowait)
            console.log('----TF-------' + postmessage)

if (postmessage == "Post"){
    console.log(`---------test passes -------`)

request.post(
    'https://engine.adzerk.net/api/v2',
    { json: { placements: [ { divName: "div1", networkId: 9820, siteId: 687249, adTypes: [20] } ] } },
    function (error, response, body) {

      if (error)
        console.log("Error:", error);
      else if (response.statusCode !== 200) {
        console.log("Expected status 200, got", response.statusCode);
	  }
      else
        console.log("OK:", JSON.stringify(body, null, 2));
        chosen_message = response.body.decisions.div1.contents[0].data.customData.chosen_message

        impression = response.body.decisions.div1.impressionUrl
  request(impression, function (error, response, body) {
      if (!error && response.statusCode == 200) {  }

    }
)

  controller.on('bot_channel_join', function (bot, message) {
    bot.reply(message, "I'm here!")
});

const botAPI = controller.spawn({
  token: token,
  retry: 'Infinity'
})

            botAPI.startRTM((err, bot, payload) => {
            bot.say({text: chosen_message, channel:"C3P05V49W"})
            setTimeout(function(){console.log('hihihi')}, 500)

  request.post(
    'https://slack.com/api/channels.history?channel=C3P05V49W&pretty=1&token=' + process.env.TOKEN,
        function (error, response, body) {
    if (error)
        console.log("Error:", error)
    else
        var time = JSON.parse(response.body)
        var timestamp = time.messages[0].ts

            bot.api.reactions.add({
                 timestamp: timestamp,
                 channel: "C3P05V49W",
                 name: 'thumbsup'})
            setTimeout(function(){
                bot.api.reactions.add({
                         timestamp: timestamp,
                         channel: "C3P05V49W",
                         name: 'thumbsdown'})
                                }, 250)
                  })

  })

            })

    }})
})

        ;<commit_msg>switch to 60 minutes<commit_after>/**
 * A Bot for Slack!
 */

/**
 * Define a function for initiating a conversation on installation
 * With custom integrations, we don't have a way to find out who installed us, so we can't message them :(
 */

function onInstallation(bot, installer) {
    if (installer) {
        bot.startPrivateConversation({user: installer}, function (err, convo) {
            if (err) {
                console.log(err);
            } else {
                convo.say('I am a bot that has just joined your team');
                convo.say('You must now /invite me to a channel so that I can be of use!');
            }
        });
    }
}

/**
 * Configure the persistence options
 */

var config = {};
if (process.env.MONGOLAB_URI) {
    var BotkitStorage = require('botkit-storage-mongo');
    config = {
        storage: BotkitStorage({mongoUri: process.env.MONGOLAB_URI}),
    };
} else {
    config = {
        json_file_store: ((process.env.TOKEN)?'./db_slack_bot_ci/':'./db_slack_bot_a/'), //use a different name if an app or CI
    };
}

/**
 * Are being run as an app or a custom integration? The initialization will differ, depending
 */

if (process.env.TOKEN || process.env.SLACK_TOKEN) {
    //Treat this as a custom integration
    var customIntegration = require('./lib/custom_integrations');
    var token = (process.env.TOKEN) ? process.env.TOKEN : process.env.SLACK_TOKEN;
    var controller = customIntegration.configure(token, config, onInstallation);
} else if (process.env.CLIENT_ID && process.env.CLIENT_SECRET && process.env.PORT) {
    //Treat this as an app
    var app = require('./lib/apps');
    var controller = app.configure(process.env.PORT, process.env.CLIENT_ID, process.env.CLIENT_SECRET, config, onInstallation);
} else {
    console.log('Error: If this is a custom integration, please specify TOKEN in the environment. If this is an app, please specify CLIENTID, CLIENTSECRET, and PORT in the environment');
    process.exit(1);
}

/**
 * A demonstration for how to handle websocket events. In this case, just log when we have and have not
 * been disconnected from the websocket. In the future, it would be super awesome to be able to specify
 * a reconnect policy, and do reconnections automatically. In the meantime, we aren't going to attempt reconnects,
 * WHICH IS A B0RKED WAY TO HANDLE BEING DISCONNECTED. So we need to fix this.
 *
 * TODO: fixed b0rked reconnect behavior
 */
// Handle events related to the websocket connection to Slack
controller.on('rtm_open', function (bot) {
    console.log('** The RTM api just connected!');
});

controller.on('rtm_close', function (bot) {
    console.log('** The RTM api just closed');
    // you may want to attempt to re-open
});

/**
 * Core bot logic goes here!
 */
// BEGIN EDITING HERE!

var date = new Date()
console.log(date.toLocaleTimeString());

var schedule = require('node-schedule');
var request = require('request');

controller.on('bot_channel_join', function (bot, message) {
    bot.reply(message, "I'm here!")
});

const botAPI = controller.spawn({
  token: token,
  retry: 'Infinity'
})

var j = schedule.scheduleJob(' */1 9-14 * * 1-5 ', function () {

    var chosen_message;

    controller.on('bot_channel_join', function (bot, message) {
    bot.reply(message, "I'm here!")
});

const botAPI = controller.spawn({
  token: token,
  retry: 'Infinity'
})

request.post(                    //Find the time the last message was posted, set to lastmessagedelay
    'https://slack.com/api/channels.history?channel=C3P05V49W&pretty=1&token=' + process.env.TOKEN,
        function (error, response, body) {
    if (error)
        console.log("Error:", error)
    else
        var time = JSON.parse(response.body);
        var timestamp = time.messages[0].ts     // find Slack timestamp
        var milliseconds = (new Date).getTime(); // find epoch timestamp
        var currenttime = (milliseconds/1000) // convert epoch to seconds
        var lastmessagedelay = currenttime-timestamp; // calculate time since last message
        var timetowait = 3600
        var postmessage = (lastmessagedelay > timetowait) ? "Post":"Dont Post";

            console.log('----currenttime-------->'+ currenttime)
            console.log('----slacktimestamp----->'+ timestamp)
            console.log('-----seconds since last message-------->'+ lastmessagedelay)
            console.log('-----time to wait-------->' + timetowait)
            console.log('-----lastmessagedelay - time to wait -------->' + lastmessagedelay-timetowait)
            console.log('----TF-------' + postmessage)

if (postmessage == "Post"){
    console.log(`---------test passes -------`)

request.post(
    'https://engine.adzerk.net/api/v2',
    { json: { placements: [ { divName: "div1", networkId: 9820, siteId: 687249, adTypes: [20] } ] } },
    function (error, response, body) {

      if (error)
        console.log("Error:", error);
      else if (response.statusCode !== 200) {
        console.log("Expected status 200, got", response.statusCode);
	  }
      else
        console.log("OK:", JSON.stringify(body, null, 2));
        chosen_message = response.body.decisions.div1.contents[0].data.customData.chosen_message

        impression = response.body.decisions.div1.impressionUrl
  request(impression, function (error, response, body) {
      if (!error && response.statusCode == 200) {  }

    }
)

  controller.on('bot_channel_join', function (bot, message) {
    bot.reply(message, "I'm here!")
});

const botAPI = controller.spawn({
  token: token,
  retry: 'Infinity'
})

            botAPI.startRTM((err, bot, payload) => {
            bot.say({text: chosen_message, channel:"C3P05V49W"})
            setTimeout(function(){console.log('hihihi')}, 500)

  request.post(
    'https://slack.com/api/channels.history?channel=C3P05V49W&pretty=1&token=' + process.env.TOKEN,
        function (error, response, body) {
    if (error)
        console.log("Error:", error)
    else
        var time = JSON.parse(response.body)
        var timestamp = time.messages[0].ts

            bot.api.reactions.add({
                 timestamp: timestamp,
                 channel: "C3P05V49W",
                 name: 'thumbsup'})
            setTimeout(function(){
                bot.api.reactions.add({
                         timestamp: timestamp,
                         channel: "C3P05V49W",
                         name: 'thumbsdown'})
                                }, 250)
                  })

  })

            })

    }})
})

        ;<|endoftext|>


<commit_before>var url = require("url");
var http = require("http");
var https = require("https");
var assert = require("assert");
var Writable = require("stream").Writable;
var debug = require("debug")("follow-redirects");

// RFC7231§4.2.1: Of the request methods defined by this specification,
// the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe.
var SAFE_METHODS = { GET: true, HEAD: true, OPTIONS: true, TRACE: true };

// Create handlers that pass events from native requests
var eventHandlers = Object.create(null);
["abort", "aborted", "error", "socket", "timeout"].forEach(function (event) {
  eventHandlers[event] = function (arg) {
    this._redirectable.emit(event, arg);
  };
});

// An HTTP(S) request that can be redirected
function RedirectableRequest(options, responseCallback) {
  // Initialize the request
  Writable.call(this);
  options.headers = options.headers || {};
  this._options = options;
  this._redirectCount = 0;
  this._redirects = [];
  this._requestBodyLength = 0;
  this._requestBodyBuffers = [];

  // Attach a callback if passed
  if (responseCallback) {
    this.on("response", responseCallback);
  }

  // React to responses of native requests
  var self = this;
  this._onNativeResponse = function (response) {
    self._processResponse(response);
  };

  // Complete the URL object when necessary
  if (!options.pathname && options.path) {
    var searchPos = options.path.indexOf("?");
    if (searchPos < 0) {
      options.pathname = options.path;
    }
    else {
      options.pathname = options.path.substring(0, searchPos);
      options.search = options.path.substring(searchPos);
    }
  }

  // Perform the first request
  this._performRequest();
}
RedirectableRequest.prototype = Object.create(Writable.prototype);

// Writes buffered data to the current native request
RedirectableRequest.prototype.write = function (data, encoding, callback) {
  if (!(typeof data === "string" || typeof data === "object" && ("length" in data))) {
    throw new Error("data should be a string, Buffer or Uint8Array");
  }
  if (this._requestBodyLength + data.length <= this._options.maxBodyLength) {
    this._requestBodyLength += data.length;
    this._requestBodyBuffers.push({ data: data, encoding: encoding });
    this._currentRequest.write(data, encoding, callback);
  }
  else {
    this.emit("error", new Error("Request body larger than maxBodyLength limit"));
    this.abort();
  }
};

// Ends the current native request
RedirectableRequest.prototype.end = function (data, encoding, callback) {
  var currentRequest = this._currentRequest;
  if (!data) {
    currentRequest.end(null, null, callback);
  }
  else {
    this.write(data, encoding, function () {
      currentRequest.end(null, null, callback);
    });
  }
};

// Sets a header value on the current native request
RedirectableRequest.prototype.setHeader = function (name, value) {
  this._options.headers[name] = value;
  this._currentRequest.setHeader(name, value);
};

// Clears a header value on the current native request
RedirectableRequest.prototype.removeHeader = function (name) {
  delete this._options.headers[name];
  this._currentRequest.removeHeader(name);
};

// Proxy all other public ClientRequest methods
[
  "abort", "flushHeaders", "getHeader",
  "setNoDelay", "setSocketKeepAlive", "setTimeout",
].forEach(function (method) {
  RedirectableRequest.prototype[method] = function (a, b) {
    return this._currentRequest[method](a, b);
  };
});

// Proxy all public ClientRequest properties
["aborted", "connection", "socket"].forEach(function (property) {
  Object.defineProperty(RedirectableRequest.prototype, property, {
    get: function () { return this._currentRequest[property]; },
  });
});

// Executes the next native request (initial or redirect)
RedirectableRequest.prototype._performRequest = function () {
  // Load the native protocol
  var protocol = this._options.protocol;
  var nativeProtocol = this._options.nativeProtocols[protocol];

  // If specified, use the agent corresponding to the protocol
  // (HTTP and HTTPS use different types of agents)
  if (this._options.agents) {
    var scheme = protocol.substr(0, protocol.length - 1);
    this._options.agent = this._options.agents[scheme];
  }

  // Create the native request
  var request = this._currentRequest =
        nativeProtocol.request(this._options, this._onNativeResponse);
  this._currentUrl = url.format(this._options);

  // Set up event handlers
  request._redirectable = this;
  for (var event in eventHandlers) {
    /* istanbul ignore else */
    if (event) {
      request.on(event, eventHandlers[event]);
    }
  }

  // End a redirected request
  // (The first request must be ended explicitly with RedirectableRequest#end)
  if (this._isRedirect) {
    // Write the request entity and end.
    var requestBodyBuffers = this._requestBodyBuffers;
    (function writeNext() {
      if (requestBodyBuffers.length !== 0) {
        var buffer = requestBodyBuffers.pop();
        request.write(buffer.data, buffer.encoding, writeNext);
      }
      else {
        request.end();
      }
    }());
  }
};

// Processes a response from the current native request
RedirectableRequest.prototype._processResponse = function (response) {
  // Store the redirected response
  if (this._options.trackRedirects) {
    this._redirects.push({
      url: this._currentUrl,
      headers: response.headers,
      statusCode: response.statusCode,
    });
  }

  // RFC7231§6.4: The 3xx (Redirection) class of status code indicates
  // that further action needs to be taken by the user agent in order to
  // fulfill the request. If a Location header field is provided,
  // the user agent MAY automatically redirect its request to the URI
  // referenced by the Location field value,
  // even if the specific status code is not understood.
  var location = response.headers.location;
  if (location && this._options.followRedirects !== false &&
      response.statusCode >= 300 && response.statusCode < 400) {
    // RFC7231§6.4: A client SHOULD detect and intervene
    // in cyclical redirections (i.e., "infinite" redirection loops).
    if (++this._redirectCount > this._options.maxRedirects) {
      this.emit("error", new Error("Max redirects exceeded."));
      return;
    }

    // RFC7231§6.4: Automatic redirection needs to done with
    // care for methods not known to be safe […],
    // since the user might not wish to redirect an unsafe request.
    // RFC7231§6.4.7: The 307 (Temporary Redirect) status code indicates
    // that the target resource resides temporarily under a different URI
    // and the user agent MUST NOT change the request method
    // if it performs an automatic redirection to that URI.
    var header;
    var headers = this._options.headers;
    if (response.statusCode !== 307 && !(this._options.method in SAFE_METHODS)) {
      this._options.method = "GET";
      // Drop a possible entity and headers related to it
      this._requestBodyBuffers = [];
      for (header in headers) {
        if (/^content-/i.test(header)) {
          delete headers[header];
        }
      }
    }

    // Drop the Host header, as the redirect might lead to a different host
    if (!this._isRedirect) {
      for (header in headers) {
        if (/^host$/i.test(header)) {
          delete headers[header];
        }
      }
    }

    // Perform the redirected request
    var redirectUrl = url.resolve(this._currentUrl, location);
    debug("redirecting to", redirectUrl);
    Object.assign(this._options, url.parse(redirectUrl));
    this._isRedirect = true;
    this._performRequest();

    // Discard the remainder of the response to avoid waiting for data
    response.destroy();
  }
  else {
    // The response is not a redirect; return it as-is
    response.responseUrl = this._currentUrl;
    response.redirects = this._redirects;
    this.emit("response", response);

    // Clean up
    this._requestBodyBuffers = [];
  }
};

// Wraps the key/value object of protocols with redirect functionality
function wrap(protocols) {
  // Default settings
  var exports = {
    maxRedirects: 21,
    maxBodyLength: 10 * 1024 * 1024,
  };

  // Wrap each protocol
  var nativeProtocols = {};
  Object.keys(protocols).forEach(function (scheme) {
    var protocol = scheme + ":";
    var nativeProtocol = nativeProtocols[protocol] = protocols[scheme];
    var wrappedProtocol = exports[scheme] = Object.create(nativeProtocol);

    // Executes a request, following redirects
    wrappedProtocol.request = function (options, callback) {
      if (typeof options === "string") {
        options = url.parse(options);
        options.maxRedirects = exports.maxRedirects;
      }
      else {
        options = Object.assign({
          protocol: protocol,
          maxRedirects: exports.maxRedirects,
          maxBodyLength: exports.maxBodyLength,
        }, options);
      }
      options.nativeProtocols = nativeProtocols;
      assert.equal(options.protocol, protocol, "protocol mismatch");
      debug("options", options);
      return new RedirectableRequest(options, callback);
    };

    // Executes a GET request, following redirects
    wrappedProtocol.get = function (options, callback) {
      var request = wrappedProtocol.request(options, callback);
      request.end();
      return request;
    };
  });
  return exports;
}

// Exports
module.exports = wrap({ http: http, https: https });
module.exports.wrap = wrap;
<commit_msg>Added support for empty buffer<commit_after>var url = require("url");
var http = require("http");
var https = require("https");
var assert = require("assert");
var Writable = require("stream").Writable;
var debug = require("debug")("follow-redirects");

// RFC7231§4.2.1: Of the request methods defined by this specification,
// the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe.
var SAFE_METHODS = { GET: true, HEAD: true, OPTIONS: true, TRACE: true };

// Create handlers that pass events from native requests
var eventHandlers = Object.create(null);
["abort", "aborted", "error", "socket", "timeout"].forEach(function (event) {
  eventHandlers[event] = function (arg) {
    this._redirectable.emit(event, arg);
  };
});

// An HTTP(S) request that can be redirected
function RedirectableRequest(options, responseCallback) {
  // Initialize the request
  Writable.call(this);
  options.headers = options.headers || {};
  this._options = options;
  this._redirectCount = 0;
  this._redirects = [];
  this._requestBodyLength = 0;
  this._requestBodyBuffers = [];

  // Attach a callback if passed
  if (responseCallback) {
    this.on("response", responseCallback);
  }

  // React to responses of native requests
  var self = this;
  this._onNativeResponse = function (response) {
    self._processResponse(response);
  };

  // Complete the URL object when necessary
  if (!options.pathname && options.path) {
    var searchPos = options.path.indexOf("?");
    if (searchPos < 0) {
      options.pathname = options.path;
    }
    else {
      options.pathname = options.path.substring(0, searchPos);
      options.search = options.path.substring(searchPos);
    }
  }

  // Perform the first request
  this._performRequest();
}
RedirectableRequest.prototype = Object.create(Writable.prototype);

// Writes buffered data to the current native request
RedirectableRequest.prototype.write = function (data, encoding, callback) {
  if (!(typeof data === "string" || typeof data === "object" && ("length" in data))) {
    throw new Error("data should be a string, Buffer or Uint8Array");
  }
  if(data instanceof Buffer && data.length === 0) {
    callback();
  }
  else if (this._requestBodyLength + data.length <= this._options.maxBodyLength) {
    this._requestBodyLength += data.length;
    this._requestBodyBuffers.push({ data: data, encoding: encoding });
    this._currentRequest.write(data, encoding, callback);
  }
  else {
    this.emit("error", new Error("Request body larger than maxBodyLength limit"));
    this.abort();
  }
};

// Ends the current native request
RedirectableRequest.prototype.end = function (data, encoding, callback) {
  var currentRequest = this._currentRequest;
  if (!data) {
    currentRequest.end(null, null, callback);
  }
  else {
    this.write(data, encoding, function () {
      currentRequest.end(null, null, callback);
    });
  }
};

// Sets a header value on the current native request
RedirectableRequest.prototype.setHeader = function (name, value) {
  this._options.headers[name] = value;
  this._currentRequest.setHeader(name, value);
};

// Clears a header value on the current native request
RedirectableRequest.prototype.removeHeader = function (name) {
  delete this._options.headers[name];
  this._currentRequest.removeHeader(name);
};

// Proxy all other public ClientRequest methods
[
  "abort", "flushHeaders", "getHeader",
  "setNoDelay", "setSocketKeepAlive", "setTimeout",
].forEach(function (method) {
  RedirectableRequest.prototype[method] = function (a, b) {
    return this._currentRequest[method](a, b);
  };
});

// Proxy all public ClientRequest properties
["aborted", "connection", "socket"].forEach(function (property) {
  Object.defineProperty(RedirectableRequest.prototype, property, {
    get: function () { return this._currentRequest[property]; },
  });
});

// Executes the next native request (initial or redirect)
RedirectableRequest.prototype._performRequest = function () {
  // Load the native protocol
  var protocol = this._options.protocol;
  var nativeProtocol = this._options.nativeProtocols[protocol];

  // If specified, use the agent corresponding to the protocol
  // (HTTP and HTTPS use different types of agents)
  if (this._options.agents) {
    var scheme = protocol.substr(0, protocol.length - 1);
    this._options.agent = this._options.agents[scheme];
  }

  // Create the native request
  var request = this._currentRequest =
        nativeProtocol.request(this._options, this._onNativeResponse);
  this._currentUrl = url.format(this._options);

  // Set up event handlers
  request._redirectable = this;
  for (var event in eventHandlers) {
    /* istanbul ignore else */
    if (event) {
      request.on(event, eventHandlers[event]);
    }
  }

  // End a redirected request
  // (The first request must be ended explicitly with RedirectableRequest#end)
  if (this._isRedirect) {
    // Write the request entity and end.
    var requestBodyBuffers = this._requestBodyBuffers;
    (function writeNext() {
      if (requestBodyBuffers.length !== 0) {
        var buffer = requestBodyBuffers.pop();
        request.write(buffer.data, buffer.encoding, writeNext);
      }
      else {
        request.end();
      }
    }());
  }
};

// Processes a response from the current native request
RedirectableRequest.prototype._processResponse = function (response) {
  // Store the redirected response
  if (this._options.trackRedirects) {
    this._redirects.push({
      url: this._currentUrl,
      headers: response.headers,
      statusCode: response.statusCode,
    });
  }

  // RFC7231§6.4: The 3xx (Redirection) class of status code indicates
  // that further action needs to be taken by the user agent in order to
  // fulfill the request. If a Location header field is provided,
  // the user agent MAY automatically redirect its request to the URI
  // referenced by the Location field value,
  // even if the specific status code is not understood.
  var location = response.headers.location;
  if (location && this._options.followRedirects !== false &&
      response.statusCode >= 300 && response.statusCode < 400) {
    // RFC7231§6.4: A client SHOULD detect and intervene
    // in cyclical redirections (i.e., "infinite" redirection loops).
    if (++this._redirectCount > this._options.maxRedirects) {
      this.emit("error", new Error("Max redirects exceeded."));
      return;
    }

    // RFC7231§6.4: Automatic redirection needs to done with
    // care for methods not known to be safe […],
    // since the user might not wish to redirect an unsafe request.
    // RFC7231§6.4.7: The 307 (Temporary Redirect) status code indicates
    // that the target resource resides temporarily under a different URI
    // and the user agent MUST NOT change the request method
    // if it performs an automatic redirection to that URI.
    var header;
    var headers = this._options.headers;
    if (response.statusCode !== 307 && !(this._options.method in SAFE_METHODS)) {
      this._options.method = "GET";
      // Drop a possible entity and headers related to it
      this._requestBodyBuffers = [];
      for (header in headers) {
        if (/^content-/i.test(header)) {
          delete headers[header];
        }
      }
    }

    // Drop the Host header, as the redirect might lead to a different host
    if (!this._isRedirect) {
      for (header in headers) {
        if (/^host$/i.test(header)) {
          delete headers[header];
        }
      }
    }

    // Perform the redirected request
    var redirectUrl = url.resolve(this._currentUrl, location);
    debug("redirecting to", redirectUrl);
    Object.assign(this._options, url.parse(redirectUrl));
    this._isRedirect = true;
    this._performRequest();

    // Discard the remainder of the response to avoid waiting for data
    response.destroy();
  }
  else {
    // The response is not a redirect; return it as-is
    response.responseUrl = this._currentUrl;
    response.redirects = this._redirects;
    this.emit("response", response);

    // Clean up
    this._requestBodyBuffers = [];
  }
};

// Wraps the key/value object of protocols with redirect functionality
function wrap(protocols) {
  // Default settings
  var exports = {
    maxRedirects: 21,
    maxBodyLength: 10 * 1024 * 1024,
  };

  // Wrap each protocol
  var nativeProtocols = {};
  Object.keys(protocols).forEach(function (scheme) {
    var protocol = scheme + ":";
    var nativeProtocol = nativeProtocols[protocol] = protocols[scheme];
    var wrappedProtocol = exports[scheme] = Object.create(nativeProtocol);

    // Executes a request, following redirects
    wrappedProtocol.request = function (options, callback) {
      if (typeof options === "string") {
        options = url.parse(options);
        options.maxRedirects = exports.maxRedirects;
      }
      else {
        options = Object.assign({
          protocol: protocol,
          maxRedirects: exports.maxRedirects,
          maxBodyLength: exports.maxBodyLength,
        }, options);
      }
      options.nativeProtocols = nativeProtocols;
      assert.equal(options.protocol, protocol, "protocol mismatch");
      debug("options", options);
      return new RedirectableRequest(options, callback);
    };

    // Executes a GET request, following redirects
    wrappedProtocol.get = function (options, callback) {
      var request = wrappedProtocol.request(options, callback);
      request.end();
      return request;
    };
  });
  return exports;
}

// Exports
module.exports = wrap({ http: http, https: https });
module.exports.wrap = wrap;
<|endoftext|>


<commit_before>/**
 * unassertify
 *   Browserify transform for unassert
 *     Encourages programming with assertions by providing tools to compile them away.
 *
 * https://github.com/unassert-js/unassertify
 *
 * Copyright (c) 2015-2017 Takuto Wada
 * Licensed under the MIT license.
 *   https://github.com/unassert-js/unassertify/blob/master/LICENSE
 */
'use strict';

var path = require('path');
var through = require('through');
var acorn = require('acorn');
var escodegen = require('escodegen');
var convert = require('convert-source-map');
var transfer = require('multi-stage-sourcemap').transfer;
var unassert = require('unassert');

function mergeSourceMap (incomingSourceMap, outgoingSourceMap) {
    if (typeof outgoingSourceMap === 'string' || outgoingSourceMap instanceof String) {
        outgoingSourceMap = JSON.parse(outgoingSourceMap);
    }
    if (!incomingSourceMap) {
        return outgoingSourceMap;
    }
    return JSON.parse(transfer({fromSourceMap: outgoingSourceMap, toSourceMap: incomingSourceMap}));
}

function overwritePropertyIfExists (name, from, to) {
    if (from.hasOwnProperty(name)) {
        to.setProperty(name, from[name]);
    }
}

function reconnectSourceMap (inMap, outMap) {
    var mergedRawMap = mergeSourceMap(inMap, outMap.toObject());
    var reMap = convert.fromObject(mergedRawMap);
    overwritePropertyIfExists('sources', inMap, reMap);
    overwritePropertyIfExists('sourceRoot', inMap, reMap);
    overwritePropertyIfExists('sourcesContent', inMap, reMap);
    return reMap;
}

function handleIncomingSourceMap (originalCode) {
    var commented = convert.fromSource(originalCode);
    if (commented) {
        return commented.toObject();
    }
    return null;
}

function applyUnassertWithSourceMap (code, filepath) {
    var ast = acorn.parse(code, {
      sourceType: 'module',
      locations: true,
      allowHashBang: true
    });
    var inMap = handleIncomingSourceMap(code);
    var instrumented = escodegen.generate(unassert(ast), {
        sourceMap: filepath,
        sourceContent: code,
        sourceMapWithCode: true
    });
    var outMap = convert.fromJSON(instrumented.map.toString());
    if (inMap) {
        var reMap = reconnectSourceMap(inMap, outMap);
        return instrumented.code + '\n' + reMap.toComment() + '\n';
    } else {
        return instrumented.code + '\n' + outMap.toComment() + '\n';
    }
}

function applyUnassertWithoutSourceMap (code) {
    var ast = acorn.parse(code, {
      sourceType: 'module',
      allowHashBang: true
    });
    return escodegen.generate(unassert(ast));
}

function shouldProduceSourceMap (options) {
    return (options && options._flags && options._flags.debug);
}

module.exports = function unassertify (filepath, options) {
    if (path.extname(filepath) === '.json') {
        return through();
    }

    var data = '',
        stream = through(write, end);

    function write(buf) {
        data += buf;
    }

    function end() {
        if (shouldProduceSourceMap(options)) {
            stream.queue(applyUnassertWithSourceMap(data, filepath));
        } else {
            stream.queue(applyUnassertWithoutSourceMap(data));
        }
        stream.queue(null);
    }

    return stream;
};
<commit_msg>style: just for consistent indentation<commit_after>/**
 * unassertify
 *   Browserify transform for unassert
 *     Encourages programming with assertions by providing tools to compile them away.
 *
 * https://github.com/unassert-js/unassertify
 *
 * Copyright (c) 2015-2017 Takuto Wada
 * Licensed under the MIT license.
 *   https://github.com/unassert-js/unassertify/blob/master/LICENSE
 */
'use strict';

var path = require('path');
var through = require('through');
var acorn = require('acorn');
var escodegen = require('escodegen');
var convert = require('convert-source-map');
var transfer = require('multi-stage-sourcemap').transfer;
var unassert = require('unassert');

function mergeSourceMap (incomingSourceMap, outgoingSourceMap) {
    if (typeof outgoingSourceMap === 'string' || outgoingSourceMap instanceof String) {
        outgoingSourceMap = JSON.parse(outgoingSourceMap);
    }
    if (!incomingSourceMap) {
        return outgoingSourceMap;
    }
    return JSON.parse(transfer({fromSourceMap: outgoingSourceMap, toSourceMap: incomingSourceMap}));
}

function overwritePropertyIfExists (name, from, to) {
    if (from.hasOwnProperty(name)) {
        to.setProperty(name, from[name]);
    }
}

function reconnectSourceMap (inMap, outMap) {
    var mergedRawMap = mergeSourceMap(inMap, outMap.toObject());
    var reMap = convert.fromObject(mergedRawMap);
    overwritePropertyIfExists('sources', inMap, reMap);
    overwritePropertyIfExists('sourceRoot', inMap, reMap);
    overwritePropertyIfExists('sourcesContent', inMap, reMap);
    return reMap;
}

function handleIncomingSourceMap (originalCode) {
    var commented = convert.fromSource(originalCode);
    if (commented) {
        return commented.toObject();
    }
    return null;
}

function applyUnassertWithSourceMap (code, filepath) {
    var ast = acorn.parse(code, {
        sourceType: 'module',
        locations: true,
        allowHashBang: true
    });
    var inMap = handleIncomingSourceMap(code);
    var instrumented = escodegen.generate(unassert(ast), {
        sourceMap: filepath,
        sourceContent: code,
        sourceMapWithCode: true
    });
    var outMap = convert.fromJSON(instrumented.map.toString());
    if (inMap) {
        var reMap = reconnectSourceMap(inMap, outMap);
        return instrumented.code + '\n' + reMap.toComment() + '\n';
    } else {
        return instrumented.code + '\n' + outMap.toComment() + '\n';
    }
}

function applyUnassertWithoutSourceMap (code) {
    var ast = acorn.parse(code, {
        sourceType: 'module',
        allowHashBang: true
    });
    return escodegen.generate(unassert(ast));
}

function shouldProduceSourceMap (options) {
    return (options && options._flags && options._flags.debug);
}

module.exports = function unassertify (filepath, options) {
    if (path.extname(filepath) === '.json') {
        return through();
    }

    var data = '',
        stream = through(write, end);

    function write(buf) {
        data += buf;
    }

    function end() {
        if (shouldProduceSourceMap(options)) {
            stream.queue(applyUnassertWithSourceMap(data, filepath));
        } else {
            stream.queue(applyUnassertWithoutSourceMap(data));
        }
        stream.queue(null);
    }

    return stream;
};
<|endoftext|>


<commit_before>/**
 * Takes a {@link GeoJSON} object of any type and flips all of its coordinates
 * from `[x, y]` to `[y, x]`.
 *
 * @module turf/flip
 * @param {GeoJSON} input input GeoJSON object
 * @returns {GeoJSON} a GeoJSON object of the same type as `input` with flipped coordinates
 * @example
 * var saudiArabia = turf.point([20.566406, 43.421008]);
 *
 * //=saudiArabia
 *
 * var serbia = turf.flip(saudiArabia);
 *
 * //=serbia
 */
module.exports = flipAny;

function flipAny(_) {
    // ensure that we don't modify features in-place and changes to the
    // output do not change the previous feature, including changes to nested
    // properties.
    var input = JSON.parse(JSON.stringify(_));
    switch (input.type) {
        case 'FeatureCollection':
            for (var i = 0; i < input.features.length; i++)
                flipGeometry(input.features[i].geometry);
            return input;
        case 'Feature':
            flipGeometry(input.geometry);
            return input;
        default:
            flipGeometry(input);
            return input;
    }
}

function flipGeometry(geometry) {
    var coords = geometry.coordinates;
    switch(geometry.type) {
      case 'Point':
        flip0(coords);
        break;
      case 'LineString':
      case 'MultiPoint':
        flip1(coords);
        break;
      case 'Polygon':
      case 'MultiLineString':
        flip2(coords);
        break;
      case 'MultiPolygon':
        flip3(coords);
        break;
      case 'GeometryCollection':
        geometry.geometries.forEach(flipGeometry);
        break;
    }
}

function flip0(coord) {
    coord.reverse();
}

function flip1(coords) {
  for(var i = 0; i < coords.length; i++) coords[i].reverse();
}

function flip2(coords) {
  for(var i = 0; i < coords.length; i++)
    for(var j = 0; j < coords[i].length; j++) coords[i][j].reverse();
}

function flip3(coords) {
  for(var i = 0; i < coords.length; i++)
    for(var j = 0; j < coords[i].length; j++)
      for(var k = 0; k < coords[i][j].length; k++) coords[i][j][k].reverse();
}
<commit_msg>Switch example to geojson primitives; fix location names<commit_after>/**
 * Takes a {@link GeoJSON} object of any type and flips all of its coordinates
 * from `[x, y]` to `[y, x]`.
 *
 * @module turf/flip
 * @param {GeoJSON} input input GeoJSON object
 * @returns {GeoJSON} a GeoJSON object of the same type as `input` with flipped coordinates
 * @example
 * var serbia = {
 *   "type": "Feature",
 *   "properties": {},
 *   "geometry": {
 *     "type": "Point",
 *     "coordinates": [20.566406, 43.421008]
 *   }
 * };
 *
 * //=serbia
 *
 * var saudiArabia = turf.flip(serbia);
 *
 * //=saudiArabia
 */
module.exports = flipAny;

function flipAny(_) {
    // ensure that we don't modify features in-place and changes to the
    // output do not change the previous feature, including changes to nested
    // properties.
    var input = JSON.parse(JSON.stringify(_));
    switch (input.type) {
        case 'FeatureCollection':
            for (var i = 0; i < input.features.length; i++)
                flipGeometry(input.features[i].geometry);
            return input;
        case 'Feature':
            flipGeometry(input.geometry);
            return input;
        default:
            flipGeometry(input);
            return input;
    }
}

function flipGeometry(geometry) {
    var coords = geometry.coordinates;
    switch(geometry.type) {
      case 'Point':
        flip0(coords);
        break;
      case 'LineString':
      case 'MultiPoint':
        flip1(coords);
        break;
      case 'Polygon':
      case 'MultiLineString':
        flip2(coords);
        break;
      case 'MultiPolygon':
        flip3(coords);
        break;
      case 'GeometryCollection':
        geometry.geometries.forEach(flipGeometry);
        break;
    }
}

function flip0(coord) {
    coord.reverse();
}

function flip1(coords) {
  for(var i = 0; i < coords.length; i++) coords[i].reverse();
}

function flip2(coords) {
  for(var i = 0; i < coords.length; i++)
    for(var j = 0; j < coords[i].length; j++) coords[i][j].reverse();
}

function flip3(coords) {
  for(var i = 0; i < coords.length; i++)
    for(var j = 0; j < coords[i].length; j++)
      for(var k = 0; k < coords[i][j].length; k++) coords[i][j][k].reverse();
}
<|endoftext|>


<commit_before>/*!
* vdom-virtualize
* Copyright 2014 by Marcel Klehr <mklehr@gmx.net>
*
* (MIT LICENSE)
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
var VNode = require("vtree/vnode")
  , VText = require("vtree/vtext")

module.exports = createVNode

function createVNode(domNode, key) {
  key = key || null // XXX: Leave out `key` for now... merely used for (re-)ordering

  if(domNode.nodeType == 1) return createFromElement(domNode, key)
  if(domNode.nodeType == 3) return createFromTextNode(domNode, key)
  return
}

createVNode.fromHTML = function(html, key) {
  var domNode = document.createElement('div'); // create container
  domNode.innerHTML = html; // browser parses HTML into DOM tree
  domNode = domNode.children[0] || domNode; // select first node in tree
  return createVNode(domNode, key);
};

function createFromTextNode(tNode) {
  return new VText(tNode.nodeValue)
}

function createFromElement(el) {
  var tagName = el.tagName
  , namespace = el.namespaceURI == 'http://www.w3.org/1999/xhtml'? null : el.namespaceURI
  , properties = getElementProperties(el)
  , children = []

  for (var i = 0; i < el.childNodes.length; i++) {
    children.push(createVNode(el.childNodes[i]/*, i*/))
  }

  return new VNode(tagName, properties, children, null, namespace)
}

function getElementProperties(el) {
  var obj = {}

  props.forEach(function(propName) {
    if(!el[propName]) return

    // Special case: style
    // .style is a DOMStyleDeclaration, thus we need to iterate over all
    // rules to create a hash of applied css properties.
    //
    // You can directly set a specific .style[prop] = value so patching with vdom
    // is possible.
    if("style" == propName) {
      var css = {}
        , styleProp
      for(var i=0; i<el.style.length; i++) {
        styleProp = el.style[i]
        css[styleProp] = el.style.getPropertyValue(styleProp) // XXX: add support for "!important" via getPropertyPriority()!
      }

      obj[propName] = css
      return
    }

    // Special case: dataset
    // we can iterate over .dataset with a simple for..in loop.
    // The all-time foo with data-* attribs is the dash-snake to camelCase
    // conversion.
    // However, I'm not sure if this is compatible with h()
    //
    // .dataset properties are directly accessible as transparent getters/setters, so
    // patching with vdom is possible.
    if("dataset" == propName) {
      var data = {}
      for(var p in el.dataset) {
        data[p] = el.dataset[p]
      }

      obj[propName] = data
      return
    }

    // Special case: attributes
    // some properties are only accessible via .attributes, so
    // that's what we'd do, if vdom-create-element could handle this.
    if("attributes" == propName) return
    if("tabIndex" == propName && el.tabIndex === -1) return

    // default: just copy the property
    obj[propName] = el[propName]
    return
  })

  return obj
}

/**
 * DOMNode property white list
 * Taken from https://github.com/Raynos/react/blob/dom-property-config/src/browser/ui/dom/DefaultDOMPropertyConfig.js
 */
var props =

module.exports.properties = [
 "accept"
,"accessKey"
,"action"
,"alt"
,"async"
,"autoComplete"
,"autoPlay"
,"cellPadding"
,"cellSpacing"
,"checked"
,"className"
,"colSpan"
,"content"
,"contentEditable"
,"controls"
,"crossOrigin"
,"data"
,"dataset"
,"defer"
,"dir"
,"download"
,"draggable"
,"encType"
,"formNoValidate"
,"href"
,"hrefLang"
,"htmlFor"
,"httpEquiv"
,"icon"
,"id"
,"label"
,"lang"
,"list"
,"loop"
,"max"
,"mediaGroup"
,"method"
,"min"
,"multiple"
,"muted"
,"name"
,"noValidate"
,"pattern"
,"placeholder"
,"poster"
,"preload"
,"radioGroup"
,"readOnly"
,"rel"
,"required"
,"rowSpan"
,"sandbox"
,"scope"
,"scrollLeft"
,"scrolling"
,"scrollTop"
,"selected"
,"span"
,"spellCheck"
,"src"
,"srcDoc"
,"srcSet"
,"start"
,"step"
,"style"
,"tabIndex"
,"target"
,"title"
,"type"
,"value"

// Non-standard Properties
,"autoCapitalize"
,"autoCorrect"
,"property"

, "attributes"
]

var attrs =
module.exports.attrs = [
 "allowFullScreen"
,"allowTransparency"
,"charSet"
,"cols"
,"contextMenu"
,"dateTime"
,"disabled"
,"form"
,"frameBorder"
,"height"
,"hidden"
,"maxLength"
,"role"
,"rows"
,"seamless"
,"size"
,"width"
,"wmode"

// SVG Properties
,"cx"
,"cy"
,"d"
,"dx"
,"dy"
,"fill"
,"fx"
,"fy"
,"gradientTransform"
,"gradientUnits"
,"offset"
,"points"
,"r"
,"rx"
,"ry"
,"spreadMethod"
,"stopColor"
,"stopOpacity"
,"stroke"
,"strokeLinecap"
,"strokeWidth"
,"textAnchor"
,"transform"
,"version"
,"viewBox"
,"x1"
,"x2"
,"x"
,"y1"
,"y2"
,"y"
]
<commit_msg>properly handle attributes instead of deleting them<commit_after>/*!
* vdom-virtualize
* Copyright 2014 by Marcel Klehr <mklehr@gmx.net>
*
* (MIT LICENSE)
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
var VNode = require("vtree/vnode")
  , VText = require("vtree/vtext")

module.exports = createVNode

function createVNode(domNode, key) {
  key = key || null // XXX: Leave out `key` for now... merely used for (re-)ordering

  if(domNode.nodeType == 1) return createFromElement(domNode, key)
  if(domNode.nodeType == 3) return createFromTextNode(domNode, key)
  return
}

createVNode.fromHTML = function(html, key) {
  var domNode = document.createElement('div'); // create container
  domNode.innerHTML = html; // browser parses HTML into DOM tree
  domNode = domNode.children[0] || domNode; // select first node in tree
  return createVNode(domNode, key);
};

function createFromTextNode(tNode) {
  return new VText(tNode.nodeValue)
}

function createFromElement(el) {
  var tagName = el.tagName
  , namespace = el.namespaceURI == 'http://www.w3.org/1999/xhtml'? null : el.namespaceURI
  , properties = getElementProperties(el)
  , children = []

  for (var i = 0; i < el.childNodes.length; i++) {
    children.push(createVNode(el.childNodes[i]/*, i*/))
  }

  return new VNode(tagName, properties, children, null, namespace)
}

function getElementProperties(el) {
  var obj = {}

  props.forEach(function(propName) {
    if(!el[propName]) return

    // Special case: style
    // .style is a DOMStyleDeclaration, thus we need to iterate over all
    // rules to create a hash of applied css properties.
    //
    // You can directly set a specific .style[prop] = value so patching with vdom
    // is possible.
    if("style" == propName) {
      var css = {}
        , styleProp
      for(var i=0; i<el.style.length; i++) {
        styleProp = el.style[i]
        css[styleProp] = el.style.getPropertyValue(styleProp) // XXX: add support for "!important" via getPropertyPriority()!
      }

      obj[propName] = css
      return
    }

    // Special case: dataset
    // we can iterate over .dataset with a simple for..in loop.
    // The all-time foo with data-* attribs is the dash-snake to camelCase
    // conversion.
    // However, I'm not sure if this is compatible with h()
    //
    // .dataset properties are directly accessible as transparent getters/setters, so
    // patching with vdom is possible.
    if("dataset" == propName) {
      var data = {}
      for(var p in el.dataset) {
        data[p] = el.dataset[p]
      }
      obj[propName] = data
      return
    }

    // Special case: attributes
    // these are a NamedNodeMap, but we can just convert them to a hash for vdom.
    if("attributes" == propName){
      var atts = Array.prototype.slice.call(el[propName]);
      var hash = atts.reduce(function(o,a){
        var name = a.name;
        if(obj[name]) return o;
        o[name] = el.getAttribute(a.name);
        return o;
      },{});
      return obj[propName] = hash;
    }
    if("tabIndex" == propName && el.tabIndex === -1) return

    // default: just copy the property
    obj[propName] = el[propName]
    return
  })

  return obj
}

/**
 * DOMNode property white list
 * Taken from https://github.com/Raynos/react/blob/dom-property-config/src/browser/ui/dom/DefaultDOMPropertyConfig.js
 */
var props =

module.exports.properties = [
 "accept"
,"accessKey"
,"action"
,"alt"
,"async"
,"autoComplete"
,"autoPlay"
,"cellPadding"
,"cellSpacing"
,"checked"
,"className"
,"colSpan"
,"content"
,"contentEditable"
,"controls"
,"crossOrigin"
,"data"
,"dataset"
,"defer"
,"dir"
,"download"
,"draggable"
,"encType"
,"formNoValidate"
,"href"
,"hrefLang"
,"htmlFor"
,"httpEquiv"
,"icon"
,"id"
,"label"
,"lang"
,"list"
,"loop"
,"max"
,"mediaGroup"
,"method"
,"min"
,"multiple"
,"muted"
,"name"
,"noValidate"
,"pattern"
,"placeholder"
,"poster"
,"preload"
,"radioGroup"
,"readOnly"
,"rel"
,"required"
,"rowSpan"
,"sandbox"
,"scope"
,"scrollLeft"
,"scrolling"
,"scrollTop"
,"selected"
,"span"
,"spellCheck"
,"src"
,"srcDoc"
,"srcSet"
,"start"
,"step"
,"style"
,"tabIndex"
,"target"
,"title"
,"type"
,"value"

// Non-standard Properties
,"autoCapitalize"
,"autoCorrect"
,"property"

, "attributes"
]

var attrs =
module.exports.attrs = [
 "allowFullScreen"
,"allowTransparency"
,"charSet"
,"cols"
,"contextMenu"
,"dateTime"
,"disabled"
,"form"
,"frameBorder"
,"height"
,"hidden"
,"maxLength"
,"role"
,"rows"
,"seamless"
,"size"
,"width"
,"wmode"

// SVG Properties
,"cx"
,"cy"
,"d"
,"dx"
,"dy"
,"fill"
,"fx"
,"fy"
,"gradientTransform"
,"gradientUnits"
,"offset"
,"points"
,"r"
,"rx"
,"ry"
,"spreadMethod"
,"stopColor"
,"stopOpacity"
,"stroke"
,"strokeLinecap"
,"strokeWidth"
,"textAnchor"
,"transform"
,"version"
,"viewBox"
,"x1"
,"x2"
,"x"
,"y1"
,"y2"
,"y"
]
<|endoftext|>


<commit_before>require('dotenv').config();

process.on('unhandledRejection', (error) => {
	logger.error(error.stack);
});

const {rtmClient, webClient} = require('./lib/slack.ts');
const {createEventAdapter} = require('@slack/events-api');
const {createMessageAdapter} = require('@slack/interactive-messages');
const fastify = require('fastify')({logger: true});
const logger = require('./lib/logger.js');

fastify.register(require('fastify-formbody'));

const plugins = [
	require('./summary'),
	require('./mahjong'),
	require('./pocky'),
	require('./emoji-notifier'),
	require('./sushi-bot'),
	require('./shogi'),
	require('./tiobot'),
	require('./checkin'),
	require('./tahoiya'),
	require('./channel-notifier'),
	require('./prime'),
	require('./dajare'),
	require('./sunrise'),
	require('./ahokusa'),
	// ...(word2vecInstalled ? [require('./vocabwar')] : []),
	require('./ricochet-robots'),
	require('./scrapbox'),
	require('./slack-log'),
	require('./welcome'),
	require('./deploy'),
	require('./achievements'),
	require('./mail-hook'),
	require('./wordhero'),
	require('./wordhero/crossword'),
	require('./oauth'),
	require('./tunnel'),
	require('./voiperrobot'),
	require('./atcoder'),
	require('./lyrics'),
	require('./ojigineko-life'),
	require('./better-custom-response'),
	require('./emoxpand'),
	require('./ponpe'),
];
const eventClient = createEventAdapter(process.env.SIGNING_SECRET);
eventClient.on('error', (error) => {
	logger.error(error.stack);
});

const messageClient = createMessageAdapter(process.env.SIGNING_SECRET);

(async () => {
	await Promise.all(plugins.map(async (plugin) => {
		if (typeof plugin === 'function') {
			await plugin({rtmClient, webClient, eventClient, messageClient});
		}
		if (typeof plugin.default === 'function') {
			await plugin.default({rtmClient, webClient, eventClient, messageClient});
		}
		if (typeof plugin.server === 'function') {
			await fastify.register(plugin.server({rtmClient, webClient, eventClient, messageClient}));
		}
	}));

	logger.info('Launched');
	webClient.chat.postMessage({
		channel: process.env.CHANNEL_SANDBOX,
		text: 'ｼｭｯｼｭｯ (起動音)',
	});
})();

fastify.use('/slack-event', (req, res, next) => {
	if (!{}.hasOwnProperty.call(req.headers, 'x-slack-signature')) {
		res.statusCode = 400;
		res.end('Bad Request');
		return;
	}
	next();
});
fastify.use('/slack-event', eventClient.expressMiddleware());
fastify.use('/slack-message', messageClient.requestListener());
fastify.listen(process.env.PORT || 21864, (error, address) => {
	if (error) {
		logger.error(error);
	} else {
		logger.info(`Server launched at ${address}`);
	}
});

let firstLogin = true;
rtmClient.on('authenticated', (data) => {
	logger.info(`Logged in as ${data.self.name} of team ${data.team.name}`);
	if (!firstLogin) {
		webClient.chat.postMessage({
			channel: process.env.CHANNEL_SANDBOX,
			text: '再接続しました',
		});
	}
	firstLogin = false;
});
<commit_msg>Update index.js<commit_after>require('dotenv').config();

process.on('unhandledRejection', (error) => {
	logger.error(error.stack);
});

const {rtmClient, webClient} = require('./lib/slack.ts');
const {createEventAdapter} = require('@slack/events-api');
const {createMessageAdapter} = require('@slack/interactive-messages');
const fastify = require('fastify')({logger: true});
const logger = require('./lib/logger.js');

fastify.register(require('fastify-formbody'));

const plugins = [
	require('./summary'),
	require('./mahjong'),
	require('./pocky'),
	require('./emoji-notifier'),
	require('./sushi-bot'),
	require('./shogi'),
	require('./tiobot'),
	require('./checkin'),
	require('./tahoiya'),
	require('./channel-notifier'),
	require('./prime'),
	require('./dajare'),
	require('./sunrise'),
	require('./ahokusa'),
	// ...(word2vecInstalled ? [require('./vocabwar')] : []),
	require('./ricochet-robots'),
	require('./scrapbox'),
	require('./slack-log'),
	require('./welcome'),
	require('./deploy'),
	require('./achievements'),
	require('./mail-hook'),
	require('./wordhero'),
	require('./wordhero/crossword'),
	require('./oauth'),
	require('./tunnel'),
	require('./voiperrobot'),
	require('./atcoder'),
	require('./lyrics'),
	require('./ojigineko-life'),
	require('./better-custom-response'),
	require('./emoxpand'),
	require('./ponpe'),
	require('./anime'),
];
const eventClient = createEventAdapter(process.env.SIGNING_SECRET);
eventClient.on('error', (error) => {
	logger.error(error.stack);
});

const messageClient = createMessageAdapter(process.env.SIGNING_SECRET);

(async () => {
	await Promise.all(plugins.map(async (plugin) => {
		if (typeof plugin === 'function') {
			await plugin({rtmClient, webClient, eventClient, messageClient});
		}
		if (typeof plugin.default === 'function') {
			await plugin.default({rtmClient, webClient, eventClient, messageClient});
		}
		if (typeof plugin.server === 'function') {
			await fastify.register(plugin.server({rtmClient, webClient, eventClient, messageClient}));
		}
	}));

	logger.info('Launched');
	webClient.chat.postMessage({
		channel: process.env.CHANNEL_SANDBOX,
		text: 'ｼｭｯｼｭｯ (起動音)',
	});
})();

fastify.use('/slack-event', (req, res, next) => {
	if (!{}.hasOwnProperty.call(req.headers, 'x-slack-signature')) {
		res.statusCode = 400;
		res.end('Bad Request');
		return;
	}
	next();
});
fastify.use('/slack-event', eventClient.expressMiddleware());
fastify.use('/slack-message', messageClient.requestListener());
fastify.listen(process.env.PORT || 21864, (error, address) => {
	if (error) {
		logger.error(error);
	} else {
		logger.info(`Server launched at ${address}`);
	}
});

let firstLogin = true;
rtmClient.on('authenticated', (data) => {
	logger.info(`Logged in as ${data.self.name} of team ${data.team.name}`);
	if (!firstLogin) {
		webClient.chat.postMessage({
			channel: process.env.CHANNEL_SANDBOX,
			text: '再接続しました',
		});
	}
	firstLogin = false;
});
<|endoftext|>