<commit_before>var wfangular = angular.module('wfangular', []);

wfangular.constant('wfangularConfig', {
	assetsLocation: 'http://static.3dwayfinder.com/shared/',
	apiLocation: 'http://api.3dwayfinder.com',
	mapType: '3d'
});
wfangular.factory('wfangular', ['$rootScope', 'wfangularConfig', function($rootScope, config) {
	var wf = false;
	WayfinderAPI.LOCATION = config.apiLocation;

	if(config.mapType == "3d")
		wf = new Wayfinder3D();
	else if(config.mapType !== "2d")
		wf = new Wayfinder2D();

	wf.options.assetsLocation = config.assetsLocation;

	if(wf){
		wf.cbOnDataLoaded = function() {
			$rootScope.$broadcast('wf.data.loaded', []);
		}

		wf.cbOnPOIClick = function(poi) {
			$rootScope.$broadcast('wf.poi.click', poi);
		}

		wf.cbOnLanguageChange = function(language) {
			$rootScope.$broadcast('wf.language.change', language);
		}

		wf.cbOnFloorChange = function(floor) {
			$rootScope.$broadcast('wf.floor.change', floor);
		}

		wf.cbOnZoomChange = function(zoom) {
			$rootScope.$broadcast('wf.zoom.change', zoom);
		}

		wf.cbOnBeforeFloorChange = function(currentFloor, nextFloor, destinationFloor) {
			$rootScope.$broadcast('wf.path.floor.change', {
				current: currentFloor,
				next: nextFloor,
				destination: destinationFloor
			});
		}

		wf.cbOnTouch = function(type, value) {
			$rootScope.$broadcast('wf.touch', {
				type: type,
				value: value
			});
		}
	}

	return wf;
}]);

wfangular.filter('wfCurrentLanguage', ['wfangular', function (wayfinder) {
    return function (input) {
        if (input && typeof input === "object") {
            if (input[wayfinder.getLanguage()]) {
                return input[wayfinder.getLanguage()];
            } else if (input["translations"][wayfinder.getLanguage()]) {
                return input["translations"][wayfinder.getLanguage()];
            } else {
                return input;
            }
        } else {
            return input;
        }
    };
}]);

wfangular.directive('wfBanner', ['$interval', 'wfangular', '$timeout', function ($interval, wayfinder, $timeout) {
    return {
        restrict: 'EA',
        scope: {},
        controller: ['$scope', '$element', '$attrs', '$timeout','$document', function ($scope, $element, $attrs, $timeout, $document) {
            var timeoutId;
            var frames = [];
            var current = 0;
            var timer = null;
            var id = false;
            var template = "default";

            //watch id attribute for the banner placement
            $scope.$watch(function () {
                      return $element.attr('id');
                  },
                  function () {
                      if (!!$attrs.id && $attrs.id !== "") {
                          id = $attrs.id;
                      }
                  }
            );

            $scope.$watch(function () {
                              return $element.attr('template');
                          },
                          function () {
                              if (!!$attrs.template && $attrs.template !== "") {
                                  template = $attrs.template;
                              }
                          }
            );

            $scope.$on('wf.data.loaded', function (event, data) {
                setup();
            });

            function setup() {
                var tpl = '

';

                if (wayfinder.advertisements["template-" + template] && wayfinder.advertisements["template-" + template][id]) {
                    frames = wayfinder.advertisements["template-" + template][id];
                }

                if(frames && frames.length > 0)
                    $document.find("body").addClass("banner-"+id);

                for (var i = 0; i < frames.length; i++) {
                    var frame = frames[i];
                    frame.element = $('
');
                    for (var j = 0; j < frame.containers.length; j++) {
                        var container = frame.containers[j];
                        var image = '';
                        if (container.advertisement_id > 0 && !(container.type && container.type.substr(0, 5) == 'video')) {
                            image = "background-image: url('{0}');".format(WayfinderAPI.advertisements.data.url(container.advertisement_id));
                        }
                        container.element = $(tpl.format(
                            container.id,
                            container.left,
                            container.top,
                            container.width,
                            container.height,
                            image));
                        if (container.advertisement_id > 0 && container.type.substr(0, 5) === 'video') {
                            container.element.append($('<video width="100%" height="auto" src="{0}" loop></video>'.format(
                                WayfinderAPI.advertisements.data.url(container.advertisement_id))));
                        }
                        frame.element.append(container.element);
                    }
                    frame.element.hide();
                }

                play();
            }

            function play() {
                if (current >= frames.length) {
                    return;
                }
                var frame = frames[current];
                frame.element.show();
                $element.empty().append(frame.element);
                for (var i = 0; i < frame.containers.length; i++) {
                    if (frame.containers[i].type && frame.containers[i].type.substr(0, 5) === 'video' && frame.containers[i].element) {
                        var el = $(frame.containers[i].element).children('video').get(0);
                        el.play();
                        if (el.readyState) {
                            el.currentTime = '0';
                        }
                    }
                    if (frame.containers[i].element && frame.containers[i].element.hammer) {
                        frame.containers[i].element.on("click", onClick);
                    }
                }
                next();

                if (timer) {
                    $timeout.cancel(timer);
                }

                timer = $timeout(play, frame.duration);
            }

            function next() {
                if (current < frames.length - 1) {
                    current++;
                } else
                    current = 0;
            }

            function onClick(event) {
                //var id = $(event.currentTarget).data('id');
                // console.log('TODO: Banner.onClick', id);
            }
        }]
    }
}]);
<commit_msg>prettify<commit_after>var wfangular = angular.module('wfangular', []);

wfangular.constant('wfangularConfig', {
    assetsLocation: 'http://static.3dwayfinder.com/shared/',
    apiLocation: 'http://api.3dwayfinder.com',
    mapType: '3d'
});
wfangular.factory('wfangular', ['$rootScope', 'wfangularConfig', function($rootScope, config) {
    var wf = false;
    WayfinderAPI.LOCATION = config.apiLocation;

    if (config.mapType == "3d")
        wf = new Wayfinder3D();
    else if (config.mapType !== "2d")
        wf = new Wayfinder2D();

    wf.options.assetsLocation = config.assetsLocation;

    if (wf) {
        wf.cbOnDataLoaded = function() {
            $rootScope.$broadcast('wf.data.loaded', []);
        }

        wf.cbOnPOIClick = function(poi) {
            $rootScope.$broadcast('wf.poi.click', poi);
        }

        wf.cbOnLanguageChange = function(language) {
            $rootScope.$broadcast('wf.language.change', language);
        }

        wf.cbOnFloorChange = function(floor) {
            $rootScope.$broadcast('wf.floor.change', floor);
        }

        wf.cbOnZoomChange = function(zoom) {
            $rootScope.$broadcast('wf.zoom.change', zoom);
        }

        wf.cbOnBeforeFloorChange = function(currentFloor, nextFloor, destinationFloor) {
            $rootScope.$broadcast('wf.path.floor.change', {
                current: currentFloor,
                next: nextFloor,
                destination: destinationFloor
            });
        }

        wf.cbOnTouch = function(type, value) {
            $rootScope.$broadcast('wf.touch', {
                type: type,
                value: value
            });
        }
    }

    return wf;
}]);

wfangular.filter('wfCurrentLanguage', ['wfangular', function(wayfinder) {
    return function(input) {
        if (input && typeof input === "object") {
            if (input[wayfinder.getLanguage()]) {
                return input[wayfinder.getLanguage()];
            } else if (input["translations"][wayfinder.getLanguage()]) {
                return input["translations"][wayfinder.getLanguage()];
            } else {
                return input;
            }
        } else {
            return input;
        }
    };
}]);

wfangular.directive('wfBanner', ['$interval', 'wfangular', '$timeout', function($interval, wayfinder, $timeout) {
    return {
        restrict: 'EA',
        scope: {},
        controller: ['$scope', '$element', '$attrs', '$timeout', '$document', function($scope, $element, $attrs, $timeout, $document) {
            var timeoutId;
            var frames = [];
            var current = 0;
            var timer = null;
            var id = false;
            var template = "default";

            //watch id attribute for the banner placement
            $scope.$watch(function() {
                    return $element.attr('id');
                },
                function() {
                    if (!!$attrs.id && $attrs.id !== "") {
                        id = $attrs.id;
                    }
                }
            );

            $scope.$watch(function() {
                    return $element.attr('template');
                },
                function() {
                    if (!!$attrs.template && $attrs.template !== "") {
                        template = $attrs.template;
                    }
                }
            );

            $scope.$on('wf.data.loaded', function(event, data) {
                setup();
            });

            function setup() {
                var tpl = '

';

                if (wayfinder.advertisements["template-" + template] && wayfinder.advertisements["template-" + template][id]) {
                    frames = wayfinder.advertisements["template-" + template][id];
                }

                if (frames && frames.length > 0)
                    $document.find("body").addClass("banner-" + id);

                for (var i = 0; i < frames.length; i++) {
                    var frame = frames[i];
                    frame.element = $('
');
                    for (var j = 0; j < frame.containers.length; j++) {
                        var container = frame.containers[j];
                        var image = '';
                        if (container.advertisement_id > 0 && !(container.type && container.type.substr(0, 5) == 'video')) {
                            image = "background-image: url('{0}');".format(WayfinderAPI.advertisements.data.url(container.advertisement_id));
                        }
                        container.element = $(tpl.format(
                            container.id,
                            container.left,
                            container.top,
                            container.width,
                            container.height,
                            image));
                        if (container.advertisement_id > 0 && container.type.substr(0, 5) === 'video') {
                            container.element.append($('<video width="100%" height="auto" src="{0}" loop></video>'.format(
                                WayfinderAPI.advertisements.data.url(container.advertisement_id))));
                        }
                        frame.element.append(container.element);
                    }
                    frame.element.hide();
                }

                play();
            }

            function play() {
                if (current >= frames.length) {
                    return;
                }
                var frame = frames[current];
                frame.element.show();
                $element.empty().append(frame.element);
                for (var i = 0; i < frame.containers.length; i++) {
                    if (frame.containers[i].type && frame.containers[i].type.substr(0, 5) === 'video' && frame.containers[i].element) {
                        var el = $(frame.containers[i].element).children('video').get(0);
                        el.play();
                        if (el.readyState) {
                            el.currentTime = '0';
                        }
                    }
                    if (frame.containers[i].element && frame.containers[i].element.hammer) {
                        frame.containers[i].element.on("click", onClick);
                    }
                }
                next();

                if (timer) {
                    $timeout.cancel(timer);
                }

                timer = $timeout(play, frame.duration);
            }

            function next() {
                if (current < frames.length - 1) {
                    current++;
                } else
                    current = 0;
            }

            function onClick(event) {
                //var id = $(event.currentTarget).data('id');
                // console.log('TODO: Banner.onClick', id);
            }
        }]
    }
}]);
<|endoftext|>


<commit_before>'use strict'

var fs = require('fs')
var tempfile = require('tempfile2')
var existsDefault = require('existential-default')

var streamErrorHandler = function (opts, stream, err) {
  if (err.code !== 'ENOENT' || opts.enoent) return stream.emit('error', err)
}

var paramsDefault = { enoent: true }

module.exports = function createWriteStream (params) {
  var path = tempfile(params)

  if (typeof params !== 'object')
    params = paramsDefault
  else
    params = existsDefault(params, 'paramsDefault')

  var writeStream = fs.createWriteStream(path)
  writeStream.path = path

  writeStream.cleanup = function (cb) {
    writeStream.end()
    fs.unlink(path, function (err) {
      if (err) streamErrorHandler(params, writeStream, err)
      if (cb) cb(err)
    })
  }

  writeStream.cleanupSync = function () {
    writeStream.end()
    try {
      fs.unlinkSync(path)
    } catch (err) {
      streamErrorHandler(params, writeStream, err)
    }
  }

  return writeStream
}
<commit_msg>Fix setup correctly defaultParams<commit_after>'use strict'

var fs = require('fs')
var tempfile = require('tempfile2')
var existsDefault = require('existential-default')

var streamErrorHandler = function (opts, stream, err) {
  if (err.code !== 'ENOENT' || opts.enoent) return stream.emit('error', err)
}

var paramsDefault = { enoent: true }

module.exports = function createWriteStream (params) {
  var path = tempfile(params)

  if (typeof params !== 'object')
    params = paramsDefault
  else
    params = existsDefault(params, paramsDefault)

  var writeStream = fs.createWriteStream(path)
  writeStream.path = path

  writeStream.cleanup = function (cb) {
    writeStream.end()
    fs.unlink(path, function (err) {
      if (err) streamErrorHandler(params, writeStream, err)
      if (cb) cb(err)
    })
  }

  writeStream.cleanupSync = function () {
    writeStream.end()
    try {
      fs.unlinkSync(path)
    } catch (err) {
      streamErrorHandler(params, writeStream, err)
    }
  }

  return writeStream
}
<|endoftext|>


<commit_before>const http = require ('httpreq');

let pkg = {
  test: {
    get: null
  },
  locations: {},
  browsers: {},
  account: {}
};

// Defaults
let config = {
  email: null,
  apikey: null,
  timeout: 5000
};

/**
 * Get info about resource type
 *
 * @param   {string}  name  The resource name
 * @return  {object}        Resource info object
 */

function resourceType (name) {
  let info = {
    binary: false,
    path: name.replace ('_', '-')
  };

  if (info.path.match (/^(filmstrip|pagespeed-files|report-pdf(-full)?|screenshot|video)$/)) {
    info.binary = true;
  }

  if (info.path === 'report-pdf-full') {
    info.path = 'report-pdf?full=1';
  }

  return info;
}

/**
 * Make an error
 *
 * @return  {Error}
 *
 * @param   {string}       msg   Error.message
 * @param   {mixed}        err   Error.error
 * @param   {number|null}  code  Error.statusCode
 * @param   {string|null}  type  Error.contentType
 */

function doError (msg, err, code, type) {
  let error = new Error (msg);

  error.error = err;
  error.statusCode = code;
  error.contentType = type;
  return error;
}

/**
 * Process API response
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {object}      options   httpreq options
 * @param     {Error|null}  err       httpreq Error
 * @param     {object}      res       httpreq response
 * @param     {function}    callback  `(err, data)`
 */

function apiResponse (options, err, res, callback) {
  let type;
  let size;
  let code;
  let data;
  let error = null;

  if (err) {
    error = doError ('request failed', err, null, null);
    callback (error);
    return;
  }

  type = String (res.headers ['content-type']) .split (';') [0];
  size = String (res.headers ['content-length']);
  code = res.statusCode;
  data = res.body;

  // Received data, expecting binary
  if (size && options.binary && type.match (/\/(pdf|jpeg|tar)$/)) {
    callback (null, data);
    return;
  }

  // Received something else
  try {
    data = JSON.parse (data);

    if (data.error) {
      error = doError ('API error', data.error, code, type);
      callback (error);
      return;
    }
  } catch (e) {
    error = doError ('invalid response', e, code, type);
    callback (error);
    return;
  }

  // It's real data
  callback (null, data);
}

/**
 * Send API request
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {object}    props
 * @param     {boolean}   [props.binary=false]  Expect binary response
 * @param     {string}    props.method          HTTP method
 * @param     {object}    [props.params]        Method parameters
 * @param     {string}    props.path            Method path
 * @param     {function}  callback              `(err, data)`
 */

function apiRequest (props, callback) {
  const options = {
    url: 'https://gtmetrix.com/api/0.1/' + props.path,
    parameters: props.params || null,
    method: props.method,
    headers: {
      'User-Agent': 'gtmetrix.js (https://www.npmjs.com/package/gtmetrix)'
    },
    timeout: config.timeout,
    auth: config.email + ':' + config.apikey,
    binary: props.binary || false
  };

  http.doRequest (options, (err, res) => {
    apiResponse (options, err, res, callback);
  });
}

/**
 * Create test
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {object}    params
 * @param     {function}  callback  `(err, data)`
 */

pkg.test.create = (params, callback) => {
  const props = {
    method: 'POST',
    path: 'test',
    params: params
  };

  apiRequest (props, callback);
};

/**
 * Process callback when polling
 *
 * @callback  callback
 * @return    {boolean}               Stop polling? true = yes
 *
 * @param     {object}      props     Request properties
 * @param     {Error|null}  err       Response error
 * @param     {object}      data      Response data
 * @param     {function}    callback  `(err, data)`
 */

function pollingCallback (props, err, data, callback) {
  // API error saying we need to wait
  if (err && String (err.error).match (/Data not yet available/)) {
    return false;
  }

  // Another API error
  if (err) {
    callback (err);
    return true;
  }

  // No API error, binary expected = ok complete
  if (props.binary) {
    callback (null, data);
    return true;
  }

  // No error, non-binary, not running = ok complete
  if (!String (data.state).match (/^(started|queued)$/)) {
    callback (null, data);
    return true;
  }

  // else keep polling
  return false;
}

/**
 * Process test response
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {object}      params
 * @param     {bool}        params.polling   Keep polling for updates
 * @param     {string}      params.testId    Test ID
 * @param     {string}      params.resource  Test resource
 * @param     {object}      params.props     Request params
 * @param     {Error|null}  err              Response error
 * @param     {mixed}       data             Response data
 * @param     {function}    callback         `(err, data)`
 */

function testResponse (params, err, data, callback) {
  let retryInterval;
  let complete;

  if (err && !params.polling) {
    callback (err);
    return;
  }

  if (!params.polling) {
    callback (null, data);
    return;
  }

  if (params.polling === true) {
    params.polling = 5000;
  }

  if (typeof params.polling === 'number') {
    complete = pollingCallback (params.props, err, data, callback);

    if (complete) {
      return;
    }

    // Test is still running
    retryInterval = setInterval (() => {
      pkg.test.get (params.testId, params.resource, (pErr, pData) => {
        const pComplete = pollingCallback (params.props, pErr, pData, callback);

        if (pComplete) {
          clearInterval (retryInterval);
        }
      });
    }, params.polling);
  }
}

/**
 * Get test result
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {string}    testId      Test ID
 * @param     {string}    [resource]  Resource to get, i.e. `screenshot`
 * @param     {number}    [polling]   Poll state until completion, in ms
 * @param     {function}  callback    `(err, data)`
 */

pkg.test.get = (testId, resource, polling, callback) => {
  let resourceInfo = {};
  let params = {
    testId,
    resource,
    polling,
    props: {
      method: 'GET',
      path: 'test/' + testId
    }
  };

  if (typeof polling === 'function') {
    callback = polling;
    params.polling = null;
  }

  switch (typeof resource) {
    case 'function':
      callback = resource;
      params.resource = null;
      params.polling = null;
      break;

    case 'number':
      params.polling = resource;
      params.resource = null;
      break;

    case 'string':
      resourceInfo = resourceType (resource);
      params.props.path += '/' + resourceInfo.path;
      params.props.binary = resourceInfo.binary;
      break;

    default:
      break;
  }

  apiRequest (params.props, (err, data) => {
    testResponse (params, err, data, callback);
  });
};

/**
 * List locations
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {function}  callback  `(err, data)`
 */

pkg.locations.list = (callback) => {
  const props = {
    method: 'GET',
    path: 'locations'
  };

  apiRequest (props, callback);
};

/**
 * List browsers
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {function}  callback  `(err, data)`
 */

pkg.browsers.list = (callback) => {
  const props = {
    method: 'GET',
    path: 'browsers'
  };

  apiRequest (props, callback);
};

/**
 * Get browser
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {string}    browserId
 * @param     {function}  callback  `(err, data)`
 */

pkg.browsers.get = (browserId, callback) => {
  const props = {
    method: 'GET',
    path: 'browsers/' + browserId
  };

  apiRequest (props, callback);
};

/**
 * Get account status
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {function}  callback  `(err, data)`
 */

pkg.account.status = (callback) => {
  const props = {
    method: 'GET',
    path: 'status'
  };

  apiRequest (props, callback);
};

/**
 * Module interface
 *
 * @return  {object}                        Methods
 *
 * @param   {object}  props
 * @param   {string}  props.email           API email
 * @param   {string}  props.apikey          API key
 * @param   {number}  [props.timeout=5000]  Request timeut in ms
 */

module.exports = (props) => {
  let key;

  for (key in props) {
    config [key] = props [key];
  }

  return pkg;
};
<commit_msg>Fix(config): parseInt timeout and defaults<commit_after>const http = require ('httpreq');

// Default config
const defaults = {
  email: null,
  apikey: null,
  timeout: 5000
};

let pkg = {
  test: {
    get: null
  },
  locations: {},
  browsers: {},
  account: {}
};

let config = {};

/**
 * Get info about resource type
 *
 * @param   {string}  name  The resource name
 * @return  {object}        Resource info object
 */

function resourceType (name) {
  let info = {
    binary: false,
    path: name.replace ('_', '-')
  };

  if (info.path.match (/^(filmstrip|pagespeed-files|report-pdf(-full)?|screenshot|video)$/)) {
    info.binary = true;
  }

  if (info.path === 'report-pdf-full') {
    info.path = 'report-pdf?full=1';
  }

  return info;
}

/**
 * Make an error
 *
 * @return  {Error}
 *
 * @param   {string}       msg   Error.message
 * @param   {mixed}        err   Error.error
 * @param   {number|null}  code  Error.statusCode
 * @param   {string|null}  type  Error.contentType
 */

function doError (msg, err, code, type) {
  let error = new Error (msg);

  error.error = err;
  error.statusCode = code;
  error.contentType = type;
  return error;
}

/**
 * Process API response
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {object}      options   httpreq options
 * @param     {Error|null}  err       httpreq Error
 * @param     {object}      res       httpreq response
 * @param     {function}    callback  `(err, data)`
 */

function apiResponse (options, err, res, callback) {
  let type;
  let size;
  let code;
  let data;
  let error = null;

  if (err) {
    error = doError ('request failed', err, null, null);
    callback (error);
    return;
  }

  type = String (res.headers ['content-type']) .split (';') [0];
  size = String (res.headers ['content-length']);
  code = res.statusCode;
  data = res.body;

  // Received data, expecting binary
  if (size && options.binary && type.match (/\/(pdf|jpeg|tar)$/)) {
    callback (null, data);
    return;
  }

  // Received something else
  try {
    data = JSON.parse (data);

    if (data.error) {
      error = doError ('API error', data.error, code, type);
      callback (error);
      return;
    }
  } catch (e) {
    error = doError ('invalid response', e, code, type);
    callback (error);
    return;
  }

  // It's real data
  callback (null, data);
}

/**
 * Send API request
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {object}    props
 * @param     {boolean}   [props.binary=false]  Expect binary response
 * @param     {string}    props.method          HTTP method
 * @param     {object}    [props.params]        Method parameters
 * @param     {string}    props.path            Method path
 * @param     {function}  callback              `(err, data)`
 */

function apiRequest (props, callback) {
  const options = {
    url: 'https://gtmetrix.com/api/0.1/' + props.path,
    parameters: props.params || null,
    method: props.method,
    headers: {
      'User-Agent': 'gtmetrix.js (https://www.npmjs.com/package/gtmetrix)'
    },
    timeout: parseInt (config.timeout, 10) || defaults.timeout,
    auth: config.email + ':' + config.apikey,
    binary: props.binary || false
  };

  http.doRequest (options, (err, res) => {
    apiResponse (options, err, res, callback);
  });
}

/**
 * Create test
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {object}    params
 * @param     {function}  callback  `(err, data)`
 */

pkg.test.create = (params, callback) => {
  const props = {
    method: 'POST',
    path: 'test',
    params: params
  };

  apiRequest (props, callback);
};

/**
 * Process callback when polling
 *
 * @callback  callback
 * @return    {boolean}               Stop polling? true = yes
 *
 * @param     {object}      props     Request properties
 * @param     {Error|null}  err       Response error
 * @param     {object}      data      Response data
 * @param     {function}    callback  `(err, data)`
 */

function pollingCallback (props, err, data, callback) {
  // API error saying we need to wait
  if (err && String (err.error).match (/Data not yet available/)) {
    return false;
  }

  // Another API error
  if (err) {
    callback (err);
    return true;
  }

  // No API error, binary expected = ok complete
  if (props.binary) {
    callback (null, data);
    return true;
  }

  // No error, non-binary, not running = ok complete
  if (!String (data.state).match (/^(started|queued)$/)) {
    callback (null, data);
    return true;
  }

  // else keep polling
  return false;
}

/**
 * Process test response
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {object}      params
 * @param     {bool}        params.polling   Keep polling for updates
 * @param     {string}      params.testId    Test ID
 * @param     {string}      params.resource  Test resource
 * @param     {object}      params.props     Request params
 * @param     {Error|null}  err              Response error
 * @param     {mixed}       data             Response data
 * @param     {function}    callback         `(err, data)`
 */

function testResponse (params, err, data, callback) {
  let retryInterval;
  let complete;

  if (err && !params.polling) {
    callback (err);
    return;
  }

  if (!params.polling) {
    callback (null, data);
    return;
  }

  if (params.polling === true) {
    params.polling = 5000;
  }

  if (typeof params.polling === 'number') {
    complete = pollingCallback (params.props, err, data, callback);

    if (complete) {
      return;
    }

    // Test is still running
    retryInterval = setInterval (() => {
      pkg.test.get (params.testId, params.resource, (pErr, pData) => {
        const pComplete = pollingCallback (params.props, pErr, pData, callback);

        if (pComplete) {
          clearInterval (retryInterval);
        }
      });
    }, params.polling);
  }
}

/**
 * Get test result
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {string}    testId      Test ID
 * @param     {string}    [resource]  Resource to get, i.e. `screenshot`
 * @param     {number}    [polling]   Poll state until completion, in ms
 * @param     {function}  callback    `(err, data)`
 */

pkg.test.get = (testId, resource, polling, callback) => {
  let resourceInfo = {};
  let params = {
    testId,
    resource,
    polling,
    props: {
      method: 'GET',
      path: 'test/' + testId
    }
  };

  if (typeof polling === 'function') {
    callback = polling;
    params.polling = null;
  }

  switch (typeof resource) {
    case 'function':
      callback = resource;
      params.resource = null;
      params.polling = null;
      break;

    case 'number':
      params.polling = resource;
      params.resource = null;
      break;

    case 'string':
      resourceInfo = resourceType (resource);
      params.props.path += '/' + resourceInfo.path;
      params.props.binary = resourceInfo.binary;
      break;

    default:
      break;
  }

  apiRequest (params.props, (err, data) => {
    testResponse (params, err, data, callback);
  });
};

/**
 * List locations
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {function}  callback  `(err, data)`
 */

pkg.locations.list = (callback) => {
  const props = {
    method: 'GET',
    path: 'locations'
  };

  apiRequest (props, callback);
};

/**
 * List browsers
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {function}  callback  `(err, data)`
 */

pkg.browsers.list = (callback) => {
  const props = {
    method: 'GET',
    path: 'browsers'
  };

  apiRequest (props, callback);
};

/**
 * Get browser
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {string}    browserId
 * @param     {function}  callback  `(err, data)`
 */

pkg.browsers.get = (browserId, callback) => {
  const props = {
    method: 'GET',
    path: 'browsers/' + browserId
  };

  apiRequest (props, callback);
};

/**
 * Get account status
 *
 * @callback  callback
 * @return    {void}
 *
 * @param     {function}  callback  `(err, data)`
 */

pkg.account.status = (callback) => {
  const props = {
    method: 'GET',
    path: 'status'
  };

  apiRequest (props, callback);
};

/**
 * Module interface
 *
 * @return  {object}                        Methods
 *
 * @param   {object}  props
 * @param   {string}  props.email           API email
 * @param   {string}  props.apikey          API key
 * @param   {number}  [props.timeout=5000]  Request timeut in ms
 */

module.exports = (props) => {
  let key;

  for (key in props) {
    config [key] = props [key];
  }

  return pkg;
};
<|endoftext|>


<commit_before>// Use Hilbert curve point generation to map 2D data to 1D space and vice-versa.
// Will later expand to allow `n` dimensions.

function Point(x, y, z) {
    this.rotations = {
        x: 0,
        y: 0,
        z: 0
    }

    this.init = function (x, y, z) {
        this.x = Math.round(x) || 0
        this.y = Math.round(y) || 0
        if (z != null) {
            this.z = Math.round(z) || 0
            this.d = 3
            this.n = 4 * this.z + 2 * this.y  + this.x
        } else {
            this.z = null
            this.d = 2
        }
    }
    if (x instanceof Array) {
        this.init(x[0], x[1], x[2])
    } else {
        this.init(x, y, z)
    }
}

Point.prototype.rotate = function (p, n) { // :: Point -> Int -> Point
    // record rotations
    if (p.n == 0) return new Point(this.z, this.x, this.y)
    if (p.n == 1 || p.n == 3) return new Point(this.y, this.z, this.x)
    if (p.n == 2 || p.n == 6) return new Point(n - this.x, n - this.y, this.z)
    return new Point(n - this.z, this.x, n - this.y)
}

Point.prototype.rotate2d = function (n, xbit, ybit) { // : Int -> Int -> Int -> Point
    return new Point(rotate2d(n, this.x, this.y, xbit, ybit))
}

Point.prototype.rotate3d = function (level) { // :: Int -> Point
    return new Point(rotate3d(level, this.x, this.y, this.z))
}

Point.prototype.rotateLeft = function (n) { // :: Int -> Point
    if (n % 3 == 0) return this
    if (n % 3 == 1) return new Point(this.y, this.z, this.x)
    return new Point(this.z, this.x, this.y)
}

Point.prototype.rotateRight = function (n) { // :: Int -> Point
    if (n % 3 == 0) return this
    if (n % 3 == 1) return new Point(this.z, this.x, this.y)
    return new Point(this.y, this.z, this.x)
}

Point.prototype.toArray = function () { // :: -> [Int, Int]
        if (this.d == 3) { return [this.x, this.y, this.z] }
        return [this.x, this.y]
}

Point.prototype.mod = function (n) { // :: Int -> Point
    return new Point(this.x % n, this.y % n, this.z % n)
}

Point.prototype.unrotate = function (n) {
    // read this.rotations and undo
}

// Accepts the height or width of a square/graph, and the coordinates to
// convert.
function convert2dPointToDistance (p, height) { // :: Int -> Int -> Int -> Int
    var xbit, ybit, level, d = 0
    var forHeight = p.x > p.y ? p.x : p.y

    // needs some tests to make sure height is compatible
    // What keeps the user from putting 54 down as the height
    while (forHeight >= height) {
            height *=2
    }
    // For each Hilbert level, we want to add an amount to
    // `d` based on which region we are in
    for (level = height / 2; level > 0; level = Math.floor(level / 2)) {
        // Determine what region we're in
        xbit = (p.x & level) > 0
        ybit = (p.y & level) > 0
        // increase distance based on region
        d += level * level * ((3 * xbit) ^ ybit)
        // rotate so that we'll be in sync with the next
        // region.
        p = p.rotate2d(level, xbit, ybit)
        // HEAD
        // p = p.rotate2d(height, xbit, ybit)
    }

    return d
}

// height and coordinates.
function convert3dPointToDistance (p, height) { // :: Int -> Int -> Int -> Int -> Int
    var s = 1, level = 0
    var max = Math.max.apply(Math, p.toArray())
    for (; 2 * s <= max; s *= 2) {
        level = (level + 1) % 3
    }

    // shuffle axes
    // rotate based on parity
}

// Accepts height or width of a square/graph and distance
function convertDistanceTo2dPoint (distance, height) { // :: Int -> Int -> [Int, Int]
    distance = Math.floor(distance)
    var xbit, ybit, level, p = new Point(0, 0)

    if (height <= Math.sqrt(distance))  {
        height = 2
        while (height <= Math.sqrt(distance)) {
            height *=2
        }
    }

    for (level = 1; level < height; level *= 2) {
        xbit = 1 & (distance / 2)
        ybit = 1 & (distance ^ xbit)

        p = p.rotate2d(level, xbit, ybit)
        p.x += level * xbit
        p.y += level * ybit
        distance = Math.floor(distance / 4)
    }

    return p.toArray()
}

// height/width of a square/graph and distance
function convertDistanceTo3dPoint (distance, height) { // Int -> Int -> [Int, Int, Int]
    distance = Math.floor(distance)
    var xbit, ybit, zbit, level, parity
    var iter = 2, log = 0, p = new Point(0, 0, 0)

    height = height || 2

    // vvv this is interesting.
    for (parity = 1; parity < height; parity *= 2, ++log) {}
    parity = log % 3;

    // the `|| distance` was removed from 2d version
    for (level = 1; level < height || distance > 0; level *=2) {
        xbit = distance & 1;
        ybit = (distance / 2) & 1;
        zbit = (distance / 4) & 1;

        var temp = rotate3d(level - 1, xbit ^ ybit, ybit ^ zbit, zbit)
        p.x = temp[0] * level + level - 1
        p.y = temp[1] * level + level - 1
        p.z = temp[2] * level + level - 1

        distance = Math.floor(distance / 8)
        level *= 2;
        iter++;
    }

    return p.rotateLeft(iter - parity + 1).toArray();
}

// Rotate the coordinate plane and (x,y)
function rotate2d (n, x, y, xbit, ybit) { // :: Int -> Int -> Int -> Int -> Int -> [Int, Int]
    if (ybit == 0  ) {
        if (xbit == 1) {
            x = n - 1 - x
            y = n - 1 - y
        }

        var temp = x
        x = y
        y = temp
    }

    return [x, y]
}

// Rotate the coordinate plane and (x,y, z)
function rotate3d(level, x, y, z) { // :: Int -> Int -> Int -> Int -> [Int, Int, Int]
    var index = 4 * z + 2 * y + x
    if (index == 0) {
        return [z, x, y]
    } else if (index == 1 || index == 3) {
        return [y, z, x]
    } else if (index == 2 || index == 6) {
        return [level - x, level - y, z]
    } else if (index == 5 || index == 7) {
        return [y, level - z, level - x]
    } else {
        return [level - z, x, level - y]
    }
}

// returns a non-negative int 'inverse' such that graycode(inverse) = g
function grayInverse (g) { // : Int -> Int
    var m = bits(g), inverse = g, j = 1
    while (j < m) {
        inverse = inverse ^ (g >> j)
        j++
    }
    return inverse
}

// Returns the number of bits required to store an integer
function bits (n) { // :: Int > Int
    var ret = 0
    while (n > 0) {
        ret++
        n = n >> 1
    }
    return ret
}

function bitwiseRotateRight (x, n) {
    var y = (x >> n) & ~(-1 << (32 - n))
    var z = x << (32 - n)
    return y | z
}

function bitwiseRotateLeft (x, n) {
    return (x << n) | (x >> (32 - n)) & ~(-1 << n)
}

function grayTransform (entry, direction, x) {
    return bitwiseRotateRight((x ^ entry), direction + 1)
}

function hilbertIndex(dim, precision, point) {
    var index = 0, entry = 0, direction = 0, i = precision - 1, arr = point.toArray(), code

    while (i >= 0) {
        var bits = 0

        for (var k = 0; k < arr.length; k++) {
            if (arr[arr.length - (k+1)] & (1 << (i - 1))) {
                bits |= 1 << k
            }
        }

        bits = grayTransform(entry, direction, bits)
        code = grayInverse(bits)

        entry = entry ^ bitwiseRotateLeft((entry * code), direction + 1)
        direction = direction + (direction * code) + (1 % dim)
        index = (index << dim) | code

        i--
    }

    return index
}

exports.xy2d = function (x, y, height) {
    height = height || 2
    return convert2dPointToDistance(new Point(x, y), height)
}

// This needs to be fixed to not return undefined.
exports.xyz2d = function(x, y, z, height) {
    height = height || 2
    return convert3dPointToDistance(new Point(x, y, z), height)
}
exports.d2xy = convertDistanceTo2dPoint
exports.d2xyz = convertDistanceTo3dPoint
exports.hilbert = function (dim, m, x, y, z) {
    return hilbertIndex(dim, m, new Point(x, y, z))
}
<commit_msg>Function signatures/comments.<commit_after>// Use Hilbert curve point generation to map 2D data to 1D space and vice-versa.
// Will later expand to allow `n` dimensions.

function Point(x, y, z) {
    this.rotations = {
        x: 0,
        y: 0,
        z: 0
    }

    this.init = function (x, y, z) {
        this.x = Math.round(x) || 0
        this.y = Math.round(y) || 0
        if (z != null) {
            this.z = Math.round(z) || 0
            this.d = 3
            this.n = 4 * this.z + 2 * this.y  + this.x
        } else {
            this.z = null
            this.d = 2
        }
    }
    if (x instanceof Array) {
        this.init(x[0], x[1], x[2])
    } else {
        this.init(x, y, z)
    }
}

Point.prototype.rotate = function (p, n) { // :: Point -> Int -> Point
    // record rotations
    if (p.n == 0) return new Point(this.z, this.x, this.y)
    if (p.n == 1 || p.n == 3) return new Point(this.y, this.z, this.x)
    if (p.n == 2 || p.n == 6) return new Point(n - this.x, n - this.y, this.z)
    return new Point(n - this.z, this.x, n - this.y)
}

Point.prototype.rotate2d = function (n, xbit, ybit) { // : Int -> Int -> Int -> Point
    return new Point(rotate2d(n, this.x, this.y, xbit, ybit))
}

Point.prototype.rotate3d = function (level) { // :: Int -> Point
    return new Point(rotate3d(level, this.x, this.y, this.z))
}

Point.prototype.rotateLeft = function (n) { // :: Int -> Point
    if (n % 3 == 0) return this
    if (n % 3 == 1) return new Point(this.y, this.z, this.x)
    return new Point(this.z, this.x, this.y)
}

Point.prototype.rotateRight = function (n) { // :: Int -> Point
    if (n % 3 == 0) return this
    if (n % 3 == 1) return new Point(this.z, this.x, this.y)
    return new Point(this.y, this.z, this.x)
}

Point.prototype.toArray = function () { // :: -> [Int, Int]
        if (this.d == 3) { return [this.x, this.y, this.z] }
        return [this.x, this.y]
}

Point.prototype.mod = function (n) { // :: Int -> Point
    return new Point(this.x % n, this.y % n, this.z % n)
}

Point.prototype.unrotate = function (n) {
    // read this.rotations and undo
}

// Accepts the height or width of a square/graph, and the coordinates to
// convert.
function convert2dPointToDistance (p, height) { // :: Int -> Int -> Int -> Int
    var xbit, ybit, level, d = 0
    var forHeight = p.x > p.y ? p.x : p.y

    // needs some tests to make sure height is compatible
    // What keeps the user from putting 54 down as the height
    while (forHeight >= height) {
            height *=2
    }
    // For each Hilbert level, we want to add an amount to
    // `d` based on which region we are in
    for (level = height / 2; level > 0; level = Math.floor(level / 2)) {
        // Determine what region we're in
        xbit = (p.x & level) > 0
        ybit = (p.y & level) > 0
        // increase distance based on region
        d += level * level * ((3 * xbit) ^ ybit)
        // rotate so that we'll be in sync with the next
        // region.
        p = p.rotate2d(level, xbit, ybit)
        // HEAD
        // p = p.rotate2d(height, xbit, ybit)
    }

    return d
}

// height and coordinates.
function convert3dPointToDistance (p, height) { // :: Int -> Int -> Int -> Int -> Int
    var s = 1, level = 0
    var max = Math.max.apply(Math, p.toArray())
    for (; 2 * s <= max; s *= 2) {
        level = (level + 1) % 3
    }

    // shuffle axes
    // rotate based on parity
}

// Accepts height or width of a square/graph and distance
function convertDistanceTo2dPoint (distance, height) { // :: Int -> Int -> [Int, Int]
    distance = Math.floor(distance)
    var xbit, ybit, level, p = new Point(0, 0)

    if (height <= Math.sqrt(distance))  {
        height = 2
        while (height <= Math.sqrt(distance)) {
            height *=2
        }
    }

    for (level = 1; level < height; level *= 2) {
        xbit = 1 & (distance / 2)
        ybit = 1 & (distance ^ xbit)

        p = p.rotate2d(level, xbit, ybit)
        p.x += level * xbit
        p.y += level * ybit
        distance = Math.floor(distance / 4)
    }

    return p.toArray()
}

// height/width of a square/graph and distance
function convertDistanceTo3dPoint (distance, height) { // Int -> Int -> [Int, Int, Int]
    distance = Math.floor(distance)
    var xbit, ybit, zbit, level, parity
    var iter = 2, log = 0, p = new Point(0, 0, 0)

    height = height || 2

    // vvv this is interesting.
    for (parity = 1; parity < height; parity *= 2, ++log) {}
    parity = log % 3;

    // the `|| distance` was removed from 2d version
    for (level = 1; level < height || distance > 0; level *=2) {
        xbit = distance & 1;
        ybit = (distance / 2) & 1;
        zbit = (distance / 4) & 1;

        var temp = rotate3d(level - 1, xbit ^ ybit, ybit ^ zbit, zbit)
        p.x = temp[0] * level + level - 1
        p.y = temp[1] * level + level - 1
        p.z = temp[2] * level + level - 1

        distance = Math.floor(distance / 8)
        level *= 2;
        iter++;
    }

    return p.rotateLeft(iter - parity + 1).toArray();
}

// Rotate the coordinate plane and (x,y)
function rotate2d (n, x, y, xbit, ybit) { // :: Int -> Int -> Int -> Int -> Int -> [Int, Int]
    if (ybit == 0  ) {
        if (xbit == 1) {
            x = n - 1 - x
            y = n - 1 - y
        }

        var temp = x
        x = y
        y = temp
    }

    return [x, y]
}

// Rotate the coordinate plane and (x,y, z)
function rotate3d(level, x, y, z) { // :: Int -> Int -> Int -> Int -> [Int, Int, Int]
    var index = 4 * z + 2 * y + x
    if (index == 0) {
        return [z, x, y]
    } else if (index == 1 || index == 3) {
        return [y, z, x]
    } else if (index == 2 || index == 6) {
        return [level - x, level - y, z]
    } else if (index == 5 || index == 7) {
        return [y, level - z, level - x]
    } else {
        return [level - z, x, level - y]
    }
}

// returns a non-negative int 'inverse' such that graycode(inverse) = g
function grayInverse (g) { // : Int -> Int
    var m = bits(g), inverse = g, j = 1
    while (j < m) {
        inverse = inverse ^ (g >> j)
        j++
    }
    return inverse
}

// Returns the number of bits required to store an integer
function bits (n) { // :: Int > Int
    var ret = 0
    while (n > 0) {
        ret++
        n = n >> 1
    }
    return ret
}

// Rotates the bits of x to the right by n. no sign preservation.
function bitwiseRotateRight (x, n) { // :: Int -> Int -> Int
    var y = (x >> n) & ~(-1 << (32 - n))
    var z = x << (32 - n)
    return y | z
}

// Rotates the bits of x to the left by n. ''
function bitwiseRotateLeft (x, n) { // :: Int -> Int -> Int
    return (x << n) | (x >> (32 - n)) & ~(-1 << n)
}

function grayTransform (entry, direction, x) { // :: Int -> Int -> Int -> Int
    return bitwiseRotateRight((x ^ entry), direction + 1)
}

function hilbertIndex(dim, precision, point) {
    var index = 0, entry = 0, direction = 0, i = precision - 1, arr = point.toArray(), code

    while (i >= 0) {
        var bits = 0

        for (var k = 0; k < arr.length; k++) {
            if (arr[arr.length - (k+1)] & (1 << (i - 1))) {
                bits |= 1 << k
            }
        }

        bits = grayTransform(entry, direction, bits)
        code = grayInverse(bits)

        entry = entry ^ bitwiseRotateLeft((entry * code), direction + 1)
        direction = direction + (direction * code) + (1 % dim)
        index = (index << dim) | code

        i--
    }

    return index
}

exports.xy2d = function (x, y, height) {
    height = height || 2
    return convert2dPointToDistance(new Point(x, y), height)
}

// This needs to be fixed to not return undefined.
exports.xyz2d = function(x, y, z, height) {
    height = height || 2
    return convert3dPointToDistance(new Point(x, y, z), height)
}
exports.d2xy = convertDistanceTo2dPoint
exports.d2xyz = convertDistanceTo3dPoint
exports.hilbert = function (dim, m, x, y, z) {
    return hilbertIndex(dim, m, new Point(x, y, z))
}
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-cli-page-object',

  included: function(app) {
    this._super.included(app);

    if (app.env === 'test') {
      app.import(app.bowerDirectory + '/ceibo/index.js');
    }
  }
};
<commit_msg>Fixes #126<commit_after>/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-cli-page-object',

  included: function(app) {
    this._super.included(app);

    if (app.env === 'test' || app.env === 'development') {
      app.import(app.bowerDirectory + '/ceibo/index.js');
    }
  }
};
<|endoftext|>


<commit_before>'use strict';

/** Proxy and cache a file and related headers
 *
 *  @copyright  Copyright (C) 2015 by Yieme
 *  @module     proxyCacheFile
 */

'use strict';
var _              = require('lodash')
var fs             = require('fs')
var mkdirp         = require('mkdirp')
var MD5            = require('MD5')
var request        = require('request')
var path           = require('path')
var options        = {
  dir:       './tmp', // falsely to disable file cache
}
var dirExists = { }

var ProxyCacheFileError = require('make-error')('ProxyCacheFileError')

/*
@param {object} request || config
- request contains: { url: 'https://domain.com/path/to/file', returnUrl: false }
- config contails:  { cacheDir: '/tmp' }
@param {function} callback
@return {object} result - { header: [{name:'', value: ''}], data: data || , piped: pipeData }
*/
function proxyCacheFile(req, callback) {
  if ('string' === typeof req) req = { url: req }
  req = req || {}
  if ('undefined' !== typeof req.dir) {
    if (options.dir != req.dir) {
      options.dir = req.dir
      options = _.extend(options, req)
    }
    if (!req.url) {
      options = _.extend(options, req)
      return proxyCacheFile
    }
  }
  req.dir = req.dir || options.dir

  function cacheFile(filePath, headers, data) {
    function writeFile() {
      var writeStream = fs.createWriteStream(filePath)
      writeStream.write(data)
      writeStream.end()
      fs.writeFile(filePath + '.json', JSON.stringify(headers), 'utf8', function(err) {
        if (err) return callback(err)
      })
    }

    if (dirExists[options.dir] || !options.dir) {
      writeFile()
    } else {
      fs.exists(options.dir, function(exists) {
        if (exists) {
          writeFile()
        } else {
          mkdirp(options.dir, function (err) {
            if (err) return callback(err)
            dirExists[options.dir] = true
            writeFile()
          })
          writeFile()
        }
      })
    }
  }

  function tryProxy(filePath) {
    var param = { method: 'GET', gzip: true, uri: req.url }
    request(param, function (error, response, body) {
      if (error) return callback(error)
      var headers   = {
        type: response.headers['content-type']
      }
      var result = { headers: headers }
      if (response.statusCode == 200) {
        if (filePath) cacheFile(filePath, headers, body)
        result.body = body
      } else {
        result.headers.code = response.statusCode
      }
      if (req.returnUrl) result.url = req.url
      callback(null, result)
    })
  }

  function tryFileCache(filePath) {
    fs.exists(filePath, function(exists) {
      if (exists) {
        fs.readFile(filePath + '.json', 'utf8', function(err, headers) {
          if (err) return callback(err)
          headers = JSON.parse(headers)
          var result = { headers: headers, cached: 'file' }
          if (req.returnUrl) result.url = req.url
          if (headers.code) return callback(null, result)
          fs.readFile(filePath, 'utf8', function(err, body) {
            if (err) return callback(err)
            result.body = body
            callback(null, result)
          })
        })
      } else {
        tryProxy(filePath)
      }
    })
  }

  if (!req.url)                   return callback(new ProxyCacheFileError('Missing req.url'))
  if (req.url.indexOf('..') >= 0) return callback(new ProxyCacheFileError('Invalid req.url: ' + req.url))
	if (req.dir) {
    tryFileCache(path.normalize(req.dir + '/' + MD5(req.url)))
	} else {
    tryProxy(req)
  }
}

module.exports = proxyCacheFile
<commit_msg>standard error body<commit_after>'use strict';

/** Proxy and cache a file and related headers
 *
 *  @copyright  Copyright (C) 2015 by Yieme
 *  @module     proxyCacheFile
 */

'use strict';
var _              = require('lodash')
var fs             = require('fs')
var mkdirp         = require('mkdirp')
var MD5            = require('MD5')
var request        = require('request')
var path           = require('path')
var options        = {
  dir:       './tmp', // falsely to disable file cache
}
var dirExists = { }

var ProxyCacheFileError = require('make-error')('ProxyCacheFileError')

/*
@param {object} request || config
- request contains: { url: 'https://domain.com/path/to/file', returnUrl: false }
- config contails:  { cacheDir: '/tmp' }
@param {function} callback
@return {object} result - { header: [{name:'', value: ''}], data: data || , piped: pipeData }
*/
function proxyCacheFile(req, callback) {
  if ('string' === typeof req) req = { url: req }
  req = req || {}
  if ('undefined' !== typeof req.dir) {
    if (options.dir != req.dir) {
      options.dir = req.dir
      options = _.extend(options, req)
    }
    if (!req.url) {
      options = _.extend(options, req)
      return proxyCacheFile
    }
  }
  req.dir = req.dir || options.dir

  function cacheFile(filePath, headers, data) {
    function writeFile() {
      var writeStream = fs.createWriteStream(filePath)
      writeStream.write(data)
      writeStream.end()
      fs.writeFile(filePath + '.json', JSON.stringify(headers), 'utf8', function(err) {
        if (err) return callback(err)
      })
    }

    if (dirExists[options.dir] || !options.dir) {
      writeFile()
    } else {
      fs.exists(options.dir, function(exists) {
        if (exists) {
          writeFile()
        } else {
          mkdirp(options.dir, function (err) {
            if (err) return callback(err)
            dirExists[options.dir] = true
            writeFile()
          })
          writeFile()
        }
      })
    }
  }

  function errorBody(code) {
    return (code) ? JSON.stringify({ code: code, message: 'Unable to proxy: ' + req.url }) : ''
  }

  function tryProxy(filePath) {
    var param = { method: 'GET', gzip: true, uri: req.url }
    request(param, function (error, response, body) {
      if (error) return callback(error)
      var headers   = {
        type: response.headers['content-type']
      }
      var result = { headers: headers }
      if (response.statusCode == 200) {
        if (filePath) cacheFile(filePath, headers, body)
        result.body = body
      } else {
        result.headers.code = response.statusCode
        result.body = errorBody(response.statusCode)
      }
      if (req.returnUrl) result.url = req.url
      callback(null, result)
    })
  }

  function tryFileCache(filePath) {
    fs.exists(filePath, function(exists) {
      if (exists) {
        fs.readFile(filePath + '.json', 'utf8', function(err, headers) {
          if (err) return callback(err)
          headers = JSON.parse(headers)
          var result = { headers: headers, body: errorBody(headers.code), cached: 'file' }
          if (req.returnUrl) result.url = req.url
          if (headers.code) return callback(null, result)
          fs.readFile(filePath, 'utf8', function(err, body) {
            if (err) return callback(err)
            result.body = body
            callback(null, result)
          })
        })
      } else {
        tryProxy(filePath)
      }
    })
  }

  if (!req.url)                   return callback(new ProxyCacheFileError('Missing req.url'))
  if (req.url.indexOf('..') >= 0) return callback(new ProxyCacheFileError('Invalid req.url: ' + req.url))
	if (req.dir) {
    tryFileCache(path.normalize(req.dir + '/' + MD5(req.url)))
	} else {
    tryProxy(req)
  }
}

module.exports = proxyCacheFile
<|endoftext|>


<commit_before>// Linha 1 - comentario
function alerta() {
	alert('Ok');
}<commit_msg>inclui funcao confirma<commit_after>// Linha 1 - comentario
function alerta() {
	alert('Ok');
}

function confirma() {
	if (confirm('Ok?'))
		return true;
}<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var templates = path.resolve.bind(path, __dirname, 'templates');
var debug = require('debug')('base:verb:verb-readme-generator');
var depdocs = require('./lib/depdocs');
var helpers = require('./lib/helpers');
var utils = require('./lib/utils');
var lint = require('./lib/lint');

/**
 * Verb readme generator
 */

function generator(app, base) {
  if (!utils.isValid(app, 'verb-readme-generator')) return;
  setAppContext(app);

  /**
   * Engine
   */

  app.engine('hbs', require('engine-handlebars'));
  app.handler('prePipeline');

  /**
   * User's CWD
   */

  var cwd = path.resolve.bind(path, app.cwd);
  // get verb config object from package.json
  var config = app.base.get('cache.config') || {};

  /**
   * Helpers
   */

  helpers(app);
  depdocs(app);
  app.helpers(require('template-helpers')());

  /**
   * Set options
   */

  app.option(app.pkg.get('verb') || {});
  app.option('toc.footer', '\n\n_(TOC generated by [verb](https://github.com/verbose/verb) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_');
  app.option('engineOpts', {delims: ['{%', '%}']});
  app.option('toAlias', function readme(name) {
    if (/^verb-.*?-\w/.test(name)) {
      return name.replace(/^verb-(.*?)-(?:\w+)/, '$1');
    }
    return name.slice(name.lastIndexOf('-') + 1);
  });

  app.option('linkify', function(token, name, slug, tocOpts) {
    if (/[{<]%=?/.test(name)) {
      var inst = new app.constructor();
      var opts = app.options;
      var engine = app.getEngine('*') || app.getEngine('md');
      inst.engine('*', engine);
      opts.engine = '*';
      inst.data(app.cache.data);
      var view = inst.view('toctemp.md', {content: name, layout: false});
      inst.compile(view, opts);
      token.content = view.fn(inst.cache.data);
    }
    utils.toc.linkify(token, name, slug, tocOpts);
    return token;
  });

  /**
   * Plugins
   */

  app.use(utils.conflicts());
  app.use(require('verb-defaults'));
  app.use(require('verb-collections'));
  app.use(require('verb-repo-helpers'));
  app.use(require('verb-repo-data'));
  app.use(require('verb-toc'));
  app.use(utils.questions());
  app.use(utils.loader());
  app.use(utils.pkg());

  /**
   * Generate `README.md` and fix missing [reflinks](#reflinks).
   *
   * ```sh
   * $ verb readme
   * ```
   * @name readme
   * @api public
   */

  app.task('readme', ['readme-build', 'readme-reflinks']);

  /**
   * Alias for the [readme]() task, generates a README.md to the user's working directory.
   *
   * ```sh
   * $ verb readme
   * ```
   * @name default
   * @api public
   */

  app.task('default', {silent: true}, ['readme']);

  /**
   * Initialize middleware used for rendering the [readme](#readme).
   *
   * ```sh
   * $ verb readme:readme-middleware
   * ```
   * @name readme-middleware
   * @api public
   */

  app.task('readme-middleware', { silent: true }, function(cb) {
    if (app.option('sections')) {
      app.onLoad(/\.md$/, require('./lib/sections')(app));
    }

    app.preRender(/(verb|readme)\.md$/i, function(file, next) {
      utils.del(path.resolve(app.cwd, 'readme.md'), next);
    });

    app.onLoad(/(verb|readme)\.md$/, lint.layout(app));
    cb();
  });

  /**
   * Loads data to used for rendering templates. Called by the [readme]() task.
   *
   * ```sh
   * $ verb readme:readme-data
   * ```
   * @name readme-data
   * @api public
   */

  app.task('readme-data', { silent: true }, function(cb) {
    debug('loading data');

    // temporary data
    app.data({
      links: {
        verb: {
          repo: 'https://github.com/verbose/verb',
          bugs: 'https://github.com/verbose/verb/issues',
          getting_started: 'https://github.com/verb/getting-started'
        },
        generate: {
          repo: 'https://github.com/generate/generate',
          bugs: 'https://github.com/generate/generate/issues',
          getting_started: 'https://github.com/generate/getting-started'
        },
        update: {
          repo: 'https://github.com/update/update',
          bugs: 'https://github.com/update/update/issues',
          getting_started: 'https://github.com/update/getting-started'
        }
      }
    });

    if (!app.cache.data.verb) {
      app.data({verb: {}});
    }

    if (!app.has('cache.data.verb.related.list')) {
      app.data({
        verb: {related: {list: []}}
      });
    }

    if (utils.exists(cwd('bower.json'))) {
      app.data({bower: true});
    }

    if (app.isGenerator) {
      app.option('toAlias', function(name) {
        return utils.camelcase(name.replace(/^generate-/, ''));
      });
    }

    app.data('name', app.pkg.get('name') || app.cache.data.name);
    app.data({prefix: 'Copyright'});
    debug('data finished');
    cb();
  });

  /**
   * Load layouts, includes and badges commonly used for generating a README.md.
   *
   * ```sh
   * $ verb readme:readme-templates
   * ```
   * @name readme-templates
   * @api public
   */

  app.task('readme-templates', { silent: true }, function(cb) {
    debug('loading templates');

    app.option('renameKey', function(key, file) {
      var name = file ? file.relative : path.relative(app.cwd, key);
      var ext = path.extname(name);
      var str = name.replace(/^(templates|docs)\/?(layouts|includes)\/?/, '');
      return ext ? str.slice(0, str.length - ext.length) : str;
    });

    // load `docs` templates in user cwd
    app.docs('*.md', {cwd: templates('docs')});
    if (utils.exists(cwd('docs')) && app.pkg.get('verb.options.docs') !== false) {
      app.docs('*.md', {cwd: path.resolve(app.cwd, 'docs')});
    }

    // load `layout` templates
    app.layouts('*.md', { cwd: templates('layouts') });

    // load `include` templates
    app.includes('**/*.md', { cwd: templates('includes') });
    app.includes(require('./templates/includes'));
    if (utils.exists(cwd('docs'))) {
      app.includes('*.md', {cwd: cwd('docs')});
    }

    // load `badges` templates
    app.badges(require('./templates/badges'));
    if (typeof config.views === 'undefined') {
      cb();
      return;
    }

    // call `.config.process` again to override built-in templates
    // with any templates defined in `package.json`
    app.config.process({views: config.views}, function(err) {
      if (err) return cb(err);
      debug('templates finished');
      cb();
    });
  });

  /**
   * Load `options`, `plugins`, `middleware` and `data` before calling a task
   * to render templats.
   *
   * ```sh
   * $ verb readme:readme-setup
   * ```
   * @name readme-setup
   * @api public
   */

  app.task('readme-setup', {silent: true}, ['readme-middleware', 'readme-data', 'readme-templates']);

  /**
   * Run after other tasks to get any missing reflinks found in rendered markdown
   * documents, and add them to the `verb.reflinks` array in package.json. Verb
   * uses this array to generate reflinks so that missing reflinks will still resolve.
   *
   * ```sh
   * $ verb readme:readme-reflinks
   * ```
   * @name readme-reflinks
   * @api public
   */

  app.task('readme-reflinks', {silent: true}, function(cb) {
    var existing = app.pkg.get('verb.reflinks') || [];
    var reflinks = app.get('cache.reflinks') || [];
    var diff = utils.diff(reflinks, existing);

    if (diff.length > 1) {
      app.pkg.union('verb.reflinks', diff);
      app.pkg.save();
      app.pkg.logInfo('updated package.json with:', {reflinks: diff});
    }
    cb();
  });

  /**
   * Generate a README.md from a `.verb.md` template. Runs the [setup](), and [verbmd]() tasks.
   * This is a [verb][docs]{tasks.md#silent} task.
   *
   * ```sh
   * $ verb readme:readme-build
   * ```
   * @name readme-build
   * @api public
   */

  app.task('readme-build', {silent: true}, ['readme-setup', 'verbmd'], function(cb) {
    debug('starting readme task');
    var readme = path.resolve(app.cwd, app.option('readme') || '.verb.md');
    app.engine('md', require('engine-base'), {delims: ['{%', '%}']});
    app.data(app.base.cache.data);
    app.helpers(app.base._.helpers.async);
    app.helpers(app.base._.helpers.sync);

    app.toStream('files', utils.filter(readme)).on('error', cb)
      .pipe(app.renderFile('hbs', app.cache.data)).on('error', cb)
      .pipe(app.renderFile('md', app.cache.data)).on('error', cb)
      .pipe(utils.handle(app, 'prePipeline')).on('error', cb)
      .pipe(utils.reflinks(app.options))
      .pipe(app.pipeline(app.options.pipeline)).on('error', cb)
      .pipe(app.dest(function(file) {
        app.union('cache.reflinks', file._reflinks);
        file.basename = 'README.md';
        return app.cwd;
      }))
      .on('error', cb)
      .on('end', cb);
  });

  /**
   * Load the `.verb.md` in the user's current working directory. If no `.verb.md`
   * file exists, the [prompt-verbmd)() task is called to ask the user if they want to
   * add the file. Disable the prompt by passing `--verbmd=false` on the command line,
   * or `app.disable('verbmd')` via API.
   *
   * ```sh
   * $ verb readme:verbmd
   * ```
   * @name verbmd
   * @api public
   */

  app.task('verbmd', { silent: true }, function(cb) {
    debug('loading .verb.md');
    if (app.views.files['README'] || app.views.files['.verb'] || app.options.verbmd === false) {
      cb();
      return;
    }

    // try to load ".verb.md" or custom file from user cwd
    var readme = cwd(app.option('readme') || '.verb.md');
    if (utils.exists(readme)) {
      app.file('README.md', readTemplate(app, readme, app.cwd));
      cb();
      return;
    }
    app.build('verbmd-prompt', cb);
  });

  /**
   * Generate a new `.verb.md` template to the current working directory.
   *
   * ```sh
   * $ verb readme:new
   * # also aliased as
   * $ verb readme:verbmd-new
   * ```
   * @name verbmd-new
   * @api public
   */

  app.task('new', ['verbmd-new']);
  app.task('verbmd-new', function() {
    var dest = path.resolve(app.option('dest') || app.cwd);
    app.file('.verb.md', readTemplate(app, 'verbmd/basic.md'));
    return app.toStream('files')
      .pipe(app.conflicts(dest))
      .pipe(app.dest(function(file) {
        file.base = dest;
        file.path = path.resolve(file.base, '.verb.md');
        return dest;
      }));
  });

  /**
   * Prompts the user to add a new `.verb.md` template to the current working directory.
   * Useful in sub-generators.
   *
   * ```sh
   * $ verb readme:verbmd-prompt
   * # alias aliased as
   * $ verb readme:ask
   * ```
   * @name verbmd-prompt
   * @api public
   */

  app.task('verbmd-prompt', function(cb) {
    // if no .verb.md exists, offer to add one
    app.confirm('verbmd', 'Can\'t find a .verb.md, want to add one?');
    app.ask('verbmd', { save: false }, function(err, answers) {
      if (err) return cb(err);
      if (answers.verbmd) {
        app.build('new', cb);
      } else {
        cb();
      }
    });
  });

  return generator;
}

function setAppContext(app) {
  var name = app.pkg.get('name');
  var platform = {};

  if (/^base-?/.test(name)) {
    platform.repo = 'node-base/base';
    platform.docs = `https://github.com/${platform.repo}/blob/master/docs`;
    platform.proper = 'Base';
    platform.name = 'base';
    platform.command = 'base';
    platform.configname = 'basefile';
    platform.configfile = 'basefile.js';
  } else if (/^assemble-?/.test(name)) {
    platform.repo = 'assemble/assemble';
    platform.docs = `https://github.com/${platform.repo}/blob/master/docs`;
    platform.proper = 'Assemble';
    platform.name = 'assemble';
    platform.command = 'assemble';
    platform.configname = 'assemblefile';
    platform.configfile = 'assemblefile.js';
  } else if (/^generate-?/.test(name)) {
    platform.repo = 'generate/generate';
    platform.docs = `https://github.com/${platform.repo}/blob/master/docs`;
    platform.proper = 'Generate';
    platform.name = 'generate';
    platform.command = 'gen';
    platform.configname = 'generator';
    platform.configfile = 'generator.js';
  } else if (/^(updater-?|update)/.test(name)) {
    platform.repo = 'update/update';
    platform.docs = `https://github.com/${platform.repo}/blob/master/docs`;
    platform.proper = 'Update';
    platform.name = 'update';
    platform.command = 'update';
    platform.configname = 'updater';
    platform.configfile = 'updatefile.js';
  } else if (/^verb-?/.test(name)) {
    platform.repo = 'verbose/verb';
    platform.docs = `https://github.com/${platform.repo}/blob/master/docs`;
    platform.proper = 'Verb';
    platform.name = 'verb';
    platform.command = 'verb';
    platform.configname = 'verbfile';
    platform.configfile = 'verbfile.js';
  }
  app.data('platform', platform);
  app.base.data('platform', platform);
}

/**
 * Read a template
 *
 * @param {Object} `verb`
 * @param {String} `fp`
 * @param {String} `base`
 * @return {String}
 */

function readTemplate(app, filepath, base) {
  var dir = base || app.env.templates || templates();
  var absolute = path.resolve(path.resolve(dir), filepath);
  return {
    contents: fs.readFileSync(absolute),
    path: absolute
  };
}

/**
 * Expose `generator`
 */

module.exports = generator;
<commit_msg>put toc options on `options.toc`<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var templates = path.resolve.bind(path, __dirname, 'templates');
var debug = require('debug')('base:verb:verb-readme-generator');
var depdocs = require('./lib/depdocs');
var helpers = require('./lib/helpers');
var utils = require('./lib/utils');
var lint = require('./lib/lint');

/**
 * Verb readme generator
 */

function generator(app, base) {
  if (!utils.isValid(app, 'verb-readme-generator')) return;
  setAppContext(app);

  /**
   * Engine
   */

  app.engine('hbs', require('engine-handlebars'));
  app.handler('prePipeline');

  /**
   * User's CWD
   */

  var cwd = path.resolve.bind(path, app.cwd);
  // get verb config object from package.json
  var config = app.base.get('cache.config') || {};

  /**
   * Helpers
   */

  helpers(app);
  depdocs(app);
  app.helpers(require('template-helpers')());

  /**
   * Set options
   */

  app.option(app.pkg.get('verb') || {});
  app.option('toc.footer', '\n\n_(TOC generated by [verb](https://github.com/verbose/verb) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_');
  app.option('engineOpts', {delims: ['{%', '%}']});
  app.option('toAlias', function readme(name) {
    if (/^verb-.*?-\w/.test(name)) {
      return name.replace(/^verb-(.*?)-(?:\w+)/, '$1');
    }
    return name.slice(name.lastIndexOf('-') + 1);
  });

  app.option('toc.linkify', function(token, name, slug, tocOpts) {
    if (/[{<]%=?/.test(name)) {
      var inst = new app.constructor();
      var opts = app.options;
      var engine = app.getEngine('*') || app.getEngine('md');
      inst.engine('*', engine);
      opts.engine = '*';
      inst.data(app.cache.data);
      var view = inst.view('toctemp.md', {content: name, layout: false});
      inst.compile(view, opts);
      token.content = view.fn(inst.cache.data);
    }
    utils.toc.linkify(token, name, slug, tocOpts);
    return token;
  });

  /**
   * Plugins
   */

  app.use(utils.conflicts());
  app.use(require('verb-defaults'));
  app.use(require('verb-collections'));
  app.use(require('verb-repo-helpers'));
  app.use(require('verb-repo-data'));
  app.use(require('verb-toc'));
  app.use(utils.questions());
  app.use(utils.loader());
  app.use(utils.pkg());

  /**
   * Generate `README.md` and fix missing [reflinks](#reflinks).
   *
   * ```sh
   * $ verb readme
   * ```
   * @name readme
   * @api public
   */

  app.task('readme', ['readme-build', 'readme-reflinks']);

  /**
   * Alias for the [readme]() task, generates a README.md to the user's working directory.
   *
   * ```sh
   * $ verb readme
   * ```
   * @name default
   * @api public
   */

  app.task('default', {silent: true}, ['readme']);

  /**
   * Initialize middleware used for rendering the [readme](#readme).
   *
   * ```sh
   * $ verb readme:readme-middleware
   * ```
   * @name readme-middleware
   * @api public
   */

  app.task('readme-middleware', { silent: true }, function(cb) {
    if (app.option('sections')) {
      app.onLoad(/\.md$/, require('./lib/sections')(app));
    }

    app.preRender(/(verb|readme)\.md$/i, function(file, next) {
      utils.del(path.resolve(app.cwd, 'readme.md'), next);
    });

    app.onLoad(/(verb|readme)\.md$/, lint.layout(app));
    cb();
  });

  /**
   * Loads data to used for rendering templates. Called by the [readme]() task.
   *
   * ```sh
   * $ verb readme:readme-data
   * ```
   * @name readme-data
   * @api public
   */

  app.task('readme-data', { silent: true }, function(cb) {
    debug('loading data');

    // temporary data
    app.data({
      links: {
        verb: {
          repo: 'https://github.com/verbose/verb',
          bugs: 'https://github.com/verbose/verb/issues',
          getting_started: 'https://github.com/verb/getting-started'
        },
        generate: {
          repo: 'https://github.com/generate/generate',
          bugs: 'https://github.com/generate/generate/issues',
          getting_started: 'https://github.com/generate/getting-started'
        },
        update: {
          repo: 'https://github.com/update/update',
          bugs: 'https://github.com/update/update/issues',
          getting_started: 'https://github.com/update/getting-started'
        }
      }
    });

    if (!app.cache.data.verb) {
      app.data({verb: {}});
    }

    if (!app.has('cache.data.verb.related.list')) {
      app.data({
        verb: {related: {list: []}}
      });
    }

    if (utils.exists(cwd('bower.json'))) {
      app.data({bower: true});
    }

    if (app.isGenerator) {
      app.option('toAlias', function(name) {
        return utils.camelcase(name.replace(/^generate-/, ''));
      });
    }

    app.data('name', app.pkg.get('name') || app.cache.data.name);
    app.data({prefix: 'Copyright'});
    debug('data finished');
    cb();
  });

  /**
   * Load layouts, includes and badges commonly used for generating a README.md.
   *
   * ```sh
   * $ verb readme:readme-templates
   * ```
   * @name readme-templates
   * @api public
   */

  app.task('readme-templates', { silent: true }, function(cb) {
    debug('loading templates');

    app.option('renameKey', function(key, file) {
      var name = file ? file.relative : path.relative(app.cwd, key);
      var ext = path.extname(name);
      var str = name.replace(/^(templates|docs)\/?(layouts|includes)\/?/, '');
      return ext ? str.slice(0, str.length - ext.length) : str;
    });

    // load `docs` templates in user cwd
    app.docs('*.md', {cwd: templates('docs')});
    if (utils.exists(cwd('docs')) && app.pkg.get('verb.options.docs') !== false) {
      app.docs('*.md', {cwd: path.resolve(app.cwd, 'docs')});
    }

    // load `layout` templates
    app.layouts('*.md', { cwd: templates('layouts') });

    // load `include` templates
    app.includes('**/*.md', { cwd: templates('includes') });
    app.includes(require('./templates/includes'));
    if (utils.exists(cwd('docs'))) {
      app.includes('*.md', {cwd: cwd('docs')});
    }

    // load `badges` templates
    app.badges(require('./templates/badges'));
    if (typeof config.views === 'undefined') {
      cb();
      return;
    }

    // call `.config.process` again to override built-in templates
    // with any templates defined in `package.json`
    app.config.process({views: config.views}, function(err) {
      if (err) return cb(err);
      debug('templates finished');
      cb();
    });
  });

  /**
   * Load `options`, `plugins`, `middleware` and `data` before calling a task
   * to render templats.
   *
   * ```sh
   * $ verb readme:readme-setup
   * ```
   * @name readme-setup
   * @api public
   */

  app.task('readme-setup', {silent: true}, ['readme-middleware', 'readme-data', 'readme-templates']);

  /**
   * Run after other tasks to get any missing reflinks found in rendered markdown
   * documents, and add them to the `verb.reflinks` array in package.json. Verb
   * uses this array to generate reflinks so that missing reflinks will still resolve.
   *
   * ```sh
   * $ verb readme:readme-reflinks
   * ```
   * @name readme-reflinks
   * @api public
   */

  app.task('readme-reflinks', {silent: true}, function(cb) {
    var existing = app.pkg.get('verb.reflinks') || [];
    var reflinks = app.get('cache.reflinks') || [];
    var diff = utils.diff(reflinks, existing);

    if (diff.length > 1) {
      app.pkg.union('verb.reflinks', diff);
      app.pkg.save();
      app.pkg.logInfo('updated package.json with:', {reflinks: diff});
    }
    cb();
  });

  /**
   * Generate a README.md from a `.verb.md` template. Runs the [setup](), and [verbmd]() tasks.
   * This is a [verb][docs]{tasks.md#silent} task.
   *
   * ```sh
   * $ verb readme:readme-build
   * ```
   * @name readme-build
   * @api public
   */

  app.task('readme-build', {silent: true}, ['readme-setup', 'verbmd'], function(cb) {
    debug('starting readme task');
    var readme = path.resolve(app.cwd, app.option('readme') || '.verb.md');
    app.engine('md', require('engine-base'), {delims: ['{%', '%}']});
    app.data(app.base.cache.data);
    app.helpers(app.base._.helpers.async);
    app.helpers(app.base._.helpers.sync);

    app.toStream('files', utils.filter(readme)).on('error', cb)
      .pipe(app.renderFile('hbs', app.cache.data)).on('error', cb)
      .pipe(app.renderFile('md', app.cache.data)).on('error', cb)
      .pipe(utils.handle(app, 'prePipeline')).on('error', cb)
      .pipe(utils.reflinks(app.options))
      .pipe(app.pipeline(app.options.pipeline)).on('error', cb)
      .pipe(app.dest(function(file) {
        app.union('cache.reflinks', file._reflinks);
        file.basename = 'README.md';
        return app.cwd;
      }))
      .on('error', cb)
      .on('end', cb);
  });

  /**
   * Load the `.verb.md` in the user's current working directory. If no `.verb.md`
   * file exists, the [prompt-verbmd)() task is called to ask the user if they want to
   * add the file. Disable the prompt by passing `--verbmd=false` on the command line,
   * or `app.disable('verbmd')` via API.
   *
   * ```sh
   * $ verb readme:verbmd
   * ```
   * @name verbmd
   * @api public
   */

  app.task('verbmd', { silent: true }, function(cb) {
    debug('loading .verb.md');
    if (app.views.files['README'] || app.views.files['.verb'] || app.options.verbmd === false) {
      cb();
      return;
    }

    // try to load ".verb.md" or custom file from user cwd
    var readme = cwd(app.option('readme') || '.verb.md');
    if (utils.exists(readme)) {
      app.file('README.md', readTemplate(app, readme, app.cwd));
      cb();
      return;
    }
    app.build('verbmd-prompt', cb);
  });

  /**
   * Generate a new `.verb.md` template to the current working directory.
   *
   * ```sh
   * $ verb readme:new
   * # also aliased as
   * $ verb readme:verbmd-new
   * ```
   * @name verbmd-new
   * @api public
   */

  app.task('new', ['verbmd-new']);
  app.task('verbmd-new', function() {
    var dest = path.resolve(app.option('dest') || app.cwd);
    app.file('.verb.md', readTemplate(app, 'verbmd/basic.md'));
    return app.toStream('files')
      .pipe(app.conflicts(dest))
      .pipe(app.dest(function(file) {
        file.base = dest;
        file.path = path.resolve(file.base, '.verb.md');
        return dest;
      }));
  });

  /**
   * Prompts the user to add a new `.verb.md` template to the current working directory.
   * Useful in sub-generators.
   *
   * ```sh
   * $ verb readme:verbmd-prompt
   * # alias aliased as
   * $ verb readme:ask
   * ```
   * @name verbmd-prompt
   * @api public
   */

  app.task('verbmd-prompt', function(cb) {
    // if no .verb.md exists, offer to add one
    app.confirm('verbmd', 'Can\'t find a .verb.md, want to add one?');
    app.ask('verbmd', { save: false }, function(err, answers) {
      if (err) return cb(err);
      if (answers.verbmd) {
        app.build('new', cb);
      } else {
        cb();
      }
    });
  });

  return generator;
}

function setAppContext(app) {
  var name = app.pkg.get('name');
  var platform = {};

  if (/^base-?/.test(name)) {
    platform.repo = 'node-base/base';
    platform.docs = `https://github.com/${platform.repo}/blob/master/docs`;
    platform.proper = 'Base';
    platform.name = 'base';
    platform.command = 'base';
    platform.configname = 'basefile';
    platform.configfile = 'basefile.js';
  } else if (/^assemble-?/.test(name)) {
    platform.repo = 'assemble/assemble';
    platform.docs = `https://github.com/${platform.repo}/blob/master/docs`;
    platform.proper = 'Assemble';
    platform.name = 'assemble';
    platform.command = 'assemble';
    platform.configname = 'assemblefile';
    platform.configfile = 'assemblefile.js';
  } else if (/^generate-?/.test(name)) {
    platform.repo = 'generate/generate';
    platform.docs = `https://github.com/${platform.repo}/blob/master/docs`;
    platform.proper = 'Generate';
    platform.name = 'generate';
    platform.command = 'gen';
    platform.configname = 'generator';
    platform.configfile = 'generator.js';
  } else if (/^(updater-?|update)/.test(name)) {
    platform.repo = 'update/update';
    platform.docs = `https://github.com/${platform.repo}/blob/master/docs`;
    platform.proper = 'Update';
    platform.name = 'update';
    platform.command = 'update';
    platform.configname = 'updater';
    platform.configfile = 'updatefile.js';
  } else if (/^verb-?/.test(name)) {
    platform.repo = 'verbose/verb';
    platform.docs = `https://github.com/${platform.repo}/blob/master/docs`;
    platform.proper = 'Verb';
    platform.name = 'verb';
    platform.command = 'verb';
    platform.configname = 'verbfile';
    platform.configfile = 'verbfile.js';
  }
  app.data('platform', platform);
  app.base.data('platform', platform);
}

/**
 * Read a template
 *
 * @param {Object} `verb`
 * @param {String} `fp`
 * @param {String} `base`
 * @return {String}
 */

function readTemplate(app, filepath, base) {
  var dir = base || app.env.templates || templates();
  var absolute = path.resolve(path.resolve(dir), filepath);
  return {
    contents: fs.readFileSync(absolute),
    path: absolute
  };
}

/**
 * Expose `generator`
 */

module.exports = generator;
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var dom5 = require('dom5');
var pred = dom5.predicates;
var _ = require('lodash');
var got = require('got');
var css = require('css');
var PinkiePromise = require('pinkie-promise');
var mkdirp = require('mkdirp');

var chromeHeader = {
  headers: {
    'user-agent': 'ozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36'
  }
};

function escape(qs) {
  return qs.replace(/\?|\=|,|:|\+/g, '_');
}

function processHTML(src, predicates) {
  return new PinkiePromise(function (resolve) {
    if (!fs.statSync(src).isFile()) {
      throw new Error('HTML path is invalid');
    }

    fs.readFile(path.resolve(src), function (err, content) {
      if (err) {
        throw err;
      }

      var dom = dom5.parse(content.toString('utf8'));
      var urls = _.map(_.pluck(dom5.queryAll(dom, pred.hasTagName('link')), 'attrs[1]'), predicates);

      resolve({
        content: dom5.serialize(dom),
        urls: urls
      });
    });
  });
}

function downloadCSS(urls) {
  function gotLink(url) {
    return new PinkiePromise(function (resolve, reject) {
      got(url, chromeHeader, function (err, content) {
        if (!err) {
          resolve({url: url, content: content});
        } else {
          reject(err);
        }
      });
    });
  }

  return PinkiePromise.all(_.map(urls, gotLink));
}

function processCSS(content, predicates) {
  var style = css.parse(content);
  var fonts = [];

  _.each(style.stylesheet.rules, function(rule) {
    var font = {};

    if (rule.type !== 'font-face' || !rule.declarations) {
      return;
    }

    _.each(rule.declarations, function(decl) {
      if (decl.property === 'src') {
        var re = /([\w]*)\(([\w\d':_.\/ -]*)\)/g;
        var source;

        // seperate values of src property
        while ((source = re.exec(decl.value))) {
          font[source[1]] = source[2].replace(/\'/g, '');
        }

        decl.value = predicates(decl.value, font.url);
      } else {
        // keep its property
        font[decl.property] = decl.value;
      }
    });

    fonts.push(font);
  });

  return {
    content: css.stringify(style),
    fonts: fonts
  };
}

function downloadFonts(predicates) {
  return function(fonts) {
    function gotFont(font) {
      return new PinkiePromise(function (resolve) {
        var fontpath = predicates(font.url);
        got(font.url).pipe(fs.createWriteStream(fontpath)).on('close', function() {
          resolve(font);
        });
      });
    }

    return PinkiePromise.all(_.map(fonts, gotFont));
  };
}

function imports(opts, done) {
  opts = opts || {};

  if (!opts.src || !opts.htmlpath) {
    throw new Error('Source path must be exist');
  }

  function preparePath() {
    mkdirp.sync(opts.htmlpath);

    if (opts.stylepath) {
      mkdirp.sync(opts.stylepath);
    } else {
      opts.stylepath = opts.htmlpath;
    }

    if (opts.fontpath) {
      mkdirp.sync(opts.fontpath);
    } else {
      opts.fontpath = opts.htmlpath;
    }
  }

  function replaceStylePath(href) {
    var url = null;
    if (href.value.indexOf('fonts.googleapis.com') >= 0) {
        url = href.value;
        // replace by updated style path
        href.value = path.join(opts.stylepath, escape(path.basename(href.value)));
    }
    return url;
  }

  function writeHTML(res) {
    fs.writeFileSync(path.resolve(path.join(opts.htmlpath, path.basename(opts.src))), res.content);
    return res.urls;
  }

  function extractFonts(res) {
    var fonts = [];

    _.forEach(res, function(r) {
      var css = processCSS(r.content, function(oldUrl, newUrl) {
        // replace the path of url to local path
        return oldUrl.replace(newUrl, path.relative(opts.stylepath,
            path.join(opts.fontpath, path.basename(newUrl))));
      });

      fonts = fonts.concat(css.fonts);

      fs.writeFileSync(path.join(opts.stylepath, escape(path.basename(r.url))), css.content);
    });

    return fonts;
  }

  function getFontFilePath(fontURL) {
    return path.join(opts.fontpath, path.basename(fontURL));
  }

  preparePath();

  return processHTML(opts.src, replaceStylePath)
    .then(writeHTML)
    .then(downloadCSS)
    .then(extractFonts)
    .then(downloadFonts(getFontFilePath))
    .then(function() {
      if (done) {
        done();
        return;
      }
    }).catch(function(e) {
      if (done) {
        done(e);
        return;
      }
    });
}

module.exports = imports;
<commit_msg>Fix relatvice path of style<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var dom5 = require('dom5');
var pred = dom5.predicates;
var _ = require('lodash');
var got = require('got');
var css = require('css');
var PinkiePromise = require('pinkie-promise');
var mkdirp = require('mkdirp');

var chromeHeader = {
  headers: {
    'user-agent': 'ozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36'
  }
};

function escape(qs) {
  return qs.replace(/\?|\=|,|:|\+/g, '_');
}

function processHTML(src, predicates) {
  return new PinkiePromise(function (resolve) {
    if (!fs.statSync(src).isFile()) {
      throw new Error('HTML path is invalid');
    }

    fs.readFile(path.resolve(src), function (err, content) {
      if (err) {
        throw err;
      }

      var dom = dom5.parse(content.toString('utf8'));
      var urls = _.map(_.pluck(dom5.queryAll(dom, pred.hasTagName('link')), 'attrs[1]'), predicates);

      resolve({
        content: dom5.serialize(dom),
        urls: urls
      });
    });
  });
}

function downloadCSS(urls) {
  function gotLink(url) {
    return new PinkiePromise(function (resolve, reject) {
      got(url, chromeHeader, function (err, content) {
        if (!err) {
          resolve({url: url, content: content});
        } else {
          reject(err);
        }
      });
    });
  }

  return PinkiePromise.all(_.map(urls, gotLink));
}

function processCSS(content, predicates) {
  var style = css.parse(content);
  var fonts = [];

  _.each(style.stylesheet.rules, function(rule) {
    var font = {};

    if (rule.type !== 'font-face' || !rule.declarations) {
      return;
    }

    _.each(rule.declarations, function(decl) {
      if (decl.property === 'src') {
        var re = /([\w]*)\(([\w\d':_.\/ -]*)\)/g;
        var source;

        // seperate values of src property
        while ((source = re.exec(decl.value))) {
          font[source[1]] = source[2].replace(/\'/g, '');
        }

        decl.value = predicates(decl.value, font.url);
      } else {
        // keep its property
        font[decl.property] = decl.value;
      }
    });

    fonts.push(font);
  });

  return {
    content: css.stringify(style),
    fonts: fonts
  };
}

function downloadFonts(predicates) {
  return function(fonts) {
    function gotFont(font) {
      return new PinkiePromise(function (resolve) {
        var fontpath = predicates(font.url);
        got(font.url).pipe(fs.createWriteStream(fontpath)).on('close', function() {
          resolve(font);
        });
      });
    }

    return PinkiePromise.all(_.map(fonts, gotFont));
  };
}

function imports(opts, done) {
  opts = opts || {};

  if (!opts.src || !opts.htmlpath) {
    throw new Error('Source path must be exist');
  }

  function preparePath() {
    mkdirp.sync(opts.htmlpath);

    if (opts.stylepath) {
      mkdirp.sync(opts.stylepath);
    } else {
      opts.stylepath = opts.htmlpath;
    }

    if (opts.fontpath) {
      mkdirp.sync(opts.fontpath);
    } else {
      opts.fontpath = opts.htmlpath;
    }
  }

  function replaceStylePath(href) {
    var url = null;
    if (href.value.indexOf('fonts.googleapis.com') >= 0) {
        url = href.value;
        // replace by updated style path
        href.value = path.join(path.relative(opts.htmlpath, opts.stylepath), escape(path.basename(href.value)));
    }
    return url;
  }

  function writeHTML(res) {
    fs.writeFileSync(path.resolve(path.join(opts.htmlpath, path.basename(opts.src))), res.content);
    return res.urls;
  }

  function extractFonts(res) {
    var fonts = [];

    _.forEach(res, function(r) {
      var css = processCSS(r.content, function(oldUrl, newUrl) {
        // replace the path of url to local path
        return oldUrl.replace(newUrl, path.relative(opts.stylepath,
            path.join(opts.fontpath, path.basename(newUrl))));
      });

      fonts = fonts.concat(css.fonts);

      fs.writeFileSync(path.join(opts.stylepath, escape(path.basename(r.url))), css.content);
    });

    return fonts;
  }

  function getFontFilePath(fontURL) {
    return path.join(opts.fontpath, path.basename(fontURL));
  }

  preparePath();

  return processHTML(opts.src, replaceStylePath)
    .then(writeHTML)
    .then(downloadCSS)
    .then(extractFonts)
    .then(downloadFonts(getFontFilePath))
    .then(function() {
      if (done) {
        done();
        return;
      }
    }).catch(function(e) {
      if (done) {
        done(e);
        return;
      }
    });
}

module.exports = imports;
<|endoftext|>


<commit_before>'use strict';

/**
 * Returns a function that when invoked executes all the listeners of the
 * given event with the given arguments.
 *
 * @returns {Function} The function that emits all the things.
 * @api public
 */
module.exports = function emits() {
  var self = this
    , parser;

  for (var i = 0, l = arguments.length, args = new Array(l); i < l; i++) {
    args[i] = arguments[i];
  }

  //
  // Assume that if the last given argument is a function, it would be
  // a parser.
  //
  if ('function' === typeof args[args.length - 1]) {
    parser = args.pop();
  }

  /**
   * The actual function does the emitting of the given event. It will return
   * a boolean indicating if the event was emitted.
   *
   * @returns {Boolean}
   * @api public
   */
  return function emitter() {
    for (var i = 0, l = arguments.length, arg = new Array(l); i < l; i++) {
      arg[i] = arguments[i];
    }

    function next(err, returned) {
      if (err) return self.emit('error', err);

      if (returned === parser) return false;
      if (returned === null) arg = [];
      else if (returned !== undefined) arg = returned;

      return self.emit.apply(self, args.concat(arg));
    }

    if (parser) {
      //
      // If we accept more arguments on the parser then the supplied arguments
      // we want to assume that the parser needs to be executed asynchronously as
      // the extra argument would be a callback.
      //
      if (parser.length > arg.length) {
        return parser.apply(self, arg.concat(next)), true;
      } else {
        return next(undefined, parser.apply(self, arg));
      }
    }

    return self.emit.apply(self, args.concat(arg));
  };
};
<commit_msg>[refactor] Assume that parsers will __always__ be async<commit_after>'use strict';

/**
 * Returns a function that when invoked executes all the listeners of the
 * given event with the given arguments.
 *
 * @returns {Function} The function that emits all the things.
 * @api public
 */
module.exports = function emits() {
  var self = this
    , parser;

  for (var i = 0, l = arguments.length, args = new Array(l); i < l; i++) {
    args[i] = arguments[i];
  }

  //
  // Assume that if the last given argument is a function, it would be
  // a parser.
  //
  if ('function' === typeof args[args.length - 1]) {
    parser = args.pop();
  }

  /**
   * The actual function does the emitting of the given event. It will return
   * a boolean indicating if the event was emitted.
   *
   * @returns {Boolean}
   * @api public
   */
  return function emitter() {
    for (var i = 0, l = arguments.length, arg = new Array(l); i < l; i++) {
      arg[i] = arguments[i];
    }

    if (!parser) return self.emit.apply(self, args.concat(arg));

    parser.apply(self, arg.slice(0, parser.length - 1).concat(function next(err, returned) {
      if (err) return self.emit('error', err);

      if (arguments.length === 1) return false;
      if (returned === null) arg = [];
      else if (returned !== undefined) arg = returned;

      self.emit.apply(self, args.concat(arg));
    }));

    return true;
  };
};
<|endoftext|>