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

'use strict';

var errors = require('./errors.js');

var TOMBSTONE_TTL_OFFSET = 500;

module.exports = Operations;

function Operations(opts) {
    var self = this;

    self.timers = opts.timers;
    self.logger = opts.logger;
    self.random = opts.random;
    self.connectionStalePeriod = opts.connectionStalePeriod;

    self.connection = opts.connection;
    self.destroyed = false; // TODO need this?

    self.requests = {
        in: Object.create(null),
        out: Object.create(null)
    };
    self.pending = {
        in: 0,
        out: 0
    };
    self.lastTimeoutTime = 0;
}

function OperationTombstone(operations, id, time, req) {
    var self = this;

    self.type = 'tchannel.operation.tombstone';
    self.isTombstone = true;
    self.logger = operations.logger;
    self.operations = operations;
    self.id = id;
    self.time = time;
    self.timeout = TOMBSTONE_TTL_OFFSET + req.timeout;
    self.timeHeapHandle = null;
    self.destroyed = false;
    self.serviceName = req.serviceName;
    self.callerName = req.headers.cn;
    self.endpoint = req.endpoint;
}

OperationTombstone.prototype.extendLogInfo = function extendLogInfo(info) {
    var self = this;

    var conn = self.operations && self.operations.connection;

    info.id = self.id;
    info.serviceName = self.serviceName;
    info.callerName = self.callerName;
    info.endpoint = self.endpoint;
    info.tombstoneTime = self.time;
    info.tombstoneTTL = self.timeout;
    info.heapCanceled = self.timeHeapHandle && !self.timeHeapHandle.item;
    info.heapExpireTime = self.timeHeapHandle && self.timeHeapHandle.expireTime;
    info.heapAmItem = self.timeHeapHandle && self.timeHeapHandle.item === self;
    info.hostPort = conn && conn.channel.hostPort;
    info.socketRemoteAddr = conn && conn.socketRemoteAddr;
    info.remoteName = conn && conn.remoteName;
    info.connClosing = conn && conn.closing;

    var other = self.operations && self.operations.requests.out[self.id];
    if (self !== other) {
        info.otherType = typeof other;
        info.otherConstructorName = other && other.constructor && other.constructor.name;
    }

    return info;
};

OperationTombstone.prototype.destroy = function destroy(now) {
    var self = this;

    self.destroyed = true;

    self.onTimeout(now);
};

OperationTombstone.prototype.onTimeout = function onTimeout(now) {
    var self = this;

    if (!self.destroyed && now < self.timeout + self.time) {
        self.logger.error('tombstone timed out too early', self.extendLogInfo({
            now: now,
            expireTime: self.timeout + self.time,
            delta: (self.timeout + self.time) - now
        }));
    }

    if (self.operations &&
        self.operations.requests.out[self.id] === self) {
        delete self.operations.requests.out[self.id];
        self.operations = null;
    } else {
        self.logger.warn('mismatched expired operation tombstone', self.extendLogInfo({}));
        self.operations = null;
    }

    self.timeHeapHandle = null;
};

Operations.prototype.checkLastTimeoutTime = function checkLastTimeoutTime(now) {
    var self = this;

    if (self.lastTimeoutTime &&
        now > self.lastTimeoutTime + self.connectionStalePeriod
    ) {
        self._deferResetDueToTimeouts(now);
    } else if (!self.lastTimeoutTime) {
        self.lastTimeoutTime = now;
    }
};

Operations.prototype._deferResetDueToTimeouts = function _deferResetDueToTimeouts(now) {
    var self = this;

    var elapsed = now - self.lastTimeoutTime;
    var err = errors.ConnectionStaleTimeoutError({
        period: self.connectionStalePeriod,
        elapsed: elapsed,
        lastTimeoutTime: self.lastTimeoutTime
    });
    process.nextTick(opCheckLastTimedout);

    function opCheckLastTimedout() {
        self.logger.warn('destroying socket from timeouts', self.connection.extendLogInfo({
            error: err
        }));
        self.connection.resetAll(err);
    }
};

Operations.prototype.getRequests = function getRequests() {
    var self = this;

    return self.requests;
};

Operations.prototype.getPending = function getPending() {
    var self = this;

    return self.pending;
};

Operations.prototype.getOutReq = function getOutReq(id) {
    var self = this;

    var req = self.requests.out[id] || null;
    if (req && req.isTombstone) {
        return null;
    } else {
        return req;
    }
};

Operations.prototype.getInReq = function getInReq(id) {
    var self = this;

    return self.requests.in[id];
};

Operations.prototype.addOutReq = function addOutReq(req) {
    var self = this;

    req.operations = self;
    self.requests.out[req.id] = req;
    self.pending.out++;

    req.timeHeapHandle = self.connection.channel.timeHeap.update(req);

    return req;
};

Operations.prototype.addInReq = function addInReq(req) {
    var self = this;

    req.operations = self;
    self.requests.in[req.id] = req;
    self.pending.in++;

    req.timeHeapHandle = self.connection.channel.timeHeap.update(req);

    return req;
};

Operations.prototype.popOutReq = function popOutReq(id, context) {
    var self = this;

    var req = self.requests.out[id];
    if (!req) {
        self.logMissingOutRequest(id, context);
        return null;
    } else if (req.isTombstone) {
        return null;
    }

    if (req.timeHeapHandle) {
        req.timeHeapHandle.cancel();
        req.timeHeapHandle = null;
    } else {
        self.logger.warn('Found OutRequest without timeHeapHandle', {
            serviceName: req.serviceName,
            endpoint: req.endpoint,
            socketRemoteAddr: req.remoteAddr,
            callerName: req.headers.cn
        });
    }

    var tombstone = new OperationTombstone(self, id, self.timers.now(), req);
    self.requests.out[id] = tombstone;
    tombstone.timeHeapHandle = self.connection.channel.timeHeap.update(tombstone, tombstone.time);

    req.operations = null;
    self.pending.out--;

    return req;
};

Operations.prototype.logMissingOutRequest =
function logMissingOutRequest(id, context) {
    var self = this;

    // context is err or res
    if (context && context.originalId) {
        context = {
            error: context,
            id: context.originalId,
            info: 'got error frame for unknown id'
        };
    } else if (context && context.id) {
        context = {
            responseId: context.id,
            code: context.code,
            arg1: Buffer.isBuffer(context.arg1) ?
                String(context.arg1) : 'streamed-arg1',
            info: 'got call response for unknown id'
        };
    }

    // This could be because of a confused / corrupted server.
    self.logger.info('popOutReq received for unknown or lost id', {
        context: context,
        socketRemoteAddr: self.connection.socketRemoteAddr,
        direction: self.connection.direction
    });
};

Operations.prototype.popInReq = function popInReq(id) {
    var self = this;

    var req = self.requests.in[id];
    if (!req) {
        // TODO warn ?
        return null;
    }

    if (req.timeHeapHandle) {
        req.timeHeapHandle.cancel();
        req.timeHeapHandle = null;
    }

    delete self.requests.in[id];
    self.pending.in--;

    return req;
};

Operations.prototype.clear = function clear() {
    var self = this;

    var now = self.timers.now();
    var inReqKeys = Object.keys(self.requests.in);
    var outReqKeys = Object.keys(self.requests.out);

    for (var i = 0; i < inReqKeys.length; i++) {
        self.popInReq(inReqKeys[i]);
    }
    for (var j = 0; j < outReqKeys.length; j++) {
        self.popOutReq(outReqKeys[j]);

        var tombstone = self.requests.out[outReqKeys[j]];
        if (tombstone.timeHeapHandle) {
            tombstone.timeHeapHandle.cancel();
        }
        tombstone.destroy(now);
    }
};

Operations.prototype.destroy = function destroy() {
    var self = this;

    self.destroyed = true;
};

Operations.prototype.sanitySweep = function sanitySweep() {
    var self = this;

    self._sweepOps(self.requests.in, 'in');
    self._sweepOps(self.requests.out, 'out');
};

Operations.prototype._sweepOps = function _sweepOps(ops, direction) {
    var self = this;

    var now = self.timers.now();
    var opKeys = Object.keys(ops);
    for (var i = 0; i < opKeys.length; i++) {
        var id = opKeys[i];
        var op = ops[id];
        if (op === undefined) {
            self.logger.warn('unexpected undefined operation', {
                direction: direction,
                id: id
            });
        } else if (op.timedOut) {
            self.logger.warn('lingering timed-out operation', {
                direction: direction,
                id: id
            });

            if (direction === 'in') {
                self.popInReq(id);
            } else if (direction === 'out') {
                self.popOutReq(id);
            }
        } else if (op.isTombstone) {
            var heap = self.connection.channel.timeHeap;
            var expireTime = op.time + op.timeout;

            if (!op.operations) {
                self.logger.warn('zombie tombstone', op.extendLogInfo({
                    direction: direction,
                    opKey: id
                }));
                delete ops[id];
                op.operations = null;
                op.timeHeapHandle.cancel();
                op.timeHeapHandle = null;
            } else if (expireTime < now && heap.lastRun > expireTime) {
                self.logger.warn('stale tombstone', op.extendLogInfo({
                    direction: direction,
                    opKey: id,
                    now: now,
                    staleDelta: op.time + op.timeout - now,
                    expireTime: expireTime,
                    heapLastRun: heap.lastRun
                }));
                delete ops[id];
                op.operations = null;
                op.timeHeapHandle.cancel();
                op.timeHeapHandle = null;
            }
        }
    }
};
<commit_msg>OperationTombstone#extendLogInfo: refactor branching<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var errors = require('./errors.js');

var TOMBSTONE_TTL_OFFSET = 500;

module.exports = Operations;

function Operations(opts) {
    var self = this;

    self.timers = opts.timers;
    self.logger = opts.logger;
    self.random = opts.random;
    self.connectionStalePeriod = opts.connectionStalePeriod;

    self.connection = opts.connection;
    self.destroyed = false; // TODO need this?

    self.requests = {
        in: Object.create(null),
        out: Object.create(null)
    };
    self.pending = {
        in: 0,
        out: 0
    };
    self.lastTimeoutTime = 0;
}

function OperationTombstone(operations, id, time, req) {
    var self = this;

    self.type = 'tchannel.operation.tombstone';
    self.isTombstone = true;
    self.logger = operations.logger;
    self.operations = operations;
    self.id = id;
    self.time = time;
    self.timeout = TOMBSTONE_TTL_OFFSET + req.timeout;
    self.timeHeapHandle = null;
    self.destroyed = false;
    self.serviceName = req.serviceName;
    self.callerName = req.headers.cn;
    self.endpoint = req.endpoint;
}

OperationTombstone.prototype.extendLogInfo = function extendLogInfo(info) {
    var self = this;

    info.id = self.id;
    info.serviceName = self.serviceName;
    info.callerName = self.callerName;
    info.endpoint = self.endpoint;
    info.tombstoneTime = self.time;
    info.tombstoneTTL = self.timeout;
    info.heapCanceled = self.timeHeapHandle && !self.timeHeapHandle.item;
    info.heapExpireTime = self.timeHeapHandle && self.timeHeapHandle.expireTime;
    info.heapAmItem = self.timeHeapHandle && self.timeHeapHandle.item === self;

    if (self.operations) {
        var conn = self.operations.connection;
        info.hostPort = conn && conn.channel.hostPort;
        info.socketRemoteAddr = conn && conn.socketRemoteAddr;
        info.remoteName = conn && conn.remoteName;
        info.connClosing = conn && conn.closing;

        var other = self.operations.requests.out[self.id];
        if (self !== other) {
            info.otherType = typeof other;
            info.otherConstructorName = other && other.constructor && other.constructor.name;
        }
    }

    return info;
};

OperationTombstone.prototype.destroy = function destroy(now) {
    var self = this;

    self.destroyed = true;

    self.onTimeout(now);
};

OperationTombstone.prototype.onTimeout = function onTimeout(now) {
    var self = this;

    if (!self.destroyed && now < self.timeout + self.time) {
        self.logger.error('tombstone timed out too early', self.extendLogInfo({
            now: now,
            expireTime: self.timeout + self.time,
            delta: (self.timeout + self.time) - now
        }));
    }

    if (self.operations &&
        self.operations.requests.out[self.id] === self) {
        delete self.operations.requests.out[self.id];
        self.operations = null;
    } else {
        self.logger.warn('mismatched expired operation tombstone', self.extendLogInfo({}));
        self.operations = null;
    }

    self.timeHeapHandle = null;
};

Operations.prototype.checkLastTimeoutTime = function checkLastTimeoutTime(now) {
    var self = this;

    if (self.lastTimeoutTime &&
        now > self.lastTimeoutTime + self.connectionStalePeriod
    ) {
        self._deferResetDueToTimeouts(now);
    } else if (!self.lastTimeoutTime) {
        self.lastTimeoutTime = now;
    }
};

Operations.prototype._deferResetDueToTimeouts = function _deferResetDueToTimeouts(now) {
    var self = this;

    var elapsed = now - self.lastTimeoutTime;
    var err = errors.ConnectionStaleTimeoutError({
        period: self.connectionStalePeriod,
        elapsed: elapsed,
        lastTimeoutTime: self.lastTimeoutTime
    });
    process.nextTick(opCheckLastTimedout);

    function opCheckLastTimedout() {
        self.logger.warn('destroying socket from timeouts', self.connection.extendLogInfo({
            error: err
        }));
        self.connection.resetAll(err);
    }
};

Operations.prototype.getRequests = function getRequests() {
    var self = this;

    return self.requests;
};

Operations.prototype.getPending = function getPending() {
    var self = this;

    return self.pending;
};

Operations.prototype.getOutReq = function getOutReq(id) {
    var self = this;

    var req = self.requests.out[id] || null;
    if (req && req.isTombstone) {
        return null;
    } else {
        return req;
    }
};

Operations.prototype.getInReq = function getInReq(id) {
    var self = this;

    return self.requests.in[id];
};

Operations.prototype.addOutReq = function addOutReq(req) {
    var self = this;

    req.operations = self;
    self.requests.out[req.id] = req;
    self.pending.out++;

    req.timeHeapHandle = self.connection.channel.timeHeap.update(req);

    return req;
};

Operations.prototype.addInReq = function addInReq(req) {
    var self = this;

    req.operations = self;
    self.requests.in[req.id] = req;
    self.pending.in++;

    req.timeHeapHandle = self.connection.channel.timeHeap.update(req);

    return req;
};

Operations.prototype.popOutReq = function popOutReq(id, context) {
    var self = this;

    var req = self.requests.out[id];
    if (!req) {
        self.logMissingOutRequest(id, context);
        return null;
    } else if (req.isTombstone) {
        return null;
    }

    if (req.timeHeapHandle) {
        req.timeHeapHandle.cancel();
        req.timeHeapHandle = null;
    } else {
        self.logger.warn('Found OutRequest without timeHeapHandle', {
            serviceName: req.serviceName,
            endpoint: req.endpoint,
            socketRemoteAddr: req.remoteAddr,
            callerName: req.headers.cn
        });
    }

    var tombstone = new OperationTombstone(self, id, self.timers.now(), req);
    self.requests.out[id] = tombstone;
    tombstone.timeHeapHandle = self.connection.channel.timeHeap.update(tombstone, tombstone.time);

    req.operations = null;
    self.pending.out--;

    return req;
};

Operations.prototype.logMissingOutRequest =
function logMissingOutRequest(id, context) {
    var self = this;

    // context is err or res
    if (context && context.originalId) {
        context = {
            error: context,
            id: context.originalId,
            info: 'got error frame for unknown id'
        };
    } else if (context && context.id) {
        context = {
            responseId: context.id,
            code: context.code,
            arg1: Buffer.isBuffer(context.arg1) ?
                String(context.arg1) : 'streamed-arg1',
            info: 'got call response for unknown id'
        };
    }

    // This could be because of a confused / corrupted server.
    self.logger.info('popOutReq received for unknown or lost id', {
        context: context,
        socketRemoteAddr: self.connection.socketRemoteAddr,
        direction: self.connection.direction
    });
};

Operations.prototype.popInReq = function popInReq(id) {
    var self = this;

    var req = self.requests.in[id];
    if (!req) {
        // TODO warn ?
        return null;
    }

    if (req.timeHeapHandle) {
        req.timeHeapHandle.cancel();
        req.timeHeapHandle = null;
    }

    delete self.requests.in[id];
    self.pending.in--;

    return req;
};

Operations.prototype.clear = function clear() {
    var self = this;

    var now = self.timers.now();
    var inReqKeys = Object.keys(self.requests.in);
    var outReqKeys = Object.keys(self.requests.out);

    for (var i = 0; i < inReqKeys.length; i++) {
        self.popInReq(inReqKeys[i]);
    }
    for (var j = 0; j < outReqKeys.length; j++) {
        self.popOutReq(outReqKeys[j]);

        var tombstone = self.requests.out[outReqKeys[j]];
        if (tombstone.timeHeapHandle) {
            tombstone.timeHeapHandle.cancel();
        }
        tombstone.destroy(now);
    }
};

Operations.prototype.destroy = function destroy() {
    var self = this;

    self.destroyed = true;
};

Operations.prototype.sanitySweep = function sanitySweep() {
    var self = this;

    self._sweepOps(self.requests.in, 'in');
    self._sweepOps(self.requests.out, 'out');
};

Operations.prototype._sweepOps = function _sweepOps(ops, direction) {
    var self = this;

    var now = self.timers.now();
    var opKeys = Object.keys(ops);
    for (var i = 0; i < opKeys.length; i++) {
        var id = opKeys[i];
        var op = ops[id];
        if (op === undefined) {
            self.logger.warn('unexpected undefined operation', {
                direction: direction,
                id: id
            });
        } else if (op.timedOut) {
            self.logger.warn('lingering timed-out operation', {
                direction: direction,
                id: id
            });

            if (direction === 'in') {
                self.popInReq(id);
            } else if (direction === 'out') {
                self.popOutReq(id);
            }
        } else if (op.isTombstone) {
            var heap = self.connection.channel.timeHeap;
            var expireTime = op.time + op.timeout;

            if (!op.operations) {
                self.logger.warn('zombie tombstone', op.extendLogInfo({
                    direction: direction,
                    opKey: id
                }));
                delete ops[id];
                op.operations = null;
                op.timeHeapHandle.cancel();
                op.timeHeapHandle = null;
            } else if (expireTime < now && heap.lastRun > expireTime) {
                self.logger.warn('stale tombstone', op.extendLogInfo({
                    direction: direction,
                    opKey: id,
                    now: now,
                    staleDelta: op.time + op.timeout - now,
                    expireTime: expireTime,
                    heapLastRun: heap.lastRun
                }));
                delete ops[id];
                op.operations = null;
                op.timeHeapHandle.cancel();
                op.timeHeapHandle = null;
            }
        }
    }
};
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  path = require('path'),
  errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller')),
  Project = mongoose.model('Project'),
  _ = require('lodash'),
  config = require(path.resolve('./config/config')),
  AlchemyAPI = require('alchemy-api'),
  projects = require('./projects.server.controller'),
  sanitizeHtml = require('sanitize-html'),
  Promise = require('bluebird'),
  fs = Promise.promisifyAll(require('fs')),
  exports = Promise.promisifyAll(exports);

function nlpKeywords(sanitizedText) {
  return new Promise(
    function (resolve, reject) {
      var alchemyApi = new AlchemyAPI(config.alchemyApi.alchemyKey);
      alchemyApi.keywords(sanitizedText, {'sentiment': 0, 'outputMode': 'json'},
        function (err, keywords) {
        if (keywords) {
          resolve(keywords);
        } else {
          let error = new Error('Error, error.');
          reject(error);
        }
      });
  });
}

//
// export default function getReplies(topicId) {
//  return new Promise(function (resolve, reject) {
//
//    _getRepliesForTopic(topicId,
//
//      function (data) {
//        if (data.replies) {
//          resolve(replies);
//        } else {
//          let error = new Error("An error occurred");
//          reject(error);
//
//        }
//      });
//  });
//}
//
// getReplies(1)
// .then(function (replies) {
//    return replies.filter(reply => !reply.isAbuse);
//  })
// .then(function (filteredReplies) {
//    console.log(filteredReplies);
//  })
// .catch(function (error) {
//    console.log(error)
//    ;
//  });

// **/

/**
 * Create a Project
 */
exports.create = function (req, res) {
  //console.log('!!!!project create req: \n', req);
  var project = new Project(req.body);
  project.user = req.user;

  //todo refactor into separate function and use in the update method as well
  if (req.category === 'video') {
    project.markerColor = '#ff0011';
  } else if (req.category === 'multimedia') {
    project.markerColor = '#ff0101';
  } else if (req.category === 'essay') {
    project.markerColor = '#0015ff';
  } else if (req.category === 'literature') {
    project.markerColor = '#15ff35';
  } else if (req.category === 'interview') {
    project.markerColor = '#ff0101';
  } else if (req.category === 'map') {
    project.markerColor = '#ff0101';
  } else if (req.category === 'audio') {
    project.markerColor = '#ff0101';
  } else {
    project.markerColor =  '#00ff44';
  }

  console.log('!!!!project create req: \n', project);
  console.log('!!!!project.markerColor: \n', project.markerColor);

  project.save(function (err) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.jsonp(project);
    }
  });
};

/**
 * Show the current Project
 */
exports.read = function (req, res) {
  res.jsonp(req.project);
};

/**
 * Update a Project
 */
exports.update = function (req, res) {
  console.log('\n\n\nreq.body:\n', req.body, '\n\n\n\nreq.project:\n', req.project);
  var projectKeywords = [];
  var project = req.project;
  project = _.extend(project, req.body);

  if (req.body.story) {
    var sanitizedText = sanitizeHtml(req.body.story, {
      allowedTags: [],
      allowedAttributes: []
    });

    /**
    //do nlp and return a promise
    nlpKeywords(sanitizedText)
      .then(function (keywords) {
        projectKeywords = keywords.keywords;
        project.keywords.push(projectKeywords);
        console.log('project.keywords v1:\n', project.keywords);
        //return projectKeywords;
      })
      .catch(function (error) {
        console.log('Error:\n', error)
      });
     **/

    //  /**
    var text = {
      body: {
        text: sanitizedText,
        useCase: 'server'
      }
    };
    //projects.nlpProjects(text, function(response) {
    //  project.keywords.push(response.keywords);
    //});

  }
  //console.log('project.keywords v2:\n', project.keywords);
  //console.log('projectKeywords:\n', projectKeywords);
  project.save(function (err) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.jsonp(project);
    }
  });

};

/**
 * Delete an Project
 */
exports.delete = function (req, res) {
  var project = req.project;

  project.remove(function (err) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.jsonp(project);
    }
  });
};

/**
 * List of Projects
 *
 * .find({ "invitees._id": req.query.invitation_id })
 * .populate('invitees.user')
 *
 */
exports.list = function (req, res) {
  Project.find()
    .sort('-created')
    .populate('user')
    .exec(function (err, projects) {
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else {
        res.jsonp(projects);
      }
    });
};

/**
 * List of Projects with status "published"
 *
 * .find({ "invitees._id": req.query.invitation_id })
 * .populate('invitees.user')
 *
 */
exports.listPublished = function (req, res) {
  //req.params
  Project.find({
      'status': 'published'
    })
    .sort('-created')
    .populate('user')
    .exec(function (err, projects) {
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else {
        res.jsonp(projects);
      }
    });
};

/**
 * List of Markers for Home Page Map
 */
exports.markerList = function (req, res) {
  //todo filter this response to contain just what's needed for markers
  Project.find({
      'status': 'published'
    })
    .sort('-created')
    .exec(function (err, projects) {
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else {
        res.jsonp(projects);
      }
    });
};

exports.findOneVideoId = function (req, res) {
  Project.findById(req.body._id)
    .exec(function (err, project) {
      if (err) {
        return next(err);
      }
      if (!project) {
        return next(new Error('Failed to load project ' + id + 'associated with the requested video.')
        )
      }
      res.vimeoId = project.vimeoId;
    });
};

/**
 * Project middleware
 */
exports.projectByID = function (req, res, next, id) {
  Project.findById(id)
    .populate('user')
    .exec(function (err, project) {
      if (err) return next(err);
      if (!project) return next(new Error('Failed to load Project ' + id));
      req.project = project;
      next();
    });
};

/**
 * Project middleware
 */
exports.updateFeaturedProjects = function (req, res) {
  //console.log('featuredProjects req::::::\n', req);
  Project.find({featured: true})
    .sort('-date')
    .exec(function (err, projects) {
      console.log('featuredProjects:\n', projects);
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else if (projects.length === 3) {
        let removeFeatureTag = projects.pop();
        console.log('removeFeatureTag:\n', removeFeatureTag);
        //projects.update(removeFeatureTag);
        console.log('featuredProjects afterwards:\n', projects);
      } else if (projects.length > 3) {
        //same as above but with a for loop
      }
      res.jsonp(projects);
      //req.project = project;
      //next();
    });
};

/**
 * Project authorization middleware
 */
exports.hasAuthorization = function (req, res, next) {
  if (req.project.user.id !== req.user.id) {
    return res.status(403).send('User is not authorized');
  }
  next();
};

/**
 * Returns an array of objects that contains the featured projects
 */
exports.getFeaturedProjects = function (req, res) {
  Project.find({featured: true})
    .sort('-date')
    .exec(function (err, projects) {
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else {
        if(projects.length > 3) {

        }
        res.jsonp(projects);
      }
    });
};

//var dirtyText = 'All decent people feel sorrow and righteous fury about the latest slaughter of innocents, in California. Law enforcement and intelligence agencies are searching for motivations, including the vital question of how the murderers might have been connected to international terrorism. That is right and proper. But motives do not matter to the dead in California, nor did they in Colorado, Oregon, South Carolina, Virginia, Connecticut and far too many other places. The attention and anger of Americans should also be directed at the elected leaders whose job is to keep us safe but who place a higher premium on the money and political power of an industry dedicated to profiting from the unfettered spread of ever more powerful firearms. It is a moral outrage and a national disgrace that civilians can legally purchase weapons designed specifically to kill people with brutal speed and efficiency. These are weapons of war, barely modified and deliberately marketed as tools of macho vigilantism and even insurrection. America’s elected leaders offer prayers for gun victims and then, callously and without fear of consequence, reject the most basic restrictions on weapons of mass killing, as they did on Thursday. They distract us with arguments about the word terrorism. Let’s be clear: These spree killings are all, in their own ways, acts of terrorism. Every weekday, get thought-provoking commentary from Op-Ed columnists, The Times editorial board and contributing writers from around the world. Opponents of gun control are saying, as they do after every killing, that no law can unfailingly forestall a specific criminal. That is true. They are talking, many with sincerity, about the constitutional challenges to effective gun regulation. Those challenges exist. They point out that determined killers obtained weapons illegally in places like France, England and Norway that have strict gun laws. Yes, they did. But at least those countries are trying. The United States is not. Worse, politicians abet would-be killers by creating gun markets for them, and voters allow those politicians to keep their jobs. It is past time to stop talking about halting the spread of firearms, and instead to reduce their number drastically — eliminating some large categories of weapons and ammunition. It is not necessary to debate the peculiar wording of the Second Amendment. No right is unlimited and immune from reasonable regulation. Certain kinds of weapons, like the slightly modified combat rifles used in California, and certain kinds of ammunition, must be outlawed for civilian ownership. It is possible to define those guns in a clear and effective way and, yes, it would require Americans who own those kinds of weapons to give them up for the good of their fellow citizens. What better time than during a presidential election to show, at long last, that our nation has retained its sense of decency?';

/**
 * Alchemy API for NLP
 **/

exports.nlpProjects = function (req, res, next) {
  console.log(req);
  var dirtyText = req.body.text;
  var sentKeywords = [];
  var sanitizedText = sanitizeHtml(dirtyText, {
    allowedTags: [],
    allowedAttributes: []
  });
  var alchemyApi = new AlchemyAPI(config.alchemyApi.alchemyKey);
  alchemyApi.keywords(sanitizedText, {'sentiment': 0, 'outputMode': 'json'}, function (err, keywords) {
    if (err) {
      throw err;
    //} else if (req.body.useCase === 'server') {
    //  res.json(response);
    } else {
      console.log('keywords.keywords l. 317:\n', keywords.keywords);
      sentKeywords.push(keywords.keywords);
      console.log('sentKeywords l. 319:\n', sentKeywords);
    }
  });
  console.log('sentKeywords l. 322:\n', sentKeywords);
  res.send(sentKeywords);
};

/**
 * Kraken.io Img Optimization
 */

//exports.krakenImageUpload = function(req, res) {
//	var kraken = new Kraken({
//		api_key: keys.krakenKey,
//		api_secret: keys.krakenSecret
//	});
//
//	var opts = {
//		file: '/path/to/image/file.jpg',
//		wait: true
//	};
//
//	kraken.upload(opts, function(data) {
//		if (data.success) {
//			console.log('Success. Optimized image URL: %s', data.kraked_url);
//		} else {
//			console.log('Fail. Error message: %s', data.error);
//		}
//	});
//
//};

/**
 *
 * @param req
 * @param res
 * @param next
 */

exports.markerData = function(req, res, next) {

  var markerColor = '';
  if (req.category === 'video') {
    markerColor = '#ff0011';
    res.send(markerColor);
  } else if (req.category === 'multimedia') {
    markerColor = '#ff0101';
    res.send(markerColor);
  } else if (req.category === 'essay') {
    markerColor = '#0015ff';
    res.send(markerColor);
  } else if (req.category === 'literature') {
    markerColor = '#15ff35';
    res.send(markerColor);
  } else if (req.category === 'interview') {
    markerColor = '#ff0101';
    res.send(markerColor);
  } else if (req.category === 'map') {
    markerColor = '#ff0101';
    res.send(markerColor);
  } else if (req.category === 'audio') {
    markerColor = '#ff0101';
   res.send(markerColor);
  } else {
    markerColor =  '#00ff44';
    res.send(markerColor);
  }
  next();

};
<commit_msg>updated backend for only latest 3 featured stories<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  path = require('path'),
  errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller')),
  Project = mongoose.model('Project'),
  _ = require('lodash'),
  config = require(path.resolve('./config/config')),
  AlchemyAPI = require('alchemy-api'),
  projects = require('./projects.server.controller'),
  sanitizeHtml = require('sanitize-html'),
  Promise = require('bluebird'),
  fs = Promise.promisifyAll(require('fs')),
  exports = Promise.promisifyAll(exports);

function nlpKeywords(sanitizedText) {
  return new Promise(
    function (resolve, reject) {
      var alchemyApi = new AlchemyAPI(config.alchemyApi.alchemyKey);
      alchemyApi.keywords(sanitizedText, {'sentiment': 0, 'outputMode': 'json'},
        function (err, keywords) {
        if (keywords) {
          resolve(keywords);
        } else {
          let error = new Error('Error, error.');
          reject(error);
        }
      });
  });
}

//
// export default function getReplies(topicId) {
//  return new Promise(function (resolve, reject) {
//
//    _getRepliesForTopic(topicId,
//
//      function (data) {
//        if (data.replies) {
//          resolve(replies);
//        } else {
//          let error = new Error("An error occurred");
//          reject(error);
//
//        }
//      });
//  });
//}
//
// getReplies(1)
// .then(function (replies) {
//    return replies.filter(reply => !reply.isAbuse);
//  })
// .then(function (filteredReplies) {
//    console.log(filteredReplies);
//  })
// .catch(function (error) {
//    console.log(error)
//    ;
//  });

// **/

/**
 * Create a Project
 */
exports.create = function (req, res) {
  //console.log('!!!!project create req: \n', req);
  var project = new Project(req.body);
  project.user = req.user;

  //todo refactor into separate function and use in the update method as well
  if (req.category === 'video') {
    project.markerColor = '#ff0011';
  } else if (req.category === 'multimedia') {
    project.markerColor = '#ff0101';
  } else if (req.category === 'essay') {
    project.markerColor = '#0015ff';
  } else if (req.category === 'literature') {
    project.markerColor = '#15ff35';
  } else if (req.category === 'interview') {
    project.markerColor = '#ff0101';
  } else if (req.category === 'map') {
    project.markerColor = '#ff0101';
  } else if (req.category === 'audio') {
    project.markerColor = '#ff0101';
  } else {
    project.markerColor =  '#00ff44';
  }

  console.log('!!!!project create req: \n', project);
  console.log('!!!!project.markerColor: \n', project.markerColor);

  project.save(function (err) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.jsonp(project);
    }
  });
};

/**
 * Show the current Project
 */
exports.read = function (req, res) {
  res.jsonp(req.project);
};

/**
 * Update a Project
 */
exports.update = function (req, res) {
  console.log('\n\n\nreq.body:\n', req.body, '\n\n\n\nreq.project:\n', req.project);
  var projectKeywords = [];
  var project = req.project;
  project = _.extend(project, req.body);

  if (req.body.story) {
    var sanitizedText = sanitizeHtml(req.body.story, {
      allowedTags: [],
      allowedAttributes: []
    });

    /**
    //do nlp and return a promise
    nlpKeywords(sanitizedText)
      .then(function (keywords) {
        projectKeywords = keywords.keywords;
        project.keywords.push(projectKeywords);
        console.log('project.keywords v1:\n', project.keywords);
        //return projectKeywords;
      })
      .catch(function (error) {
        console.log('Error:\n', error)
      });
     **/

    //  /**
    var text = {
      body: {
        text: sanitizedText,
        useCase: 'server'
      }
    };
    //projects.nlpProjects(text, function(response) {
    //  project.keywords.push(response.keywords);
    //});

  }
  //console.log('project.keywords v2:\n', project.keywords);
  //console.log('projectKeywords:\n', projectKeywords);
  project.save(function (err) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.jsonp(project);
    }
  });

};

/**
 * Delete an Project
 */
exports.delete = function (req, res) {
  var project = req.project;

  project.remove(function (err) {
    if (err) {
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    } else {
      res.jsonp(project);
    }
  });
};

/**
 * List of Projects
 *
 * .find({ "invitees._id": req.query.invitation_id })
 * .populate('invitees.user')
 *
 */
exports.list = function (req, res) {
  Project.find()
    .sort('-created')
    .populate('user')
    .exec(function (err, projects) {
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else {
        res.jsonp(projects);
      }
    });
};

/**
 * List of Projects with status "published"
 *
 * .find({ "invitees._id": req.query.invitation_id })
 * .populate('invitees.user')
 *
 */
exports.listPublished = function (req, res) {
  //req.params
  Project.find({
      'status': 'published'
    })
    .sort('-created')
    .populate('user')
    .exec(function (err, projects) {
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else {
        res.jsonp(projects);
      }
    });
};

/**
 * List of Markers for Home Page Map
 */
exports.markerList = function (req, res) {
  //todo filter this response to contain just what's needed for markers
  Project.find({
      'status': 'published'
    })
    .sort('-created')
    .exec(function (err, projects) {
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else {
        res.jsonp(projects);
      }
    });
};

exports.findOneVideoId = function (req, res) {
  Project.findById(req.body._id)
    .exec(function (err, project) {
      if (err) {
        return next(err);
      }
      if (!project) {
        return next(new Error('Failed to load project ' + id + 'associated with the requested video.')
        )
      }
      res.vimeoId = project.vimeoId;
    });
};

/**
 * Project middleware
 */
exports.projectByID = function (req, res, next, id) {
  Project.findById(id)
    .populate('user')
    .exec(function (err, project) {
      if (err) return next(err);
      if (!project) return next(new Error('Failed to load Project ' + id));
      req.project = project;
      next();
    });
};

/**
 * Project middleware
 */
exports.updateFeaturedProjects = function (req, res) {
  //console.log('featuredProjects req::::::\n', req);
  Project.find({featured: true})
    .sort('-date')
    .exec(function (err, projects) {
      console.log('featuredProjects:\n', projects);
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else if (projects.length === 3) {
        let removeFeatureTag = projects.pop();
        console.log('removeFeatureTag:\n', removeFeatureTag);
        //projects.update(removeFeatureTag);
        console.log('featuredProjects afterwards:\n', projects);
      } else if (projects.length > 3) {
        //same as above but with a for loop
      }
      res.jsonp(projects);
      //req.project = project;
      //next();
    });
};

/**
 * Project authorization middleware
 */
exports.hasAuthorization = function (req, res, next) {
  if (req.project.user.id !== req.user.id) {
    return res.status(403).send('User is not authorized');
  }
  next();
};

/**
 * Returns an array of objects that contains the featured projects
 */
//exports.getFeaturedProjects = function (req, res) {
//  Project.find({featured: true})
//    .sort('-date')
//    .exec(function (err, projects) {
//      if (err) {
//        return res.status(400).send({
//          message: errorHandler.getErrorMessage(err)
//        });
//      } else {
//        if(projects.length > 3) {
//
//        }
//        res.jsonp(projects);
//      }
//    });
//};

exports.getFeaturedProjects = function (req, res) {
    Project.find({featured: true})
        .sort('featuredBeginDate')
        .limit(3)
        .exec(function (err, projects) {
            if (err) {
                return res.status(400).send({
                    message: errorHandler.getErrorMessage(err)
                });
            } else {

                res.jsonp(projects);
            }
        });
};

//var dirtyText = 'All decent people feel sorrow and righteous fury about the latest slaughter of innocents, in California. Law enforcement and intelligence agencies are searching for motivations, including the vital question of how the murderers might have been connected to international terrorism. That is right and proper. But motives do not matter to the dead in California, nor did they in Colorado, Oregon, South Carolina, Virginia, Connecticut and far too many other places. The attention and anger of Americans should also be directed at the elected leaders whose job is to keep us safe but who place a higher premium on the money and political power of an industry dedicated to profiting from the unfettered spread of ever more powerful firearms. It is a moral outrage and a national disgrace that civilians can legally purchase weapons designed specifically to kill people with brutal speed and efficiency. These are weapons of war, barely modified and deliberately marketed as tools of macho vigilantism and even insurrection. America’s elected leaders offer prayers for gun victims and then, callously and without fear of consequence, reject the most basic restrictions on weapons of mass killing, as they did on Thursday. They distract us with arguments about the word terrorism. Let’s be clear: These spree killings are all, in their own ways, acts of terrorism. Every weekday, get thought-provoking commentary from Op-Ed columnists, The Times editorial board and contributing writers from around the world. Opponents of gun control are saying, as they do after every killing, that no law can unfailingly forestall a specific criminal. That is true. They are talking, many with sincerity, about the constitutional challenges to effective gun regulation. Those challenges exist. They point out that determined killers obtained weapons illegally in places like France, England and Norway that have strict gun laws. Yes, they did. But at least those countries are trying. The United States is not. Worse, politicians abet would-be killers by creating gun markets for them, and voters allow those politicians to keep their jobs. It is past time to stop talking about halting the spread of firearms, and instead to reduce their number drastically — eliminating some large categories of weapons and ammunition. It is not necessary to debate the peculiar wording of the Second Amendment. No right is unlimited and immune from reasonable regulation. Certain kinds of weapons, like the slightly modified combat rifles used in California, and certain kinds of ammunition, must be outlawed for civilian ownership. It is possible to define those guns in a clear and effective way and, yes, it would require Americans who own those kinds of weapons to give them up for the good of their fellow citizens. What better time than during a presidential election to show, at long last, that our nation has retained its sense of decency?';

/**
 * Alchemy API for NLP
 **/

exports.nlpProjects = function (req, res, next) {
  console.log(req);
  var dirtyText = req.body.text;
  var sentKeywords = [];
  var sanitizedText = sanitizeHtml(dirtyText, {
    allowedTags: [],
    allowedAttributes: []
  });
  var alchemyApi = new AlchemyAPI(config.alchemyApi.alchemyKey);
  alchemyApi.keywords(sanitizedText, {'sentiment': 0, 'outputMode': 'json'}, function (err, keywords) {
    if (err) {
      throw err;
    //} else if (req.body.useCase === 'server') {
    //  res.json(response);
    } else {
      console.log('keywords.keywords l. 317:\n', keywords.keywords);
      sentKeywords.push(keywords.keywords);
      console.log('sentKeywords l. 319:\n', sentKeywords);
    }
  });
  console.log('sentKeywords l. 322:\n', sentKeywords);
  res.send(sentKeywords);
};

/**
 * Kraken.io Img Optimization
 */

//exports.krakenImageUpload = function(req, res) {
//	var kraken = new Kraken({
//		api_key: keys.krakenKey,
//		api_secret: keys.krakenSecret
//	});
//
//	var opts = {
//		file: '/path/to/image/file.jpg',
//		wait: true
//	};
//
//	kraken.upload(opts, function(data) {
//		if (data.success) {
//			console.log('Success. Optimized image URL: %s', data.kraked_url);
//		} else {
//			console.log('Fail. Error message: %s', data.error);
//		}
//	});
//
//};

/**
 *
 * @param req
 * @param res
 * @param next
 */

exports.markerData = function(req, res, next) {

  var markerColor = '';
  if (req.category === 'video') {
    markerColor = '#ff0011';
    res.send(markerColor);
  } else if (req.category === 'multimedia') {
    markerColor = '#ff0101';
    res.send(markerColor);
  } else if (req.category === 'essay') {
    markerColor = '#0015ff';
    res.send(markerColor);
  } else if (req.category === 'literature') {
    markerColor = '#15ff35';
    res.send(markerColor);
  } else if (req.category === 'interview') {
    markerColor = '#ff0101';
    res.send(markerColor);
  } else if (req.category === 'map') {
    markerColor = '#ff0101';
    res.send(markerColor);
  } else if (req.category === 'audio') {
    markerColor = '#ff0101';
   res.send(markerColor);
  } else {
    markerColor =  '#00ff44';
    res.send(markerColor);
  }
  next();

};
<|endoftext|>


<commit_before>/** vim: et:ts=2:sw=2:sts=2
 * @license Coggle OPML Importer Copyright (c) 2014, CoggleIt Limited. All Rights Reserved.
 * Licensed under the MIT license, http://opensource.org/licenses/MIT
 */
var libxmljs  = require('libxmljs');
var CoggleApi = require('coggle');
var async     = require('async');
var _         = require('underscore');

var y_space = 10;
var x_space = 150;

function elementIsOutlineElement(el){
  return el.name().toLowerCase() === 'outline';
}

function addChildrenRecursive(new_node, diagram_node, cb){
  var y_off = 0;

  async.eachSeries(new_node.children, function(new_child, callback){
    var text = new_child.text;
    var url  = new_child.url;

    var first_line = text.split('\n')[0];
    // if we have a URL, aud it as a Markdown URL around the first line of text
    if(url){
      text = '[' + first_line + '](' + url + ')\n' + text.slice(first_line.length);
    }
    y_off += y_space;
    // we don't re-arrange the whole diagram using the .arrange() function
    // provided by the API, so this x/y positioning is only temporary
    diagram_node.addChild(text, {x:x_space, y:y_off}, function(err, node){
      if(err)
        return callback(err);
      addChildrenRecursive(new_child, node, callback);
    });
  }, cb);
}

function filterNodesRecursive(el, level){
  var child_els = _.filter(el.childNodes(), elementIsOutlineElement);
  var node = {};
  var child_nodes = [];

  for(var i = 0; i < child_els.length; i++){
    child_nodes.push(filterNodesRecursive(child_els[i], level+1));
  }

  node.text = el.attr('text');
  node.text = (node.text && node.text.value()) || '';
  node.url = el.attr('url');
  node.url = (node.url && node.url.value()) || '';
  node.children = child_nodes;

  return node;
}

function importOutlineToCoggle(root_el, diagram, callback){

  // get the root node of the diagram in order to add child nodes to it: since
  // we just created the diagram we know that the root node is the one and only
  // node in it
  diagram.getNodes(function(err, nodes){
    if(err)
      return callback(err);
    var diagram_root_node = nodes[0];

    // convert the OPML into an object representation looking like:
    // {text:"", children:[...]}
    root_to_add = filterNodesRecursive(root_el, 0);

    addChildrenRecursive(root_to_add, diagram_root_node, function(err){
      if(err)
        return callback(err);
      diagram.arrange(function(err){
        callback(err, diagram.webUrl());
      });
    });
  });
}

exports.process = function(opml_data, acess_token, callback){
  // Create a Coggle API Client, see https://github.com/coggle/coggle-js for
  // documentation
  var coggle = new CoggleApi({
    token: acess_token,
 base_url: "http://localdev.coggle.it"
  });

  // Parse the OPML using libxmljs
  var doc;
  try{
    doc  = libxmljs.parseXmlString(opml_data.toString());
  }catch(e){
    return callback(new Error("Not a valid OPML file: " + e.message));
  }
  var title = doc.get('//title');
  var body = doc.get('//body');

  if(!body){
    return callback(new Error("Failed to parse OPML."));
  }

  // Create a new Coggle diagram with the same title as the OPML document, if
  // it had a title
  var title_text = (title && title.text()) || "Imported OPML Outline";

  coggle.createDiagram(title_text, function(err, diagram){
    if(err)
      return callback(err);
    importOutlineToCoggle(body, diagram, callback);
  });
};
<commit_msg>remove local testing configuration<commit_after>/** vim: et:ts=2:sw=2:sts=2
 * @license Coggle OPML Importer Copyright (c) 2014, CoggleIt Limited. All Rights Reserved.
 * Licensed under the MIT license, http://opensource.org/licenses/MIT
 */
var libxmljs  = require('libxmljs');
var CoggleApi = require('coggle');
var async     = require('async');
var _         = require('underscore');

var y_space = 10;
var x_space = 150;

function elementIsOutlineElement(el){
  return el.name().toLowerCase() === 'outline';
}

function addChildrenRecursive(new_node, diagram_node, cb){
  var y_off = 0;

  async.eachSeries(new_node.children, function(new_child, callback){
    var text = new_child.text;
    var url  = new_child.url;

    var first_line = text.split('\n')[0];
    // if we have a URL, aud it as a Markdown URL around the first line of text
    if(url){
      text = '[' + first_line + '](' + url + ')\n' + text.slice(first_line.length);
    }
    y_off += y_space;
    // we don't re-arrange the whole diagram using the .arrange() function
    // provided by the API, so this x/y positioning is only temporary
    diagram_node.addChild(text, {x:x_space, y:y_off}, function(err, node){
      if(err)
        return callback(err);
      addChildrenRecursive(new_child, node, callback);
    });
  }, cb);
}

function filterNodesRecursive(el, level){
  var child_els = _.filter(el.childNodes(), elementIsOutlineElement);
  var node = {};
  var child_nodes = [];

  for(var i = 0; i < child_els.length; i++){
    child_nodes.push(filterNodesRecursive(child_els[i], level+1));
  }

  node.text = el.attr('text');
  node.text = (node.text && node.text.value()) || '';
  node.url = el.attr('url');
  node.url = (node.url && node.url.value()) || '';
  node.children = child_nodes;

  return node;
}

function importOutlineToCoggle(root_el, diagram, callback){

  // get the root node of the diagram in order to add child nodes to it: since
  // we just created the diagram we know that the root node is the one and only
  // node in it
  diagram.getNodes(function(err, nodes){
    if(err)
      return callback(err);
    var diagram_root_node = nodes[0];

    // convert the OPML into an object representation looking like:
    // {text:"", children:[...]}
    root_to_add = filterNodesRecursive(root_el, 0);

    addChildrenRecursive(root_to_add, diagram_root_node, function(err){
      if(err)
        return callback(err);
      diagram.arrange(function(err){
        callback(err, diagram.webUrl());
      });
    });
  });
}

exports.process = function(opml_data, acess_token, callback){
  // Create a Coggle API Client, see https://github.com/coggle/coggle-js for
  // documentation
  var coggle = new CoggleApi({
    token: acess_token
  });

  // Parse the OPML using libxmljs
  var doc;
  try{
    doc  = libxmljs.parseXmlString(opml_data.toString());
  }catch(e){
    return callback(new Error("Not a valid OPML file: " + e.message));
  }
  var title = doc.get('//title');
  var body = doc.get('//body');

  if(!body){
    return callback(new Error("Failed to parse OPML."));
  }

  // Create a new Coggle diagram with the same title as the OPML document, if
  // it had a title
  var title_text = (title && title.text()) || "Imported OPML Outline";

  coggle.createDiagram(title_text, function(err, diagram){
    if(err)
      return callback(err);
    importOutlineToCoggle(body, diagram, callback);
  });
};
<|endoftext|>


<commit_before>global._ = require('underscore')

var express = require('express')
  , socketio = require('socket.io')
  , http = require('http')
  , path = require('path')

/*
 * Create Express app, HTTP server and Socket IO server
 */
var app = express()
  , server = http.createServer(app)
  , io = socketio.listen(server)

app.set('__dirname', __dirname)

require('./config')(app)

require('./app/middleware')(app)

require('./config/routes')(app)

<% if (mongoose) { %>require('./app/models')(app)<% } %>

require('./app/sockets')(app, io)

server.listen(app.get('port'), function() {
  console.log('Express server listening on port ' + app.get('port'))
})
<commit_msg>add an uncaughtException handler<commit_after>global._ = require('underscore')

var express = require('express')
  , socketio = require('socket.io')
  , http = require('http')
  , path = require('path')

/*
 * Create Express app, HTTP server and Socket IO server
 */
var app = express()
  , server = http.createServer(app)
  , io = socketio.listen(server)

app.set('__dirname', __dirname)

require('./config')(app)

require('./app/middleware')(app)

require('./config/routes')(app)

<% if (mongoose) { %>require('./app/models')(app)<% } %>

require('./app/sockets')(app, io)

process.on('uncaughtException', function(err) {
  console.log('Received an uncaughtException');
  console.log(err);
})

server.listen(app.get('port'), function() {
  console.log('Express server listening on port ' + app.get('port'))
})
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var async = require('async');
var core = require('../core.js');
var EventEmitter = require('events').EventEmitter;
var tsort = require('tsort');

// Singleton array to store registered steps.
var steps = [];

var count = exports.count = function() {
  return steps.length;
};

// Event emitter for module.
var events = exports.events = new EventEmitter();

// Blueprint for a step.
var blueprint = {
  name: null,
  description: null,
  deps: [],
  all: {
    darwin: null,
    linux: {
      debian: null,
      fedora: null,
      other: null
    },
    win32: null
  },
  isStep: true
};

/*
 * Format a step object in a nicer way.
 */
var prettyPrint = function(step) {
  return JSON.stringify(step);
};

/*
 * Valid top level property names for a step object.
 */
var validKeys = ['name', 'description', 'deps', 'all', 'isStep'];

/*
 * Validation function for a step.
 */
var invariant = function(step) {
  // Validate step is an object and has the isStep property.
  if (typeof step !== 'object' || !step.isStep) {
    throw new TypeError('Invalid step object: ' +
      prettyPrint(step));
  }
  // Validate name.
  if (typeof step.name !== 'string') {
    throw new Error('Install step has an invalid name: ' +
      prettyPrint(step));
  }
  // Validate description.
  if (typeof step.description !== 'string') {
    throw new Error('Install step has an invalid description: ' +
      prettyPrint(step));
  }
  // Validate dependencies.
  if (!Array.isArray(step.deps)) {
    throw new Error('Install step with invalid deps: ' +
      prettyPrint(step));
  }
  // Validate all key names.
  _.keys(step).forEach(function(key) {
    if (!_.contains(validKeys, key)) {
      throw new Error('Install step with invalid key [' + key + ']: ' +
        prettyPrint(step));
    }
  });
  // @todo: validate the names and types of all the functions inside all.

  // Validate there is at least one function implemented.
  var fns = [];
  var rec = function(node) {
    if (node === null) {

    } else if (typeof node === 'function') {
      fns.push(node);
    } else if (typeof node === 'object') {
      _.forIn(node, function(val, key) {
        rec(val);
      });
    } else {
      throw new Error('Invalid install step: ' + prettyPrint(step));
    }
  };
  rec(step.all);
  if (fns.length === 0) {
    throw new Error('Install step does not implement any step functions: ' +
      prettyPrint(step));
  }
};

/*
 * Perform a deep clone on our step blueprint.
 */
var cloneBlueprint = function() {
  return _.cloneDeep(blueprint);
};

/*
 * Register a step.
 */
var registerStep = exports.registerStep = function(handler) {
  if (typeof handler !== 'function') {
    throw new TypeError('Invalid step handler: ' + handler);
  }

  var step = cloneBlueprint();
  // If handler doesn't include a callback, treat it as sync.
  if (handler.length === 1) {
    // Synchronous handler.
    handler(step);
    invariant(step);
    steps.push(step);
  } else if (handler.length === 2) {
    // Asynchronous handler.
    handler(step, function() {
      invariant(step);
      steps.push(step);
    });
  } else {
    throw new Error('Invalid install step registration handler: ' +
      handler.toString());
  }
};

/*
 * Clear all registered steps, mostly just for use with unit testing.
 */
var clearSteps = exports.clearSteps = function() {
  steps = [];
};

/*
 * Does step x require step y as a dependecy.
 */
/*var requires = function(x, y) {
  // Does x require y?
  return _.contains(x.deps, y.name);
};*/

/*
 * Compare two steps based on if one requires the other vice versa.
 */
/*var compareSteps = function(x, y) {
  if (typeof x !== 'object') {
    throw new TypeError('Invalid step object: ' + x);
  }
  if (typeof y !== 'object') {
    throw new TypeError('Invalid step object: ' + y);
  }
  if (requires(x, y) && requires(y, x)) {
    throw new Error('Two steps cannot both require each other!');
  }

  if (requires(x, y)) {
    return 1;
  } else if (requires(y, x)) {
    return -1;
  } else {
    return 0;
  }
};*/

/*
 * Unpack the implementation of a step for a given platform.
 */
var unpackStep = function(step, platform) {
  if (typeof step !== 'object') {
    throw new TypeError('Invalid step object: ' + step);
  }
  if (typeof platform !== 'string') {
    throw new TypeError('Invalid platform: ' + platform);
  }

  if (typeof step.all === 'function') {
    return step.all;
  } else if (platform === 'darwin' && step.all.darwin) {
    return step.all.darwin;
  } else if (platform === 'win32' && step.all.win32) {
    return step.all.win32;
  } else if (platform === 'linux') {
    throw new Error('not implemented yet :(');
  } else {
    return null;
  }
};

/*
 * Filter steps with no implementation for given platform.
 */
var filterSteps = function(platform) {
  if (typeof platform !== 'string') {
    throw new TypeError('Invalid platform: ' + platform);
  }

  return _.filter(steps, function(step) {
    return unpackStep(step, platform) !== null;
  });
};

/*
 * Get list of registered install steps, filters, sorts, and validates them.
 */
var getFilterAndSortSteps = exports.getSteps = function(platform) {
  if (typeof platform !== 'string') {
    throw new TypeError('Invalid platform: ' + platform);
  }

  // Filter out steps without an implementation for given platform.
  var filteredSteps = filterSteps(platform);

  // Use a topo sort for dependency sorting.
  // Graph to hold dependency tree.
  var graph = tsort();
  // Dictionary for holding steps by name.
  var stepMap = {};
  // Add each step to dependency graph and dictionary.
  filteredSteps.forEach(function(step) {
    graph.add([step.name].concat(step.deps));
    stepMap[step.name] = step;
  });
  // Sort the graph and reverse.
  var graphResults = graph.sort();
  graphResults.reverse();
  // Rebuild ordered array of steps from graph results.
  var orderedSteps = _.map(graphResults, function(name) {
    var result = stepMap[name];
    if (!result) {
      throw new Error('Install step does not exist: ' + name);
    } else {
      return result;
    }
  });

  // Validate all dependencies are included and in the right order.
  var names = [];
  var nameExists = function(name) {
    return _.contains(names, name);
  };
  orderedSteps.forEach(function(step) {
    step.deps.forEach(function(dep) {
      if (!nameExists(dep)) {
        throw new Error('Install step dependency [' + dep + ']' +
          ' was referenced by step [' + step.name + ']' +
          ' before dependency has been encountered.');
      }
    });
    if (nameExists(step.name)) {
      throw new Error('Duplicate install step name [' + step.name + '].');
    } else {
      names.push(step.name);
    }
  });

  return orderedSteps;
};

/*
 * Return a function that will run each install step in the correct order
 * and handle and errors that occur.
 */
var getInstall = exports.getInstall = function(platform) {
  // @todo: validate all dependencies were found.
  if (!platform) {
    platform = core.env.platform;
  }

  // Validate platform.
  if (typeof platform !== 'string') {
    throw new TypeError('Invalid platform: ' + platform);
  }

  return function(state) {
    var steps = getFilterAndSortSteps(platform);
    async.eachSeries(steps, function(step, next) {
      var fn = unpackStep(step, platform);
      if (!fn) {
        // Step has no implementation for this platform.
        next();
      } else {
        if (fn.length === 1) {
          // Step implementation is synchronous.
          events.emit('pre-step', step);
          fn(state);
          events.emit('post-step', step);
          next();
        } else if (fn.length === 2) {
          // Step implementation is asynchronous.
          events.emit('pre-step', step);
          fn(state, function(err) {
            events.emit('post-step', step);
            next(err);
          });
        } else {
          // Step does not have a valid number of arguments.
          var err = new Error('Invalid install step callback: ' +
            fn.toString());
          next(err);
        }
      }
    },
    function(err) {
      if (err) {
        events.emit('error', err);
      } else {
        events.emit('end', state);
      }
    });
  };
};

/*

registerStep(function(step, done) {
  step.name = 'ASYNC - Download cat!';
  step.deps = ['downloader'];
  step.all.darwin = function(state, next) {
    state.downloader.download('http://catsrkewl.com/tabby4.gif', function(err) {
      next(err);
    });
  };
  done();
});

registerStep(function(step) {
  step.name = 'SYNC - Set state with cat names!';
  step.deps = ['ASYNC - Download cat!'];
  step.all.darwin = function(state) {
    state.catsRKewl = true;
  };
});

*/
<commit_msg>Added a timeout guard in case someone registers a install step with a done function but never calls the done function.<commit_after>'use strict';

var _ = require('lodash');
var async = require('async');
var core = require('../core.js');
var EventEmitter = require('events').EventEmitter;
var tsort = require('tsort');

// Singleton array to store registered steps.
var steps = [];

var count = exports.count = function() {
  return steps.length;
};

// Event emitter for module.
var events = exports.events = new EventEmitter();

// Blueprint for a step.
var blueprint = {
  name: null,
  description: null,
  deps: [],
  all: {
    darwin: null,
    linux: {
      debian: null,
      fedora: null,
      other: null
    },
    win32: null
  },
  isStep: true
};

/*
 * Format a step object in a nicer way.
 */
var prettyPrint = function(step) {
  return JSON.stringify(step);
};

/*
 * Valid top level property names for a step object.
 */
var validKeys = ['name', 'description', 'deps', 'all', 'isStep'];

/*
 * Validation function for a step.
 */
var invariant = function(step) {
  // Validate step is an object and has the isStep property.
  if (typeof step !== 'object' || !step.isStep) {
    throw new TypeError('Invalid step object: ' +
      prettyPrint(step));
  }
  // Validate name.
  if (typeof step.name !== 'string') {
    throw new Error('Install step has an invalid name: ' +
      prettyPrint(step));
  }
  // Validate description.
  if (typeof step.description !== 'string') {
    throw new Error('Install step has an invalid description: ' +
      prettyPrint(step));
  }
  // Validate dependencies.
  if (!Array.isArray(step.deps)) {
    throw new Error('Install step with invalid deps: ' +
      prettyPrint(step));
  }
  // Validate all key names.
  _.keys(step).forEach(function(key) {
    if (!_.contains(validKeys, key)) {
      throw new Error('Install step with invalid key [' + key + ']: ' +
        prettyPrint(step));
    }
  });
  // @todo: validate the names and types of all the functions inside all.

  // Validate there is at least one function implemented.
  var fns = [];
  var rec = function(node) {
    if (node === null) {

    } else if (typeof node === 'function') {
      fns.push(node);
    } else if (typeof node === 'object') {
      _.forIn(node, function(val, key) {
        rec(val);
      });
    } else {
      throw new Error('Invalid install step: ' + prettyPrint(step));
    }
  };
  rec(step.all);
  if (fns.length === 0) {
    throw new Error('Install step does not implement any step functions: ' +
      prettyPrint(step));
  }
};

/*
 * Perform a deep clone on our step blueprint.
 */
var cloneBlueprint = function() {
  return _.cloneDeep(blueprint);
};

/*
 * Register a step.
 */
var registerStep = exports.registerStep = function(handler) {
  if (typeof handler !== 'function') {
    throw new TypeError('Invalid step handler: ' + handler);
  }

  var step = cloneBlueprint();
  // If handler doesn't include a callback, treat it as sync.
  if (handler.length === 1) {
    // Synchronous handler.
    handler(step);
    invariant(step);
    steps.push(step);
  } else if (handler.length === 2) {
    // Make sure the defined done callback gets called in a timely manner.
    var timeout = setTimeout(function() {
      throw new Error('Install step registration defined but did NOT call' +
        'the completion callback: ' + step.name);
    }, 2 * 60 * 1000);
    // Asynchronous handler.
    handler(step, function() {
      clearTimeout(timeout);
      invariant(step);
      steps.push(step);
    });
  } else {
    throw new Error('Invalid install step registration handler: ' +
      handler.toString());
  }
};

/*
 * Clear all registered steps, mostly just for use with unit testing.
 */
var clearSteps = exports.clearSteps = function() {
  steps = [];
};

/*
 * Does step x require step y as a dependecy.
 */
/*var requires = function(x, y) {
  // Does x require y?
  return _.contains(x.deps, y.name);
};*/

/*
 * Compare two steps based on if one requires the other vice versa.
 */
/*var compareSteps = function(x, y) {
  if (typeof x !== 'object') {
    throw new TypeError('Invalid step object: ' + x);
  }
  if (typeof y !== 'object') {
    throw new TypeError('Invalid step object: ' + y);
  }
  if (requires(x, y) && requires(y, x)) {
    throw new Error('Two steps cannot both require each other!');
  }

  if (requires(x, y)) {
    return 1;
  } else if (requires(y, x)) {
    return -1;
  } else {
    return 0;
  }
};*/

/*
 * Unpack the implementation of a step for a given platform.
 */
var unpackStep = function(step, platform) {
  if (typeof step !== 'object') {
    throw new TypeError('Invalid step object: ' + step);
  }
  if (typeof platform !== 'string') {
    throw new TypeError('Invalid platform: ' + platform);
  }

  if (typeof step.all === 'function') {
    return step.all;
  } else if (platform === 'darwin' && step.all.darwin) {
    return step.all.darwin;
  } else if (platform === 'win32' && step.all.win32) {
    return step.all.win32;
  } else if (platform === 'linux') {
    throw new Error('not implemented yet :(');
  } else {
    return null;
  }
};

/*
 * Filter steps with no implementation for given platform.
 */
var filterSteps = function(platform) {
  if (typeof platform !== 'string') {
    throw new TypeError('Invalid platform: ' + platform);
  }

  return _.filter(steps, function(step) {
    return unpackStep(step, platform) !== null;
  });
};

/*
 * Get list of registered install steps, filters, sorts, and validates them.
 */
var getFilterAndSortSteps = exports.getSteps = function(platform) {
  if (typeof platform !== 'string') {
    throw new TypeError('Invalid platform: ' + platform);
  }

  // Filter out steps without an implementation for given platform.
  var filteredSteps = filterSteps(platform);

  // Use a topo sort for dependency sorting.
  // Graph to hold dependency tree.
  var graph = tsort();
  // Dictionary for holding steps by name.
  var stepMap = {};
  // Add each step to dependency graph and dictionary.
  filteredSteps.forEach(function(step) {
    graph.add([step.name].concat(step.deps));
    stepMap[step.name] = step;
  });
  // Sort the graph and reverse.
  var graphResults = graph.sort();
  graphResults.reverse();
  // Rebuild ordered array of steps from graph results.
  var orderedSteps = _.map(graphResults, function(name) {
    var result = stepMap[name];
    if (!result) {
      throw new Error('Install step does not exist: ' + name);
    } else {
      return result;
    }
  });

  // Validate all dependencies are included and in the right order.
  var names = [];
  var nameExists = function(name) {
    return _.contains(names, name);
  };
  orderedSteps.forEach(function(step) {
    step.deps.forEach(function(dep) {
      if (!nameExists(dep)) {
        throw new Error('Install step dependency [' + dep + ']' +
          ' was referenced by step [' + step.name + ']' +
          ' before dependency has been encountered.');
      }
    });
    if (nameExists(step.name)) {
      throw new Error('Duplicate install step name [' + step.name + '].');
    } else {
      names.push(step.name);
    }
  });

  return orderedSteps;
};

/*
 * Return a function that will run each install step in the correct order
 * and handle and errors that occur.
 */
var getInstall = exports.getInstall = function(platform) {
  // @todo: validate all dependencies were found.
  if (!platform) {
    platform = core.env.platform;
  }

  // Validate platform.
  if (typeof platform !== 'string') {
    throw new TypeError('Invalid platform: ' + platform);
  }

  return function(state) {
    var steps = getFilterAndSortSteps(platform);
    async.eachSeries(steps, function(step, next) {
      var fn = unpackStep(step, platform);
      if (!fn) {
        // Step has no implementation for this platform.
        next();
      } else {
        if (fn.length === 1) {
          // Step implementation is synchronous.
          events.emit('pre-step', step);
          fn(state);
          events.emit('post-step', step);
          next();
        } else if (fn.length === 2) {
          // Step implementation is asynchronous.
          events.emit('pre-step', step);
          fn(state, function(err) {
            events.emit('post-step', step);
            next(err);
          });
        } else {
          // Step does not have a valid number of arguments.
          var err = new Error('Invalid install step callback: ' +
            fn.toString());
          next(err);
        }
      }
    },
    function(err) {
      if (err) {
        events.emit('error', err);
      } else {
        events.emit('end', state);
      }
    });
  };
};

/*

registerStep(function(step, done) {
  step.name = 'ASYNC - Download cat!';
  step.deps = ['downloader'];
  step.all.darwin = function(state, next) {
    state.downloader.download('http://catsrkewl.com/tabby4.gif', function(err) {
      next(err);
    });
  };
  done();
});

registerStep(function(step) {
  step.name = 'SYNC - Set state with cat names!';
  step.deps = ['ASYNC - Download cat!'];
  step.all.darwin = function(state) {
    state.catsRKewl = true;
  };
});

*/
<|endoftext|>


<commit_before>'use strict';

/**
 * Import plugins
 */
var gulp = require('gulp'),
    $ = require('gulp-load-plugins')(),
    browserSync = require('browser-sync'),
    reload = browserSync.reload,
    runSequence = require('run-sequence'),
    argv = require('yargs').argv,
    del = require('del');

/**
 * Build vendors dependencies
 */
gulp.task('vendors', function() {

  /**
   * CSS VENDORS
   */
  gulp.src([
        ''
      ])
      .pipe($.concat('vendors.css'))
      .pipe($.minifyCss())
      .pipe(gulp.dest('build/css'));

  /**
   * JS VENDORS
   * (with jQuery and Bootstrap dependencies first)
   */

  gulp.src([
      'bower_components/jquery/dist/jquery.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/affix.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/alert.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/button.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/carousel.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/collapse.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/dropdown.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/modal.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/tooltip.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/popover.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/scrollspy.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/tab.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/transition.js'
    ])
    .pipe($.concat('vendors.min.js'))
    .pipe($.uglify())
    .pipe(gulp.dest('build/js'));

  /**
   * FONTS SOURCES
   * Important to add the bootstrap fonts to avoid issues with the fonts include path
   */
  gulp.src([
      'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
      'assets/fonts/*'
    ])
    .pipe(gulp.dest('build/fonts'));
});

/**
 * Build styles from SCSS files
 * With error reporting on compiling (so that there's no crash)
 */
gulp.task('styles', function() {
  return gulp.src('assets/sass/<%=appname%>.scss')
    .pipe($.rubySass())
      .on('error', $.notify.onError(function (error) {
         console.log(error.message);
         if (!argv.production) {
           return 'Message to the notifier: ' + error.message;
         }
      }))
    .pipe($.autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1'))
    .pipe($.minifyCss())
    .pipe(gulp.dest('build/css'));
});

/**
 * Build JS
 * With error reporting on compiling (so that there's no crash)
 * And jshint check to highlight errors as we go.
 */
gulp.task('scripts', function() {
  return gulp.src('assets/js/*.js')
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.concat('main.js'))
    .pipe(gulp.dest('build/js'))
    .pipe($.rename({ suffix: '.min' }))
    .pipe($.uglify())
    .pipe(gulp.dest('build/js'));
});

/**
 * Build Hologram Styleguide
 */
gulp.task('styleguide', function () {
  return gulp.src('hologram_config.yml')
    .pipe($.hologram());
});

/**
 * Clean output directories
 */
gulp.task('clean', del.bind(null, ['build', 'styleguide']));

/**
 * Serve
 */
gulp.task('serve', ['styles', 'scripts'], function () {
  browserSync({
    server: {
      baseDir: ['styleguide'],
    },
    open: false
  });
  gulp.watch(['**/*.html'], reload);
  gulp.watch(['assets/sass/**/*.scss'], function() {
    runSequence('styles', 'styleguide', reload);
  });
  gulp.watch(['assets/js/**/*.js'], function() {
    runSequence('scripts', reload);
  });
});

/**
 * Deploy to GH pages
 */

gulp.task('deploy', function () {
  gulp.src("styleguide/**/*")
    .pipe($.ghPages());
});

/**
 * Default task
 */
gulp.task('default', ['clean'], function(cb) {
  runSequence('vendors', 'styles', 'scripts', 'styleguide', cb);
});

<commit_msg>add gulp production task fix #13<commit_after>'use strict';

/**
 * Import plugins
 */
var gulp = require('gulp'),
    $ = require('gulp-load-plugins')(),
    browserSync = require('browser-sync'),
    reload = browserSync.reload,
    runSequence = require('run-sequence'),
    argv = require('yargs').argv,
    del = require('del');

/**
 * Build vendors dependencies
 */
gulp.task('vendors', function() {

  /**
   * CSS VENDORS
   */
  gulp.src([
        ''
      ])
      .pipe($.concat('vendors.css'))
      .pipe($.minifyCss())
      .pipe(gulp.dest('build/css'));

  /**
   * JS VENDORS
   * (with jQuery and Bootstrap dependencies first)
   */

  gulp.src([
      'bower_components/jquery/dist/jquery.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/affix.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/alert.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/button.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/carousel.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/collapse.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/dropdown.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/modal.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/tooltip.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/popover.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/scrollspy.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/tab.js',
      'bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/transition.js'
    ])
    .pipe($.concat('vendors.min.js'))
    .pipe($.uglify())
    .pipe(gulp.dest('build/js'));

  /**
   * FONTS SOURCES
   * Important to add the bootstrap fonts to avoid issues with the fonts include path
   */
  gulp.src([
      'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
      'assets/fonts/*'
    ])
    .pipe(gulp.dest('build/fonts'));
});

/**
 * Build styles from SCSS files
 * With error reporting on compiling (so that there's no crash)
 */
gulp.task('styles', function() {
  if (argv.production) { console.log('Processing styles for production env.' ); }
  return gulp.src('assets/sass/<%=appname%>.scss')
    .pipe($.rubySass())
      .on('error', $.notify.onError(function (error) {
         console.log(error.message);
         if (!argv.production) {
           return 'Message to the notifier: ' + error.message;
         }
      }))
    .pipe($.autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1'))
    .pipe($.minifyCss())
    .pipe(gulp.dest('build/css'));
});

/**
 * Build JS
 * With error reporting on compiling (so that there's no crash)
 * And jshint check to highlight errors as we go.
 */
gulp.task('scripts', function() {
  return gulp.src('assets/js/*.js')
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.concat('main.js'))
    .pipe(gulp.dest('build/js'))
    .pipe($.rename({ suffix: '.min' }))
    .pipe($.uglify())
    .pipe(gulp.dest('build/js'));
});

/**
 * Build Hologram Styleguide
 */
gulp.task('styleguide', function () {
  return gulp.src('hologram_config.yml')
    .pipe($.hologram());
});

/**
 * Clean output directories
 */
gulp.task('clean', del.bind(null, ['build', 'styleguide']));

/**
 * Serve
 */
gulp.task('serve', ['styles', 'scripts'], function () {
  browserSync({
    server: {
      baseDir: ['styleguide'],
    },
    open: false
  });
  gulp.watch(['**/*.html'], reload);
  gulp.watch(['assets/sass/**/*.scss'], function() {
    runSequence('styles', 'styleguide', reload);
  });
  gulp.watch(['assets/js/**/*.js'], function() {
    runSequence('scripts', reload);
  });
});

/**
 * Deploy to GH pages
 */

gulp.task('deploy', function () {
  gulp.src("styleguide/**/*")
    .pipe($.ghPages());
});

/**
 * Task to build assets on production server
 */
gulp.task('production',['clean'], function() {
    argv.production = true;
    runSequence('vendors', 'styles', 'scripts');
});

/**
 * Default task
 */
gulp.task('default', ['clean'], function(cb) {
  runSequence('vendors', 'styles', 'scripts', 'styleguide', cb);
});

<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');
var del = require('del');
var chalk = require('chalk');
var bowerFiles = require('main-bower-files');
var runSequence = require('run-sequence');
var sq = require('streamqueue');
var path = require('path');
var $ = require('gulp-load-plugins')();

process.env.NODE_ENV = $.util.env.env || 'development';

var config = require('./server/config/environment');

var openOpts = {
  url: 'http://localhost:' + config.port
};

var toInject = [
  'client/app.js',
  'client/directives/**/*.js', '!client/directives/**/*.spec.js',
  'client/filters/**/*.js', '!client/filters/**/*.spec.js',
  'client/services/**/*.js', '!client/services/**/*.spec.js',
  'client/views/**/*.js', '!client/views/**/*.spec.js',
  'client/styles/css/app.css'
];

var toDelete = [];

/**
 * Log. With options.
 *
 * @param {String} msg
 * @param {Object} options
 */
function log (msg, options) {
  options = options || {};
  console.log(
    (options.padding ? '\n' : '') +
    chalk.yellow(' > ' + msg) +
    (options.padding ? '\n' : '')
  );
}

/**
 * Compile sass
 */
gulp.task('sass', function () {
  return gulp.src('client/styles/app.scss')
    .pipe($.plumber())
    .pipe($.sass())
    .pipe(gulp.dest('client/styles/css'));
});

/**
 * Inject css/js files in index.html
 */
gulp.task('inject', function () {
  var sources = gulp.src(toInject, { read: false });

  return gulp.src('client/index.html')
    .pipe($.inject(gulp.src(bowerFiles(), { read: false }), {
      name: 'bower',
      relative: 'true'
    }))
    .pipe($.inject(sources, { relative: true }))
    .pipe(gulp.dest('client'));
});

/**
 * Watch files and reload page.
 * Recompile scss if needed.
 * Reinject files
 */
gulp.task('watch', ['inject'], function () {

  $.livereload.listen();

  $.watch('client/styles/**/*.scss', function () {
    gulp.src('client/styles/app.scss')
      .pipe($.plumber())
      .pipe($.sass())
      .pipe(gulp.dest('client/styles/css'))
      .pipe($.livereload());
  });

  $.watch([
    'client/index.html',
    'client/app.js'
  ]).pipe($.livereload());

  $.watch([
    'client/views',
    'client/views/**/*.html',
    'client/views/**/*.js',
    '!client/views/**/*.spec.js',
    'client/directives',
    'client/directives/**/*.html',
    'client/directives/**/*.js',
    '!client/directives/**/*.spec.js',
    'client/services',
    'client/services/**/*.js',
    '!client/services/**/*.spec.js',
    'client/filters',
    'client/filters/**/*.js',
    '!client/filters/**/*.spec.js'
  ], function (ev, done) {
    gulp.src('client/index.html')
      .pipe($.inject(gulp.src(toInject), { relative: true }))
      .pipe(gulp.dest('client'));
    done();
  });

  $.watch('bower.json', function () {
    gulp.src('client/index.html')
      .pipe($.inject(gulp.src(bowerFiles(), { read: false }), {
        name: 'bower',
        relative: 'true'
      }))
      .pipe(gulp.dest('client'));
  });

});

/**
 * Control things
 */
gulp.task('control', function () {
  return gulp.src([
    'client/**/**/*.js',
    'server/**/**/*.js',
    '!client/bower_components/**'
  ])
    .pipe($.jshint())
    .pipe($.jshint.reporter('default'));
});

/**
 * Tests
 */
function testServer (done) {

  log('Running server test...', { padding: true });

  gulp.src('server/**/*.spec.js', { read: false })
    .pipe($.plumber())
    .pipe($.mocha({ reporter: 'spec' }))
    .once('end', function () {
      done();
    });
}

function testClient (done) {

  log('Running client test...', { padding: true });

  gulp.src([
    'client/bower_components/angular/angular.js',
    'client/bower_components/angular-mocks/angular-mocks.js',
    'client/bower_components/angular-route/angular-route.js',
    'client/app.js',
    'client/views/**/*.js',
    'client/services/**/*.js',
    'client/directives/**/*.js',
    'client/filters/**/*.js'
  ])
    .pipe($.karma({
      action: 'run',
      configFile: 'client/karma.conf.js'
    }))
    .on('error', function (err) {
      console.log(err);
      this.emit('end');
    })
    .once('end', function () {
      done();
    });
}

gulp.task('test', function (done) {
  process.env.NODE_ENV = 'test';
  var filter = process.argv[3] ? process.argv[3].substr(2) : false;
  if (filter === 'client') {
    return testClient(function () { process.exit(); done(); });
  } else if (filter === 'server') {
    return testServer(function () { process.exit(); done(); });
  } else if (filter === false) {
    return testClient(function () {
      testServer(function () {
        process.exit();
        done();
      });
    });
  } else {
    console.log('Wrong parameter [%s], availables : --client, --server', filter);
  }
});

/**
 * Launch server
 */
gulp.task('serve', ['sass', 'inject', 'watch'], function () {
  require('./server/server');
  return gulp.src('client/index.html')
    .pipe($.open('', openOpts));
});

gulp.task('serve:dist', ['build'], function () {
  process.env.NODE_ENV = 'production';
  require('./dist/server/server');
  return gulp.src('client/index.html')
    .pipe($.open('', openOpts));
});

/**
 * Build
 */
gulp.task('clean:dist', function (cb) {
  del(['dist/**', '!dist', '!dist/.git{,/**}'], cb);
});

gulp.task('clean:finish', function (cb) {
  del([
    '.tmp/**',
    'dist/client/app.{css,js}'
  ].concat(toDelete), cb);
});

gulp.task('copy:dist', function () {

  var main = gulp.src(['server/**/*', 'package.json'], { base: './' });
  var assets = gulp.src('client/assets/**/*', { base: './' });

  return sq({ objectMode: true }, main, assets)
    .pipe(gulp.dest('dist/'));
});

gulp.task('usemin', ['inject'], function () {
  return gulp.src('client/index.html')
    .pipe($.usemin())
    .pipe(gulp.dest('dist/client/'));
});

gulp.task('imagemin', function () {
  return gulp.src('dist/client/assets/images/*.{png,gif,jpg,jpeg,svg}')
    .pipe($.imagemin())
    .pipe(gulp.dest('dist/client/assets/images/'));
});

gulp.task('cssmin', function () {
  return gulp.src('dist/client/app.css')
    .pipe($.minifyCss())
    .pipe(gulp.dest('dist/client/'));
});

gulp.task('scripts', function () {
  var tpl = gulp.src('client/views/**/*.html')
    .pipe($.angularTemplatecache({
      root: 'views',
      module: '<%= _.slugify(appname) %>'
    }));

  var app = gulp.src('dist/client/app.js');

  return sq({ objectMode: true }, app, tpl)
    .pipe($.concat('app.js'))
    .pipe($.ngAnnotate())
    .pipe($.uglify())
    .pipe(gulp.dest('dist/client/'));
});

gulp.task('rev', function () {
  return gulp.src('dist/client/**')
    .pipe($.revAll({
      ignore: ['favicon.ico', '.html'],
      quiet: true,
      transformFilename: function (file, hash) {
        toDelete.push(path.resolve(file.path));
        var ext = path.extname(file.path);
        return path.basename(file.path, ext) + '.' + hash.substr(0, 8) + ext;
      }
    }))
    .pipe(gulp.dest('dist/client/'))
});

gulp.task('build', function (cb) {
  runSequence(
    ['clean:dist', 'sass'],
    ['usemin', 'copy:dist'],
    ['scripts', 'imagemin', 'cssmin'],
    'rev',
    'clean:finish',
    cb);
});

gulp.task('default', ['serve']);
<commit_msg>fix(gen): resolve deps for server, watch and inject tasks<commit_after>'use strict';

var gulp = require('gulp');
var del = require('del');
var chalk = require('chalk');
var bowerFiles = require('main-bower-files');
var runSequence = require('run-sequence');
var sq = require('streamqueue');
var path = require('path');
var $ = require('gulp-load-plugins')();

process.env.NODE_ENV = $.util.env.env || 'development';

var config = require('./server/config/environment');

var openOpts = {
  url: 'http://localhost:' + config.port
};

var toInject = [
  'client/app.js',
  'client/directives/**/*.js', '!client/directives/**/*.spec.js',
  'client/filters/**/*.js', '!client/filters/**/*.spec.js',
  'client/services/**/*.js', '!client/services/**/*.spec.js',
  'client/views/**/*.js', '!client/views/**/*.spec.js',
  'client/styles/css/app.css'
];

var toDelete = [];

/**
 * Log. With options.
 *
 * @param {String} msg
 * @param {Object} options
 */
function log (msg, options) {
  options = options || {};
  console.log(
    (options.padding ? '\n' : '') +
    chalk.yellow(' > ' + msg) +
    (options.padding ? '\n' : '')
  );
}

/**
 * Compile sass
 */
gulp.task('sass', function () {
  return gulp.src('client/styles/app.scss')
    .pipe($.plumber())
    .pipe($.sass())
    .pipe(gulp.dest('client/styles/css'));
});

/**
 * Inject css/js files in index.html
 */
gulp.task('inject', ['sass'], function () {
  var sources = gulp.src(toInject, { read: false });

  return gulp.src('client/index.html')
    .pipe($.inject(gulp.src(bowerFiles(), { read: false }), {
      name: 'bower',
      relative: 'true'
    }))
    .pipe($.inject(sources, { relative: true }))
    .pipe(gulp.dest('client'));
});

/**
 * Watch files and reload page.
 * Recompile scss if needed.
 * Reinject files
 */
gulp.task('watch', ['inject'], function () {

  $.livereload.listen();

  $.watch('client/styles/**/*.scss', function () {
    gulp.src('client/styles/app.scss')
      .pipe($.plumber())
      .pipe($.sass())
      .pipe(gulp.dest('client/styles/css'))
      .pipe($.livereload());
  });

  $.watch([
    'client/index.html',
    'client/app.js'
  ]).pipe($.livereload());

  $.watch([
    'client/views',
    'client/views/**/*.html',
    'client/views/**/*.js',
    '!client/views/**/*.spec.js',
    'client/directives',
    'client/directives/**/*.html',
    'client/directives/**/*.js',
    '!client/directives/**/*.spec.js',
    'client/services',
    'client/services/**/*.js',
    '!client/services/**/*.spec.js',
    'client/filters',
    'client/filters/**/*.js',
    '!client/filters/**/*.spec.js'
  ], function (ev, done) {
    gulp.src('client/index.html')
      .pipe($.inject(gulp.src(toInject), { relative: true }))
      .pipe(gulp.dest('client'));
    done();
  });

  $.watch('bower.json', function () {
    gulp.src('client/index.html')
      .pipe($.inject(gulp.src(bowerFiles(), { read: false }), {
        name: 'bower',
        relative: 'true'
      }))
      .pipe(gulp.dest('client'));
  });

});

/**
 * Control things
 */
gulp.task('control', function () {
  return gulp.src([
    'client/**/**/*.js',
    'server/**/**/*.js',
    '!client/bower_components/**'
  ])
    .pipe($.jshint())
    .pipe($.jshint.reporter('default'));
});

/**
 * Tests
 */
function testServer (done) {

  log('Running server test...', { padding: true });

  gulp.src('server/**/*.spec.js', { read: false })
    .pipe($.plumber())
    .pipe($.mocha({ reporter: 'spec' }))
    .once('end', function () {
      done();
    });
}

function testClient (done) {

  log('Running client test...', { padding: true });

  gulp.src([
    'client/bower_components/angular/angular.js',
    'client/bower_components/angular-mocks/angular-mocks.js',
    'client/bower_components/angular-route/angular-route.js',
    'client/app.js',
    'client/views/**/*.js',
    'client/services/**/*.js',
    'client/directives/**/*.js',
    'client/filters/**/*.js'
  ])
    .pipe($.karma({
      action: 'run',
      configFile: 'client/karma.conf.js'
    }))
    .on('error', function (err) {
      console.log(err);
      this.emit('end');
    })
    .once('end', function () {
      done();
    });
}

gulp.task('test', function (done) {
  process.env.NODE_ENV = 'test';
  var filter = process.argv[3] ? process.argv[3].substr(2) : false;
  if (filter === 'client') {
    return testClient(function () { process.exit(); done(); });
  } else if (filter === 'server') {
    return testServer(function () { process.exit(); done(); });
  } else if (filter === false) {
    return testClient(function () {
      testServer(function () {
        process.exit();
        done();
      });
    });
  } else {
    console.log('Wrong parameter [%s], availables : --client, --server', filter);
  }
});

/**
 * Launch server
 */
gulp.task('serve', ['watch'], function () {
  require('./server/server');
  return gulp.src('client/index.html')
    .pipe($.open('', openOpts));
});

gulp.task('serve:dist', ['build'], function () {
  process.env.NODE_ENV = 'production';
  require('./dist/server/server');
  return gulp.src('client/index.html')
    .pipe($.open('', openOpts));
});

/**
 * Build
 */
gulp.task('clean:dist', function (cb) {
  del(['dist/**', '!dist', '!dist/.git{,/**}'], cb);
});

gulp.task('clean:finish', function (cb) {
  del([
    '.tmp/**',
    'dist/client/app.{css,js}'
  ].concat(toDelete), cb);
});

gulp.task('copy:dist', function () {
  var main = gulp.src(['server/**/*', 'package.json'], { base: './' });
  var assets = gulp.src('client/assets/**/*', { base: './' });

  return sq({ objectMode: true }, main, assets)
    .pipe(gulp.dest('dist/'));
});

gulp.task('usemin', ['inject'], function () {
  return gulp.src('client/index.html')
    .pipe($.usemin())
    .pipe(gulp.dest('dist/client/'));
});

gulp.task('imagemin', function () {
  return gulp.src('dist/client/assets/images/*.{png,gif,jpg,jpeg,svg}')
    .pipe($.imagemin())
    .pipe(gulp.dest('dist/client/assets/images/'));
});

gulp.task('cssmin', function () {
  return gulp.src('dist/client/app.css')
    .pipe($.minifyCss())
    .pipe(gulp.dest('dist/client/'));
});

gulp.task('scripts', function () {
  var tpl = gulp.src('client/views/**/*.html')
    .pipe($.angularTemplatecache({
      root: 'views',
      module: '<%= _.slugify(appname) %>'
    }));

  var app = gulp.src('dist/client/app.js');

  return sq({ objectMode: true }, app, tpl)
    .pipe($.concat('app.js'))
    .pipe($.ngAnnotate())
    .pipe($.uglify())
    .pipe(gulp.dest('dist/client/'));
});

gulp.task('rev', function () {
  return gulp.src('dist/client/**')
    .pipe($.revAll({
      ignore: ['favicon.ico', '.html'],
      quiet: true,
      transformFilename: function (file, hash) {
        toDelete.push(path.resolve(file.path));
        var ext = path.extname(file.path);
        return path.basename(file.path, ext) + '.' + hash.substr(0, 8) + ext;
      }
    }))
    .pipe(gulp.dest('dist/client/'))
});

gulp.task('build', function (cb) {
  runSequence(
    ['clean:dist', 'sass'],
    ['usemin', 'copy:dist'],
    ['scripts', 'imagemin', 'cssmin'],
    'rev',
    'clean:finish',
    cb);
});

gulp.task('default', ['serve']);
<|endoftext|>