<commit_before>/* global analytics */
/* eslint no-console:0, no-unused-vars:0, no-extra-parens:0 */

'use strict';

var integration = require('analytics.js-integration');
var request = require('visionmedia/superagent');
var prefix = require('johntron/superagent-prefix');
var async = require('caolan/async');
window._astq = window._astq || [];

/**
 * Expose `Astronomer` integration.
 */
var Astronomer = module.exports = exports = integration('astronomer')
  .global('_astq')
  .option('appId', null)
  .option('credentialServer', 'https://app.astronomer.io:443')
  .option('credentialsExpiration', 900)
  .option('trackAllPages', false)
  .option('trackNamedPages', true)
  .option('trackCategorizedPages', true)
  .tag('aws', '<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1.33.min.js">');

/**
 * Initialize astronomer.
 * @param {Facade} page The page object
 */
Astronomer.prototype.initialize = function() {
  var self = this;
  // Hold user data
  self.props = {};
  // The kinesis service object
  self.kinesis = null;
  // Need concurrency 1 here to prevent multiple auth requests simultaneously
  self.queue = async.queue(self.putRecord.bind(self), 1);
  // Load aws sdk, then signal ready
  self.load('aws', function() {
    self.ready();
    self.replay();
  });
};

/**
 * Authenticate with our server
 * @param {Function} callback Callback
 */
Astronomer.prototype.ensureKinesisConfig = function(callback) {
  var self = this;

  if (!self.expired()) {
    callback(null, { config: self.config, kinesis: self.kinesis });
    return;
  }

  // Request fresh config (token)
  self.requestConfig(function(err, response) {
    if (err) { return callback(err); }

    // Update global config object
    self.config = response.body;

    var params = {
      region: self.config.region,
      credentials: new window.AWS.WebIdentityCredentials({
        RoleArn: self.config.roleArn,
        WebIdentityToken: self.config.credentials.Token,
        DurationSeconds: self.options.credentialsExpiration
      })
    };

    // Assign kinesis service object to new one with fresh config
    self.kinesis = new window.AWS.Kinesis(params);

    callback(null, { config: self.config, kinesis: self.kinesis });
  });
};

/**
 * Check credentials on kinesis service object
 * @return {Boolean} If expired
 */
Astronomer.prototype.expired = function() {
  var expireTime = (((this.kinesis || {}).config || {}).credentials || {}).expireTime;
  return !expireTime || expireTime.getTime() <= Date.now();
};

/**
 * Worker handler function
 * @param {Object} record Record to put to kinesis
 * @param {Function} callback Function to callback to queue
 */
Astronomer.prototype.putRecord = function(record, callback) {
  var self = this;
  self.ensureKinesisConfig(function(err, config) {
    if (err) {
      console.error("Error retrieving config.");
      return callback();
    }

    var params = {
      Data: record,
      StreamName: config.config.streamName,
      PartitionKey: self.options.appId
    };

    config.kinesis.putRecord(params, function(err, data) {
      if (err) {
        console.log(err);
      }
      callback();
    });
  });
};

/**
 * Request new configuration from server, including fresh token
 * @param {Function} callback Callback passing in response
 */
Astronomer.prototype.requestConfig = function(callback) {
  request.get('/api/v1/applications/credentials/' + this.options.appId)
    .use(prefix(this.options.credentialServer))
    .end(callback);
};

/**
 * Replay the events that have been queued prior to initialization
 */
Astronomer.prototype.replay = function() {
  while (window._astq.length > 0) {
    var item = window._astq.shift();
    var method = item.shift();
    if (analytics[method]) analytics[method].apply(analytics, item);
  }
};

/**
 * Has the astronomer library been loaded yet?
 * @return {Boolean}
 */
Astronomer.prototype.loaded = function() {
  return !!((((window.AWS) || {}).config || {}).credentials || {}).accessKeyId;
};

/**
 * Trigger a page view.
 * @param {Facade} page A page object
 */
Astronomer.prototype.page = function(page) {
  var category = page.category();
  var props = page.properties();
  var name = page.fullName();
  var opts = this.options;

  // all pages
  if (opts.trackAllPages) {
    this.track(page.track());
  }

  // named pages
  if (name && opts.trackNamedPages) {
    this.track(page.track(name));
  }

  // categorized pages
  // if (category && opts.trackCategorizedPages) {
  //   this.track(page.track(category));
  // }
};

/**
 * Identify a user.
 * @param {Facade} identify An identify object
 */
Astronomer.prototype.identify = function(identify) {
  var id = identify.userId();
  var traits = identify.traits();
  this.props.userId = id;
  this.props.userProperties = traits;
};

/**
 * Associate the current user with a group of users.
 * @param {Facade} group A group object
 */
Astronomer.prototype.group = function(group) {
  var id = group.groupId();
  var traits = group.traits();
  this.props.groupId = id;
  this.props.groupProperties = traits;
};

/**
 * Track an event.
 * @param {Facade} track A track object
 */
Astronomer.prototype.track = function(track) {
  this.push(track.json());
};

/**
 * Push a message to the outgoing queue.
 * @param {Object} msg
 */
Astronomer.prototype.push = function(msg) {
  // var record = JSON.stringify({
  //   event: track.event(),
  //   properties: track.properties(),
  //   anonymousId: analytics.user().anonymousId(),
  //   userId: this.props.userId,
  //   traits: this.props.userProperties
  // });
  msg = this.normalize(msg);
  // this.queue.push(msg);
};

/**
 * Normalize a given msg.
 * @param {Object} msg
 */
Astronomer.prototype.normalize = function(msg) {
  console.log(this.analytics.user());
};<commit_msg>SAVEPOINT<commit_after>/* global analytics */
/* eslint no-console:0, no-unused-vars:0, no-extra-parens:0 */

'use strict';

var integration = require('analytics.js-integration');
var request = require('visionmedia/superagent');
var prefix = require('johntron/superagent-prefix');
var async = require('caolan/async');
window._astq = window._astq || [];

/**
 * Expose `Astronomer` integration.
 */
var Astronomer = module.exports = exports = integration('astronomer')
  .global('_astq')
  .option('appId', null)
  .option('credentialServer', 'https://app.astronomer.io:443')
  .option('credentialsExpiration', 900)
  .option('trackAllPages', false)
  .option('trackNamedPages', true)
  .option('trackCategorizedPages', true)
  .tag('aws', '<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1.33.min.js">');

/**
 * Initialize astronomer.
 * @param {Facade} page The page object
 */
Astronomer.prototype.initialize = function() {
  var self = this;
  // Hold user data
  self.props = {};
  // The kinesis service object
  self.kinesis = null;
  // Need concurrency 1 here to prevent multiple auth requests simultaneously
  self.queue = async.queue(self.putRecord.bind(self), 1);
  // Load aws sdk, then signal ready
  self.load('aws', function() {
    self.ready();
    self.replay();
  });
};

/**
 * Authenticate with our server
 * @param {Function} callback Callback
 */
Astronomer.prototype.ensureKinesisConfig = function(callback) {
  var self = this;

  if (!self.expired()) {
    callback(null, { config: self.config, kinesis: self.kinesis });
    return;
  }

  // Request fresh config (token)
  self.requestConfig(function(err, response) {
    if (err) { return callback(err); }

    // Update global config object
    self.config = response.body;

    var params = {
      region: self.config.region,
      credentials: new window.AWS.WebIdentityCredentials({
        RoleArn: self.config.roleArn,
        WebIdentityToken: self.config.credentials.Token,
        DurationSeconds: self.options.credentialsExpiration
      })
    };

    // Assign kinesis service object to new one with fresh config
    self.kinesis = new window.AWS.Kinesis(params);

    callback(null, { config: self.config, kinesis: self.kinesis });
  });
};

/**
 * Check credentials on kinesis service object
 * @return {Boolean} If expired
 */
Astronomer.prototype.expired = function() {
  var expireTime = (((this.kinesis || {}).config || {}).credentials || {}).expireTime;
  return !expireTime || expireTime.getTime() <= Date.now();
};

/**
 * Worker handler function
 * @param {Object} record Record to put to kinesis
 * @param {Function} callback Function to callback to queue
 */
Astronomer.prototype.putRecord = function(record, callback) {
  var self = this;
  self.ensureKinesisConfig(function(err, config) {
    if (err) {
      console.error("Error retrieving config.");
      return callback();
    }

    var params = {
      Data: record,
      StreamName: config.config.streamName,
      PartitionKey: self.options.appId
    };

    config.kinesis.putRecord(params, function(err, data) {
      if (err) {
        console.log(err);
      }
      callback();
    });
  });
};

/**
 * Request new configuration from server, including fresh token
 * @param {Function} callback Callback passing in response
 */
Astronomer.prototype.requestConfig = function(callback) {
  request.get('/api/v1/applications/credentials/' + this.options.appId)
    .use(prefix(this.options.credentialServer))
    .end(callback);
};

/**
 * Replay the events that have been queued prior to initialization
 */
Astronomer.prototype.replay = function() {
  while (window._astq.length > 0) {
    var item = window._astq.shift();
    var method = item.shift();
    if (analytics[method]) analytics[method].apply(analytics, item);
  }
};

/**
 * Has the astronomer library been loaded yet?
 * @return {Boolean}
 */
Astronomer.prototype.loaded = function() {
  return !!((((window.AWS) || {}).config || {}).credentials || {}).accessKeyId;
};

/**
 * Trigger a page view.
 * @param {Facade} page A page object
 */
Astronomer.prototype.page = function(page) {
  var category = page.category();
  var props = page.properties();
  var name = page.fullName();
  var opts = this.options;

  // all pages
  if (opts.trackAllPages) {
    this.track(page.track());
  }

  // named pages
  if (name && opts.trackNamedPages) {
    this.track(page.track(name));
  }

  // categorized pages
  // if (category && opts.trackCategorizedPages) {
  //   this.track(page.track(category));
  // }
};

/**
 * Identify a user.
 * @param {Facade} identify An identify object
 */
Astronomer.prototype.identify = function(identify) {
  var id = identify.userId();
  var traits = identify.traits();
  this.props.userId = id;
  this.props.userProperties = traits;
};

/**
 * Associate the current user with a group of users.
 * @param {Facade} group A group object
 */
// Astronomer.prototype.group = function(group) {
//   var id = group.groupId();
//   var traits = group.traits();
//   this.props.groupId = id;
//   this.props.groupProperties = traits;
// };

/**
 * Track an event.
 * @param {Facade} track A track object
 */
Astronomer.prototype.track = function(track) {
  this.push(track.json());
};

/**
 * Push a message to the outgoing queue.
 * @param {Object} msg
 */
Astronomer.prototype.push = function(msg) {
  // var record = JSON.stringify({
  //   event: track.event(),
  //   properties: track.properties(),
  //   anonymousId: analytics.user().anonymousId(),
  //   userId: this.props.userId,
  //   traits: this.props.userProperties
  // });
  msg = this.normalize(msg);
  // this.queue.push(msg);
};

/**
 * Normalize a given msg.
 * @param {Object} msg
 */
Astronomer.prototype.normalize = function(msg) {
  var user = this.analytics.user();
  console.log(user.id());
};<|endoftext|>


<commit_before>var gulp = require('gulp'),
  uglify = require('gulp-uglify'),
  concat = require('gulp-concat'),
  handlebars = require('gulp-handlebars'),
  wrap = require('gulp-wrap'),
  declare = require('gulp-declare'),
  concat = require('gulp-concat'),
  minify_css = require('gulp-minify-css'),
  sourcemaps = require('gulp-sourcemaps'),
  manifest = require('./manifest.json'),
  project = require('./package.json'),
  crx = require('gulp-crx'),
  fs = require('fs');

var paths = {
  'swarm:js:src': ['js/namespace.js', 'js/**/*.js'],
  'swarm:templates:src': ['templates/*.hbs'],
  'swarm:css:src': ['css/feeds.css', 'css/profile.css', 'css/overrides.css', 'css/loading.css', 'css/templates.css'],
  'swarm:plugin:src': ['build/**/*', 'img/**/*', 'libs/**/*', 'oauth2/**/*', 'background.js', 'popup.js', 'manifest.json', 'home.html']
};

var options = {
  'declare:templates': {
    namespace: 'Swarm.templates',
    noRedeclare: true
  }
};

gulp.task('move:fonts', function () {
  gulp.src(['libs/fonts/**/*'], { base: 'libs' })
    .pipe(gulp.dest('build'));
});

gulp.task('move:plugin:src', function () {
  gulp.src(paths['swarm:plugin:src'], { base: './' })
    .pipe(gulp.dest('dist'));
});

gulp.task('build:js', function () {
  gulp.src(paths['swarm:js:src'])
    .pipe(concat('swarm.js'))
    .pipe(gulp.dest('build/js'))
    .pipe(uglify())
    .pipe(concat('swarm.min.js'))
    .pipe(gulp.dest('build/js'));
});

gulp.task('build:css', ['move:fonts'], function () {
  gulp.src(paths['swarm:css:src'])
    .pipe(concat('swarm.css'))
    .pipe(gulp.dest('build/css'))
    .pipe(minify_css())
    .pipe(concat('swarm.min.css'))
    .pipe(gulp.dest('build/css'));
});

gulp.task('build:src', ['build:js', 'build:css']);

gulp.task('build:templates', function () {
  gulp.src(paths['swarm:templates:src'])
    .pipe(handlebars())
    .pipe(wrap('Handlebars.template(<%= contents %>)'))
    .pipe(declare(options['declare:templates']))
    .pipe(concat('swarm.templates.js'))
    .pipe(gulp.dest('build/js'));/*
    .pipe(uglify('swarm.templates.min.js'))
    .pipe(gulp.dest('build/js'));*/
});

gulp.task('watch:src', function () {
  gulp.watch(paths['swarm:js:src'].concat(paths['swarm:css:src'])
    , ['build:src']);
});

gulp.task('watch:templates', function () {
  gulp.watch(paths['swarm:templates:src', ['build:templates']]);
});

gulp.task('create:dist', ['build:src', 'build:templates', 'move:plugin:src']);
gulp.task('create:crx', ['create:dist'], function() {
  return gulp.src('./dist')
    .pipe(crx({
      privateKey: fs.readFileSync('./dist.pem', 'utf8'),
      filename: manifest.name + '-' + project.version + '.crx',
      codebase: '.',
      updateXmlFilename: 'update.xml'
    }))
    .pipe(gulp.dest('./releases'));
});
gulp.task('release', ['create:crx']);

gulp.task('default', ['build:src', 'build:templates', 'watch:src', 'watch:templates']);
<commit_msg>Preventing fonts from being packaged twice in crx file<commit_after>var gulp = require('gulp'),
  uglify = require('gulp-uglify'),
  concat = require('gulp-concat'),
  handlebars = require('gulp-handlebars'),
  wrap = require('gulp-wrap'),
  declare = require('gulp-declare'),
  concat = require('gulp-concat'),
  minify_css = require('gulp-minify-css'),
  sourcemaps = require('gulp-sourcemaps'),
  manifest = require('./manifest.json'),
  project = require('./package.json'),
  crx = require('gulp-crx'),
  fs = require('fs');

var paths = {
  'swarm:js:src': ['js/namespace.js', 'js/**/*.js'],
  'swarm:templates:src': ['templates/*.hbs'],
  'swarm:css:src': ['css/feeds.css', 'css/profile.css', 'css/overrides.css', 'css/loading.css', 'css/templates.css'],
  'swarm:plugin:src': ['build/**/*', 'img/**/*', 'libs/css/**/*', 'libs/js/**/*', 'oauth2/**/*', 'background.js', 'popup.js', 'manifest.json', 'home.html']
};

var options = {
  'declare:templates': {
    namespace: 'Swarm.templates',
    noRedeclare: true
  }
};

gulp.task('move:fonts', function () {
  gulp.src(['libs/fonts/**/*'], { base: 'libs' })
    .pipe(gulp.dest('build'));
});

gulp.task('move:plugin:src', function () {
  gulp.src(paths['swarm:plugin:src'], { base: './' })
    .pipe(gulp.dest('dist'));
});

gulp.task('build:js', function () {
  gulp.src(paths['swarm:js:src'])
    .pipe(concat('swarm.js'))
    .pipe(gulp.dest('build/js'))
    .pipe(uglify())
    .pipe(concat('swarm.min.js'))
    .pipe(gulp.dest('build/js'));
});

gulp.task('build:css', ['move:fonts'], function () {
  gulp.src(paths['swarm:css:src'])
    .pipe(concat('swarm.css'))
    .pipe(gulp.dest('build/css'))
    .pipe(minify_css())
    .pipe(concat('swarm.min.css'))
    .pipe(gulp.dest('build/css'));
});

gulp.task('build:src', ['build:js', 'build:css']);

gulp.task('build:templates', function () {
  gulp.src(paths['swarm:templates:src'])
    .pipe(handlebars())
    .pipe(wrap('Handlebars.template(<%= contents %>)'))
    .pipe(declare(options['declare:templates']))
    .pipe(concat('swarm.templates.js'))
    .pipe(gulp.dest('build/js'));/*
    .pipe(uglify('swarm.templates.min.js'))
    .pipe(gulp.dest('build/js'));*/
});

gulp.task('watch:src', function () {
  gulp.watch(paths['swarm:js:src'].concat(paths['swarm:css:src'])
    , ['build:src']);
});

gulp.task('watch:templates', function () {
  gulp.watch(paths['swarm:templates:src', ['build:templates']]);
});

gulp.task('create:dist', ['build:src', 'build:templates', 'move:plugin:src']);
gulp.task('create:crx', ['create:dist'], function() {
  return gulp.src('./dist')
    .pipe(crx({
      privateKey: fs.readFileSync('./dist.pem', 'utf8'),
      filename: manifest.name + '-' + project.version + '.crx',
      codebase: '.',
      updateXmlFilename: 'update.xml'
    }))
    .pipe(gulp.dest('./releases'));
});
gulp.task('release', ['create:crx']);

gulp.task('default', ['build:src', 'build:templates', 'watch:src', 'watch:templates']);
<|endoftext|>


<commit_before>/*
 * najax
 * https://github.com/alanclarke/najax
 *
 * Copyright (c) 2012 Alan Clarke
 * Licensed under the MIT license.
 */

var https   = require('https'),
http        = require('http'),
querystring = require('querystring'),
url         = require('url'),
$           = require('jquery-deferred'),
_           = require('underscore'),
default_settings = { type: 'GET', rejectUnauthorized: true },
najax       = module.exports = request;

/* set default settings */
module.exports.defaults = function(opts) {
	return _.extend(default_settings, opts);
};

function _parseOptions(options, a, b){
	var args = [], opts = _.extend({}, default_settings); ;
	if (_.isString(options)) { opts.url = options; }
	else { _.extend(opts, options); }
	_.each([a, b], function(fn) {
		if (_.isFunction(fn)) { opts.success = fn; }
	});
	if (!_.isFunction(a)) { _.extend(opts, a); }
	return opts;
}

/* auto rest interface go! */
_.each('get post put delete'.split(' '),function(method){
	najax[method] = module.exports[method] = function(options, a, b) {
		var opts = _parseOptions(options, a, b);
		opts.type = method.toUpperCase();
		return najax(opts);
	};
});

/* main function definition */
function request(options, a, b) {
//OPTIONS
	/*
		method overloading, can use:
		-function(url, opts, callback) or
		-function(url, callback)
		-function(opts)
	*/

	if (_.isString(options) || _.isFunction(a)) {
		return request(_parseOptions(options, a, b));
	}

	var dfd = new $.Deferred(),
		o = _.extend({}, default_settings, options),
		l = url.parse(o.url),
		ssl = l.protocol.indexOf('https') === 0,
		data = '';

	//DATA
		/* massage request data according to options */
		o.data = o.data || '';
		o.contentType = o.contentType ? 'application/'+o.contentType :'application/x-www-form-urlencoded';

		if(!o.encoder){
			switch(o.contentType){
				case 'application/json': o.data = JSON.stringify(o.data); break;
				case 'application/x-www-form-urlencoded': o.data = querystring.stringify(o.data); break;
				default: o.data = o.data.toString();
			}
		} else {
			o.data = o.encoder(o.data);
		}

		/* if get, use querystring method for data */
		if (o.type === 'GET') {
			l.search = (l.search ? l.search + '&' : ( o.data ? '?'+o.data : '' ));
		}

	/* if get, use querystring method for data */
	options = {
		host: l.hostname,
		path: l.pathname + (l.search||''),
		method: o.type,
		port: l.port || (ssl? 443 : 80),
		headers: {},
		rejectUnauthorized: o.rejectUnauthorized
	};

		/* set data content type */
		if(o.type!=='GET' && o.data){
			o.data = o.data+'\n';
			options.headers = {
				'Content-Type': o.contentType+';charset=utf-8',
				'Content-Length': o.data ? Buffer.byteLength(o.data) : 0
			};
		}

//AUTHENTICATION
	/* add authentication to http request */
	if (l.auth) {
		options.auth = l.auth;
	} else if (o.username && o.password) {
		options.auth = o.username + ':' + o.password;
	} else if (o.auth){
		options.auth = o.auth;
	}

	/* apply header overrides */
	if(typeof o.headers != "undefined" && typeof options.headers == "undefined")
		options.headers = {};
	_.extend(options.headers, o.headers);
	_.extend(options, _.pick(o, ['auth', 'agent']));

	/* for debugging, method to get options and return */
	if(o.getopts){
		var getopts =  [ssl, options, o.data||false, o.success||false, o.error||false];
		return getopts;
	}

//REQUEST
	var req = (ssl ? https : http).request(options, function(res) {
			// Allow getting Response Headers from the XMLHTTPRequest object
			dfd.getResponseHeader = function(header) {
				return res.headers[header.toLowerCase()];
			};
		res.on('data', function(d) {
			data += d;
		});
		res.on('end', function() {
			if (o.dataType === 'json') {
				//replace control characters
				try { data = JSON.parse(data.replace(/[\cA-\cZ]/gi,'')); }
				catch(e){ return !o.error||o.error(e, res.statusCode); }
			}
			if ( _.isFunction(o.success)) { o.success(data, res.statusCode); }
			dfd.resolve(data);
		});
	});

//ERROR
	req.on('error', function(e) {
		if (_.isFunction(o.error)) { o.error(e); }
		dfd.reject(e);
	});

//SEND DATA
	if (o.type !== 'GET' && o.data) {
		req.write(o.data , 'utf-8');
	}
	req.end();

//DEFERRED
	dfd.success = dfd.done;
	dfd.error = dfd.fail;
	return dfd;
}
<commit_msg>querystring fix<commit_after>/*
 * najax
 * https://github.com/alanclarke/najax
 *
 * Copyright (c) 2012 Alan Clarke
 * Licensed under the MIT license.
 */

var https   = require('https'),
http        = require('http'),
querystring = require('querystring'),
url         = require('url'),
$           = require('jquery-deferred'),
_           = require('underscore'),
default_settings = { type: 'GET', rejectUnauthorized: true },
najax       = module.exports = request;

/* set default settings */
module.exports.defaults = function(opts) {
	return _.extend(default_settings, opts);
};

function _parseOptions(options, a, b){
	var args = [], opts = _.extend({}, default_settings); ;
	if (_.isString(options)) { opts.url = options; }
	else { _.extend(opts, options); }
	_.each([a, b], function(fn) {
		if (_.isFunction(fn)) { opts.success = fn; }
	});
	if (!_.isFunction(a)) { _.extend(opts, a); }
	return opts;
}

/* auto rest interface go! */
_.each('get post put delete'.split(' '),function(method){
	najax[method] = module.exports[method] = function(options, a, b) {
		var opts = _parseOptions(options, a, b);
		opts.type = method.toUpperCase();
		return najax(opts);
	};
});

/* main function definition */
function request(options, a, b) {
//OPTIONS
	/*
		method overloading, can use:
		-function(url, opts, callback) or
		-function(url, callback)
		-function(opts)
	*/

	if (_.isString(options) || _.isFunction(a)) {
		return request(_parseOptions(options, a, b));
	}

	var dfd = new $.Deferred(),
		o = _.extend({}, default_settings, options),
		l = url.parse(o.url),
		ssl = l.protocol.indexOf('https') === 0,
		data = '';

	//DATA
		/* massage request data according to options */
		o.data = o.data || '';
		o.contentType = o.contentType ? 'application/'+o.contentType :'application/x-www-form-urlencoded';

		if(!o.encoder){
			switch(o.contentType){
				case 'application/json': o.data = JSON.stringify(o.data); break;
				case 'application/x-www-form-urlencoded': o.data = querystring.stringify(o.data); break;
				default: o.data = o.data.toString();
			}
		} else {
			o.data = o.encoder(o.data);
		}

		/* if get, use querystring method for data */
		if (o.type === 'GET') {
			l.search = (l.search ? l.search + ( o.data ? '&' + o.data : '' ) : ( o.data ? '?' + o.data : '' ));
		}

	/* if get, use querystring method for data */
	options = {
		host: l.hostname,
		path: l.pathname + (l.search||''),
		method: o.type,
		port: l.port || (ssl? 443 : 80),
		headers: {},
		rejectUnauthorized: o.rejectUnauthorized
	};

		/* set data content type */
		if(o.type!=='GET' && o.data){
			o.data = o.data+'\n';
			options.headers = {
				'Content-Type': o.contentType+';charset=utf-8',
				'Content-Length': o.data ? Buffer.byteLength(o.data) : 0
			};
		}

//AUTHENTICATION
	/* add authentication to http request */
	if (l.auth) {
		options.auth = l.auth;
	} else if (o.username && o.password) {
		options.auth = o.username + ':' + o.password;
	} else if (o.auth){
		options.auth = o.auth;
	}

	/* apply header overrides */
	if(typeof o.headers != "undefined" && typeof options.headers == "undefined")
		options.headers = {};
	_.extend(options.headers, o.headers);
	_.extend(options, _.pick(o, ['auth', 'agent']));

	/* for debugging, method to get options and return */
	if(o.getopts){
		var getopts =  [ssl, options, o.data||false, o.success||false, o.error||false];
		return getopts;
	}

//REQUEST
	var req = (ssl ? https : http).request(options, function(res) {
			// Allow getting Response Headers from the XMLHTTPRequest object
			dfd.getResponseHeader = function(header) {
				return res.headers[header.toLowerCase()];
			};
		res.on('data', function(d) {
			data += d;
		});
		res.on('end', function() {
			if (o.dataType === 'json') {
				//replace control characters
				try { data = JSON.parse(data.replace(/[\cA-\cZ]/gi,'')); }
				catch(e){ return !o.error||o.error(e, res.statusCode); }
			}
			if ( _.isFunction(o.success)) { o.success(data, res.statusCode); }
			dfd.resolve(data);
		});
	});

//ERROR
	req.on('error', function(e) {
		if (_.isFunction(o.error)) { o.error(e); }
		dfd.reject(e);
	});

//SEND DATA
	if (o.type !== 'GET' && o.data) {
		req.write(o.data , 'utf-8');
	}
	req.end();

//DEFERRED
	dfd.success = dfd.done;
	dfd.error = dfd.fail;
	return dfd;
}
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';

import Button from './Button.ffs';

function injectCSS(css) {
  const style = document.createElement('style');
  style.innerHTML = css;
  document.head.appendChild(style);
}

export default () => {
  injectCSS('button { color: red }');
  return <Button />;
};

export const anotherVariant = () => {
  injectCSS('button { text-align: center }');
  return <button>Click meish</button>;
};

const PortalComponent = ({ children }) => {
  const element = document.createElement('div');
  document.body.appendChild(element);
  return ReactDOM.createPortal(children, element);
};

export const portalExample = () => (
  <PortalComponent>
    {window.localStorage.getItem('foobar')}
    <button>I am in a portal</button>
  </PortalComponent>
);

class AsyncComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  componentDidMount() {
    setTimeout(() => this.setState({ ready: true }), 10);
  }

  setLabel(label) {
    this.setState({ label });
  }

  render() {
    if (!this.state.ready) {
      return null;
    }
    return <button>{this.state.label}</button>;
  }
}

export const asyncExample = (render) => {
  const component = render(<AsyncComponent />);
  component.setLabel('Ready');
  return new Promise((resolve) => setTimeout(resolve, 11));
};
<commit_msg>Fix lint in Foo-react-happo.js<commit_after>/* global window */
import React from 'react';
import ReactDOM from 'react-dom';

import Button from './Button.ffs';

function injectCSS(css) {
  const style = document.createElement('style');
  style.innerHTML = css;
  document.head.appendChild(style);
}

export default () => {
  injectCSS('button { color: red }');
  return <Button />;
};

export const anotherVariant = () => {
  injectCSS('button { text-align: center }');
  return <button>Click meish</button>;
};

const PortalComponent = ({ children }) => {
  const element = document.createElement('div');
  document.body.appendChild(element);
  return ReactDOM.createPortal(children, element);
};

export const portalExample = () => (
  <PortalComponent>
    {window.localStorage.getItem('foobar')}
    <button>I am in a portal</button>
  </PortalComponent>
);

class AsyncComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  componentDidMount() {
    setTimeout(() => this.setState({ ready: true }), 10);
  }

  setLabel(label) {
    this.setState({ label });
  }

  render() {
    if (!this.state.ready) {
      return null;
    }
    return <button>{this.state.label}</button>;
  }
}

export const asyncExample = (render) => {
  const component = render(<AsyncComponent />);
  component.setLabel('Ready');
  return new Promise((resolve) => setTimeout(resolve, 11));
};
<|endoftext|>


<commit_before>
// Copyright 2011 Splunk, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

(function() {
    "use strict";

    var Class   = require('./jquery.class').Class;

    var root = exports || this;

    // Our basic class to represent an OData resposne object.
    root.ODataResponse = Class.extend({
        offset: 0,
        count: 0,
        totalCount: 0,
        messages: [],
        timings: [],
        results: null,

        init: function() {

        },

        isCollection: function() {
            return this.results instanceof Array;
        }
    });

    // A static utility function to convert an object derived from JSON
    // into an ODataResponse
    root.ODataResponse.fromJson = function(json) {
        if (!json || !json.d) {
            console.log('Invalid JSON object passed; cannot parse into OData.');
            return null;
        }

        var d = json.d;

        var output = new root.ODataResponse();

        // Look for our special keys, and add them to the results
        var prefixedKeys = ['messages', 'offset', 'count', 'timings', 'total_count'];
        for (var i=0; i < prefixedKeys.length; i++) {
            if (d.hasOwnProperty('__' + prefixedKeys[i])) {
                output[prefixedKeys[i]] = d['__' + prefixedKeys[i]];
            }
        }

        output["__metadata"] = d["__metadata"];
        output["__name"] = d["__name"];
        if (d.results) {
            output.results = d.results;
        }

        return output;
    };

    // Print any messages that came with the response, as encoded
    // in the ODataResponse.
    root.ODataResponse.printMessages = function(struct) {
        var list = struct.messages || struct.__messages || [];

        if (list) {
            for (var i = 0; i < list.length; i++) {
                var msg = '[SPLUNKD] ' + list[i].text;
                switch (list[i].type) {
                    case 'FATAL':
                    case 'ERROR':
                        console.error(msg);
                        break;
                    case 'WARN':
                        console.warn(msg);
                        break;
                    case 'INFO':
                        console.info(msg);
                        break;
                    case 'HTTP':
                        break;
                    default:
                        console.info('[SPLUNKD] ' + list[i].type + ' - ' + msg);
                        break;
                }
            }
        }

        return list;
    };
})();<commit_msg>(SPL-44874) Add the ability to output HTTP errors in odata.js<commit_after>
// Copyright 2011 Splunk, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

(function() {
    "use strict";

    var Class   = require('./jquery.class').Class;

    var root = exports || this;

    // Our basic class to represent an OData resposne object.
    root.ODataResponse = Class.extend({
        offset: 0,
        count: 0,
        totalCount: 0,
        messages: [],
        timings: [],
        results: null,

        init: function() {

        },

        isCollection: function() {
            return this.results instanceof Array;
        }
    });

    // A static utility function to convert an object derived from JSON
    // into an ODataResponse
    root.ODataResponse.fromJson = function(json) {
        if (!json || !json.d) {
            console.log('Invalid JSON object passed; cannot parse into OData.');
            return null;
        }

        var d = json.d;

        var output = new root.ODataResponse();

        // Look for our special keys, and add them to the results
        var prefixedKeys = ['messages', 'offset', 'count', 'timings', 'total_count'];
        for (var i=0; i < prefixedKeys.length; i++) {
            if (d.hasOwnProperty('__' + prefixedKeys[i])) {
                output[prefixedKeys[i]] = d['__' + prefixedKeys[i]];
            }
        }

        output["__metadata"] = d["__metadata"];
        output["__name"] = d["__name"];
        if (d.results) {
            output.results = d.results;
        }

        return output;
    };

    // Print any messages that came with the response, as encoded
    // in the ODataResponse.
    root.ODataResponse.printMessages = function(struct) {
        var list = struct.messages || struct.__messages || [];

        if (list) {
            for (var i = 0; i < list.length; i++) {
                var msg = '[SPLUNKD] ' + list[i].text;
                switch (list[i].type) {
                    case 'HTTP':
                    case 'FATAL':
                    case 'ERROR':
                        console.error(msg);
                        break;
                    case 'WARN':
                        console.warn(msg);
                        break;
                    case 'INFO':
                        console.info(msg);
                        break;
                    case 'HTTP':
                        break;
                    default:
                        console.info('[SPLUNKD] ' + list[i].type + ' - ' + msg);
                        break;
                }
            }
        }

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


<commit_before>var _ = require('underscore');
var fs = require('fs');
var handlebars = require('handlebars');
var path = require('path');
var rimraf = require('rimraf');

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

// Baller meta directory
var BALLER_META_DIR = '.baller';

// Files introduced by Baller
var BALLER_FILES = [
  BALLER_META_DIR
].concat(
  fs.readdirSync(getScriptPath()),
  fs.readdirSync(getResourcePath()),
  _.map(fs.readdirSync(getTemplatePath()), function (template) {
    return template.slice(0, template.lastIndexOf('.'));
  })
);

// Files never managed by a ball
var IGNORED_FILES = BALLER_FILES.concat([
  '.git',
  'LICENSE'
]);

/*
 * Create a new, empty ball in a new directory.
 *
 * Returns a success message if successful. Throws an error if unsuccessful.
 */
function create(name) {
  var errorMessage = 'Could not create ball';

  if (!name) {
    throw new Error(errorMessage + ': no name given');
  }

  // Create a new directory (fail and exist if dir exists or other failure)
  try {
    fs.mkdirSync(name);
  } catch (e) {
    if (e.errno === 47) {
      errorMessage += ': Directory "' + name + '" already exists';
    }
    throw new Error(errorMessage);
  }

  createFilesFile({
    dir: name,
    errorMessage: errorMessage
  });

  createBallerMetadata({
    dir: name,
    errorMessage: errorMessage
  });

  writeRenderedReadme({
    name: name,
    dir: name,
    errorMessage: errorMessage
  });

  copyScriptsToDirectory({
    dir: name,
    errorMessage: errorMessage
  });

  return 'Created "' + name + '" ball';
}

/*
 * Initialize current directory and files as a ball.
 *
 * Returns a success message if successful. Throws an error if unsuccessful.
 */
function init() {
  var errorMessage = 'Could not initialize ball';
  var name = path.basename(process.cwd());

  createFilesFile({
    errorMessage: errorMessage
  });

  createBallerMetadata({
    errorMessage: errorMessage
  });

  writeRenderedReadme({
    name: name,
    errorMessage: errorMessage
  });

  copyScriptsToDirectory({
    errorMessage: errorMessage
  });

  return 'Initialized "' + name + '" ball';
}

/*
 * Update the current ball to latest Baller scripts.
 *
 * Returns a success message if successful. Throws an error if unsuccessful.
 */
function update() {
  throw new Error('update not yet implemented');
}

/*
 * Remove all Baller scripts from current ball.
 *
 * Returns a success message if successful. Throws an error if unsuccessful.
 */
function destroy() {
  var errorMessage = 'Could not destroy ball';
  var name = path.basename(process.cwd());

  var isBall = fs.existsSync(BALLER_META_DIR);
  if (!isBall) {
    throw new Error(errorMessage + ': directory "' + name + '" is not a ball');
  }

  try {
    _.each(BALLER_FILES, function (file) {
      rimraf.sync(file);
    });
    return 'Destroyed "' + name + '" ball';
  } catch (e) {
    throw new Error(errorMessage);
  }
}

/*
 * Deploy the current ball to GitHub (or update existing deploy).
 *
 * Returns a success message if successful. Throws an error if unsuccessful.
 */
function deploy() {
  throw new Error('deploy not yet implemented');
}

/*
 * Return absolute path for module-owned file
 */
function getModulePath(name, dir) {
  var path = __dirname + '/../' + dir;
  if (name) {
    path += '/' + name;
  }
  return path;
}

/*
 * Return path for template
 */
function getTemplatePath(template) {
  return getModulePath(template, 'templates');
}

/*
 * Return path for resource
 */
function getResourcePath(resource) {
  return getModulePath(resource, 'resources');
}

/*
 * Return path for script
 */
function getScriptPath(script) {
  return getModulePath(script, 'scripts');
}

/*
 * Render template resource with given context and return result
 */
function renderTemplate(template, context) {
  var source = fs.readFileSync(getTemplatePath(template)).toString();
  var compiledTemplate = handlebars.compile(source);
  return compiledTemplate(context);
}

/*
 * Render README for current user with given ball name and return result
 */
function renderReadme(name) {
  var context = {
    name: name,
    username: process.env.USER
  };
  return renderTemplate('README.md.hbs', context);
}

/*
 * Create `files` file in directory, prepending list of existing files
 * in that directory (excluding Baller files)
 *
 * Options:
 * - dir: Directory in which `files` will be created (default: '.')
 * - errorMessage: Base error message (default: 'Error')
 */
function createFilesFile(options) {
  options.dir = options.dir || '.';
  options.errorMessage = options.errorMessage || 'Error';

  try {
    var files = _.chain(fs.readdirSync(options.dir))
      .reject(function (file) {
        return _.contains(IGNORED_FILES, file);
      })
      .filter(function (file) {
        try {
          return fs.statSync(file).isFile();
        } catch (e) {
          return false;
        }
      })
      .value();

    var filesName = 'files';
    var originalPath = getResourcePath(filesName);
    var copyPath = path.join(options.dir, filesName);
    var content = _.map(files, function (file) {
      return file + '\n';
    }).join('');
    content += fs.readFileSync(originalPath);
    fs.writeFileSync(copyPath, content);
  } catch (e) {
    throw new Error(options.errorMessage + ': `files` creation failed');
  }
}

/*
 * Add Baller metadata to directory. This turns a directory into a "ball".
 *
 * If directory already contains Baller metadata, creation will be aborted.
 *
 * Options:
 * - dir: Directory in which metadata will be create (default: '.')
 * - errorMessage: Base error message (default: 'Error')
 */
function createBallerMetadata(options) {
  options.dir = options.dir || '.';
  options.errorMessage = options.errorMessage || 'Error';

  var ballerMetaPath = path.join(options.dir, BALLER_META_DIR);
  var isBall = fs.existsSync(ballerMetaPath);

  if (isBall) {
    throw new Error(options.errorMessage + ': directory is already a ball');
  }

  try {
    fs.mkdirSync(ballerMetaPath);
    fs.writeFileSync(path.join(ballerMetaPath, 'version'), pkg.version);
  } catch (e) {
    throw new Error(options.errorMessage + ': metadata creation failed');
  }
}

/*
 * Write rendered README.md to directory
 *
 * Options:
 * - name: Ball name that will be used in README.md (required)
 * - dir: Directory to which files will be copied (default: '.')
 * - errorMessage: Base error message (default: 'Error')
 */
function writeRenderedReadme(options) {
  options.dir = options.dir || '.';
  options.errorMessage = options.errorMessage || 'Error';

  try {
    var readmePath = path.join(options.dir, 'README.md');
    var readme = renderReadme(options.name);
    fs.writeFileSync(readmePath, readme);
  } catch (e) {
    throw new Error(options.errorMessage + ': README creation failed');
  }
}

/*
 * Copy scripts to directory
 *
 * Options:
 * - dir: Directory to which files will be copied (default: '.')
 * - errorMessage: Base error message (default: 'Error')
 */
function copyScriptsToDirectory(options) {
  options.dir = options.dir || '.';
  options.errorMessage = options.errorMessage || 'Error';

  try {
    var scripts = fs.readdirSync(getScriptPath());
    _.each(scripts, function (script) {
      var originalPath = getScriptPath(script);
      var copyPath = path.join(options.dir, script);
      var content = fs.readFileSync(originalPath);
      fs.writeFileSync(copyPath, content);
      fs.chmodSync(copyPath, 0755);
    });
  } catch (e) {
    throw new Error(options.errorMessage + ': scripts creation failed');
  }
}

module.exports = {
  create: create,
  init: init,
  update: update,
  destroy: destroy,
  deploy: deploy
};
<commit_msg>Added createFilesDir() implementation<commit_after>var _ = require('underscore');
var fs = require('fs');
var handlebars = require('handlebars');
var path = require('path');
var rimraf = require('rimraf');

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

// Baller meta directory
var BALLER_META_DIR = '.baller';

// Files introduced by Baller
var BALLER_FILES = [
  BALLER_META_DIR
].concat(
  fs.readdirSync(getScriptPath()),
  fs.readdirSync(getResourcePath()),
  _.map(fs.readdirSync(getTemplatePath()), function (template) {
    return template.slice(0, template.lastIndexOf('.'));
  })
);

// Files never managed by a ball
var IGNORED_FILES = BALLER_FILES.concat([
  '.git',
  'LICENSE'
]);

/*
 * Create a new, empty ball in a new directory.
 *
 * Returns a success message if successful. Throws an error if unsuccessful.
 */
function create(name) {
  var errorMessage = 'Could not create ball';

  if (!name) {
    throw new Error(errorMessage + ': no name given');
  }

  // Create a new directory (fail and exist if dir exists or other failure)
  try {
    fs.mkdirSync(name);
  } catch (e) {
    if (e.errno === 47) {
      errorMessage += ': Directory "' + name + '" already exists';
    }
    throw new Error(errorMessage);
  }

  createFilesFile({
    dir: name,
    errorMessage: errorMessage
  });

  createBallerMetadata({
    dir: name,
    errorMessage: errorMessage
  });

  writeRenderedReadme({
    name: name,
    dir: name,
    errorMessage: errorMessage
  });

  copyScriptsToDirectory({
    dir: name,
    errorMessage: errorMessage
  });

  return 'Created "' + name + '" ball';
}

/*
 * Initialize current directory and files as a ball.
 *
 * Returns a success message if successful. Throws an error if unsuccessful.
 */
function init() {
  var errorMessage = 'Could not initialize ball';
  var name = path.basename(process.cwd());

  createFilesFile({
    errorMessage: errorMessage
  });

  createBallerMetadata({
    errorMessage: errorMessage
  });

  writeRenderedReadme({
    name: name,
    errorMessage: errorMessage
  });

  copyScriptsToDirectory({
    errorMessage: errorMessage
  });

  return 'Initialized "' + name + '" ball';
}

/*
 * Update the current ball to latest Baller scripts.
 *
 * Returns a success message if successful. Throws an error if unsuccessful.
 */
function update() {
  throw new Error('update not yet implemented');
}

/*
 * Remove all Baller scripts from current ball.
 *
 * Returns a success message if successful. Throws an error if unsuccessful.
 */
function destroy() {
  var errorMessage = 'Could not destroy ball';
  var name = path.basename(process.cwd());

  var isBall = fs.existsSync(BALLER_META_DIR);
  if (!isBall) {
    throw new Error(errorMessage + ': directory "' + name + '" is not a ball');
  }

  try {
    _.each(BALLER_FILES, function (file) {
      rimraf.sync(file);
    });
    return 'Destroyed "' + name + '" ball';
  } catch (e) {
    throw new Error(errorMessage);
  }
}

/*
 * Deploy the current ball to GitHub (or update existing deploy).
 *
 * Returns a success message if successful. Throws an error if unsuccessful.
 */
function deploy() {
  throw new Error('deploy not yet implemented');
}

/*
 * Return absolute path for module-owned file
 */
function getModulePath(name, dir) {
  var path = __dirname + '/../' + dir;
  if (name) {
    path += '/' + name;
  }
  return path;
}

/*
 * Return path for template
 */
function getTemplatePath(template) {
  return getModulePath(template, 'templates');
}

/*
 * Return path for resource
 */
function getResourcePath(resource) {
  return getModulePath(resource, 'resources');
}

/*
 * Return path for script
 */
function getScriptPath(script) {
  return getModulePath(script, 'scripts');
}

/*
 * Render template resource with given context and return result
 */
function renderTemplate(template, context) {
  var source = fs.readFileSync(getTemplatePath(template)).toString();
  var compiledTemplate = handlebars.compile(source);
  return compiledTemplate(context);
}

/*
 * Render README for current user with given ball name and return result
 */
function renderReadme(name) {
  var context = {
    name: name,
    username: process.env.USER
  };
  return renderTemplate('README.md.hbs', context);
}

/*
 * Create `files` file in directory, prepending list of existing files
 * in that directory (excluding Baller files)
 *
 * Options:
 * - dir: Directory in which `files` will be created (default: '.')
 * - errorMessage: Base error message (default: 'Error')
 */
function createFilesFile(options) {
  options.dir = options.dir || '.';
  options.errorMessage = options.errorMessage || 'Error';

  try {
    var files = _.chain(fs.readdirSync(options.dir))
      .reject(function (file) {
        return _.contains(IGNORED_FILES, file);
      })
      .filter(function (file) {
        try {
          return fs.statSync(file).isFile();
        } catch (e) {
          return false;
        }
      })
      .value();

    var filesName = 'files';
    var originalPath = getResourcePath(filesName);
    var copyPath = path.join(options.dir, filesName);
    var content = _.map(files, function (file) {
      return file + '\n';
    }).join('');
    content += fs.readFileSync(originalPath);
    fs.writeFileSync(copyPath, content);
  } catch (e) {
    throw new Error(options.errorMessage + ': `files` creation failed');
  }
}

/*
 * Create `files` subdirectory and move any existing files into it (excluding
 * Baller files)
 *
 * Options:
 * - dir: Directory in which `files` subdirectory will be created (default: '.')
 * - errorMessage: Base error message (default: 'Error')
 */
function createFilesDir(options) {
  options.dir = options.dir || '.';
  options.errorMessage = options.errorMessage || 'Error';

  try {
    var files = _.chain(fs.readdirSync(options.dir))
      .reject(function (file) {
        return _.contains(IGNORED_FILES, file);
      })
      .filter(function (file) {
        try {
          return fs.statSync(file).isFile();
        } catch (e) {
          return false;
        }
      })
      .value();

    var filesDirName = 'files';
    var filesDir = path.join(options.dir, filesDirName);
    fs.mkdirSync(filesDir);
    _.each(files, function (file) {
      fs.renameSync(file, path.join(filesDir, file));
    });
  } catch (e) {
    throw new Error(options.errorMessage + ': "files" subdirectory creation failed');
  }
}

/*
 * Add Baller metadata to directory. This turns a directory into a "ball".
 *
 * If directory already contains Baller metadata, creation will be aborted.
 *
 * Options:
 * - dir: Directory in which metadata will be create (default: '.')
 * - errorMessage: Base error message (default: 'Error')
 */
function createBallerMetadata(options) {
  options.dir = options.dir || '.';
  options.errorMessage = options.errorMessage || 'Error';

  var ballerMetaPath = path.join(options.dir, BALLER_META_DIR);
  var isBall = fs.existsSync(ballerMetaPath);

  if (isBall) {
    throw new Error(options.errorMessage + ': directory is already a ball');
  }

  try {
    fs.mkdirSync(ballerMetaPath);
    fs.writeFileSync(path.join(ballerMetaPath, 'version'), pkg.version);
  } catch (e) {
    throw new Error(options.errorMessage + ': metadata creation failed');
  }
}

/*
 * Write rendered README.md to directory
 *
 * Options:
 * - name: Ball name that will be used in README.md (required)
 * - dir: Directory to which files will be copied (default: '.')
 * - errorMessage: Base error message (default: 'Error')
 */
function writeRenderedReadme(options) {
  options.dir = options.dir || '.';
  options.errorMessage = options.errorMessage || 'Error';

  try {
    var readmePath = path.join(options.dir, 'README.md');
    var readme = renderReadme(options.name);
    fs.writeFileSync(readmePath, readme);
  } catch (e) {
    throw new Error(options.errorMessage + ': README creation failed');
  }
}

/*
 * Copy scripts to directory
 *
 * Options:
 * - dir: Directory to which files will be copied (default: '.')
 * - errorMessage: Base error message (default: 'Error')
 */
function copyScriptsToDirectory(options) {
  options.dir = options.dir || '.';
  options.errorMessage = options.errorMessage || 'Error';

  try {
    var scripts = fs.readdirSync(getScriptPath());
    _.each(scripts, function (script) {
      var originalPath = getScriptPath(script);
      var copyPath = path.join(options.dir, script);
      var content = fs.readFileSync(originalPath);
      fs.writeFileSync(copyPath, content);
      fs.chmodSync(copyPath, 0755);
    });
  } catch (e) {
    throw new Error(options.errorMessage + ': scripts creation failed');
  }
}

module.exports = {
  create: create,
  init: init,
  update: update,
  destroy: destroy,
  deploy: deploy
};
<|endoftext|>


<commit_before>'use strict';
// generated on 2014-06-15 using generator-gulp-webapp 0.1.0

var gulp = require('gulp');

// load plugins
var $ = require('gulp-load-plugins')();

var PORT = 5000,
    OUTPUT = 'dist',
    TMP = '.tmp';

gulp.task('jade', function () {
    // render jade files excepts templates
    return gulp.src(['app/**/*.jade', '!app/**/_*.jade', '!app/includes/**/*.jade'])
        .pipe($.jade())
        .pipe(gulp.dest(TMP + '/'));
});

gulp.task('styles', function () {
    return gulp.src('app/styles/main.scss')
        .pipe($.rubySass({
            style: 'expanded',
            precision: 10
        }))
        .pipe($.autoprefixer('last 1 version'))
        .pipe(gulp.dest(TMP + '/styles'))
        .pipe($.size());
});

gulp.task('scripts', function () {
    return gulp.src('app/scripts/**/*.js')
        .pipe($.jshint())
        .pipe($.jshint.reporter(require('jshint-stylish')))
        .pipe($.size());
});

gulp.task('html', ['jade', 'styles', 'scripts'], function () {
    var jsFilter = $.filter('**/*.js');
    var cssFilter = $.filter('**/*.css');

    return gulp.src(['app/*.html', TMP + '/**/*.html'])
        .pipe($.useref.assets({searchPath: '{' + TMP + ',app}'}))
        .pipe(jsFilter)
        .pipe($.uglify())
        .pipe(jsFilter.restore())
        .pipe(cssFilter)
        .pipe($.csso())
        .pipe(cssFilter.restore())
        .pipe($.rev())
        .pipe($.useref.restore())
        .pipe($.useref())
        .pipe($.revReplace())
        .pipe(gulp.dest(OUTPUT))
        .pipe($.size());
});

gulp.task('images', function () {
    return gulp.src('app/images/**/*')
        .pipe($.cache($.imagemin({
            optimizationLevel: 3,
            progressive: true,
            interlaced: true
        })))
        .pipe(gulp.dest(OUTPUT + '/images'))
        .pipe($.size());
});

gulp.task('fonts', function () {
    return $.bowerFiles()
        .pipe($.filter('**/*.{eot,svg,ttf,woff}'))
        .pipe($.flatten())
        .pipe(gulp.dest(OUTPUT + '/fonts'))
        .pipe($.size());
});

gulp.task('extras', function () {
    return gulp.src(['app/*.*', '!app/*.html', '!app/**/*.jade'], { dot: true })
        .pipe(gulp.dest(OUTPUT));
});

gulp.task('clean', function () {
    return gulp.src([TMP, OUTPUT], { read: false }).pipe($.clean());
});

gulp.task('build', ['html', 'images', 'fonts', 'extras']);

gulp.task('default', ['clean'], function () {
    gulp.start('build');
});

gulp.task('connect', function () {
    var connect = require('connect');
    var app = connect()
        .use(connect.static('app'))
        .use(connect.static(TMP))
        .use(connect.directory('app'));

    require('http').createServer(app)
        .listen(PORT)
        .on('listening', function () {
            console.log('Started connect web server on http://localhost:' + PORT);
        });
});

gulp.task('serve', ['connect', 'jade', 'styles'], function () {
    require('opn')('http://localhost:' + PORT);
});

// inject bower components
gulp.task('wiredep', function () {
    var wiredep = require('wiredep').stream;

    gulp.src('app/styles/*.scss')
        .pipe(wiredep({
            directory: 'app/bower_components'
        }))
        .pipe(gulp.dest('app/styles'));

    gulp.src('app/*.html')
        .pipe(wiredep({
            directory: 'app/bower_components',
            exclude: ['bootstrap-sass-official']
        }))
        .pipe(gulp.dest('app'));
});

gulp.task('watch', ['connect', 'serve'], function () {
    gulp.watch('app/styles/**/*.scss', ['styles']);
    gulp.watch('app/**/*.jade', ['jade']);
    gulp.watch('app/scripts/**/*.js', ['scripts']);
    gulp.watch('app/images/**/*', ['images']);
    gulp.watch('bower.json', ['wiredep']);
});
<commit_msg>gulp: build each scss files.<commit_after>'use strict';
// generated on 2014-06-15 using generator-gulp-webapp 0.1.0

var gulp = require('gulp');

// load plugins
var $ = require('gulp-load-plugins')();

var PORT = 5000,
    OUTPUT = 'dist',
    TMP = '.tmp';

gulp.task('jade', function () {
    // render jade files excepts templates
    return gulp.src(['app/**/*.jade', '!app/**/_*.jade', '!app/includes/**/*.jade'])
        .pipe($.jade())
        .pipe(gulp.dest(TMP + '/'));
});

gulp.task('styles', function () {
    return gulp.src(['app/styles/*.scss'])
        .pipe($.rubySass({
            style: 'expanded',
            precision: 10
        }))
        .pipe($.autoprefixer('last 1 version'))
        .pipe(gulp.dest(TMP + '/styles'))
        .pipe($.size());
});

gulp.task('scripts', function () {
    return gulp.src('app/scripts/**/*.js')
        .pipe($.jshint())
        .pipe($.jshint.reporter(require('jshint-stylish')))
        .pipe($.size());
});

gulp.task('html', ['jade', 'styles', 'scripts'], function () {
    var jsFilter = $.filter('**/*.js');
    var cssFilter = $.filter('**/*.css');

    return gulp.src(['app/*.html', TMP + '/**/*.html'])
        .pipe($.useref.assets({searchPath: '{' + TMP + ',app}'}))
        .pipe(jsFilter)
        .pipe($.uglify())
        .pipe(jsFilter.restore())
        .pipe(cssFilter)
        .pipe($.csso())
        .pipe(cssFilter.restore())
        .pipe($.rev())
        .pipe($.useref.restore())
        .pipe($.useref())
        .pipe($.revReplace())
        .pipe(gulp.dest(OUTPUT))
        .pipe($.size());
});

gulp.task('images', function () {
    return gulp.src('app/images/**/*')
        .pipe($.cache($.imagemin({
            optimizationLevel: 3,
            progressive: true,
            interlaced: true
        })))
        .pipe(gulp.dest(OUTPUT + '/images'))
        .pipe($.size());
});

gulp.task('fonts', function () {
    return $.bowerFiles()
        .pipe($.filter('**/*.{eot,svg,ttf,woff}'))
        .pipe($.flatten())
        .pipe(gulp.dest(OUTPUT + '/fonts'))
        .pipe($.size());
});

gulp.task('extras', function () {
    return gulp.src(['app/*.*', '!app/*.html', '!app/**/*.jade'], { dot: true })
        .pipe(gulp.dest(OUTPUT));
});

gulp.task('clean', function () {
    return gulp.src([TMP, OUTPUT], { read: false }).pipe($.clean());
});

gulp.task('build', ['html', 'images', 'fonts', 'extras']);

gulp.task('default', ['clean'], function () {
    gulp.start('build');
});

gulp.task('connect', function () {
    var connect = require('connect');
    var app = connect()
        .use(connect.static('app'))
        .use(connect.static(TMP))
        .use(connect.directory('app'));

    require('http').createServer(app)
        .listen(PORT)
        .on('listening', function () {
            console.log('Started connect web server on http://localhost:' + PORT);
        });
});

gulp.task('serve', ['connect', 'jade', 'styles'], function () {
    require('opn')('http://localhost:' + PORT);
});

// inject bower components
gulp.task('wiredep', function () {
    var wiredep = require('wiredep').stream;

    gulp.src('app/styles/*.scss')
        .pipe(wiredep({
            directory: 'app/bower_components'
        }))
        .pipe(gulp.dest('app/styles'));

    gulp.src('app/*.html')
        .pipe(wiredep({
            directory: 'app/bower_components',
            exclude: ['bootstrap-sass-official']
        }))
        .pipe(gulp.dest('app'));
});

gulp.task('watch', ['connect', 'serve'], function () {
    gulp.watch('app/styles/**/*.scss', ['styles']);
    gulp.watch('app/**/*.jade', ['jade']);
    gulp.watch('app/scripts/**/*.js', ['scripts']);
    gulp.watch('app/images/**/*', ['images']);
    gulp.watch('bower.json', ['wiredep']);
});
<|endoftext|>


<commit_before>var gulp = require('gulp');
var jshint = require('gulp-jshint');
var mocha = require('gulp-mocha');
var connect = require('gulp-connect');
// var vulcanize = require('gulp-vulcanize');
var replace = require('gulp-replace');
var rename = require('gulp-rename');
var sass = require('gulp-sass');
var insert = require('gulp-insert');

var src = ['index.js', 'lib/**.js', 'test/**/*.js'];

gulp.task('lint', function() {
  return gulp.src(src)
    .pipe(jshint())
    .pipe(jshint.reporter( 'jshint-stylish' ))
});

gulp.task('test', gulp.series('lint', function(done) {
  return gulp.src('test/tags.spec.js', {read: false})
    .pipe(mocha());
}));

// create the polymer script for the handlebars template to use
gulp.task('vulcanize', function() {
  return gulp.src('assets/polymer.html')
    .pipe(vulcanize({
      inlineScripts: true,
      stripComments: true
    }))
    // escape double {{ for handlebars
    .pipe(replace(/\(\\\\\[\\\\\[\|\{\{\)/, '(\\\\[\\\\[|\\\\{\\\\{)'))
    // remove html and body tags
    .pipe(replace(/[\s\S]*?(


<commit_before>module.exports = WatchIgnorePlugin

function WatchIgnorePlugin(paths) {
    this.paths = paths
}

WatchIgnorePlugin.prototype.apply = function (compiler) {
    compiler.plugin('after-environment', function () {
        compiler.watchFileSystem = new IgnoringWatchFileSystem(compiler.watchFileSystem, this.paths)
    }.bind(this))
}

function IgnoringWatchFileSystem(wfs, paths) {
    this.wfs = wfs
    this.paths = paths
}

IgnoringWatchFileSystem.prototype.watch = function (files, dirs, missing, startTime, delay, callback, callbackUndelayed) {
    var ignored = function (path) {
        return this.paths.some(function (p) {
            return path.match(p)
        })
    }.bind(this)
    var notIgnored = function (path) { return !ignored(path) }
    var ignoredFiles = files.filter(ignored)
    var ignoredDirs = dirs.filter(ignored)
    this.wfs.watch(files.filter(notIgnored), dirs.filter(notIgnored), missing, startTime, delay, function (err, filesModified, dirsModified, fileTimestamps, dirTimestamps) {
        if (err) return callback(err)
        ignoredFiles.forEach(function (path) {
            fileTimestamps[path] = 1
        })
        ignoredDirs.forEach(function (path) {
            dirTimestamps[path] = 1
        })
        callback(err, filesModified, dirsModified, fileTimestamps, dirTimestamps)
    }, callbackUndelayed)
}
<commit_msg>Use .search for browser compatibility.<commit_after>module.exports = WatchIgnorePlugin

function WatchIgnorePlugin(paths) {
    this.paths = paths
}

WatchIgnorePlugin.prototype.apply = function (compiler) {
    compiler.plugin('after-environment', function () {
        compiler.watchFileSystem = new IgnoringWatchFileSystem(compiler.watchFileSystem, this.paths)
    }.bind(this))
}

function IgnoringWatchFileSystem(wfs, paths) {
    this.wfs = wfs
    this.paths = paths
}

IgnoringWatchFileSystem.prototype.watch = function (files, dirs, missing, startTime, delay, callback, callbackUndelayed) {
    var ignored = function (path) {
        return this.paths.some(function (p) {
            return path.search(p) >= 0
        })
    }.bind(this)
    var notIgnored = function (path) { return !ignored(path) }
    var ignoredFiles = files.filter(ignored)
    var ignoredDirs = dirs.filter(ignored)
    this.wfs.watch(files.filter(notIgnored), dirs.filter(notIgnored), missing, startTime, delay, function (err, filesModified, dirsModified, fileTimestamps, dirTimestamps) {
        if (err) return callback(err)
        ignoredFiles.forEach(function (path) {
            fileTimestamps[path] = 1
        })
        ignoredDirs.forEach(function (path) {
            dirTimestamps[path] = 1
        })
        callback(err, filesModified, dirsModified, fileTimestamps, dirTimestamps)
    }, callbackUndelayed)
}
<|endoftext|>


<commit_before>var webpackMerge = require('webpack-merge');
var webpack = require('webpack');
var path = require('path');
var helpers = require('./config/helpers');

module.exports = webpackMerge(helpers.webpackDepsConfig(), {
  context: helpers.root('..', '..'),
  entry: {
    'bootstrap': helpers.root('bootstrap.ts'),
    'js/vendor': helpers.root('js/vendor.ts'),
    'js/polyfills': helpers.root('js/polyfills.ts'),
  },

  resolve: {
    root: helpers.root(),
    modulesDirectories: [
      helpers.root('node_modules'),].concat(
      helpers.getMicroservices().map(ms => path.join(ms, 'frontend', 'node_modules'))
    ),
    extensions: ['', '.js', 'es6', '.ts'],
  },

  get resolveLoader() {
    return this.resolve;
  },

  module: {
    loaders: [
      {
        test: /\.ts$/,
        loaders: [
          'awesome-typescript-loader',
          'angular2-template-loader',
        ]
      },
      {
        test: /\.html$/,
        loader: 'raw-loader',
        exclude: [helpers.root('index.html')],
      },
      {
        test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
        loader: 'file?name=assets/[name].[hash].[ext]'
      },
      {
        test: /\.css$/,
        loader: 'raw'
      },
      {
        test: /\.es6$/,
        loader: 'babel',
        exclude: /(node_modules|bower_components|dist)/i,
      },
      {
        test: /\.json$/,
        loader: 'json',
      },
    ],
  },

  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: ['js/vendor', 'js/polyfills'],
    }),
  ],

  output: {
    path: helpers.root(),
    filename: '[name].js',
    chunkFilename: '[id].chunk.js'
  },
});
<commit_msg>Added json extension<commit_after>var webpackMerge = require('webpack-merge');
var webpack = require('webpack');
var path = require('path');
var helpers = require('./config/helpers');

module.exports = webpackMerge(helpers.webpackDepsConfig(), {
  context: helpers.root('..', '..'),
  entry: {
    'bootstrap': helpers.root('bootstrap.ts'),
    'js/vendor': helpers.root('js/vendor.ts'),
    'js/polyfills': helpers.root('js/polyfills.ts'),
  },

  resolve: {
    root: helpers.root(),
    modulesDirectories: [
      helpers.root('node_modules'),].concat(
      helpers.getMicroservices().map(ms => path.join(ms, 'frontend', 'node_modules'))
    ),
    extensions: ['', '.js', 'es6', '.ts', 'json'],
  },

  get resolveLoader() {
    return this.resolve;
  },

  module: {
    loaders: [
      {
        test: /\.ts$/,
        loaders: [
          'awesome-typescript-loader',
          'angular2-template-loader',
        ]
      },
      {
        test: /\.html$/,
        loader: 'raw-loader',
        exclude: [helpers.root('index.html')],
      },
      {
        test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
        loader: 'file?name=assets/[name].[hash].[ext]'
      },
      {
        test: /\.css$/,
        loader: 'raw'
      },
      {
        test: /\.es6$/,
        loader: 'babel',
        exclude: /(node_modules|bower_components|dist)/i,
      },
      {
        test: /\.json$/,
        loader: 'json',
      },
    ],
  },

  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: ['js/vendor', 'js/polyfills'],
    }),
  ],

  output: {
    path: helpers.root(),
    filename: '[name].js',
    chunkFilename: '[id].chunk.js'
  },
});
<|endoftext|>


<commit_before>
// useful es6 shim
if( !Array.prototype.find ) {
  Array.prototype.find = function (iteratee, thisArg) {
    if( typeof iteratee !== 'function' ) throw new TypeError('predicate must be a function');

    for( var i = 0, n = this.length ; i < n ; i++ ) {
      if( iteratee.call(thisArg, this[i]) ) {
        return this[i];
      }
    }
  };
}

// nitro declaration

var nitro = function (handler) {
      if( handler instanceof Function ) handler(nitro);
      return nitro;
    },
    _ = require('nitro-tools'),
    fs = require('fs'),
    color = require('./color'),
    deasync = require('deasync'),
    noop = function (value) { return value; },
    YAML = require('js-yaml');

var file = require('./file'),
    dir = require('./dir'),
    processors = require('./processors'),
    tasks = require('./tasks'),
    joinPaths = require('./join-paths'),
    server = require('./server'),
    livereload = require('./livereload'),
    autoRequire = require('./auto-require'),
    dirExpand = require('./dir-expand');

function returnNitro (fn) {
  return function () {
    fn.apply(this, arguments);
    return nitro;
  };
}

_.extend(nitro, {
  color: color,
  noop: noop,
  cwdRoot: process.cwd(),
  cwd: require('./cwd'),
  joinPaths: joinPaths,
  exec: require('child_process').execSync || deasync( require('child_process').exec ),
  deasync: deasync,
  dir: dir,
  expand: function (pattern, options) {
    return dir('.').expand(pattern, options);
  },
  isDir: function (dirpath) {
    try {
      return fs.statSync(dirpath).isDirectory();
    } catch(err) {
      return false;
    }
  },
  file: file,
  isFile: function (dirpath) {
    try {
      return fs.statSync(dirpath).isFile();
    } catch(err) {
      return false;
    }
  },
  tools: _,
  copy: function () {
    dir.copy.apply(this, arguments);
    return nitro;
  },
  symlink: function (_path, target, type) {
    var dirpath = joinPaths.root( _path.replace(/\/[^\/]+$/, '') );
    if( !dir.exists(dirpath) ) {
      dir.create(dirpath);
    }
    fs.symlinkSync( target, joinPaths.root(_path), type);
    return nitro;
  },
  load: function (pattern, options) {
    return dir.load('.', pattern, options);
  },
  // addPreset: returnNitro( processors.addPreset ),
  // loadProcessors: returnNitro( processors.loadPresets ),
  dirExpand: dirExpand,
  require: autoRequire,
  import: function (dirpath, filter) {
    if( !dir.exists(dirpath) ) {
      console.error('directory ' + color.yellow(dirpath) + ' does not exists');
      process.exit(1);
    }

    dir(dirpath).load( filter || ( filter === false ? '*.js' : '{,**/}*.js' ) )
      .each(function (f) {
        var fullpath = joinPaths.root( f.cwd, f.path );
        if( fullpath === __filename ) return;
        require( fullpath )(nitro);
      });

    return nitro;
  },
  registerProcessor: returnNitro(processors.register),
  task: tasks,
  template: require('trisquel'),
  libs2html: dir.libs2html,
  watch: require('./watch'),
  livereload: function (dirpath, options) {
    options = options ? _.copy(options) : {};

    if( options.highlight ) {
      options.highlight = autoRequire('cardinal').highlight;
    }

    livereload(options.server || server(__dirname + '/livereload', { port: options.port || 12345, log: false }), dirpath, options);
  },
  parseJSON: function (json) {
    return JSON.parse(json);
  },
  parseYAML: function (yaml, options) {
    options = options || {};
    return YAML.safeLoad(yaml, {
      filename: options.filename,
      schema: options.schema,
      json: options.json,
      onWarning: function () {
        console.log.apply(console, ['YAML error'].concat(arguments));
        if( options.onWarning instanceof Function ) options.onWarning.apply(this, arguments);
      }
    });
  },
  stringify: function (data, format, options) {
    format = format || 'json';
    options = options || {};

    if( format === 'json' ) {
      return JSON.stringify(data, null, options.indentBy || '\t' );
    } else if( format === 'yaml' ) {
      return YAML.safeDump(data);
    }

    throw new Error('Stringify to ' + format + ' format not supported.');
  },
  run: function (taskList) {
    if( taskList && process.argv.length < 3 ) {
      console.error('needs at least 1 argument');
      process.exit(1);
    }

    return tasks.run( taskList || [].slice.call(process.argv, 2) );
  },
  server: server
});

nitro.package = require('./package')(nitro);

module.exports = nitro;
<commit_msg>nitro run exiting with 0<commit_after>
// useful es6 shim
if( !Array.prototype.find ) {
  Array.prototype.find = function (iteratee, thisArg) {
    if( typeof iteratee !== 'function' ) throw new TypeError('predicate must be a function');

    for( var i = 0, n = this.length ; i < n ; i++ ) {
      if( iteratee.call(thisArg, this[i]) ) {
        return this[i];
      }
    }
  };
}

// nitro declaration

var nitro = function (handler) {
      if( handler instanceof Function ) handler(nitro);
      return nitro;
    },
    _ = require('nitro-tools'),
    fs = require('fs'),
    color = require('./color'),
    deasync = require('deasync'),
    noop = function (value) { return value; },
    YAML = require('js-yaml');

var file = require('./file'),
    dir = require('./dir'),
    processors = require('./processors'),
    tasks = require('./tasks'),
    joinPaths = require('./join-paths'),
    server = require('./server'),
    livereload = require('./livereload'),
    autoRequire = require('./auto-require'),
    dirExpand = require('./dir-expand');

function returnNitro (fn) {
  return function () {
    fn.apply(this, arguments);
    return nitro;
  };
}

_.extend(nitro, {
  color: color,
  noop: noop,
  cwdRoot: process.cwd(),
  cwd: require('./cwd'),
  joinPaths: joinPaths,
  exec: require('child_process').execSync || deasync( require('child_process').exec ),
  deasync: deasync,
  dir: dir,
  expand: function (pattern, options) {
    return dir('.').expand(pattern, options);
  },
  isDir: function (dirpath) {
    try {
      return fs.statSync(dirpath).isDirectory();
    } catch(err) {
      return false;
    }
  },
  file: file,
  isFile: function (dirpath) {
    try {
      return fs.statSync(dirpath).isFile();
    } catch(err) {
      return false;
    }
  },
  tools: _,
  copy: function () {
    dir.copy.apply(this, arguments);
    return nitro;
  },
  symlink: function (_path, target, type) {
    var dirpath = joinPaths.root( _path.replace(/\/[^\/]+$/, '') );
    if( !dir.exists(dirpath) ) {
      dir.create(dirpath);
    }
    fs.symlinkSync( target, joinPaths.root(_path), type);
    return nitro;
  },
  load: function (pattern, options) {
    return dir.load('.', pattern, options);
  },
  // addPreset: returnNitro( processors.addPreset ),
  // loadProcessors: returnNitro( processors.loadPresets ),
  dirExpand: dirExpand,
  require: autoRequire,
  import: function (dirpath, filter) {
    if( !dir.exists(dirpath) ) {
      console.error('directory ' + color.yellow(dirpath) + ' does not exists');
      process.exit(1);
    }

    dir(dirpath).load( filter || ( filter === false ? '*.js' : '{,**/}*.js' ) )
      .each(function (f) {
        var fullpath = joinPaths.root( f.cwd, f.path );
        if( fullpath === __filename ) return;
        require( fullpath )(nitro);
      });

    return nitro;
  },
  registerProcessor: returnNitro(processors.register),
  task: tasks,
  template: require('trisquel'),
  libs2html: dir.libs2html,
  watch: require('./watch'),
  livereload: function (dirpath, options) {
    options = options ? _.copy(options) : {};

    if( options.highlight ) {
      options.highlight = autoRequire('cardinal').highlight;
    }

    livereload(options.server || server(__dirname + '/livereload', { port: options.port || 12345, log: false }), dirpath, options);
  },
  parseJSON: function (json) {
    return JSON.parse(json);
  },
  parseYAML: function (yaml, options) {
    options = options || {};
    return YAML.safeLoad(yaml, {
      filename: options.filename,
      schema: options.schema,
      json: options.json,
      onWarning: function () {
        console.log.apply(console, ['YAML error'].concat(arguments));
        if( options.onWarning instanceof Function ) options.onWarning.apply(this, arguments);
      }
    });
  },
  stringify: function (data, format, options) {
    format = format || 'json';
    options = options || {};

    if( format === 'json' ) {
      return JSON.stringify(data, null, options.indentBy || '\t' );
    } else if( format === 'yaml' ) {
      return YAML.safeDump(data);
    }

    throw new Error('Stringify to ' + format + ' format not supported.');
  },
  run: function (taskList) {
    if( taskList && process.argv.length < 3 ) {
      console.error('needs at least 1 argument');
      process.exit(1);
    }

    return tasks.run( taskList || [].slice.call(process.argv, 2), function () {
      process.exit(0);
    });
  },
  server: server
});

nitro.package = require('./package')(nitro);

module.exports = nitro;
<|endoftext|>


<commit_before>var debug = require('debug')('metalsmith-seo-checker');
var _ = require('lodash');
var defaultsDeep = _.partialRight(_.merge, function deep(value, other) {
    return _.merge(value, other, deep);
});

module.exports = plugin;

function plugin(options) {
    options = options || {};
    defaultsDeep(options, {
        ignoreFiles: [],
        trailingSlash : true,
        lengths: {
            title: 60,
            description: 160
        },
        seo: {
            title: true,
            robots: 'index, follow'
        },
        ogp: {
            defaultType: 'website',
            defaultImage: false,
            ignoreMissingImage: false
        }
    });

    var shouldInspect = getInspectDecider(options),
        values = options.values || {};

    return function(files, metalsmith, done) {
        var fileNames = Object.keys(files),
            file;

        for (var i = 0; i < fileNames.length; i++) {
            file = fileNames[i];

            if (!shouldInspect(file)) {
                continue;
            }

            debug('checking file: %s', file);
            var data = files[file];
            data.seo = data.seo || {};

            data.seo.canonical = options.canonicalBase;

            //Check if path exists in this context
            //i.e. index/archival pages
            if (data.path) {
              data.seo.canonical += "/" + data.path;
            }

            // Attach trailingSlash
            if (options.trailingSlash) {
              //Prevent double slash if path contains a trailing slash already
              data.seo.canonical += data.seo.canonical.substr(-1) !== "/" ? "/" : "";
            }

            // Make private pages noindex, nofollow
            if (!data.seo.robots && data.private) {
              data.seo.robots = 'noindex, nofollow';
            } else if (!data.seo.robots && options.seo.robots && !data.private) {
              //Get from file definition and fall back to options/defaults
              data.seo.robots = options.seo.robots;
            }

            var keys = Object.keys(values),
                container,
                length,
                value,
                attr,
                max,
                j;
            for (j = 0; j < keys.length; j++) {
                attr = keys[j];
                container = attr === 'title' ? data : data.seo;

                if (values[attr] === true) {
                    if (!container[attr]) {
                        return done(error(file, 'Missing required seo attribute: ' + attr));
                    }
                } else if (!container[attr]) {
                    container[attr] = values[attr];
                }
            }

            keys = Object.keys(options.lengths);
            for (j = 0; j < keys.length; j++) {
                attr = keys[j];
                if (attr === 'title') {
                    value = data.title;
                } else {
                    value = data.seo[attr];
                }
                length = value ? value.length : 0;

                max = options.lengths[attr];
                if (max && length > max) {
                    return done(error(file, attr + ' is too long, the max is '
                            + max + ', currently: ' + length + ' long.'));
                }
            }

            data.seo.ogp = data.seo.ogp || {};
            data.seo.ogp.title = data.seo.ogp.title || data.title;
            data.seo.ogp.type = data.seo.ogp.type || options.ogp.defaultType;
            data.seo.ogp.image = data.seo.ogp.image || options.ogp.defaultImage;

            if (!data.seo.ogp.image && !options.ogp.ignoreMissingImage) {
                return done(error(file, 'Missing OGP image.\n' +
                        'To ignore this error set ' +
                        'options.ogp.ignoreMissingImages to true or provide ' +
                        'a default image with options.ogp.defaultImage.'));
            }
        }

        done();
    };
}

function error(file, message) {
    return message + '\nFile: ' + file +
            '\nTo skip validation on this file add it to the ' +
            'ignoreFiles array.\n\n';
}

function getInspectDecider(options) {
    var toInspectRegexs = [/.md$|.markdown$|.html?$/];
    if (options.toInspect &&
                Object.prototype.toString.call(options.toInspect) === '[object Array]') {
        toInspectRegexs = options.toInspect;
    } else if (options.toInspect) {
        toInspectRegexs = [options.toInspect];
    }

    return function (file) {
        if (options.ignoreFiles.indexOf(file) !== -1) {
            return false;
        }

        for (var i = 0; i < toInspectRegexs.length; i++) {
            if (toInspectRegexs[i].test(file)) {
                return true;
            }
        }

        return false;
    };
}
<commit_msg>Fix seo-canonical to allow manual definition of canonical url<commit_after>var debug = require('debug')('metalsmith-seo-checker');
var _ = require('lodash');
var defaultsDeep = _.partialRight(_.merge, function deep(value, other) {
    return _.merge(value, other, deep);
});

module.exports = plugin;

function plugin(options) {
    options = options || {};
    defaultsDeep(options, {
        ignoreFiles: [],
        trailingSlash : true,
        lengths: {
            title: 60,
            description: 160
        },
        seo: {
            title: true,
            robots: 'index, follow'
        },
        ogp: {
            defaultType: 'website',
            defaultImage: false,
            ignoreMissingImage: false
        }
    });

    var shouldInspect = getInspectDecider(options),
        values = options.values || {};

    return function(files, metalsmith, done) {
        var fileNames = Object.keys(files),
            file;

        for (var i = 0; i < fileNames.length; i++) {
            file = fileNames[i];

            if (!shouldInspect(file)) {
                continue;
            }

            debug('checking file: %s', file);
            var data = files[file];
            data.seo = data.seo || {};

            data.seo.canonical = data.seo.canonical || options.canonicalBase;

            //Check if path exists in this context
            //i.e. index/archival pages
            if (data.path) {
              data.seo.canonical += "/" + data.path;
            }

            // Attach trailingSlash
            if (options.trailingSlash) {
              //Prevent double slash if path contains a trailing slash already
              data.seo.canonical += data.seo.canonical.substr(-1) !== "/" ? "/" : "";
            }

            // Make private pages noindex, nofollow
            if (!data.seo.robots && data.private) {
              data.seo.robots = 'noindex, nofollow';
            } else if (!data.seo.robots && options.seo.robots && !data.private) {
              //Get from file definition and fall back to options/defaults
              data.seo.robots = options.seo.robots;
            }

            var keys = Object.keys(values),
                container,
                length,
                value,
                attr,
                max,
                j;
            for (j = 0; j < keys.length; j++) {
                attr = keys[j];
                container = attr === 'title' ? data : data.seo;

                if (values[attr] === true) {
                    if (!container[attr]) {
                        return done(error(file, 'Missing required seo attribute: ' + attr));
                    }
                } else if (!container[attr]) {
                    container[attr] = values[attr];
                }
            }

            keys = Object.keys(options.lengths);
            for (j = 0; j < keys.length; j++) {
                attr = keys[j];
                if (attr === 'title') {
                    value = data.title;
                } else {
                    value = data.seo[attr];
                }
                length = value ? value.length : 0;

                max = options.lengths[attr];
                if (max && length > max) {
                    return done(error(file, attr + ' is too long, the max is '
                            + max + ', currently: ' + length + ' long.'));
                }
            }

            data.seo.ogp = data.seo.ogp || {};
            data.seo.ogp.title = data.seo.ogp.title || data.title;
            data.seo.ogp.type = data.seo.ogp.type || options.ogp.defaultType;
            data.seo.ogp.image = data.seo.ogp.image || options.ogp.defaultImage;

            if (!data.seo.ogp.image && !options.ogp.ignoreMissingImage) {
                return done(error(file, 'Missing OGP image.\n' +
                        'To ignore this error set ' +
                        'options.ogp.ignoreMissingImages to true or provide ' +
                        'a default image with options.ogp.defaultImage.'));
            }
        }

        done();
    };
}

function error(file, message) {
    return message + '\nFile: ' + file +
            '\nTo skip validation on this file add it to the ' +
            'ignoreFiles array.\n\n';
}

function getInspectDecider(options) {
    var toInspectRegexs = [/.md$|.markdown$|.html?$/];
    if (options.toInspect &&
                Object.prototype.toString.call(options.toInspect) === '[object Array]') {
        toInspectRegexs = options.toInspect;
    } else if (options.toInspect) {
        toInspectRegexs = [options.toInspect];
    }

    return function (file) {
        if (options.ignoreFiles.indexOf(file) !== -1) {
            return false;
        }

        for (var i = 0; i < toInspectRegexs.length; i++) {
            if (toInspectRegexs[i].test(file)) {
                return true;
            }
        }

        return false;
    };
}
<|endoftext|>