<commit_before>"use strict";

const Module = require("module");
const require_ = Module.prototype.require;
const InstantiateReactComponent = require("react/lib/instantiateReactComponent");

const get = require("lodash/get");
const set = require("lodash/set");
const wrap = require("lodash/wrap");
const template = require("lodash/template");
const isObject = require("lodash/isObject");
const cache = require("lru-cache");

const MILLISECONDS_IN_ONE_SECOND = 1000;
const SECONDS_IN_ONE_MINUTE = 60;
const DEFAULT_MINUTES_TO_CACHE = 60;

const DEFAULT_LRU_CONFIG = {
  max: 500,  //The maximum size of the cache
  maxAge: DEFAULT_MINUTES_TO_CACHE * SECONDS_IN_ONE_MINUTE * MILLISECONDS_IN_ONE_SECOND
};

const EMPTY_ID = -1;

const defaultCacheKeyFunction = () => {
  return "_defaultKey";
};

const genAttrBasedKeyFunction = (attrs) => {
  return ((props) => {
    let key = "";
    attrs.forEach((attr) => {
      const val = get(props, attr);
      key += isObject(val) ? JSON.stringify(val) : val;
    });
    return key;
  });
};

class InstantiateReactComponentOptimizer {

  constructor(config) {
    if (process.env.NODE_ENV !== "production") {
      console.info(  // eslint-disable-line no-console
        "Caching is disabled in non-production environments."
      );
    } else {
      this.config = config;
      this.componentsToCache = config.components ? Object.keys(config.components) : [];
      this.componentsToCache.forEach((cmpName) => {
        let cacheConfig = config.components[cmpName];
        if (cacheConfig instanceof Function) {
          cacheConfig = config.components[cmpName] = {
            cacheKeyGen: cacheConfig
          };
        }
        if (isObject(cacheConfig) && !cacheConfig.cacheKeyGen) {
          cacheConfig.cacheKeyGen = cacheConfig.cacheAttrs && cacheConfig.cacheAttrs.length
            ? genAttrBasedKeyFunction(cacheConfig.cacheAttrs)
            : defaultCacheKeyFunction;
        }
      }, this);
      /* eslint-disable no-nested-ternary */
      this.lruCache = (config.cacheImpl) ? config.cacheImpl :
        (config.lruCacheSettings) ? cache(config.lruCacheSettings) : cache(DEFAULT_LRU_CONFIG);
      this.enabled = !(config.disabled === true);
      this.eventCallback = config.eventCallback;
      this.shouldCollectLoadTimeStats = config.collectLoadTimeStats;
      this.wrapInstantiateReactComponent();
    }
  }

  wrapInstantiateReactComponent() {
    const self = this;

    function eventCallback(event) {
      if (self.eventCallback) {
        process.nextTick(() => {
          self.eventCallback(event);
        });
      }
    }

    /* eslint-disable max-params, no-console*/
    const restorePropsAndProcessTemplate = (compiled, templateAttrs, templateAttrValues, curEl) => {
      templateAttrs.forEach((attrKey) => {
        const _attrKey = attrKey.replace(".", "__");
        set(curEl.props, attrKey, templateAttrValues[_attrKey]);
      });
      return compiled(templateAttrValues);
    };
    /* eslint-enable max-params, no-console*/

    const shouldComponentBeCached = function (curEl) {
      return curEl && curEl.type &&
        (self.componentsToCache.indexOf(curEl.type.displayName) > EMPTY_ID ||
        self.componentsToCache.indexOf(curEl.type.name) > EMPTY_ID);
    };

    /* eslint-disable max-params */
    const templatizeProps = function (attrKey, templateAttrValues, curEl, cmpName) {
      const _attrKey = attrKey.replace(".", "__");
      templateAttrValues[_attrKey] = get(curEl.props, attrKey);
      if (isObject(templateAttrValues[_attrKey])) {
        throw new Error(
          `Cannot templatize Object at ${attrKey} for component ${cmpName}`
        );
      }
      /* eslint-disable prefer-template */
      set(curEl.props, attrKey, "${" + _attrKey + "}");
    };

    const WrappedInstantiateReactComponent = wrap(InstantiateReactComponent,
      function (instantiate) {
        const component = instantiate.apply(
          instantiate, [].slice.call(arguments, 1));
        if (component._instantiateReactComponent
          && (!component._instantiateReactComponent.__wrapped)) {
          component._instantiateReactComponent = WrappedInstantiateReactComponent;
        }
        if (self.enabled) {
          const curEl = component._currentElement;
          if (shouldComponentBeCached(curEl)) {
            /* eslint-disable max-statements */
            component.mountComponent = wrap(
              component.mountComponent,
              function (mount) {
                const cmpName = (curEl.type.displayName || curEl.type.name);
                const generatedKey = self.config.components[cmpName].cacheKeyGen(curEl.props);
                if (generatedKey === null) {
                  return mount.apply(component, [].slice.call(arguments, 1));
                }
                const cacheKey = `${cmpName}:${generatedKey}`;
                const rootID = arguments[1];
                const templateAttrs = self.config.components[cmpName].templateAttrs || [];
                const templateAttrValues = {};
                templateAttrs.forEach((attrKey) => {
                  templatizeProps(attrKey, templateAttrValues, curEl, cmpName);
                });
                const cachedObj = self.lruCache.get(cacheKey);
                if (cachedObj) {
                  eventCallback({type: "cache", event: "hit", cmpName: cmpName});
                  const cacheMarkup = templateAttrs.length ?
                    restorePropsAndProcessTemplate(cachedObj.compiled, templateAttrs,
                      templateAttrValues, curEl)
                    : cachedObj.markup;
                  /* eslint-disable quotes */
                  return cacheMarkup.replace(
                    new RegExp(`data-reactid="${cachedObj.rootId}`, "g"),
                    `data-reactid="${rootID}`);
                }

                const markUpGenerateStartTime = self.shouldCollectLoadTimeStats ?
                  process.hrtime() : 0;
                const markup = mount.apply(component, [].slice.call(arguments, 1));
                const compiledMarkup = templateAttrs.length ? template(markup) : null;
                const markUpGenerateEndTime = self.shouldCollectLoadTimeStats ?
                  process.hrtime(markUpGenerateStartTime) : 0;
                eventCallback({type: "cache", event: "miss", cmpName: cmpName,
                  loadTimeNS: (markUpGenerateEndTime[1])});
                self.lruCache.set(cacheKey, {
                  markup: markup, compiled: compiledMarkup, rootId: rootID
                });
                return templateAttrs.length ? restorePropsAndProcessTemplate(
                  compiledMarkup, templateAttrs, templateAttrValues, curEl)
                  : markup;
              });

            /* eslint-enable max-statements */
          }
        }
        return component;
      }
    );

    WrappedInstantiateReactComponent.__wrapped = true;

    Module.prototype.require = function (path) {
      const m = require_.apply(this, arguments);

      if (path === "./instantiateReactComponent") {
        return WrappedInstantiateReactComponent;
      }

      return m;
    };
  }

  enable(enableFlag) {
    this.enabled = enableFlag;
  }

  cacheDump() {
    return this.lruCache.dump();
  }

  cacheLength() {
    return this.lruCache.length;
  }

  cacheReset() {
    return this.lruCache.reset();
  }
}

module.exports = (config) => new InstantiateReactComponentOptimizer(config);
<commit_msg>Fixing XSS vurnerability with templateAttrs<commit_after>"use strict";

const Module = require("module");
const require_ = Module.prototype.require;
const InstantiateReactComponent = require("react/lib/instantiateReactComponent");
const EscapeTextContentForBrowser = require("react/lib/escapeTextContentForBrowser");

const get = require("lodash/get");
const set = require("lodash/set");
const wrap = require("lodash/wrap");
const template = require("lodash/template");
const isObject = require("lodash/isObject");
const cache = require("lru-cache");

const MILLISECONDS_IN_ONE_SECOND = 1000;
const SECONDS_IN_ONE_MINUTE = 60;
const DEFAULT_MINUTES_TO_CACHE = 60;

const DEFAULT_LRU_CONFIG = {
  max: 500,  //The maximum size of the cache
  maxAge: DEFAULT_MINUTES_TO_CACHE * SECONDS_IN_ONE_MINUTE * MILLISECONDS_IN_ONE_SECOND
};

const EMPTY_ID = -1;

const defaultCacheKeyFunction = () => {
  return "_defaultKey";
};

const genAttrBasedKeyFunction = (attrs) => {
  return ((props) => {
    let key = "";
    attrs.forEach((attr) => {
      const val = get(props, attr);
      key += isObject(val) ? JSON.stringify(val) : val;
    });
    return key;
  });
};

class InstantiateReactComponentOptimizer {

  constructor(config) {
    if (process.env.NODE_ENV !== "production") {
      console.info(  // eslint-disable-line no-console
        "Caching is disabled in non-production environments."
      );
    } else {
      this.config = config;
      this.componentsToCache = config.components ? Object.keys(config.components) : [];
      this.componentsToCache.forEach((cmpName) => {
        let cacheConfig = config.components[cmpName];
        if (cacheConfig instanceof Function) {
          cacheConfig = config.components[cmpName] = {
            cacheKeyGen: cacheConfig
          };
        }
        if (isObject(cacheConfig) && !cacheConfig.cacheKeyGen) {
          cacheConfig.cacheKeyGen = cacheConfig.cacheAttrs && cacheConfig.cacheAttrs.length
            ? genAttrBasedKeyFunction(cacheConfig.cacheAttrs)
            : defaultCacheKeyFunction;
        }
      }, this);
      /* eslint-disable no-nested-ternary */
      this.lruCache = (config.cacheImpl) ? config.cacheImpl :
        (config.lruCacheSettings) ? cache(config.lruCacheSettings) : cache(DEFAULT_LRU_CONFIG);
      this.enabled = !(config.disabled === true);
      this.eventCallback = config.eventCallback;
      this.shouldCollectLoadTimeStats = config.collectLoadTimeStats;
      this.wrapInstantiateReactComponent();
    }
  }

  wrapInstantiateReactComponent() {
    const self = this;

    function eventCallback(event) {
      if (self.eventCallback) {
        process.nextTick(() => {
          self.eventCallback(event);
        });
      }
    }

    /* eslint-disable max-params, no-console*/
    const restorePropsAndProcessTemplate = (compiled, templateAttrs, templateAttrValues, curEl) => {
      templateAttrs.forEach((attrKey) => {
        const _attrKey = attrKey.replace(".", "__");
        set(curEl.props, attrKey, templateAttrValues[_attrKey]);
        templateAttrValues[_attrKey] = EscapeTextContentForBrowser(templateAttrValues[_attrKey]);
      });
      return compiled(templateAttrValues);
    };
    /* eslint-enable max-params, no-console*/

    const shouldComponentBeCached = function (curEl) {
      return curEl && curEl.type &&
        (self.componentsToCache.indexOf(curEl.type.displayName) > EMPTY_ID ||
        self.componentsToCache.indexOf(curEl.type.name) > EMPTY_ID);
    };

    /* eslint-disable max-params */
    const templatizeProps = function (attrKey, templateAttrValues, curEl, cmpName) {
      const _attrKey = attrKey.replace(".", "__");
      templateAttrValues[_attrKey] = get(curEl.props, attrKey);
      if (isObject(templateAttrValues[_attrKey])) {
        throw new Error(
          `Cannot templatize Object at ${attrKey} for component ${cmpName}`
        );
      }
      /* eslint-disable prefer-template */
      set(curEl.props, attrKey, "${" + _attrKey + "}");
    };

    const WrappedInstantiateReactComponent = wrap(InstantiateReactComponent,
      function (instantiate) {
        const component = instantiate.apply(
          instantiate, [].slice.call(arguments, 1));
        if (component._instantiateReactComponent
          && (!component._instantiateReactComponent.__wrapped)) {
          component._instantiateReactComponent = WrappedInstantiateReactComponent;
        }
        if (self.enabled) {
          const curEl = component._currentElement;
          if (shouldComponentBeCached(curEl)) {
            /* eslint-disable max-statements */
            component.mountComponent = wrap(
              component.mountComponent,
              function (mount) {
                const cmpName = (curEl.type.displayName || curEl.type.name);
                const generatedKey = self.config.components[cmpName].cacheKeyGen(curEl.props);
                if (generatedKey === null) {
                  return mount.apply(component, [].slice.call(arguments, 1));
                }
                const cacheKey = `${cmpName}:${generatedKey}`;
                const rootID = arguments[1];
                const templateAttrs = self.config.components[cmpName].templateAttrs || [];
                const templateAttrValues = {};
                templateAttrs.forEach((attrKey) => {
                  templatizeProps(attrKey, templateAttrValues, curEl, cmpName);
                });
                const cachedObj = self.lruCache.get(cacheKey);
                if (cachedObj) {
                  eventCallback({type: "cache", event: "hit", cmpName: cmpName});
                  const cacheMarkup = templateAttrs.length ?
                    restorePropsAndProcessTemplate(cachedObj.compiled, templateAttrs,
                      templateAttrValues, curEl)
                    : cachedObj.markup;
                  /* eslint-disable quotes */
                  return cacheMarkup.replace(
                    new RegExp(`data-reactid="${cachedObj.rootId}`, "g"),
                    `data-reactid="${rootID}`);
                }

                const markUpGenerateStartTime = self.shouldCollectLoadTimeStats ?
                  process.hrtime() : 0;
                const markup = mount.apply(component, [].slice.call(arguments, 1));
                const compiledMarkup = templateAttrs.length ? template(markup) : null;
                const markUpGenerateEndTime = self.shouldCollectLoadTimeStats ?
                  process.hrtime(markUpGenerateStartTime) : 0;
                eventCallback({type: "cache", event: "miss", cmpName: cmpName,
                  loadTimeNS: (markUpGenerateEndTime[1])});
                self.lruCache.set(cacheKey, {
                  markup: markup, compiled: compiledMarkup, rootId: rootID
                });
                return templateAttrs.length ? restorePropsAndProcessTemplate(
                  compiledMarkup, templateAttrs, templateAttrValues, curEl)
                  : markup;
              });

            /* eslint-enable max-statements */
          }
        }
        return component;
      }
    );

    WrappedInstantiateReactComponent.__wrapped = true;

    Module.prototype.require = function (path) {
      const m = require_.apply(this, arguments);

      if (path === "./instantiateReactComponent") {
        return WrappedInstantiateReactComponent;
      }

      return m;
    };
  }

  enable(enableFlag) {
    this.enabled = enableFlag;
  }

  cacheDump() {
    return this.lruCache.dump();
  }

  cacheLength() {
    return this.lruCache.length;
  }

  cacheReset() {
    return this.lruCache.reset();
  }
}

module.exports = (config) => new InstantiateReactComponentOptimizer(config);
<|endoftext|>


<commit_before>'use strict';
const FS = require('fs');
const Joi = require('joi');
const Path = require('path');

const internals = {};

const optionsSchema = Joi.object().keys({
    relativeTo: Joi.string().default(''),
    methods: Joi.array().items(Joi.object().keys({
        prefix: Joi.string().required(),
        path: Joi.string().required()
    })) });

exports.register = (server, options, next) => {

    Joi.validate(options, optionsSchema, (err, validOptions) => {

        if (err) {
            return next(err);
        }
        internals.implementation(server, validOptions.relativeTo, validOptions.methods);

    });
    return next();
};

internals.implementation = (server, relativeTo, methods) => {

    for (const groupMethods of methods) {
        const methodsPath = Path.join(relativeTo, groupMethods.path);
        const files = FS.readdirSync(methodsPath);
        for (const file of files) {
            const filePath = Path.join(methodsPath, file);
            const serviceName = Path.basename(filePath, '.js');
            const stat = FS.statSync(filePath);
            if (stat.isFile()) {
                const module = require(filePath);
                const keys = Object.keys(module);

                for (const key of keys) {
                    const moduleProp = module[key];
                    const hapiMethodName = groupMethods.prefix + '.' + serviceName + '.' + key;
                    if (typeof (moduleProp) === 'function') {
                        server.method(hapiMethodName, moduleProp);
                    }
                    else if (moduleProp.options && moduleProp.method && typeof (moduleProp.method) === 'function') {
                        server.method(hapiMethodName, moduleProp.method, moduleProp.options);
                    }
                }
            }
        }
    }
};

exports.register.attributes = {
    pkg: require('../package.json')
};
<commit_msg>register context to be used later if we want to call a hapi method inside another hapi method<commit_after>'use strict';
const FS = require('fs');
const Joi = require('joi');
const Path = require('path');

const internals = {};

const registeredMethods = {};

const schema = Joi.object().keys({
    relativeTo: Joi.string().default(''),
    methods: Joi.array().items(Joi.object().keys({
        prefix: Joi.string().required(),
        path: Joi.string().required()
    })) });

exports.register = (server, options, next) => {

    Joi.validate(options, schema, (err, validOptions) => {

        if (err) {
            return next(err);
        }
        internals.implementation(server, validOptions.relativeTo, validOptions.methods);

    });
    return next();
};

internals.implementation = (server, relativeTo, methods) => {

    for (const groupMethods of methods) {
        const methodsPath = Path.join(relativeTo, groupMethods.path);
        const files = FS.readdirSync(methodsPath);
        for (const file of files) {
            const filePath = Path.join(methodsPath, file);
            const serviceName = Path.basename(filePath, '.js');
            const stat = FS.statSync(filePath);
            if (stat.isFile()) {
                const module = require(filePath);
                const keys = Object.keys(module);

                for (const key of keys) {
                    const moduleProp = module[key];
                    const hapiMethodName = groupMethods.prefix + '.' + serviceName + '.' + key;
                    if (typeof (moduleProp) === 'function') {
                        server.method(hapiMethodName, moduleProp);
                    }
                    else if (moduleProp.options && moduleProp.method && typeof (moduleProp.method) === 'function') {
                        server.method(hapiMethodName, moduleProp.method, moduleProp.options);
                    }
                }
            }
        }
        for (const key in server.methods) {
            registeredMethods[key] = server.methods[key];
        }
    }
};

module.exports.methods = registeredMethods;

exports.register.attributes = {
    pkg: require('../package.json')
};
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var MailParser = require("mailparser").MailParser;
var Encoder = require('node-html-encoder').Encoder;
var AnyfetchClient = require('anyfetch');
var async = require('async');

/**
 * HYDRATING FUNCTION
 *
 * @param {string} path Path of the specified file
 * @param {string} document to hydrate
 * @param {function} cb Callback, first parameter, is the error if any, then the processed data
 */

var reg = new RegExp("(<([^>]+)>)", "g");

function exists(item){
  return item ? item : '';
}

module.exports = function(path, document, cb) {
  if(!document.metadatas) {
    document.metadatas = {};
  }
  if(!document.datas) {
    document.datas = {};
  }

  var mailparser = new MailParser();
  var encoder = new Encoder('entity');
  mailparser.on("end", function(mail_object){
    document.document_type = "email";
    document.metadatas.to = [];
    (mail_object.to || []).forEach(function(item){
      document.metadatas.to.push(item);
    });
    document.metadatas.cc = [];
    (mail_object.cc || []).forEach(function(item){
      document.metadatas.cc.push(item);
    });
    document.metadatas.bcc = [];
    (mail_object.bcc || []).forEach(function(item){
      document.metadatas.bcc.push(item);
    });
    document.metadatas.from = exists(mail_object.from);
    document.metadatas.subject = exists(mail_object.subject);

    if (mail_object.html) {
      document.datas.html = encoder.htmlDecode(mail_object.html).trim();
    }

    if (mail_object.headers && mail_object.headers.date) {
      document.creation_date = new Date(mail_object.headers.date);
      document.metadatas.date = new Date(mail_object.headers.date);
    }
    else if (mail_object.date){
      document.creation_date = new Date(mail_object.date);
      document.metadatas.date = new Date(mail_object.date);
    }
    if (mail_object.text) {
      document.metadatas.text = mail_object.text;
    }
    else if (document.datas.html) {
      document.metadatas.text = document.datas.html.replace(reg, " ");
      document.metadatas.text = document.metadatas.text.replace("  ", " ");
    }

    // Format text
    document.metadatas.text = document.metadatas.text.trim();
    document.metadatas.text = document.metadatas.text.replace(/</g, '<').replace(/>/g, '>');

    document.related = [];

    // Delete doc without name and extention
    var attachments = mail_object.attachments || [];
    var filtered_attachments = [];
    for (var i=0; i < attachments.length; i += 1) {
      if (attachments[i].fileName || attachments[i].generatedFileName.lastIndexOf(".") !== -1){
        attachments[i].fileName = attachments[i].generatedFileName;
        filtered_attachments.push(attachments[i]);
      }
    }

    async.each(filtered_attachments, function(attachment, cb) {
      var fn = attachment.fileName;
      var embedded_image = new RegExp('<img[^>]*' + fn + '[^>]*/>', 'g');
      if (!mail_object.html || !embedded_image.test(document.datas.html)) {
        var anyfetchClient = new AnyfetchClient();
        anyfetchClient.setAccessToken(document.access_token);
        var docAttachment = {};
        docAttachment.identifier = document.identifier + "/" + fn;
        docAttachment.document_type = "file";
        docAttachment.metadatas = {};
        docAttachment.metadatas.path = "/" + fn;
        docAttachment.user_access = document.user_access;
        if (mail_object.headers && mail_object.headers.date) {
          docAttachment.creation_date = new Date(mail_object.headers.date);
        }
        else if (mail_object.date){
          docAttachment.creation_date = new Date(mail_object.date);
        }
        docAttachment.related = [document.id,];
        document.related.push(docAttachment.identifier);
        // File to send
        var fileConfigAttachment = function(){
          return {
            file: attachment.content,
            filename: attachment.fileName,
            knownLength: attachment.length
          };
        };

        anyfetchClient.sendDocumentAndFile(docAttachment, fileConfigAttachment, cb);
      }
      else {
        var extension = fn.substr(fn.lastIndexOf('.') + 1);
        if (extension === 'jpeg') {
          extension = 'jpg';
        }

        var image = new Buffer(attachment.content).toString('base64');

        var before = document.datas.html.match(embedded_image);
        var after = before[0].replace(new RegExp('alt=.*' + fn + '.* />', 'g'), 'alt="' + fn + '" src=data:image/' + extension + ';base64,' + image + ' />');
        document.datas.html = document.datas.html.replace(before, after);
        cb();
      }
    }, function(err){
      cb(err, document);
    });
  });

  fs.createReadStream(path).pipe(mailparser);
};
<commit_msg>some fix<commit_after>'use strict';

var fs = require('fs');
var MailParser = require("mailparser").MailParser;
var Encoder = require('node-html-encoder').Encoder;
var AnyfetchClient = require('anyfetch');
var async = require('async');

/**
 * HYDRATING FUNCTION
 *
 * @param {string} path Path of the specified file
 * @param {string} document to hydrate
 * @param {function} cb Callback, first parameter, is the error if any, then the processed data
 */

var reg = new RegExp("(<([^>]+)>)", "g");

function exists(item){
  return item ? item : '';
}

module.exports = function(path, document, cb) {
  if(!document.metadatas) {
    document.metadatas = {};
  }
  if(!document.datas) {
    document.datas = {};
  }

  var mailparser = new MailParser();
  var encoder = new Encoder('entity');
  mailparser.on("end", function(mail_object){
    document.document_type = "email";
    document.metadatas.to = [];
    (mail_object.to || []).forEach(function(item){
      document.metadatas.to.push(item);
    });
    document.metadatas.cc = [];
    (mail_object.cc || []).forEach(function(item){
      document.metadatas.cc.push(item);
    });
    document.metadatas.bcc = [];
    (mail_object.bcc || []).forEach(function(item){
      document.metadatas.bcc.push(item);
    });
    document.metadatas.from = exists(mail_object.from);
    document.metadatas.subject = exists(mail_object.subject);

    if (mail_object.html) {
      document.datas.html = encoder.htmlDecode(mail_object.html).trim();
    }

    if (mail_object.headers && mail_object.headers.date) {
      document.creation_date = new Date(mail_object.headers.date);
      document.metadatas.date = new Date(mail_object.headers.date);
    }
    else if (mail_object.date){
      document.creation_date = new Date(mail_object.date);
      document.metadatas.date = new Date(mail_object.date);
    }
    if (mail_object.text) {
      document.metadatas.text = mail_object.text;
    }
    else if (document.datas.html) {
      document.metadatas.text = document.datas.html.replace(reg, " ");
      document.metadatas.text = document.metadatas.text.replace("  ", " ");
    }

    // Format text
    document.metadatas.text = document.metadatas.text.trim();
    document.metadatas.text = document.metadatas.text.replace(/</g, '<').replace(/>/g, '>');

    document.related = [];

    // Delete doc without name and extension
    var attachments = mail_object.attachments || [];
    var filtered_attachments = [];
    attachments.forEach(function(attachment){
      if (attachment.fileName || attachment.generatedFileName.lastIndexOf(".") !== -1){
        attachment.fileName = attachment.generatedFileName;
        filtered_attachments.push(attachment);
      }
    });

    async.each(filtered_attachments, function(attachment, cb) {
      var fn = attachment.fileName;
      var embedded_image = new RegExp('<img[^>]*' + fn + '[^>]*/>', 'g');
      if (!mail_object.html || !embedded_image.test(document.datas.html)) {
        var anyfetchClient = new AnyfetchClient();
        anyfetchClient.setAccessToken(document.access_token);
        var docAttachment = {};
        docAttachment.identifier = document.identifier + "/" + fn;
        docAttachment.document_type = "file";
        docAttachment.metadatas = {};
        docAttachment.metadatas.path = "/" + fn;
        docAttachment.user_access = document.user_access;
        docAttachment.creation_date = document.creation_date;
        docAttachment.related = [document.id,];
        document.related.push(docAttachment.identifier);
        // File to send
        var fileConfigAttachment = function(){
          return {
            file: attachment.content,
            filename: attachment.fileName,
            knownLength: attachment.length
          };
        };

        anyfetchClient.sendDocumentAndFile(docAttachment, fileConfigAttachment, cb);
      }
      else {
        var extension = fn.substr(fn.lastIndexOf('.') + 1);
        if (extension === 'jpeg') {
          extension = 'jpg';
        }

        var image = new Buffer(attachment.content).toString('base64');

        var before = document.datas.html.match(embedded_image);
        var after = before[0].replace(new RegExp('alt=.*' + fn + '.* />', 'g'), 'alt="' + fn + '" src=data:image/' + extension + ';base64,' + image + ' />');
        document.datas.html = document.datas.html.replace(before, after);
        cb();
      }
    }, function(err){
      cb(err, document);
    });
  });

  fs.createReadStream(path).pipe(mailparser);
};
<|endoftext|>


<commit_before>'use strict';

var hoxy = require('hoxy');
var merge = require('lodash.merge');
var chalk = require('chalk');
var path = require('path');
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var networkProfiles = require('./network-profiles');

var noop = function () {};
var defaults = {
  hostname: '',
  docroot: '',
  port: 8888,
  upstream: undefined,
  network: undefined,
  silent: false
};

// Constructor
var Replocal = function (options) {

  EventEmitter.call(this);

  var self = this;
  var opts = this._options = merge({}, defaults, options);
  var networkProfile = networkProfiles[opts.network];
  var slow = networkProfile ? {
    rate: networkProfile.rate,
    latency: networkProfile.latency
  } : {};
  var proxy = this._proxy = hoxy.createServer({
    upstreamProxy: opts.upstream,
    slow: slow
  }).listen(opts.port, function () {
    self.log('Proxy server is running on ' + chalk.magenta.underline('localhost:' + opts.port));
    self.log('  Target website   : ' + (opts.hostname ? chalk.cyan(opts.hostname) : chalk.gray('(none)')));
    self.log('  Document root    : ' + (opts.docroot ? chalk.cyan(opts.docroot) : chalk.gray('(current directory)')));
    self.log('  Upstream proxy   : ' + (opts.upstream ? chalk.cyan(opts.upstream) : chalk.gray('(none)')));
    self.log('  Network throttle : ' + (networkProfile ? chalk.cyan(networkProfile.label) : chalk.gray('(none)')));
    self.emit('start');
  });

  proxy.intercept({
    phase: 'request',
    hostname: opts.hostname
  }, function (req, resp, cycle) {
    return cycle.serve({
      docroot: path.resolve(opts.docroot),
      strategy: 'overlay'
    });
  });

};

// Inherit EventEmitter
util.inherits(Replocal, EventEmitter);

// Close proxy server
Replocal.prototype.close = function (callback) {
  var self = this;
  callback = callback || noop;
  this._proxy.close(function () {
    self.emit('close');
    callback();
  });
};

// Log to stdout
Replocal.prototype.log = function () {
  if (this._options.silent) {
    return;
  }
  console.log.apply(this, arguments);
};

module.exports = Replocal;
<commit_msg>Display docroot as absolute path<commit_after>'use strict';

var hoxy = require('hoxy');
var merge = require('lodash.merge');
var chalk = require('chalk');
var path = require('path');
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var networkProfiles = require('./network-profiles');

var noop = function () {};
var defaults = {
  hostname: '',
  docroot: '',
  port: 8888,
  upstream: undefined,
  network: undefined,
  silent: false
};

// Constructor
var Replocal = function (options) {

  EventEmitter.call(this);

  var self = this;
  var opts = this._options = merge({}, defaults, options);
  var docroot = path.resolve(opts.docroot);
  var networkProfile = networkProfiles[opts.network];
  var slow = networkProfile ? {
    rate: networkProfile.rate,
    latency: networkProfile.latency
  } : {};
  var proxy = this._proxy = hoxy.createServer({
    upstreamProxy: opts.upstream,
    slow: slow
  }).listen(opts.port, function () {
    self.log('Proxy server is running on ' + chalk.magenta.underline('localhost:' + opts.port));
    self.log('  Target website   : ' + (opts.hostname ? chalk.cyan(opts.hostname) : chalk.gray('(none)')));
    self.log('  Document root    : ' + chalk.cyan(docroot));
    self.log('  Upstream proxy   : ' + (opts.upstream ? chalk.cyan(opts.upstream) : chalk.gray('(none)')));
    self.log('  Network throttle : ' + (networkProfile ? chalk.cyan(networkProfile.label) : chalk.gray('(none)')));
    self.emit('start');
  });

  proxy.intercept({
    phase: 'request',
    hostname: opts.hostname
  }, function (req, resp, cycle) {
    return cycle.serve({
      docroot: docroot,
      strategy: 'overlay'
    });
  });

};

// Inherit EventEmitter
util.inherits(Replocal, EventEmitter);

// Close proxy server
Replocal.prototype.close = function (callback) {
  var self = this;
  callback = callback || noop;
  this._proxy.close(function () {
    self.emit('close');
    callback();
  });
};

// Log to stdout
Replocal.prototype.log = function () {
  if (this._options.silent) {
    return;
  }
  console.log.apply(this, arguments);
};

module.exports = Replocal;
<|endoftext|>


<commit_before>"use strict";

var chalk = require("chalk"),
    fs = require("fs"),
    homedir = require("os-homedir"),
    path = require("path"),
    pathExists = require("path-exists").sync,
    util = require("util");

var defaultColorMap = {  // jscs: ignore requireMultipleVarDecl
    file: chalk.green.bold,
    location: chalk.bold,
    message: chalk.bold,
    rule: chalk.bold.dim,
    separator: chalk.dim,
    source: null,
    caret: chalk.magenta.bold,
    summary: chalk.red.bold
};

/**
 * @param {object[]} errorsCollection
 */
module.exports = function(errorsCollection)
{
    var output = "\n",
        options = loadOptions(),
        colorMap = defaultColorMap,
        colorize;

    colorize = typeof options.colorize === "boolean" ? options.colorize : chalk.enabled;

    if (colorize && typeof options.colors === "object")
        colorMap = setColorMap(options.colors);

    var errorCount = 0;

    /**
     * Format every error set.
     */
    errorsCollection.forEach(function(errors)
    {
        if (!errors.isEmpty())
        {
            /**
             * Format every error.
             */
            var errorList = errors.getErrorList(),
                lines = errors._file.getLines();

            errorList.forEach(function(error)
            {
                ++errorCount;
                output += explainError(lines, error, errors._verbose, colorize, colorMap);
            });
        }
    });

    if (errorCount)
    {
        var summary = util.format("\n%d error%s found.", errorCount, errorCount === 1 ? "" : "s");

        colorMap.summary.enabled = colorize;
        output += colorMap.summary(summary);
    }

    console.log(output);
};

function loadOptions()
{
    var dir = process.cwd(),
        home = homedir(),
        visitedHome,
        rcPath;

    while (true)
    {
        visitedHome = dir === home;
        rcPath = path.join(dir, ".clangformatterrc");

        if (pathExists(rcPath))
            return JSON.parse(fs.readFileSync(rcPath, "utf8"));

        var previousDir = dir;

        dir = path.dirname(dir);

        // If it hasn't changed, we were at the root
        if (dir === previousDir)
            break;
    }

    rcPath = path.join(home, ".clangformatterrc");

    if (!visitedHome && pathExists(rcPath))
        return JSON.parse(fs.readFileSync(rcPath, "utf8"));

    return {};
}

function setColorMap(map)
{
    function parseStyle(style)
    {
        if (typeof style === "string")
        {
            var parsedStyle = chalk,
                styles = style.split(".");

            for (var i = 0; i < styles.length; ++i)
            {
                parsedStyle = parsedStyle[styles[i]];

                if (parsedStyle === undefined)
                    return undefined;
            }

            return parsedStyle;
        }

        return style;
    }

    var colors = {};

    Object.keys(defaultColorMap).forEach(function(key)
    {
        var color;

        if (map.hasOwnProperty(key))
            color = parseStyle(map[key]);

        colors[key] = color || defaultColorMap[key];
    });

    return colors;
}

function colorizeText(colorize, colorMap, color, text)
{
    if (colorize)
    {
        var func = colorMap[color];

        if (func)
        {
            // enabled flag is in func
            func.enabled = true;
            return func(text);
        }
    }

    return text;
}

function explainError(lines, error, showRule, colorize, colorMap)
{
    var line = lines[error.line - 1].replace("\t", " "),
        source = colorizeText(colorize, colorMap, "source", line),
        file = colorizeText(colorize, colorMap, "file", error.filename),
        location = colorizeText(colorize, colorMap, "location", error.line + ":" + (error.column + 1)),
        sep = colorizeText(colorize, colorMap, "separator", ":"),
        caret = line.substr(0, error.column).replace(/./g, " ") + colorizeText(colorize, colorMap, "caret", "^"),
        message = error.message;

    if (showRule)
    {
        var match = message.match(/([a-z][\w\-]*?): (.+)/);

        if (match)
        {
            var rule = colorizeText(colorize, colorMap, "rule", " [" + match[1] + "]");

            message = colorizeText(colorize, colorMap, "message", match[2]) + rule;
        }
    }
    else
        message = colorizeText(colorize, colorMap, "message", message);

    return file + sep + location + sep + " " + message + "\n" + source + "\n" + caret + "\n";
}
<commit_msg>Changed colors, allow for config to be passed<commit_after>"use strict";

var chalk = require("chalk"),
    fs = require("fs"),
    homedir = require("os-homedir"),
    path = require("path"),
    pathExists = require("path-exists").sync,
    util = require("util");

var defaultColorMap = {  // jscs: ignore requireMultipleVarDecl
    file: chalk.cyan.bold,
    location: chalk.bold,
    message: chalk.bold,
    rule: chalk.bold.dim,
    separator: chalk.dim,
    source: null,
    caret: chalk.green.bold,
    summary: chalk.red.bold
};

/**
 * @param {object[]} errorsCollection
 * @param {object} [config]
 */
module.exports = function(errorsCollection, config)
{
    if (!config || typeof config.clangFormatter !== "object")
        config = loadConfig();
    else
        config = config.clangFormatter;

    var colorize = typeof config.colorize === "boolean" ? config.colorize : chalk.enabled,
        colorMap = defaultColorMap;

    if (colorize && typeof config.colors === "object")
        colorMap = setColorMap(config.colors);

    var output = "\n",
        errorCount = 0;

    /**
     * Format every error set.
     */
    errorsCollection.forEach(function(errors)
    {
        if (!errors.isEmpty())
        {
            /**
             * Format every error.
             */
            var errorList = errors.getErrorList(),
                lines = errors._file.getLines();

            errorList.forEach(function(error)
            {
                ++errorCount;
                output += explainError(lines, error, errors._verbose, colorize, colorMap);
            });
        }
    });

    if (errorCount)
    {
        var summary = util.format("\n%d error%s found.", errorCount, errorCount === 1 ? "" : "s");

        colorMap.summary.enabled = colorize;
        output += colorMap.summary(summary);
    }

    console.log(output);
};

function loadConfig()
{
    var dir = process.cwd(),
        home = homedir(),
        visitedHome,
        rcPath;

    while (true)
    {
        visitedHome = dir === home;
        rcPath = path.join(dir, ".clangformatterrc");

        if (pathExists(rcPath))
            return JSON.parse(fs.readFileSync(rcPath, "utf8"));

        var previousDir = dir;

        dir = path.dirname(dir);

        // If it hasn't changed, we were at the root
        if (dir === previousDir)
            break;
    }

    rcPath = path.join(home, ".clangformatterrc");

    if (!visitedHome && pathExists(rcPath))
        return JSON.parse(fs.readFileSync(rcPath, "utf8"));

    return {};
}

function setColorMap(map)
{
    function parseStyle(style)
    {
        if (typeof style === "string")
        {
            var parsedStyle = chalk,
                styles = style.split(".");

            for (var i = 0; i < styles.length; ++i)
            {
                parsedStyle = parsedStyle[styles[i]];

                if (parsedStyle === undefined)
                    return undefined;
            }

            return parsedStyle;
        }

        return style;
    }

    var colors = {};

    Object.keys(defaultColorMap).forEach(function(key)
    {
        var color;

        if (map.hasOwnProperty(key))
            color = parseStyle(map[key]);

        colors[key] = color || defaultColorMap[key];
    });

    return colors;
}

function colorizeText(colorize, colorMap, color, text)
{
    if (colorize)
    {
        var func = colorMap[color];

        if (func)
        {
            // enabled flag is in func
            func.enabled = true;
            return func(text);
        }
    }

    return text;
}

function explainError(lines, error, showRule, colorize, colorMap)
{
    var line = lines[error.line - 1].replace("\t", " "),
        source = colorizeText(colorize, colorMap, "source", line),
        file = colorizeText(colorize, colorMap, "file", error.filename),
        location = colorizeText(colorize, colorMap, "location", error.line + ":" + (error.column + 1)),
        sep = colorizeText(colorize, colorMap, "separator", ":"),
        caret = line.substr(0, error.column).replace(/./g, " ") + colorizeText(colorize, colorMap, "caret", "^"),
        message = error.message;

    if (showRule)
    {
        var match = message.match(/([a-z][\w\-]*?): (.+)/);

        if (match)
        {
            var rule = colorizeText(colorize, colorMap, "rule", " [" + match[1] + "]");

            message = colorizeText(colorize, colorMap, "message", match[2]) + rule;
        }
    }
    else
        message = colorizeText(colorize, colorMap, "message", message);

    return file + sep + location + sep + " " + message + "\n" + source + "\n" + caret + "\n";
}
<|endoftext|>


<commit_before>'use babel';
/* @flow */

import { CompositeDisposable } from 'atom';
import path from 'path';

import handleData from './message.js';
import { check } from './helpers';

import type { LinterMessage } from './message';

type BufferType = {
  cachedText: string;
  getText(): string;
}

type TextEditorType = {
  getPath(): string;
  buffer: BufferType;
  isModified(): boolean;
}

type Linter = {
  grammarScopes: Array<string>;
  scope: 'file' | 'project';
  name?: string;
  lintOnFly: boolean;
  lint(TextEditor: TextEditorType): Array<LinterMessage> | Promise<Array<LinterMessage>>;
};

export default {
  config: {
    executablePath: {
      type: 'string',
      default: 'flow',
      description: 'Absolute path to the Flow executable on your system.',
    },
  },

  activate(): void {
    require('atom-package-deps').install('linter-flow');

    this.subscriptions = new CompositeDisposable();
    this.subscriptions.add(atom.config.observe('linter-flow.executablePath', (pathToFlow) => {
      this.pathToFlow = pathToFlow;
    }));
  },

  deactivate(): void {
    const helpers = require('atom-linter');
    console.log('deactivating... lintet-flow');
    helpers.exec(this.pathToFlow, ['stop'], {}).catch(() => null);
    this.subscriptions.dispose();
  },

  provideLinter(): Linter {
    const helpers = require('atom-linter');

    return {
      grammarScopes: [
        'source.js',
        'source.js.jsx',
        'source.babel',
        'source.js-semantic',
        'source.es6',
      ],
      scope: 'project',
      name: 'Flow',
      lintOnFly: true,
      lint: (TextEditor) => {
        const filePath = TextEditor.getPath();
        const fileText = TextEditor.buffer.cachedText;

        // Is flow enabled for current file ?
        const firstComStart = fileText.indexOf('\/*');
        const firstComEnd = fileText.indexOf('*\/');
        if (firstComStart !== -1 &&
          firstComEnd !== -1 &&
          fileText.slice(firstComStart + 2, firstComEnd).indexOf('@flow') === -1) {
          return Promise.resolve([]);
        }

        // Check if .flowconfig file is present
        const flowConfig = helpers.find(filePath, '.flowconfig');
        if (!flowConfig) {
          atom.notifications.addWarning('[Linter-Flow] Missing .flowconfig file.', {
            detail: 'To get started with Flow, run `flow init`.',
            dismissable: true,
          });
          return Promise.resolve([]);
        }

        let args;
        let options;

        // Use `check-contents` for unsaved files. and `status` for saved files.
        if (TextEditor.isModified()) {
          args = ['check-contents', '--json', filePath];
          options = { cwd: path.dirname(filePath), stdin: fileText };
        } else {
          args = ['status', '--json', filePath];
          options = { cwd: path.dirname(filePath) };
        }

        return check(this.pathToFlow, args, options)
          .then(JSON.parse)
          .then(handleData);
      },
    };
  },
};
<commit_msg>revert(flow-comment-detection): revert back to simple @flow detecting to fix regressions<commit_after>'use babel';
/* @flow */

import { CompositeDisposable } from 'atom';
import path from 'path';

import handleData from './message.js';
import { check } from './helpers';

import type { LinterMessage } from './message';

type BufferType = {
  cachedText: string;
  getText(): string;
}

type TextEditorType = {
  getPath(): string;
  buffer: BufferType;
  isModified(): boolean;
}

type Linter = {
  grammarScopes: Array<string>;
  scope: 'file' | 'project';
  name?: string;
  lintOnFly: boolean;
  lint(TextEditor: TextEditorType): Array<LinterMessage> | Promise<Array<LinterMessage>>;
};

export default {
  config: {
    executablePath: {
      type: 'string',
      default: 'flow',
      description: 'Absolute path to the Flow executable on your system.',
    },
  },

  activate(): void {
    require('atom-package-deps').install('linter-flow');

    this.subscriptions = new CompositeDisposable();
    this.subscriptions.add(atom.config.observe('linter-flow.executablePath', (pathToFlow) => {
      this.pathToFlow = pathToFlow;
    }));
  },

  deactivate(): void {
    const helpers = require('atom-linter');
    console.log('deactivating... linter-flow');
    helpers.exec(this.pathToFlow, ['stop'], {}).catch(() => null);
    this.subscriptions.dispose();
  },

  provideLinter(): Linter {
    const helpers = require('atom-linter');

    return {
      grammarScopes: [
        'source.js',
        'source.js.jsx',
        'source.babel',
        'source.js-semantic',
        'source.es6',
      ],
      scope: 'project',
      name: 'Flow',
      lintOnFly: true,
      lint: (TextEditor) => {
        const filePath = TextEditor.getPath();
        const fileText = TextEditor.buffer.cachedText;

        // Is flow enabled for current file ?
        if (!fileText || fileText.indexOf('@flow') === -1) {
          return Promise.resolve([]);
        }

        // Check if .flowconfig file is present
        const flowConfig = helpers.find(filePath, '.flowconfig');
        if (!flowConfig) {
          atom.notifications.addWarning('[Linter-Flow] Missing .flowconfig file.', {
            detail: 'To get started with Flow, run `flow init`.',
            dismissable: true,
          });
          return Promise.resolve([]);
        }

        let args;
        let options;

        // Use `check-contents` for unsaved files. and `status` for saved files.
        if (TextEditor.isModified()) {
          args = ['check-contents', '--json', filePath];
          options = { cwd: path.dirname(filePath), stdin: fileText };
        } else {
          args = ['status', '--json', filePath];
          options = { cwd: path.dirname(filePath) };
        }

        return check(this.pathToFlow, args, options)
          .then(JSON.parse)
          .then(handleData);
      },
    };
  },
};
<|endoftext|>


<commit_before>/*
 * hello-project
 *
 * https://github.com/jostw/hello-project
 *
 * Copyright (c) 2014 jos
 * Licensed under the MIT license.
 */

"use strict";

var gulp =    require("gulp"),

    fs =      require("fs"),
    wiredep = require("wiredep").stream,
    yargs =   require("yargs"),

    plugins = require("gulp-load-plugins")(),

    app =     require("./project.json").app,

    /**
     * Usage: gulp [task] [--pre=stylus]
     *     - Use compass as default preprocessor
     */
    preprocessor = yargs.argv.pre || app.preprocessor,

    isWatch = false;

app.folder.vendor = JSON.parse(fs.readFileSync(app.config.bower, "utf8")).directory;

app.regex = {
    html5shiv: new RegExp(app.regex.html5shiv),
    respond: new RegExp(app.regex.respond)
};

// ##      ##    ###    ########  ######  ##     ##
// ##  ##  ##   ## ##      ##    ##    ## ##     ##
// ##  ##  ##  ##   ##     ##    ##       ##     ##
// ##  ##  ## ##     ##    ##    ##       #########
// ##  ##  ## #########    ##    ##       ##     ##
// ##  ##  ## ##     ##    ##    ##    ## ##     ##
//  ###  ###  ##     ##    ##     ######  ##     ##

gulp.task("watch", function() {
    var livereload = plugins.livereload();

    gulp.watch(app.folder.scss +"/**/*.scss", [
        // css-init
        "compass:dev",
        "clean:css",

        // css-lint
        "csslint:dist"
    ]);

    gulp.watch(app.folder.stylus +"/**/*.styl", [
        // css-init
        "stylus:dev",
        "autoprefixer:dist",

        // css-lint
        "csslint:dist"
    ]);

    gulp.watch(app.folder.js +"/**/*.js", [
        // js-init
        "copy:js",
        "clean:js",

        // js-lint
        "jshint:js"
    ]);

    gulp.watch(["*.slim", app.folder.template +"/*.slim"], [
        // html-init
        "slim:dev",
        "rename:partial",
        "concat:main",
        "htmlmin:dev", "clean:partial",

        // html-lint
        "htmlhint:dist"
    ]);

    // gulp.watch([app.folder.dist +"/**"]).on("change", function(file) {
    //     livereload.changed(file.path);
    // });
});

// ########  ######## ##    ##    ###    ##     ## ########
// ##     ## ##       ###   ##   ## ##   ###   ### ##
// ##     ## ##       ####  ##  ##   ##  #### #### ##
// ########  ######   ## ## ## ##     ## ## ### ## ######
// ##   ##   ##       ##  #### ######### ##     ## ##
// ##    ##  ##       ##   ### ##     ## ##     ## ##
// ##     ## ######## ##    ## ##     ## ##     ## ########

gulp.task("rename:partial", ["slim:dev"], function() {
    return gulp.src(app.folder.partial +"/*.html")
               .pipe(plugins.rename(function(path) {
                   path.basename = path.basename.match(/_(.+).html/)[1];
               }))
               .pipe(gulp.dest(app.folder.partial));
});

//  ######   #######  ##    ##  ######     ###    ########
// ##    ## ##     ## ###   ## ##    ##   ## ##      ##
// ##       ##     ## ####  ## ##        ##   ##     ##
// ##       ##     ## ## ## ## ##       ##     ##    ##
// ##       ##     ## ##  #### ##       #########    ##
// ##    ## ##     ## ##   ### ##    ## ##     ##    ##
//  ######   #######  ##    ##  ######  ##     ##    ##

gulp.task("concat:main", ["rename:partial"], function() {
    var count = 0,
        src = [
            app.folder.partial +"/"+ app.file.head,
            app.folder.partial +"/"+ app.file.style,

            app.folder.partial +"/"+ app.file.main,

            app.folder.partial +"/"+ app.file.foot,
            app.folder.partial +"/"+ app.file.script
        ];

    /**
     *     * Add livereload.js to html when using html-watch task
     */
    if(isWatch) {
        src.push(app.folder.partial +"/"+ app.file.livereload);
    }

    return gulp.src(src)
               .pipe(plugins.concatUtil(app.file.index, {
                   process: function(src) {
                       if(count === 2) {
                           src = "\n\n"+ src;
                       }

                       count++;

                       return src;
                   }
               }))
               .pipe(plugins.concatUtil.header("<!DOCTYPE html>\n\n\n"))
               .pipe(plugins.concatUtil.footer("\n\n"))
               .pipe(gulp.dest(app.folder.dist));
});

//  ######   #######  ########  ##    ##
// ##    ## ##     ## ##     ##  ##  ##
// ##       ##     ## ##     ##   ####
// ##       ##     ## ########     ##
// ##       ##     ## ##           ##
// ##    ## ##     ## ##           ##
//  ######   #######  ##           ##

gulp.task("copy:vendor", function() {
    gulp.src([
            app.folder.vendor +"/**/*.css",
            app.folder.vendor +"/**/*.js"
        ])
        .pipe(gulp.dest(app.folder.dist +"/"+ app.folder.vendor));

    return gulp.src([
                   app.folder.vendor +"/"+ app.vendor.html5shiv.path +"/"+ app.vendor.html5shiv.file,
                   app.folder.vendor +"/"+ app.vendor.respond.path +"/"+ app.vendor.respond.file
               ])
               .pipe(gulp.dest(app.folder.js +"/"+ app.folder.vendor));
});

gulp.task("copy:js", ["copy:vendor"], function() {
    return gulp.src(app.folder.js +"/**/*.js")
               .pipe(gulp.dest(app.folder.dist +"/"+ app.folder.js));
});

//  ######  ##       ########    ###    ##    ##
// ##    ## ##       ##         ## ##   ###   ##
// ##       ##       ##        ##   ##  ####  ##
// ##       ##       ######   ##     ## ## ## ##
// ##       ##       ##       ######### ##  ####
// ##    ## ##       ##       ##     ## ##   ###
//  ######  ######## ######## ##     ## ##    ##

gulp.task("clean:all", function() {
    return gulp.src([
                   app.folder.css,
                   app.folder.js +"/"+ app.folder.vendor,
                   app.folder.partial,
                   app.folder.temp,
                   app.folder.dist
               ])
               .pipe(plugins.clean(app.config.clean));
});

gulp.task("clean:css", [preprocessor +":dev"], function() {
    return gulp.src(app.folder.css)
               .pipe(plugins.clean(app.config.clean));
});

gulp.task("clean:js", ["copy:js"], function() {
    gulp.src(app.folder.js +"/"+ app.folder.vendor)
        .pipe(plugins.clean(app.config.clean));
});

gulp.task("clean:partial", ["concat:main"], function() {
    gulp.src(app.folder.partial)
        .pipe(plugins.clean(app.config.clean));
});

// ##     ## ######## ##     ## ##
// ##     ##    ##    ###   ### ##
// ##     ##    ##    #### #### ##
// #########    ##    ## ### ## ##
// ##     ##    ##    ##     ## ##
// ##     ##    ##    ##     ## ##
// ##     ##    ##    ##     ## ########

gulp.task("bowerInstall:dev", function() {
    return gulp.src([
                   app.template.style,
                   app.template.script
               ])
               .pipe(wiredep({
                   directory: app.folder.vendor,
                   exclude: [
                       app.regex.html5shiv,
                       app.regex.respond
                   ]
               }))
               .pipe(gulp.dest("."));
});

gulp.task("slim:dev", function() {
    return gulp.src([
                   app.template.style,
                   app.template.script,

                   app.folder.template +"/"+ app.template.head,
                   app.folder.template +"/"+ app.template.main,
                   app.folder.template +"/"+ app.template.foot,

                   app.folder.template +"/"+ app.template.livereload
               ])
               .pipe(plugins.slim(app.config.slim))
               .pipe(gulp.dest(app.folder.partial));
});

gulp.task("htmlmin:dev", ["concat:main"], function() {
    return gulp.src(app.folder.dist +"/"+ app.file.index)
               .pipe(plugins.htmlmin())
               .pipe(gulp.dest(app.folder.dist));
});

gulp.task("htmlhint:dist", ["htmlmin:dev"], function() {
    gulp.src(app.folder.dist +"/"+ app.file.index)
        .pipe(plugins.htmlhint({ htmlhintrc: app.config.htmlhint }))
        .pipe(plugins.htmlhint.reporter());
});

//  ######   ######   ######
// ##    ## ##    ## ##    ##
// ##       ##       ##
// ##        ######   ######
// ##             ##       ##
// ##    ## ##    ## ##    ##
//  ######   ######   ######

gulp.task("compass:dev", function() {
    return gulp.src(app.folder.scss +"/**/*.scss")
               .pipe(plugins.compass({
                   config_file: app.config.compass,
                   css: app.folder.css,
                   sass: app.folder.scss
               }))
               .pipe(gulp.dest(app.folder.dist +"/"+ app.folder.css));
});

gulp.task("stylus:dev", function() {
    return gulp.src(app.folder.stylus +"/**/*.styl")
               .pipe(plugins.stylus(app.config.stylus))
               .pipe(gulp.dest(app.folder.dist +"/"+ app.folder.css));
});

gulp.task("autoprefixer:dist", ["stylus:dev"], function() {
    return gulp.src(app.folder.dist +"/"+ app.folder.css +"/**/*.css")
               .pipe(plugins.autoprefixer())
               .pipe(gulp.dest(app.folder.dist +"/"+ app.folder.css));
});

gulp.task("csslint:dist", preprocessor === "compass" ? [preprocessor +":dev"] : ["stylus:dev", "autoprefixer:dist"], function() {
    gulp.src(app.folder.dist +"/"+ app.folder.css +"/"+ app.file.css)
        .pipe(plugins.csslint(app.config.csslint))
        .pipe(plugins.csslint.reporter());
});

//       ##  ######
//       ## ##    ##
//       ## ##
//       ##  ######
// ##    ##       ##
// ##    ## ##    ##
//  ######   ######

gulp.task("jshint:gulp", function() {
    return gulp.src(app.file.gulp)
               .pipe(plugins.jshint(app.config.jshint))
               .pipe(plugins.jshint.reporter("jshint-stylish"));
});

gulp.task("jshint:js", ["copy:js"], function() {
    gulp.src(app.folder.dist +"/"+ app.folder.js +"/"+ app.file.js)
        .pipe(plugins.jshint(app.config.jshint))
        .pipe(plugins.jshint.reporter("jshint-stylish"));
});

//  ######  ##     ## ########  ########    ###     ######  ##    ##  ######
// ##    ## ##     ## ##     ##    ##      ## ##   ##    ## ##   ##  ##    ##
// ##       ##     ## ##     ##    ##     ##   ##  ##       ##  ##   ##
//  ######  ##     ## ########     ##    ##     ##  ######  #####     ######
//       ## ##     ## ##     ##    ##    #########       ## ##  ##         ##
// ##    ## ##     ## ##     ##    ##    ##     ## ##    ## ##   ##  ##    ##
//  ######   #######  ########     ##    ##     ##  ######  ##    ##  ######

/**
 * Create html file:
 *     - Create partial html files from slim templates
 *     - Rename partial html files
 *     - Concat partial html files into a single html file
 *     - Remove redudant code in the html file
 *     - Remove partial html files
 *
 *     * Add livereload.js to html when using html-watch task
 */
gulp.task("html-init", function() {
    gulp.start(
        "slim:dev",
        "rename:partial",
        "concat:main",
        "htmlmin:dev", "clean:partial"
    );
});

gulp.task("html-watch", function() {
    isWatch = true;

    gulp.start("html-init");
});

/**
 * Lint html file:
 *     - Validate the html file
 */
gulp.task("html-lint", function() {
    gulp.start("htmlhint:dist");
});

/**
 * Create css file:
 *     - Create a css file from scss/stylus files
 *
 *     * Remove the original css file when using compass
 *     * Add vendor prefix with autoprefixer when using stylus
 */
gulp.task("css-init", function() {
    if(preprocessor === "compass") {
        gulp.start(
            "compass:dev",
            "clean:css"
        );
    }
    else if(preprocessor === "stylus") {
        gulp.start(
            "stylus:dev",
            "autoprefixer:dist"
        );
    }
});

/**
 * Lint css file:
 *     - Lint css file in distribution folder
 */
gulp.task("css-lint", function() {
    gulp.start("csslint:dist");
});

/**
 * Create js file:
 *     - Copy js file to distribution folder
 *     - Remove vendor folder in js folder
 */
gulp.task("js-init", function() {
    gulp.start(
        "copy:js",
        "clean:js"
    );
});

/**
 * Lint js file:
 *     - Lint js file in distribution folder
 */
gulp.task("js-lint", function() {
    gulp.start("jshint:js");
});

// ########    ###     ######  ##    ##  ######
//    ##      ## ##   ##    ## ##   ##  ##    ##
//    ##     ##   ##  ##       ##  ##   ##
//    ##    ##     ##  ######  #####     ######
//    ##    #########       ## ##  ##         ##
//    ##    ##     ## ##    ## ##   ##  ##    ##
//    ##    ##     ##  ######  ##    ##  ######

gulp.task("default", ["jshint:gulp", "html-watch"], function() {
    gulp.start("watch");
});

gulp.task("clear", ["clean:all"], function() {
    return gulp.start("bowerInstall:dev");
});

gulp.task("reset", ["jshint:gulp", "clear"], function() {
    gulp.start(
        "copy:vendor",

        // css-init
        preprocessor +":dev",
        preprocessor === "compass" ? "clean:css" : "autoprefixer:dist",

        // css-lint
        "csslint:dist",

        // js-init
        "copy:js",
        "clean:js",

        // js-lint
        "jshint:js",

        // html-init
        "slim:dev",
        "rename:partial",
        "concat:main",
        "htmlmin:dev", "clean:partial",

        // html-lint
        "htmlhint:dist"
    );
});
<commit_msg>Fix: watch task with timeout for empty files<commit_after>/*
 * hello-project
 *
 * https://github.com/jostw/hello-project
 *
 * Copyright (c) 2014 jos
 * Licensed under the MIT license.
 */

"use strict";

var gulp =    require("gulp"),

    fs =      require("fs"),
    wiredep = require("wiredep").stream,
    yargs =   require("yargs"),

    plugins = require("gulp-load-plugins")(),

    app =     require("./project.json").app,

    /**
     * Usage: gulp [task] [--pre=stylus]
     *     - Use compass as default preprocessor
     */
    preprocessor = yargs.argv.pre || app.preprocessor,

    isWatch = false;

app.folder.vendor = JSON.parse(fs.readFileSync(app.config.bower, "utf8")).directory;

app.regex = {
    html5shiv: new RegExp(app.regex.html5shiv),
    respond: new RegExp(app.regex.respond)
};

// ##      ##    ###    ########  ######  ##     ##
// ##  ##  ##   ## ##      ##    ##    ## ##     ##
// ##  ##  ##  ##   ##     ##    ##       ##     ##
// ##  ##  ## ##     ##    ##    ##       #########
// ##  ##  ## #########    ##    ##       ##     ##
// ##  ##  ## ##     ##    ##    ##    ## ##     ##
//  ###  ###  ##     ##    ##     ######  ##     ##

gulp.task("watch", ["slim:dev", "rename:partial", "concat:main", "htmlmin:dev", "clean:partial"], function() {
    var livereload = plugins.livereload();

    gulp.watch(app.folder.scss +"/**/*.scss", function() {
        setTimeout(function() {
            gulp.start(
                // css-init
                "compass:dev",
                "clean:css",

                // css-lint
                "csslint:dist"
            );
        }, 500);
    });

    gulp.watch(app.folder.stylus +"/**/*.styl", function() {
        setTimeout(function() {
            gulp.start(
                // css-init
                "stylus:dev",
                "autoprefixer:dist",

                // css-lint
                "csslint:dist"
            );
        }, 500);
    });

    gulp.watch(app.folder.js +"/**/*.js", function() {
        setTimeout(function() {
            gulp.start(
                // js-init
                "copy:js",
                "clean:js",

                // js-lint
                "jshint:js"
            );
        }, 500);
    });

    gulp.watch(["*.slim", app.folder.template +"/*.slim"], function() {
        setTimeout(function() {
            gulp.start(
                // html-init
                "slim:dev",
                "rename:partial",
                "concat:main",
                "htmlmin:dev", "clean:partial",

                // html-lint
                "htmlhint:dist"
            );
        }, 500);
    });

    gulp.watch([app.folder.dist +"/**"]).on("change", function(file) {
        livereload.changed(file.path);
    });
});

// ########  ######## ##    ##    ###    ##     ## ########
// ##     ## ##       ###   ##   ## ##   ###   ### ##
// ##     ## ##       ####  ##  ##   ##  #### #### ##
// ########  ######   ## ## ## ##     ## ## ### ## ######
// ##   ##   ##       ##  #### ######### ##     ## ##
// ##    ##  ##       ##   ### ##     ## ##     ## ##
// ##     ## ######## ##    ## ##     ## ##     ## ########

gulp.task("rename:partial", ["slim:dev"], function() {
    return gulp.src(app.folder.partial +"/*.html")
               .pipe(plugins.rename(function(path) {
                   path.basename = path.basename.match(/_(.+).html/)[1];
               }))
               .pipe(gulp.dest(app.folder.partial));
});

//  ######   #######  ##    ##  ######     ###    ########
// ##    ## ##     ## ###   ## ##    ##   ## ##      ##
// ##       ##     ## ####  ## ##        ##   ##     ##
// ##       ##     ## ## ## ## ##       ##     ##    ##
// ##       ##     ## ##  #### ##       #########    ##
// ##    ## ##     ## ##   ### ##    ## ##     ##    ##
//  ######   #######  ##    ##  ######  ##     ##    ##

gulp.task("concat:main", ["rename:partial"], function() {
    var count = 0,
        src = [
            app.folder.partial +"/"+ app.file.head,
            app.folder.partial +"/"+ app.file.style,

            app.folder.partial +"/"+ app.file.main,

            app.folder.partial +"/"+ app.file.foot,
            app.folder.partial +"/"+ app.file.script
        ];

    if(isWatch) {
        src.push(app.folder.partial +"/"+ app.file.livereload);
    }

    return gulp.src(src)
               .pipe(plugins.concatUtil(app.file.index, {
                   process: function(src) {
                       if(count === 2) {
                           src = "\n\n"+ src;
                       }

                       count++;

                       return src;
                   }
               }))
               .pipe(plugins.concatUtil.header("<!DOCTYPE html>\n\n\n"))
               .pipe(plugins.concatUtil.footer("\n\n"))
               .pipe(gulp.dest(app.folder.dist));
});

//  ######   #######  ########  ##    ##
// ##    ## ##     ## ##     ##  ##  ##
// ##       ##     ## ##     ##   ####
// ##       ##     ## ########     ##
// ##       ##     ## ##           ##
// ##    ## ##     ## ##           ##
//  ######   #######  ##           ##

gulp.task("copy:vendor", function() {
    gulp.src([
            app.folder.vendor +"/**/*.css",
            app.folder.vendor +"/**/*.js"
        ])
        .pipe(gulp.dest(app.folder.dist +"/"+ app.folder.vendor));

    return gulp.src([
                   app.folder.vendor +"/"+ app.vendor.html5shiv.path +"/"+ app.vendor.html5shiv.file,
                   app.folder.vendor +"/"+ app.vendor.respond.path +"/"+ app.vendor.respond.file
               ])
               .pipe(gulp.dest(app.folder.js +"/"+ app.folder.vendor));
});

gulp.task("copy:js", ["copy:vendor"], function() {
    return gulp.src(app.folder.js +"/**/*.js")
               .pipe(gulp.dest(app.folder.dist +"/"+ app.folder.js));
});

//  ######  ##       ########    ###    ##    ##
// ##    ## ##       ##         ## ##   ###   ##
// ##       ##       ##        ##   ##  ####  ##
// ##       ##       ######   ##     ## ## ## ##
// ##       ##       ##       ######### ##  ####
// ##    ## ##       ##       ##     ## ##   ###
//  ######  ######## ######## ##     ## ##    ##

gulp.task("clean:all", function() {
    return gulp.src([
                   app.folder.css,
                   app.folder.js +"/"+ app.folder.vendor,
                   app.folder.partial,
                   app.folder.temp,
                   app.folder.dist
               ])
               .pipe(plugins.clean(app.config.clean));
});

gulp.task("clean:css", [preprocessor +":dev"], function() {
    return gulp.src(app.folder.css)
               .pipe(plugins.clean(app.config.clean));
});

gulp.task("clean:js", ["copy:js"], function() {
    gulp.src(app.folder.js +"/"+ app.folder.vendor)
        .pipe(plugins.clean(app.config.clean));
});

gulp.task("clean:partial", ["concat:main"], function() {
    gulp.src(app.folder.partial)
        .pipe(plugins.clean(app.config.clean));
});

// ##     ## ######## ##     ## ##
// ##     ##    ##    ###   ### ##
// ##     ##    ##    #### #### ##
// #########    ##    ## ### ## ##
// ##     ##    ##    ##     ## ##
// ##     ##    ##    ##     ## ##
// ##     ##    ##    ##     ## ########

gulp.task("bowerInstall:dev", function() {
    return gulp.src([
                   app.template.style,
                   app.template.script
               ])
               .pipe(wiredep({
                   directory: app.folder.vendor,
                   exclude: [
                       app.regex.html5shiv,
                       app.regex.respond
                   ]
               }))
               .pipe(gulp.dest("."));
});

gulp.task("slim:dev", function() {
    return gulp.src([
                   app.template.style,
                   app.template.script,

                   app.folder.template +"/"+ app.template.head,
                   app.folder.template +"/"+ app.template.main,
                   app.folder.template +"/"+ app.template.foot,

                   app.folder.template +"/"+ app.template.livereload
               ])
               .pipe(plugins.slim(app.config.slim))
               .pipe(gulp.dest(app.folder.partial));
});

gulp.task("htmlmin:dev", ["concat:main"], function() {
    return gulp.src(app.folder.dist +"/"+ app.file.index)
               .pipe(plugins.htmlmin())
               .pipe(gulp.dest(app.folder.dist));
});

gulp.task("htmlhint:dist", ["htmlmin:dev"], function() {
    gulp.src(app.folder.dist +"/"+ app.file.index)
        .pipe(plugins.htmlhint({ htmlhintrc: app.config.htmlhint }))
        .pipe(plugins.htmlhint.reporter());
});

//  ######   ######   ######
// ##    ## ##    ## ##    ##
// ##       ##       ##
// ##        ######   ######
// ##             ##       ##
// ##    ## ##    ## ##    ##
//  ######   ######   ######

gulp.task("compass:dev", function() {
    return gulp.src(app.folder.scss +"/**/*.scss")
               .pipe(plugins.compass({
                   config_file: app.config.compass,
                   css: app.folder.css,
                   sass: app.folder.scss
               }))
               .pipe(gulp.dest(app.folder.dist +"/"+ app.folder.css));
});

gulp.task("stylus:dev", function() {
    return gulp.src(app.folder.stylus +"/**/*.styl")
               .pipe(plugins.stylus(app.config.stylus))
               .pipe(gulp.dest(app.folder.dist +"/"+ app.folder.css));
});

gulp.task("autoprefixer:dist", ["stylus:dev"], function() {
    return gulp.src(app.folder.dist +"/"+ app.folder.css +"/**/*.css")
               .pipe(plugins.autoprefixer())
               .pipe(gulp.dest(app.folder.dist +"/"+ app.folder.css));
});

gulp.task("csslint:dist", preprocessor === "compass" ? [preprocessor +":dev"] : ["stylus:dev", "autoprefixer:dist"], function() {
    gulp.src(app.folder.dist +"/"+ app.folder.css +"/"+ app.file.css)
        .pipe(plugins.csslint(app.config.csslint))
        .pipe(plugins.csslint.reporter());
});

//       ##  ######
//       ## ##    ##
//       ## ##
//       ##  ######
// ##    ##       ##
// ##    ## ##    ##
//  ######   ######

gulp.task("jshint:gulp", function() {
    return gulp.src(app.file.gulp)
               .pipe(plugins.jshint(app.config.jshint))
               .pipe(plugins.jshint.reporter("jshint-stylish"));
});

gulp.task("jshint:js", ["copy:js"], function() {
    gulp.src(app.folder.dist +"/"+ app.folder.js +"/"+ app.file.js)
        .pipe(plugins.jshint(app.config.jshint))
        .pipe(plugins.jshint.reporter("jshint-stylish"));
});

//  ######  ##     ## ########  ########    ###     ######  ##    ##  ######
// ##    ## ##     ## ##     ##    ##      ## ##   ##    ## ##   ##  ##    ##
// ##       ##     ## ##     ##    ##     ##   ##  ##       ##  ##   ##
//  ######  ##     ## ########     ##    ##     ##  ######  #####     ######
//       ## ##     ## ##     ##    ##    #########       ## ##  ##         ##
// ##    ## ##     ## ##     ##    ##    ##     ## ##    ## ##   ##  ##    ##
//  ######   #######  ########     ##    ##     ##  ######  ##    ##  ######

/**
 * Create html file:
 *     - Create partial html files from slim templates
 *     - Rename partial html files
 *     - Concat partial html files into a single html file
 *     - Remove redudant code in the html file
 *     - Remove partial html files
 */
gulp.task("html-init", function() {
    gulp.start(
        "slim:dev",
        "rename:partial",
        "concat:main",
        "htmlmin:dev", "clean:partial"
    );
});

/**
 * Lint html file:
 *     - Validate the html file
 */
gulp.task("html-lint", function() {
    gulp.start("htmlhint:dist");
});

/**
 * Create css file:
 *     - Create a css file from scss/stylus files
 *
 *     * Remove the original css file when using compass
 *     * Add vendor prefix with autoprefixer when using stylus
 */
gulp.task("css-init", function() {
    if(preprocessor === "compass") {
        gulp.start(
            "compass:dev",
            "clean:css"
        );
    }
    else if(preprocessor === "stylus") {
        gulp.start(
            "stylus:dev",
            "autoprefixer:dist"
        );
    }
});

/**
 * Lint css file:
 *     - Lint css file in distribution folder
 */
gulp.task("css-lint", function() {
    gulp.start("csslint:dist");
});

/**
 * Create js file:
 *     - Copy js file to distribution folder
 *     - Remove vendor folder in js folder
 */
gulp.task("js-init", function() {
    gulp.start(
        "copy:js",
        "clean:js"
    );
});

/**
 * Lint js file:
 *     - Lint js file in distribution folder
 */
gulp.task("js-lint", function() {
    gulp.start("jshint:js");
});

// ########    ###     ######  ##    ##  ######
//    ##      ## ##   ##    ## ##   ##  ##    ##
//    ##     ##   ##  ##       ##  ##   ##
//    ##    ##     ##  ######  #####     ######
//    ##    #########       ## ##  ##         ##
//    ##    ##     ## ##    ## ##   ##  ##    ##
//    ##    ##     ##  ######  ##    ##  ######

/**
 * Default task:
 *     - Lint Gruntfile.js
 *     - html-init task
 *     - Watch files
 *
 *     * Add livereload.js to html
 */
gulp.task("default", ["jshint:gulp"], function() {
    isWatch = true;

    gulp.start(
        // html-init
        "slim:dev",
        "rename:partial",
        "concat:main",
        "htmlmin:dev", "clean:partial",

        "watch"
    );
});

/**
 * Clear task:
 *     - Remove all generated files
 *     - Insert bower files into slim templates
 */
gulp.task("clear", ["clean:all"], function() {
    return gulp.start("bowerInstall:dev");
});

/**
 * Reset task:
 *     - Lint Gruntfile.js
 *     - Clear task
 *
 *     - Copy vendor files to distribution folder
 *
 *     - Create css file
 *     - Create js file
 *     - Creat html file
 *
 *     - Lint css file
 *     - Lint js file
 *     - Lint html file
 */
gulp.task("reset", ["jshint:gulp", "clear"], function() {
    gulp.start(
        "copy:vendor",

        // css-init
        preprocessor +":dev",
        preprocessor === "compass" ? "clean:css" : "autoprefixer:dist",

        // css-lint
        "csslint:dist",

        // js-init
        "copy:js",
        "clean:js",

        // js-lint
        "jshint:js",

        // html-init
        "slim:dev",
        "rename:partial",
        "concat:main",
        "htmlmin:dev", "clean:partial",

        // html-lint
        "htmlhint:dist"
    );
});
<|endoftext|>


<commit_before>'use strict';

(function() {

    // Time constants used across the script
    var SECONDS_IN_YEAR = 31536000;
    var SECONDS_IN_DAY = 86400;
    var SECONDS_IN_HOUR = 3600;
    var SECONDS_IN_MINUTE = 60;
    var SECONDS_IN_MILLISECOND = 0.001;
    var MILLISECONDS_IN_SECOND = 1000;
    var ONE_SECOND = 1;

    var TimeSpan = (function TimeSpan() {
        function TimeSpan(seconds) {
            this.val = seconds;
        }

        //Converters
        TimeSpan.prototype.ms = TimeSpan.prototype.milliseconds = function ms() {
            return this.val * MILLISECONDS_IN_SECOND;
        };

        TimeSpan.prototype.seconds = TimeSpan.prototype.second = function seconds() {
            return this.val;
        };

        TimeSpan.prototype.minutes = TimeSpan.prototype.minute = function minutes() {
            return this.val / SECONDS_IN_MINUTE;
        };

        TimeSpan.prototype.hours = TimeSpan.prototype.hour = function hours() {
            return this.val / SECONDS_IN_HOUR;
        };

        TimeSpan.prototype.days = TimeSpan.prototype.day = function days() {
            return this.val / SECONDS_IN_DAY;
        };

        TimeSpan.prototype.years = TimeSpan.prototype.year = function years() {
            return this.val / SECONDS_IN_YEAR;
        };

        //Appenders
        TimeSpan.prototype.addSeconds = function(seconds) {
            this.val += seconds;
            return this;
        };

        TimeSpan.prototype.addMinutes = function(minutes) {
            this.val += minutes * SECONDS_IN_MINUTE;
            return this;
        };

        TimeSpan.prototype.addHours = function(hours) {
            this.val += hours * SECONDS_IN_HOUR;
            return this;
        };

        TimeSpan.prototype.addDays = function(days) {
            this.val += days * SECONDS_IN_DAY;
            return this;
        };

        TimeSpan.prototype.addYears = function(years) {
            this.val += years * SECONDS_IN_YEAR;
            return this;
        };

        TimeSpan.prototype.addMilliseconds = function(milliseconds) {
            this.val += milliseconds * SECONDS_IN_MILLISECOND;
            return this;
        };

        //Formaters
        TimeSpan.prototype.humanize = function humanize() {
            var val = this.val;

            var transforms = [
                ['Years', SECONDS_IN_YEAR],
                ['Days', SECONDS_IN_DAY],
                ['Hours', SECONDS_IN_HOUR],
                ['Minutes', SECONDS_IN_MINUTE],
                ['Seconds', ONE_SECOND],
                ['Milliseconds', SECONDS_IN_MILLISECOND]
            ];

            /**
             * Function to compute modulo value
             * JS doesn't have a modulo operator built into the language
             * Code taken from this StackOverflow post:
             * http://stackoverflow.com/questions/3966484/floating-point-numbers-and-javascript-modulus-operator
             */
            function floatSafeRemainder(val, step) {
                var valDecCount = (val.toString().split('.')[1] || '').length;
                var stepDecCount = (step.toString().split('.')[1] || '').length;
                var decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;
                var valInt = parseInt(val.toFixed(decCount).replace('.', ''));
                var stepInt = parseInt(step.toFixed(decCount).replace('.', ''));

                return (valInt % stepInt) / Math.pow(10, decCount);
            }

            var results = [];
            transforms.forEach(function(t) {
                if (typeof t[2] !== 'undefined' && t[2] === true) {
                    return;
                }
                var div = Math.floor(val / t[1]);
                if (div > 0) {
                    results.push(div + ' ' + t[0]);
                }
                val = floatSafeRemainder(val, t[1]);
            });

            return results.join(', ');
        };

        TimeSpan.prototype.toString = function toString() {
            return this.humanize(false);
        };

        return TimeSpan;
    }());

    var toTime = (function() {
        function toTime(text) {
            var units = {};
            units.y = units.year = units.years = SECONDS_IN_YEAR;
            units.d = units.day = units.days = SECONDS_IN_DAY;
            units.h = units.hour = units.hours = SECONDS_IN_HOUR;
            units.m = units.minute = units.minutes = SECONDS_IN_MINUTE;
            units.s = units.second = units.seconds = ONE_SECOND;
            units.ms = units.millisecond = units.milliseconds = SECONDS_IN_MILLISECOND;

            var matchPattern = /^[\d]+[\w]+$/;

            var splitted = text.toLowerCase()
                //Replace double whitespaces with single whitespace
                .replace(/\s+/gi, ' ')
                //Remove all commas
                .replace(/[,]/g, '')
                //Used for supporting strings such as '30 Years, 2 Hours'
                .replace(/([\d])\s([\w])/gi, '$1$2')
                //Split array to number-type combinations
                .split(' ');

            var errors = splitted.some(function(v) {
                return v.match(matchPattern) === null;
            });

            if (errors) {
                throw new Error('Invalid format');
            }

            var seconds = splitted
                .filter(function(v) {
                    return v.match(matchPattern);
                })
                .map(function(v) {
                    var numeric = v.match(/[\d]+/)[0];
                    return [parseInt(v.substr(0, numeric.length)), v.substr(numeric.length).toLowerCase()];
                })
                .map(function(v) {
                    return v[0] * units[v[1]];
                })
                .reduce(function(prev, curr) {
                    return prev + curr;
                }, 0);

            if (isNaN(seconds)) {
                throw new Error('Invalid format');
            }

            return new TimeSpan(seconds);
        }

        //Constructors
        toTime.fromMilliseconds = function(milliseconds) {
            return new TimeSpan(milliseconds * SECONDS_IN_MILLISECOND);
        };

        toTime.fromSeconds = function(seconds) {
            return new TimeSpan(seconds);
        };

        toTime.fromMinutes = function(minutes) {
            return new TimeSpan(minutes * SECONDS_IN_MINUTE);
        };

        toTime.fromHours = function(hours) {
            return new TimeSpan(hours * SECONDS_IN_HOUR);
        };

        toTime.fromDays = function(days) {
            return new TimeSpan(days * SECONDS_IN_DAY);
        };

        toTime.fromYears = function(years) {
            return new TimeSpan(years * SECONDS_IN_YEAR);
        };

        return toTime;
    }());

    // Code below was taken from underscore sourcecode
    // Establish the root object, `window` (`self`) in the browser, `global`
    // on the server, or `this` in some virtual machines. We use `self`
    // instead of `window` for `WebWorker` support.
    var root = typeof self == 'object' && self.self === self && self ||
        typeof global == 'object' && global.global === global && global ||
        this;

    // Export the library for NodeJS, with backward compatability
    // Export code was taken from Underscore sourcecode
    if (typeof exports != 'undefined' && !exports.nodeType) {
        if (typeof module != 'undefined' && !module.nodeType && module.exports) {
            exports = module.exports = toTime;
        }
        exports._ = toTime;
    } else {
        root._ = toTime;
    }

}());<commit_msg>feat: added support for weeks, removed toString method<commit_after>'use strict';

(function() {

    // Time constants used across the script
    var SECONDS_IN_YEAR = 31536000;
    var SECONDS_IN_WEEK = 604800;
    var SECONDS_IN_DAY = 86400;
    var SECONDS_IN_HOUR = 3600;
    var SECONDS_IN_MINUTE = 60;
    var SECONDS_IN_MILLISECOND = 0.001;
    var MILLISECONDS_IN_SECOND = 1000;
    var ONE_SECOND = 1;

    var TimeSpan = (function TimeSpan() {
        function TimeSpan(seconds) {
            this.val = seconds;
        }

        //Converters
        TimeSpan.prototype.ms = TimeSpan.prototype.milliseconds = function ms() {
            return this.val * MILLISECONDS_IN_SECOND;
        };

        TimeSpan.prototype.seconds = TimeSpan.prototype.second = function seconds() {
            return this.val;
        };

        TimeSpan.prototype.minutes = TimeSpan.prototype.minute = function minutes() {
            return this.val / SECONDS_IN_MINUTE;
        };

        TimeSpan.prototype.hours = TimeSpan.prototype.hour = function hours() {
            return this.val / SECONDS_IN_HOUR;
        };

        TimeSpan.prototype.days = TimeSpan.prototype.day = function days() {
            return this.val / SECONDS_IN_DAY;
        };

        TimeSpan.prototype.weeks = TimeSpan.prototype.day = function weeks() {
            return this.val / SECONDS_IN_WEEK;
        };

        TimeSpan.prototype.years = TimeSpan.prototype.year = function years() {
            return this.val / SECONDS_IN_YEAR;
        };

        //Appenders
        TimeSpan.prototype.addSeconds = function(seconds) {
            this.val += seconds;
            return this;
        };

        TimeSpan.prototype.addMinutes = function(minutes) {
            this.val += minutes * SECONDS_IN_MINUTE;
            return this;
        };

        TimeSpan.prototype.addHours = function(hours) {
            this.val += hours * SECONDS_IN_HOUR;
            return this;
        };

        TimeSpan.prototype.addDays = function(days) {
            this.val += days * SECONDS_IN_DAY;
            return this;
        };

        TimeSpan.prototype.addWeeks = function(weeks) {
            this.val += weeks * SECONDS_IN_WEEK;
            return this;
        };

        TimeSpan.prototype.addYears = function(years) {
            this.val += years * SECONDS_IN_YEAR;
            return this;
        };

        TimeSpan.prototype.addMilliseconds = function(milliseconds) {
            this.val += milliseconds * SECONDS_IN_MILLISECOND;
            return this;
        };

        //Formaters
        TimeSpan.prototype.humanize = function humanize() {
            var val = this.val;

            var transforms = [
                ['Years', SECONDS_IN_YEAR],
                ['Days', SECONDS_IN_DAY],
                ['Hours', SECONDS_IN_HOUR],
                ['Minutes', SECONDS_IN_MINUTE],
                ['Seconds', ONE_SECOND],
                ['Milliseconds', SECONDS_IN_MILLISECOND]
            ];

            /**
             * Function to compute modulo value
             * JS doesn't have a modulo operator built into the language
             * Code taken from this StackOverflow post:
             * http://stackoverflow.com/questions/3966484/floating-point-numbers-and-javascript-modulus-operator
             */
            function floatSafeRemainder(val, step) {
                var valDecCount = (val.toString().split('.')[1] || '').length;
                var stepDecCount = (step.toString().split('.')[1] || '').length;
                var decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;
                var valInt = parseInt(val.toFixed(decCount).replace('.', ''));
                var stepInt = parseInt(step.toFixed(decCount).replace('.', ''));

                return (valInt % stepInt) / Math.pow(10, decCount);
            }

            var results = [];
            transforms.forEach(function(t) {
                var div = Math.floor(val / t[1]);
                if (div > 0) {
                    results.push(div + ' ' + t[0]);
                }
                val = floatSafeRemainder(val, t[1]);
            });

            return results.join(', ');
        };

        return TimeSpan;
    }());

    var toTime = (function() {
        function toTime(text) {
            var units = {};
            units.y = units.year = units.years = SECONDS_IN_YEAR;
            units.w = units.week = units.weeks = SECONDS_IN_WEEK;
            units.d = units.day = units.days = SECONDS_IN_DAY;
            units.h = units.hour = units.hours = SECONDS_IN_HOUR;
            units.m = units.minute = units.minutes = SECONDS_IN_MINUTE;
            units.s = units.second = units.seconds = ONE_SECOND;
            units.ms = units.millisecond = units.milliseconds = SECONDS_IN_MILLISECOND;

            var matchPattern = /^[\d]+[\w]+$/;

            var splitted = text.toLowerCase()
                //Replace double whitespaces with single whitespace
                .replace(/\s+/gi, ' ')
                //Remove all commas
                .replace(/[,]/g, '')
                //Used for supporting strings such as '30 Years, 2 Hours'
                .replace(/([\d])\s([\w])/gi, '$1$2')
                //Split array to number-type combinations
                .split(' ');

            var errors = splitted.some(function(v) {
                return v.match(matchPattern) === null;
            });

            if (errors) {
                throw new Error('Invalid format');
            }

            var seconds = splitted
                .filter(function(v) {
                    return v.match(matchPattern);
                })
                .map(function(v) {
                    var numeric = v.match(/[\d]+/)[0];
                    return [parseInt(v.substr(0, numeric.length)), v.substr(numeric.length).toLowerCase()];
                })
                .map(function(v) {
                    return v[0] * units[v[1]];
                })
                .reduce(function(prev, curr) {
                    return prev + curr;
                }, 0);

            if (isNaN(seconds)) {
                throw new Error('Invalid format');
            }

            return new TimeSpan(seconds);
        }

        //Constructors
        toTime.fromMilliseconds = function(milliseconds) {
            return new TimeSpan(milliseconds * SECONDS_IN_MILLISECOND);
        };

        toTime.fromSeconds = function(seconds) {
            return new TimeSpan(seconds);
        };

        toTime.fromMinutes = function(minutes) {
            return new TimeSpan(minutes * SECONDS_IN_MINUTE);
        };

        toTime.fromHours = function(hours) {
            return new TimeSpan(hours * SECONDS_IN_HOUR);
        };

        toTime.fromDays = function(days) {
            return new TimeSpan(days * SECONDS_IN_DAY);
        };

        toTime.fromWeeks = function(weeks) {
            return new TimeSpan(weeks * SECONDS_IN_WEEK);
        };

        toTime.fromYears = function(years) {
            return new TimeSpan(years * SECONDS_IN_YEAR);
        };

        return toTime;
    }());

    // Code below was taken from underscore sourcecode
    // Establish the root object, `window` (`self`) in the browser, `global`
    // on the server, or `this` in some virtual machines. We use `self`
    // instead of `window` for `WebWorker` support.
    var root = typeof self == 'object' && self.self === self && self ||
        typeof global == 'object' && global.global === global && global ||
        this;

    // Export the library for NodeJS, with backward compatability
    // Export code was taken from Underscore sourcecode
    if (typeof exports != 'undefined' && !exports.nodeType) {
        if (typeof module != 'undefined' && !module.nodeType && module.exports) {
            exports = module.exports = toTime;
        }
        exports._ = toTime;
    } else {
        root._ = toTime;
    }

}());<|endoftext|>


<commit_before>'use strict';

const B = require('bluebird');

const Reminisce = class Reminisce {
  constructor(setup) {
    setup = Object.assign({
      memories: [],
      options: { ttl: 60000, interval: 30000 }
    }, setup);

    this.options = setup.options;

    setup.memories = Array.isArray(setup.memories) ? setup.memories : [ setup.memories ];
    this.memories = setup.memories.reduce((memories, memory) => {
      memories[memory.key] = {
        val: memory.val,
        ttl: memory.ttl || this.options.ttl,
        expires: new Date().getTime() + memory.ttl
      };

      return memories;
    }, {});
  }

  get(keys) {
    keys = Array.isArray(keys) ? keys : [ keys ];

    return B.map(keys, (key) => {
      if (!this.memories[key]) {
        return B.resolve(undefined);
      }

      return B.resolve(Object.assign({ key }, this.memories[key]));
    });
  }

  set(memories) {
    memories = Array.isArray(memories) ? memories : [ memories ];

    return B.map(memories, (memory) => {
      this.memories[memory.key] = {
        val: memory.val,
        ttl: memory.ttl || this.options.ttl,
        expires: new Date().getTime() + memory.ttl
      };

      return B.resolve(Object.assign({ key: memory.key }, this.memories[memory.key]));
    });
  }

  delete(keys) {
    keys = Array.isArray(keys) ? keys : [ keys ];

    return B.map(keys, (key) => B.resolve(delete this.memories[key]));
  }
};

module.exports = Reminisce;
<commit_msg>Fix memory timestamps.<commit_after>'use strict';

const B = require('bluebird');

const Reminisce = class Reminisce {
  constructor(setup) {
    setup = Object.assign({
      memories: [],
      options: { ttl: 60000, interval: 30000 }
    }, setup);

    this.options = setup.options;

    setup.memories = Array.isArray(setup.memories) ? setup.memories : [ setup.memories ];
    this.memories = setup.memories.reduce((memories, memory) => {
      const ttl = memory.ttl || this.options.ttl;

      memories[memory.key] = {
        val: memory.val,
        ttl,
        expires: new Date().getTime() + ttl
      };

      return memories;
    }, {});
  }

  get(keys) {
    keys = Array.isArray(keys) ? keys : [ keys ];

    return B.map(keys, (key) => {
      if (!this.memories[key]) {
        return B.resolve(undefined);
      }

      return B.resolve(Object.assign({ key }, this.memories[key]));
    });
  }

  set(memories) {
    memories = Array.isArray(memories) ? memories : [ memories ];

    return B.map(memories, (memory) => {
      const ttl = memory.ttl || this.options.ttl;

      this.memories[memory.key] = {
        val: memory.val,
        ttl,
        expires: new Date().getTime() + ttl
      };

      return B.resolve(Object.assign({ key: memory.key }, this.memories[memory.key]));
    });
  }

  delete(keys) {
    keys = Array.isArray(keys) ? keys : [ keys ];

    return B.map(keys, (key) => B.resolve(delete this.memories[key]));
  }
};

module.exports = Reminisce;
<|endoftext|>