<commit_before>var Backbone = require("backbone");
var _ = require("underscore");
var AppVersion = require("../models/AppVersion");
var AppVersionCollection = require("../models/AppVersionCollection");
var Task = require("../models/Task");
var TaskCollection = require("../models/TaskCollection");

function ValidationError(attribute, message) {
  this.attribute = attribute;
  this.message = message;
}

var DEFAULT_HEALTH_MSG = "Unknown";
var EDITABLE_ATTRIBUTES = ["cmd", "constraints", "container", "cpus", "env",
  "executor", "id", "instances", "mem", "disk", "ports", "uris"];
var UPDATEABLE_ATTRIBUTES = ["instances", "tasksRunning", "tasksStaged",
  "tasksHealthy", "tasksUnhealthy", "deployments"];

// Matches the command executor, like "//cmd", and custom executors starting
// with or without a "/" but never two "//", like "/custom/exec". Double slash
// is only permitted as a prefix to the cmd executor, "/custom//exec" is
// invalid for example.
var VALID_EXECUTOR_PATTERN = "^(|\\/\\/cmd|\\/?[^\\/]+(\\/[^\\/]+)*)$";
var VALID_EXECUTOR_REGEX = new RegExp(VALID_EXECUTOR_PATTERN);

var VALID_CONSTRAINTS = ["unique", "like", "unlike", "cluster", "group_by"];

function findHealthCheckMsg(healthCheckResults, context) {
  return healthCheckResults.map(function (hc, index) {
    if (hc && !hc.alive) {
      var failedCheck = this.get("healthChecks")[index];
      return "Warning: Health check '" +
        (failedCheck.protocol ? failedCheck.protocol + " " : "") +
        (this.get("host") ? this.get("host") : "") +
        (failedCheck.path ? failedCheck.path : "") + "'" +
        (hc.lastFailureCause ?
          " returned with status: '" + hc.lastFailureCause + "'" :
          " failed") +
        ".";
    }
  }, context);
}

function isValidConstraint(p) {
  if (p.length < 2 || p.length > 3) {
    return false;
  }

  /* TODO: should be dynamic. It should be in Scala, but it's impossible to
   * return an error on a specific field.
   */
  var operator = p[1];
  return (_.indexOf(VALID_CONSTRAINTS, operator.toLowerCase()) !== -1);
}

var App = Backbone.Model.extend({
  defaults: function () {
    return {
      cmd: null,
      constraints: [],
      container: null,
      cpus: 0.1,
      deployments: [],
      env: {},
      executor: "",
      healthChecks: [],
      id: null,
      instances: 1,
      mem: 16.0,
      disk: 0.0,
      ports: [0],
      uris: []
    };
  },

  initialize: function () {
    _.bindAll(this, "formatTaskHealthMessage");
    // If this model belongs to a collection when it is instantiated, it has
    // already been persisted to the server.
    this.persisted = (this.collection != null);

    this.tasks = new TaskCollection(null, {appId: this.id});
    this.versions = new AppVersionCollection(null, {appId: this.id});
    this.on({
      "change:id": function (model, value) {
        // Inform AppVersionCollection and TaskCollection of new ID so it can
        // send requests to the new endpoint.
        this.tasks.options.appId = value;
        this.versions.options.appId = value;
      },
      "sync": function () {
        this.persisted = true;
      }
    });
  },

  isNew: function () {
    return !this.persisted;
  },

  isDeploying: function () {
    return !_.isEmpty(this.get("deployments"));
  },

  allInstancesBooted: function () {
    return this.get("tasksRunning") === this.get("instances");
  },

  formatTasksRunning: function () {
    var tasksRunning = this.get("tasksRunning");
    return tasksRunning == null ? "-" : tasksRunning;
  },

  formatTaskHealthMessage: function (task) {
    if (task) {
      var msg;

      switch (task.getHealth()) {
        case Task.HEALTH.HEALTHY:
          msg = "Healthy";
          break;
        case Task.HEALTH.UNHEALTHY:
          var healthCheckResults = task.get("healthCheckResults");
          if (healthCheckResults != null) {
            msg = findHealthCheckMsg(healthCheckResults, this);
          }
          break;
        default:
          msg = DEFAULT_HEALTH_MSG;
          break;
      }

      return msg;
    }
    return null;
  },

  parse: function (data) {
    // When PUTing the response is a 204 (No content) and should not be
    // parsed.
    if (data != null) {
      var parsedVersion = Date.parse(data.version);
      if (!isNaN(parsedVersion)) { data.version = new Date(parsedVersion); }
    }

    return data;
  },

  /* Updates only those attributes listed in `UPDATEABLE_ATTRIBUTES` to prevent
   * showing values that cannot be changed.
   */
  update: function (attrs) {

    var filteredAttributes = _.filter(UPDATEABLE_ATTRIBUTES, function (attr) {
      return attrs[attr] != null;
    });

    var allowedAttrs = _.pick(attrs, filteredAttributes);

    this.set(allowedAttrs);
  },

  /* Sends only those attributes listed in `EDITABLE_ATTRIBUTES` to prevent
   * sending immutable values like "tasksRunning" and "tasksStaged" and the
   * "version" value, which when sent prevents any other attributes from being
   * changed.
   */
  save: function (attrs, options) {
    /* jshint -W030 */
    options || (options = {});
    /* jshint +W030 */

    var allAttrs;
    if (options.patch === true) {
      allAttrs = _.extend({}, this.changedAttributes, attrs);
    } else {
      allAttrs = _.extend({}, this.attributes, attrs);
    }

    // Filter out null and undefined values
    var filteredAttributes = _.filter(EDITABLE_ATTRIBUTES, function (attr) {
      return allAttrs[attr] != null;
    });

    var allowedAttrs = _.pick(allAttrs, filteredAttributes);

    /* When `options.data` is supplied, Backbone does not attempt to infer its
     * content type. It must be explicitly set for the content to be
     * interpreted as JSON.
     */
    options.contentType = "application/json";
    options.data = JSON.stringify(allowedAttrs);

    return Backbone.Model.prototype.save.call(
      this, allowedAttrs, options);
  },

  setVersion: function (version) {
    this.set(_.pick(version.attributes, EDITABLE_ATTRIBUTES));
  },

  getCurrentVersion: function () {
    var version = new AppVersion();
    version.set(this.attributes);

    // make sure date is a string
    version.set({
      "version": version.get("version").toISOString()
    });

    // transfer app id
    version.options = {
      appId: this.get("id")
    };

    return version;
  },

  getStatus: function () {
    var status = "Running";
    if (this.isDeploying()) {
      status = "Deploying";
    } else if (this.get("instances") === 0 && this.formatTasksRunning() === 0) {
      status = "Suspended";
    }

    return status;
  },

  restart: function (options) {
    /* jshint -W030 */
    options || (options = {});
    /* jshint +W030 */

    if (options.force == null) {
      options.force = false;
    }

    options.contentType = "application/json";
    options.data = JSON.stringify({force: options.force});
    options.method = "POST";
    options.url = this.url() + "/restart";

    this.fetch(options);
  },

  hasHealth: function () {
    return this.get("healthChecks") != null &&
      this.get("healthChecks").length > 0;
  },

  suspend: function (options) {
    this.save({instances: 0}, options);
  },

  validate: function (attrs) {
    var errors = [];

    if (_.isNaN(attrs.mem) || !_.isNumber(attrs.mem) || attrs.mem < 0) {
      errors.push(
        new ValidationError("mem", "Memory must be a non-negative Number"));
    }

    if (_.isNaN(attrs.cpus) || !_.isNumber(attrs.cpus) || attrs.cpus < 0) {
      errors.push(
        new ValidationError("cpus", "CPUs must be a non-negative Number"));
    }

    if (_.isNaN(attrs.disk) || !_.isNumber(attrs.disk) || attrs.disk < 0) {
      errors.push(
        new ValidationError(
          "disk",
          "Disk Space must be a non-negative Number"
        )
      );
    }

    if (_.isNaN(attrs.instances) || !_.isNumber(attrs.instances) ||
        attrs.instances < 0) {
      errors.push(
        new ValidationError(
          "instances",
          "Instances must be a non-negative Number"
        )
      );
    }

    if (!_.isString(attrs.id) || attrs.id.length < 1) {
      errors.push(new ValidationError("id", "ID must not be empty"));
    }

    if (_.isString(attrs.executor) &&
        !VALID_EXECUTOR_REGEX.test(attrs.executor)) {
      errors.push(
        new ValidationError(
          "executor",
          "Executor must be the string '//cmd', a string containing only " +
          "single slashes ('/'), or blank."
        )
      );
    }

    if (!_.every(attrs.ports, function (p) { return _.isNumber(p); })) {
      errors.push(
        new ValidationError("ports", "Ports must be a list of Numbers"));
    }

    if (!attrs.constraints.every(isValidConstraint)) {
      errors.push(
        new ValidationError("constraints",
          "Invalid constraints format or operator. Supported operators are " +
          VALID_CONSTRAINTS.map(function (c) {
            return "`" + c + "`";
          }).join(", ") +
          ". See https://github.com/mesosphere/marathon/wiki/Constraints."
        )
      );
    }

    if (errors.length > 0) { return errors; }
  },

  url : function () {
    return this.isNew() ? "v2/apps" : "v2/apps/" + this.id;
  }
}, {
  VALID_EXECUTOR_PATTERN: VALID_EXECUTOR_PATTERN
});

module.exports = App;
<commit_msg>Change link to new Constraints Marathon Documentation page.<commit_after>var Backbone = require("backbone");
var _ = require("underscore");
var AppVersion = require("../models/AppVersion");
var AppVersionCollection = require("../models/AppVersionCollection");
var Task = require("../models/Task");
var TaskCollection = require("../models/TaskCollection");

function ValidationError(attribute, message) {
  this.attribute = attribute;
  this.message = message;
}

var DEFAULT_HEALTH_MSG = "Unknown";
var EDITABLE_ATTRIBUTES = ["cmd", "constraints", "container", "cpus", "env",
  "executor", "id", "instances", "mem", "disk", "ports", "uris"];
var UPDATEABLE_ATTRIBUTES = ["instances", "tasksRunning", "tasksStaged",
  "tasksHealthy", "tasksUnhealthy", "deployments"];

// Matches the command executor, like "//cmd", and custom executors starting
// with or without a "/" but never two "//", like "/custom/exec". Double slash
// is only permitted as a prefix to the cmd executor, "/custom//exec" is
// invalid for example.
var VALID_EXECUTOR_PATTERN = "^(|\\/\\/cmd|\\/?[^\\/]+(\\/[^\\/]+)*)$";
var VALID_EXECUTOR_REGEX = new RegExp(VALID_EXECUTOR_PATTERN);

var VALID_CONSTRAINTS = ["unique", "like", "unlike", "cluster", "group_by"];

function findHealthCheckMsg(healthCheckResults, context) {
  return healthCheckResults.map(function (hc, index) {
    if (hc && !hc.alive) {
      var failedCheck = this.get("healthChecks")[index];
      return "Warning: Health check '" +
        (failedCheck.protocol ? failedCheck.protocol + " " : "") +
        (this.get("host") ? this.get("host") : "") +
        (failedCheck.path ? failedCheck.path : "") + "'" +
        (hc.lastFailureCause ?
          " returned with status: '" + hc.lastFailureCause + "'" :
          " failed") +
        ".";
    }
  }, context);
}

function isValidConstraint(p) {
  if (p.length < 2 || p.length > 3) {
    return false;
  }

  /* TODO: should be dynamic. It should be in Scala, but it's impossible to
   * return an error on a specific field.
   */
  var operator = p[1];
  return (_.indexOf(VALID_CONSTRAINTS, operator.toLowerCase()) !== -1);
}

var App = Backbone.Model.extend({
  defaults: function () {
    return {
      cmd: null,
      constraints: [],
      container: null,
      cpus: 0.1,
      deployments: [],
      env: {},
      executor: "",
      healthChecks: [],
      id: null,
      instances: 1,
      mem: 16.0,
      disk: 0.0,
      ports: [0],
      uris: []
    };
  },

  initialize: function () {
    _.bindAll(this, "formatTaskHealthMessage");
    // If this model belongs to a collection when it is instantiated, it has
    // already been persisted to the server.
    this.persisted = (this.collection != null);

    this.tasks = new TaskCollection(null, {appId: this.id});
    this.versions = new AppVersionCollection(null, {appId: this.id});
    this.on({
      "change:id": function (model, value) {
        // Inform AppVersionCollection and TaskCollection of new ID so it can
        // send requests to the new endpoint.
        this.tasks.options.appId = value;
        this.versions.options.appId = value;
      },
      "sync": function () {
        this.persisted = true;
      }
    });
  },

  isNew: function () {
    return !this.persisted;
  },

  isDeploying: function () {
    return !_.isEmpty(this.get("deployments"));
  },

  allInstancesBooted: function () {
    return this.get("tasksRunning") === this.get("instances");
  },

  formatTasksRunning: function () {
    var tasksRunning = this.get("tasksRunning");
    return tasksRunning == null ? "-" : tasksRunning;
  },

  formatTaskHealthMessage: function (task) {
    if (task) {
      var msg;

      switch (task.getHealth()) {
        case Task.HEALTH.HEALTHY:
          msg = "Healthy";
          break;
        case Task.HEALTH.UNHEALTHY:
          var healthCheckResults = task.get("healthCheckResults");
          if (healthCheckResults != null) {
            msg = findHealthCheckMsg(healthCheckResults, this);
          }
          break;
        default:
          msg = DEFAULT_HEALTH_MSG;
          break;
      }

      return msg;
    }
    return null;
  },

  parse: function (data) {
    // When PUTing the response is a 204 (No content) and should not be
    // parsed.
    if (data != null) {
      var parsedVersion = Date.parse(data.version);
      if (!isNaN(parsedVersion)) { data.version = new Date(parsedVersion); }
    }

    return data;
  },

  /* Updates only those attributes listed in `UPDATEABLE_ATTRIBUTES` to prevent
   * showing values that cannot be changed.
   */
  update: function (attrs) {

    var filteredAttributes = _.filter(UPDATEABLE_ATTRIBUTES, function (attr) {
      return attrs[attr] != null;
    });

    var allowedAttrs = _.pick(attrs, filteredAttributes);

    this.set(allowedAttrs);
  },

  /* Sends only those attributes listed in `EDITABLE_ATTRIBUTES` to prevent
   * sending immutable values like "tasksRunning" and "tasksStaged" and the
   * "version" value, which when sent prevents any other attributes from being
   * changed.
   */
  save: function (attrs, options) {
    /* jshint -W030 */
    options || (options = {});
    /* jshint +W030 */

    var allAttrs;
    if (options.patch === true) {
      allAttrs = _.extend({}, this.changedAttributes, attrs);
    } else {
      allAttrs = _.extend({}, this.attributes, attrs);
    }

    // Filter out null and undefined values
    var filteredAttributes = _.filter(EDITABLE_ATTRIBUTES, function (attr) {
      return allAttrs[attr] != null;
    });

    var allowedAttrs = _.pick(allAttrs, filteredAttributes);

    /* When `options.data` is supplied, Backbone does not attempt to infer its
     * content type. It must be explicitly set for the content to be
     * interpreted as JSON.
     */
    options.contentType = "application/json";
    options.data = JSON.stringify(allowedAttrs);

    return Backbone.Model.prototype.save.call(
      this, allowedAttrs, options);
  },

  setVersion: function (version) {
    this.set(_.pick(version.attributes, EDITABLE_ATTRIBUTES));
  },

  getCurrentVersion: function () {
    var version = new AppVersion();
    version.set(this.attributes);

    // make sure date is a string
    version.set({
      "version": version.get("version").toISOString()
    });

    // transfer app id
    version.options = {
      appId: this.get("id")
    };

    return version;
  },

  getStatus: function () {
    var status = "Running";
    if (this.isDeploying()) {
      status = "Deploying";
    } else if (this.get("instances") === 0 && this.formatTasksRunning() === 0) {
      status = "Suspended";
    }

    return status;
  },

  restart: function (options) {
    /* jshint -W030 */
    options || (options = {});
    /* jshint +W030 */

    if (options.force == null) {
      options.force = false;
    }

    options.contentType = "application/json";
    options.data = JSON.stringify({force: options.force});
    options.method = "POST";
    options.url = this.url() + "/restart";

    this.fetch(options);
  },

  hasHealth: function () {
    return this.get("healthChecks") != null &&
      this.get("healthChecks").length > 0;
  },

  suspend: function (options) {
    this.save({instances: 0}, options);
  },

  validate: function (attrs) {
    var errors = [];

    if (_.isNaN(attrs.mem) || !_.isNumber(attrs.mem) || attrs.mem < 0) {
      errors.push(
        new ValidationError("mem", "Memory must be a non-negative Number"));
    }

    if (_.isNaN(attrs.cpus) || !_.isNumber(attrs.cpus) || attrs.cpus < 0) {
      errors.push(
        new ValidationError("cpus", "CPUs must be a non-negative Number"));
    }

    if (_.isNaN(attrs.disk) || !_.isNumber(attrs.disk) || attrs.disk < 0) {
      errors.push(
        new ValidationError(
          "disk",
          "Disk Space must be a non-negative Number"
        )
      );
    }

    if (_.isNaN(attrs.instances) || !_.isNumber(attrs.instances) ||
        attrs.instances < 0) {
      errors.push(
        new ValidationError(
          "instances",
          "Instances must be a non-negative Number"
        )
      );
    }

    if (!_.isString(attrs.id) || attrs.id.length < 1) {
      errors.push(new ValidationError("id", "ID must not be empty"));
    }

    if (_.isString(attrs.executor) &&
        !VALID_EXECUTOR_REGEX.test(attrs.executor)) {
      errors.push(
        new ValidationError(
          "executor",
          "Executor must be the string '//cmd', a string containing only " +
          "single slashes ('/'), or blank."
        )
      );
    }

    if (!_.every(attrs.ports, function (p) { return _.isNumber(p); })) {
      errors.push(
        new ValidationError("ports", "Ports must be a list of Numbers"));
    }

    if (!attrs.constraints.every(isValidConstraint)) {
      errors.push(
        new ValidationError("constraints",
          "Invalid constraints format or operator. Supported operators are " +
          VALID_CONSTRAINTS.map(function (c) {
            return "`" + c + "`";
          }).join(", ") +
          ". See https://mesosphere.github.io/marathon/docs/constraints.html."
        )
      );
    }

    if (errors.length > 0) { return errors; }
  },

  url : function () {
    return this.isNew() ? "v2/apps" : "v2/apps/" + this.id;
  }
}, {
  VALID_EXECUTOR_PATTERN: VALID_EXECUTOR_PATTERN
});

module.exports = App;
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyleft Ian Buttimer
 *
 * @file        gulpfile.js
 * @author      Ian Buttimer
 * @date        26/05/16
 *
 * @type        javascript
 *
 * Based on:
 * @see https://www.mikestreety.co.uk/blog/advanced-gulp-file
 * @see http://stackoverflow.com/questions/23023650/is-it-possible-to-pass-a-flag-to-gulp-to-have-it-run-tasks-in-different-ways
 *
 * Run 'gulp --production' to enable production mode
 */

var gulp = require('gulp'),
  print = require('gulp-print'),
  cleancss = require('gulp-clean-css'),
  less = require('gulp-less'),
  jshint = require('gulp-jshint'),
  stylish = require('jshint-stylish'),
  uglify = require('gulp-uglify'),
  usemin = require('gulp-usemin'),      // Replaces references to non-optimized scripts or stylesheets into a set of HTML files
  sourcemaps = require('gulp-sourcemaps'),
  imagemin = require('gulp-imagemin'),
  rename = require('gulp-rename'),
  concat = require('gulp-concat'),
  notify = require('gulp-notify'),
  cache = require('gulp-cache'),
  changed = require('gulp-changed'),
  rev = require('gulp-rev'),            // Static asset revisioning by appending content hash to filenames
  browserSync = require('browser-sync'),
  del = require('del'),
  gutil = require('gulp-util'),
  argv = require('yargs')
    .usage('Usage: $0 -production')
    .argv,
    production = argv.production,
  gulpif = require('gulp-if'),
  gulpIgnore = require('gulp-ignore'),
  ngannotate = require('gulp-ng-annotate'),
  replace = require('gulp-replace-task'),
  path = require('path'),
  fs = require('fs');

var basePaths = {
    src: 'app/',
    dest: 'dist/',
    config: 'config/',
    bower: 'bower_components/'
  };
var paths = {
    images: {
      src: basePaths.src + 'images/',
      dest: basePaths.dest + 'images/'
    },
    scripts: {
      src: basePaths.src,
      dest: basePaths.dest
    },
    styles: {
      src: basePaths.src + 'styles/',
      dest: basePaths.dest + 'styles/'
    },
    fonts: {
      src: basePaths.src + 'fonts/',
      dest: basePaths.dest + 'fonts/'
    },
    views: {
      src: basePaths.src,
      dest: basePaths.dest
    },
    vendor: {
      src: basePaths.bower,
      dest: basePaths.dest + 'bower_components/'
    }
  };
paths.less = {
  src: basePaths.src + 'less/',
  dest: paths.styles.src
};

//canvasses
//election
//layout
//login
//people
//surveys
//users

/* for glob functionality see https://github.com/isaacs/node-glob */

var appFiles = {
  less: paths.less.src + '**/*.less',
  styles: paths.styles.src + '**/*.css',
  views: paths.views.src + '**/*.html',
  images: paths.images.src + '**/*',
  scripts: [paths.scripts.src + '**/*.js']  // all js files in paths.scripts.src or subdirectories
};
var vendorFiles = {
  fonts: [paths.vendor.src + 'font-awesome/fonts/**/*.{ttf,woff,eof,svg}*',
          paths.vendor.src + 'bootstrap/dist/fonts/**/*.{ttf,woff,eof,svg}*'],
  dev_fonts: [paths.vendor.src + '**/*.{ttf,woff,eof,svg}*'],
  styles: '',
//  scripts: [paths.vendor.src + '**/*.js'],
//  css: [paths.vendor.src + '**/*.css']
  scriptscss: [paths.vendor.src + '**/*.+(js|css)', // vendor js & css files
                // vendor js folders to exclude
                '!' + paths.vendor.src + 'angular-ui-router/src/*.js',
                '!' + paths.vendor.src + 'bootstrap/grunt/*.js',
                '!' + paths.vendor.src + 'bootstrap/js/*.js',
                '!' + paths.vendor.src + 'chart.js/samples/*.js',
                '!' + paths.vendor.src + 'chart.js/src/*.js',
                '!' + paths.vendor.src + 'chart.js/test/*.js',
                '!' + paths.vendor.src + 'jquery/src/*.js',
                '!' + paths.vendor.src + 'nya-bootstrap-select/e2e-test/*.js',
                '!' + paths.vendor.src + 'nya-bootstrap-select/tasks/*.js'
  ]
};

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

// Clean all output files
gulp.task('cleanall', function () {
  return del([basePaths.dest], {
//          force: true,  // Allow deleting the current working directory and outside
//          dryRun: true  // See what would be deleted
        }
       );
});

function noTrailingSlash (path) {
  var slashless,
    idx = path.length - 1;
  if (path.lastIndexOf('/') === idx) {
    slashless = path.substring(0, idx);
  } else {
    slashless = path;
  }
  return slashless;
}

// Clean just the app files
gulp.task('clean', function () {
  return del([basePaths.dest + '**',  // NOTE this deletes both parent & comtent!
              '!' + noTrailingSlash(basePaths.dest),  // exclude parent
              '!' + paths.vendor.dest + '**'          // exclude vendor files
        ], {
//          force: true,  // Allow deleting the current working directory and outside
//          dryRun: true  // See what would be deleted
        }
//        ).then(paths => {
//          console.log('Deleted files and folders:\n', paths.join('\n'));
//        }
       );
});

gulp.task('replace', function () {
  // based on http://geekindulgence.com/environment-variables-in-angularjs-and-ionic/

  // Get the environment from the command line
  var env = argv.env || 'localdev',

  // Read the settings from the right file
    filename = env + '.json',
    settings = JSON.parse(fs.readFileSync(basePaths.config + filename, 'utf8')),
    // basic patterns
    patterns = [
    // server/management app common settings
      { match: 'baseURL', replacement: settings.baseURL },
      { match: 'forceHttps', replacement: settings.forceHttps },
      { match: 'httpPort', replacement: settings.httpPort },
      { match: 'httpsPortOffset',  replacement: settings.httpsPortOffset },
      // management app settings
      { match: 'mapsApiKey', replacement: settings.mapsApiKey },
      { match: 'DEV_MODE', replacement: settings.DEV_MODE },
      { match: 'DEV_USER', replacement: settings.DEV_USER },
      { match: 'DEV_PASSWORD', replacement: settings.DEV_PASSWORD }
    ];

  // add dbg settins to patterns
  [ 'storeFactory',
    'localStorage',
    'surveyFactory',
    'canvassFactory',
    'electionFactory',
    'CanvassController',
    'CanvassActionController',
    'SurveyController',
    'navService'
  ].forEach(function (key) {
    var keyVal = settings[key] || false;
    patterns.push({ match: key, replacement: keyVal });
  });

  // Replace each placeholder with the correct value for the variable.
  gulp.src(basePaths.config + 'env.js')
  .pipe(replace({ patterns: patterns }))
    .pipe(gulp.dest(basePaths.src));
});

// Less css preprocessor
gulp.task('less', function () {

  return gulp.src(appFiles.less)
    .pipe(less())
    .pipe(gulp.dest(paths.less.dest));
});

function jsProcessChain() {
  // TODO get unknown provider error with uglify so skip for now
//  return [sourcemaps.init(), ngannotate(), uglify(), /*rev(),*/ sourcemaps.write()];
  return [ngannotate()];
}

function cssProcessChain() {
  return [cleancss()  /*, rev()*/];
}

gulp.task('usemin', ['jshint'], function () {

  if (!production) {
    gulp.src(appFiles.scripts)
      .pipe(changed(basePaths.dest))
      .pipe(gulp.dest(basePaths.dest));

    gulp.src(appFiles.styles)
      .pipe(changed(paths.styles.dest))
      .pipe(gulp.dest(paths.styles.dest));
  }

  return gulp.src(appFiles.views)
    .pipe(gulpif(production,
      usemin({
        css: cssProcessChain(),
        appcss: cssProcessChain(),
        js: jsProcessChain(),
        appjs: jsProcessChain()
      })))
    .pipe(gulp.dest(basePaths.dest))
    .pipe(notify(production ?
                 { message: 'Usemin task complete' } :
                 { message: 'Usemin task skipped in dev mode' }));
});

// Images
gulp.task('imagemin', function () {
  del(paths.images.dest);
  return gulp.src(appFiles.images)
    .pipe(cache(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true })))
    .pipe(gulp.dest(paths.images.dest))
    .pipe(notify({ message: 'Images task complete' }));
});

gulp.task('copyfonts', /*['clean'],*/ function () {
  var src = (production ? vendorFiles.fonts : vendorFiles.dev_fonts),
    dest = (production ? paths.fonts.dest : paths.vendor.dest);
  gulp.src(src)
    .pipe(changed(dest))
    .pipe(print())
    .pipe(gulp.dest(dest))
    .pipe(print(function(filepath) {
      return "copied: " + filepath;
    }))
    .pipe(notify({ message: 'Fonts task complete' }));
});

gulp.task('copyvendorscripts', function () {
  var src = vendorFiles.scripts,
    dest = paths.vendor.dest;
  gulp.src(src)
    .pipe(changed(dest))
    .pipe(print())
    .pipe(gulp.dest(dest))
    .pipe(notify({ message: 'Vendor scripts task complete' }));
});

gulp.task('copyvendorcss', function () {
  var src = vendorFiles.css,
    dest = paths.vendor.dest;
  gulp.src(src)
    .pipe(changed(dest))
    .pipe(print())
    .pipe(gulp.dest(dest))
    .pipe(notify({ message: 'Vendor css task complete' }));
});

//gulp.task('copyvendor', [/*'copyvendorcss',*/ 'copyvendorscripts'], function () {
gulp.task('copyvendor', function () {

  // TODO need the prints otherwise some files are not copied

  var src = vendorFiles.scriptscss,
    dest = paths.vendor.dest;
  gulp.src(src)
    .pipe(changed(dest))
    .pipe(print())
    .pipe(gulp.dest(dest))
    .pipe(print(function(filepath) {
      return "built: " + filepath;
    }))

    .pipe(notify({ message: 'Vendor script/css task complete' }));

});

// Watch
gulp.task('watch', ['browser-sync'], function() {
  // Watch js, css & html files
  gulp.watch([appFiles.scripts, appFiles.styles, appFiles.views], ['usemin']);
  // Watch image files
  gulp.watch(appFiles.images, ['imagemin']);

});

gulp.task('browser-sync', ['default'], function () {
  // files to watch
  var files = [
//      appFiles.views,
//      appFiles.styles,
//      appFiles.images,
//      appFiles.scripts//,
      basePaths.dest + '**/*'
    ];

    browserSync.init(/*files,*/ {
      files: files,
      server: {
        baseDir: basePaths.dest,
        index: 'index.html'
      }
    });

    // Watch any files in destination, reload on change
    gulp.watch([basePaths.dest + '**/*']).on('change', browserSync.reload);
});

// Default task
gulp.task('default', ['clean', 'replace', 'less'], function () {
  // TODO needs update, default shouldn't finish until these tasks are finished

  if (!production) {
    gulp.start('copyfonts',
             'usemin',
             'imagemin',
//        'copyvendorcss',
//        'copyvendorscripts',
            'copyvendor');
  } else {
    gulp.start('copyfonts',
             'usemin',
             'imagemin');
  }
});

// additional added tasks
gulp.task('clearCache', function () {
  // Still pass the files to clear cache for
  gulp.src(appFiles.images)
    .pipe(cache.clear());

  // Or, just call this for everything
//  cache.clearAll();
});

// Default task with acache clean
gulp.task('postmove', ['clean', 'clearCache'], function () {
    gulp.start('usemin', 'imagemin', 'copyfonts');
});
<commit_msg>less output from gulp<commit_after>/**************************************************************************
 * Copyleft Ian Buttimer
 *
 * @file        gulpfile.js
 * @author      Ian Buttimer
 * @date        26/05/16
 *
 * @type        javascript
 *
 * Based on:
 * @see https://www.mikestreety.co.uk/blog/advanced-gulp-file
 * @see http://stackoverflow.com/questions/23023650/is-it-possible-to-pass-a-flag-to-gulp-to-have-it-run-tasks-in-different-ways
 *
 * Run 'gulp --production' to enable production mode
 */

var gulp = require('gulp'),
  print = require('gulp-print'),
  cleancss = require('gulp-clean-css'),
  less = require('gulp-less'),
  jshint = require('gulp-jshint'),
  stylish = require('jshint-stylish'),
  uglify = require('gulp-uglify'),
  usemin = require('gulp-usemin'),      // Replaces references to non-optimized scripts or stylesheets into a set of HTML files
  sourcemaps = require('gulp-sourcemaps'),
  imagemin = require('gulp-imagemin'),
  rename = require('gulp-rename'),
  concat = require('gulp-concat'),
  notify = require('gulp-notify'),
  cache = require('gulp-cache'),
  changed = require('gulp-changed'),
  rev = require('gulp-rev'),            // Static asset revisioning by appending content hash to filenames
  browserSync = require('browser-sync'),
  del = require('del'),
  gutil = require('gulp-util'),
  argv = require('yargs')
    .usage('Usage: $0 -production')
    .argv,
    production = argv.production,
  gulpif = require('gulp-if'),
  gulpIgnore = require('gulp-ignore'),
  ngannotate = require('gulp-ng-annotate'),
  replace = require('gulp-replace-task'),
  path = require('path'),
  fs = require('fs');

var basePaths = {
    src: 'app/',
    dest: 'dist/',
    config: 'config/',
    bower: 'bower_components/'
  };
var paths = {
    images: {
      src: basePaths.src + 'images/',
      dest: basePaths.dest + 'images/'
    },
    scripts: {
      src: basePaths.src,
      dest: basePaths.dest
    },
    styles: {
      src: basePaths.src + 'styles/',
      dest: basePaths.dest + 'styles/'
    },
    fonts: {
      src: basePaths.src + 'fonts/',
      dest: basePaths.dest + 'fonts/'
    },
    views: {
      src: basePaths.src,
      dest: basePaths.dest
    },
    vendor: {
      src: basePaths.bower,
      dest: basePaths.dest + 'bower_components/'
    }
  };
paths.less = {
  src: basePaths.src + 'less/',
  dest: paths.styles.src
};

//canvasses
//election
//layout
//login
//people
//surveys
//users

/* for glob functionality see https://github.com/isaacs/node-glob */

var appFiles = {
  less: paths.less.src + '**/*.less',
  styles: paths.styles.src + '**/*.css',
  views: paths.views.src + '**/*.html',
  images: paths.images.src + '**/*',
  scripts: [paths.scripts.src + '**/*.js']  // all js files in paths.scripts.src or subdirectories
};
var vendorFiles = {
  fonts: [paths.vendor.src + 'font-awesome/fonts/**/*.{ttf,woff,eof,svg}*',
          paths.vendor.src + 'bootstrap/dist/fonts/**/*.{ttf,woff,eof,svg}*'],
  dev_fonts: [paths.vendor.src + '**/*.{ttf,woff,eof,svg}*'],
  styles: '',
//  scripts: [paths.vendor.src + '**/*.js'],
//  css: [paths.vendor.src + '**/*.css']
  scriptscss: [paths.vendor.src + '**/*.+(js|css)', // vendor js & css files
                // vendor js folders to exclude
                '!' + paths.vendor.src + 'angular-ui-router/src/*.js',
                '!' + paths.vendor.src + 'bootstrap/grunt/*.js',
                '!' + paths.vendor.src + 'bootstrap/js/*.js',
                '!' + paths.vendor.src + 'chart.js/samples/*.js',
                '!' + paths.vendor.src + 'chart.js/src/*.js',
                '!' + paths.vendor.src + 'chart.js/test/*.js',
                '!' + paths.vendor.src + 'jquery/src/*.js',
                '!' + paths.vendor.src + 'nya-bootstrap-select/e2e-test/*.js',
                '!' + paths.vendor.src + 'nya-bootstrap-select/tasks/*.js'
  ]
};

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

// Clean all output files
gulp.task('cleanall', function () {
  return del([basePaths.dest], {
//          force: true,  // Allow deleting the current working directory and outside
//          dryRun: true  // See what would be deleted
        }
       );
});

function noTrailingSlash (path) {
  var slashless,
    idx = path.length - 1;
  if (path.lastIndexOf('/') === idx) {
    slashless = path.substring(0, idx);
  } else {
    slashless = path;
  }
  return slashless;
}

// Clean just the app files
gulp.task('clean', function () {
  return del([basePaths.dest + '**',  // NOTE this deletes both parent & comtent!
              '!' + noTrailingSlash(basePaths.dest),  // exclude parent
              '!' + paths.vendor.dest + '**'          // exclude vendor files
        ], {
//          force: true,  // Allow deleting the current working directory and outside
//          dryRun: true  // See what would be deleted
        }
//        ).then(paths => {
//          console.log('Deleted files and folders:\n', paths.join('\n'));
//        }
       );
});

gulp.task('replace', function () {
  // based on http://geekindulgence.com/environment-variables-in-angularjs-and-ionic/

  // Get the environment from the command line
  var env = argv.env || 'localdev',

  // Read the settings from the right file
    filename = env + '.json',
    settings = JSON.parse(fs.readFileSync(basePaths.config + filename, 'utf8')),
    // basic patterns
    patterns = [
    // server/management app common settings
      { match: 'baseURL', replacement: settings.baseURL },
      { match: 'forceHttps', replacement: settings.forceHttps },
      { match: 'httpPort', replacement: settings.httpPort },
      { match: 'httpsPortOffset',  replacement: settings.httpsPortOffset },
      // management app settings
      { match: 'mapsApiKey', replacement: settings.mapsApiKey },
      { match: 'DEV_MODE', replacement: settings.DEV_MODE },
      { match: 'DEV_USER', replacement: settings.DEV_USER },
      { match: 'DEV_PASSWORD', replacement: settings.DEV_PASSWORD }
    ];

  // add dbg settins to patterns
  [ 'storeFactory',
    'localStorage',
    'surveyFactory',
    'canvassFactory',
    'electionFactory',
    'CanvassController',
    'CanvassActionController',
    'SurveyController',
    'navService'
  ].forEach(function (key) {
    var keyVal = settings[key] || false;
    patterns.push({ match: key, replacement: keyVal });
  });

  // Replace each placeholder with the correct value for the variable.
  gulp.src(basePaths.config + 'env.js')
  .pipe(replace({ patterns: patterns }))
    .pipe(gulp.dest(basePaths.src));
});

// Less css preprocessor
gulp.task('less', function () {

  return gulp.src(appFiles.less)
    .pipe(less())
    .pipe(gulp.dest(paths.less.dest));
});

function jsProcessChain() {
  // TODO get unknown provider error with uglify so skip for now
//  return [sourcemaps.init(), ngannotate(), uglify(), /*rev(),*/ sourcemaps.write()];
  return [ngannotate()];
}

function cssProcessChain() {
  return [cleancss()  /*, rev()*/];
}

gulp.task('usemin', ['jshint'], function () {
  var cmt;

  if (!production) {
    cmt = 'non-usemin: '
    gulp.src(appFiles.scripts)
      .pipe(changed(basePaths.dest))
      .pipe(gulp.dest(basePaths.dest));

    gulp.src(appFiles.styles)
      .pipe(changed(paths.styles.dest))
      .pipe(gulp.dest(paths.styles.dest));
  } else {
    cmt = 'usemin: '
  }

  return gulp.src(appFiles.views)
    .pipe(gulpif(production,
      usemin({
        css: cssProcessChain(),
        appcss: cssProcessChain(),
        js: jsProcessChain(),
        appjs: jsProcessChain()
      })))
    .pipe(gulp.dest(basePaths.dest))
    .pipe(print(function(filepath) {
      return cmt + filepath;
    }));
//    .pipe(notify(production ?
//                 { message: 'Usemin task complete' } :
//                 { message: 'Usemin task skipped in dev mode' }));
});

// Images
gulp.task('imagemin', function () {
  del(paths.images.dest);
  return gulp.src(appFiles.images)
    .pipe(cache(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true })))
    .pipe(gulp.dest(paths.images.dest))
    .pipe(notify({ message: 'Images task complete' }));
});

gulp.task('copyfonts', /*['clean'],*/ function () {
  var src = (production ? vendorFiles.fonts : vendorFiles.dev_fonts),
    dest = (production ? paths.fonts.dest : paths.vendor.dest);
  gulp.src(src)
    .pipe(changed(dest))
    .pipe(print())
    .pipe(gulp.dest(dest))
    .pipe(print(function(filepath) {
      return "copied: " + filepath;
    }))
    .pipe(notify({ message: 'Fonts task complete' }));
});

gulp.task('copyvendorscripts', function () {
  var src = vendorFiles.scripts,
    dest = paths.vendor.dest;
  gulp.src(src)
    .pipe(changed(dest))
    .pipe(print())
    .pipe(gulp.dest(dest))
    .pipe(notify({ message: 'Vendor scripts task complete' }));
});

gulp.task('copyvendorcss', function () {
  var src = vendorFiles.css,
    dest = paths.vendor.dest;
  gulp.src(src)
    .pipe(changed(dest))
    .pipe(print())
    .pipe(gulp.dest(dest))
    .pipe(notify({ message: 'Vendor css task complete' }));
});

//gulp.task('copyvendor', [/*'copyvendorcss',*/ 'copyvendorscripts'], function () {
gulp.task('copyvendor', function () {

  // TODO need the prints otherwise some files are not copied

  var src = vendorFiles.scriptscss,
    dest = paths.vendor.dest;
  gulp.src(src)
    .pipe(changed(dest))
    .pipe(print())
    .pipe(gulp.dest(dest))
    .pipe(print(function(filepath) {
      return "Vendor script/css: " + filepath;
    }));

//    .pipe(notify({ message: 'Vendor script/css task complete' }));

});

// Watch
gulp.task('watch', ['browser-sync'], function() {
  // Watch js, css & html files
  gulp.watch([appFiles.scripts, appFiles.styles, appFiles.views], ['usemin']);
  // Watch image files
  gulp.watch(appFiles.images, ['imagemin']);

});

gulp.task('browser-sync', ['default'], function () {
  // files to watch
  var files = [
//      appFiles.views,
//      appFiles.styles,
//      appFiles.images,
//      appFiles.scripts//,
      basePaths.dest + '**/*'
    ];

    browserSync.init(/*files,*/ {
      files: files,
      server: {
        baseDir: basePaths.dest,
        index: 'index.html'
      }
    });

    // Watch any files in destination, reload on change
    gulp.watch([basePaths.dest + '**/*']).on('change', browserSync.reload);
});

// Default task
gulp.task('default', ['clean', 'replace', 'less'], function () {
  // TODO needs update, default shouldn't finish until these tasks are finished

  if (!production) {
    gulp.start('copyfonts',
             'usemin',
             'imagemin',
//        'copyvendorcss',
//        'copyvendorscripts',
            'copyvendor');
  } else {
    gulp.start('copyfonts',
             'usemin',
             'imagemin');
  }
});

// additional added tasks
gulp.task('clearCache', function () {
  // Still pass the files to clear cache for
  gulp.src(appFiles.images)
    .pipe(cache.clear());

  // Or, just call this for everything
//  cache.clearAll();
});

// Default task with acache clean
gulp.task('postmove', ['clean', 'clearCache'], function () {
    gulp.start('usemin', 'imagemin', 'copyfonts');
});
<|endoftext|>


<commit_before>// FOUNDATION FOR APPS TEMPLATE GULPFILE
// -------------------------------------
// This file processes all of the assets in the "client" folder, combines them with the Foundation for Apps assets, and outputs the finished files in the "build" folder as a finished app.

// 1. LIBRARIES
// - - - - - - - - - - - - - - -

var $        = require('gulp-load-plugins')();
var argv     = require('yargs').argv;
var gulp     = require('gulp');
var rimraf   = require('rimraf');
var router   = require('front-router');
var sequence = require('run-sequence');
var browserSync = require('browser-sync').create();
var directiveReplace = require('gulp-directive-replace');

// Check for --production flag
var isProduction = !!(argv.production);

// 2. FILE PATHS
// - - - - - - - - - - - - - - -

var paths = {
  assets: [
    './client/**/*.*',
    '!./client/templates/**/*.*',
    '!./client/assets/{scss,js,components}/**/*.*'
  ],
  // Sass will check these folders for files when you use @import.
  sass: [
    'client/assets/scss',
    'bower_components/foundation-apps/scss',
    'client/assets/components/**/*.scss'
  ],
  // These files include Foundation for Apps and its dependencies
  foundationJS: [
    'bower_components/fastclick/lib/fastclick.js',
    'bower_components/viewport-units-buggyfill/viewport-units-buggyfill.js',
    'bower_components/tether/tether.js',
    'bower_components/hammerjs/hammer.js',
    'bower_components/angular/angular.js',
    'bower_components/angular-animate/angular-animate.js',
    'bower_components/angular-ui-router/release/angular-ui-router.js',
    'bower_components/foundation-apps/js/vendor/**/*.js',
    'bower_components/foundation-apps/js/angular/**/*.js',
    '!bower_components/foundation-apps/js/angular/app.js'
  ],
  // These files are for your app's JavaScript
  appJS: [
    'client/assets/js/app.js',
    'client/assets/js/services/*.js',
    'client/assets/js/utils/*.js',
    'client/assets/components/**/*.js',
  ],
  configJS: [
    './FUSION_CONFIG.js'
  ]
};

// 3. TASKS
// - - - - - - - - - - - - - - -

// Cleans the build directory
gulp.task('clean', function(cb) {
  rimraf('./build', cb);
});

// Copies everything in the client folder except templates, Sass, and JS
gulp.task('copy', function() {
  return gulp.src(paths.assets, {
    base: './client/'
  })
    .pipe(gulp.dest('./build'));
});

// Copies your app's page templates and generates URLs for them
gulp.task('copy:templates', function() {
  return gulp.src('./client/templates/**/*.html')
    .pipe(router({
      path: 'build/assets/js/routes.js',
      root: 'client'
    }))
    .pipe(gulp.dest('./build/templates'));
});

// Copies your app's page templates and generates URLs for them
gulp.task('copy:config', function() {
  return gulp.src(paths.configJS).pipe(gulp.dest('./build/assets/js/'));
});

// Compiles the Foundation for Apps directive partials into a single JavaScript file
gulp.task('copy:foundation', function(cb) {
  gulp.src('bower_components/foundation-apps/js/angular/components/**/*.html')
    .pipe($.ngHtml2js({
      prefix: 'components/',
      moduleName: 'foundation',
      declareModule: false
    }))
    .pipe($.uglify())
    .pipe($.concat('templates.js'))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('./build/assets/js'));

  // Iconic SVG icons
  gulp.src('./bower_components/foundation-apps/iconic/**/*')
    .pipe(gulp.dest('./build/assets/img/iconic/'));

  cb();
});

// Compiles Sass
gulp.task('sass', function () {
  var cssnano = $.if(isProduction, $.cssnano());

  return gulp.src('client/assets/scss/app.scss')
    .pipe($.sass({
      includePaths: paths.sass,
      outputStyle: (isProduction ? 'compressed' : 'nested'),
      errLogToConsole: true
    }))
    .pipe($.autoprefixer({
      browsers: ['last 2 versions', 'ie 10']
    }))
    .pipe(cssnano)
    .pipe(gulp.dest('./build/assets/css/'));
});

// Compiles and copies the Foundation for Apps JavaScript, as well as your app's custom JS
gulp.task('uglify', ['uglify:foundation', 'uglify:app']);

gulp.task('uglify:foundation', function(cb) {
  var uglify = $.if(isProduction, $.uglify()
    .on('error', function (e) {
      console.log(e);
    }));

  return gulp.src(paths.foundationJS)
    .pipe(uglify)
    .pipe($.concat('foundation.js'))
    .pipe(gulp.dest('./build/assets/js/'));
});

gulp.task('uglify:app', function() {
  var uglify = $.if(isProduction, $.uglify()
    .on('error', function (e) {
      console.log(e);
    }));

  return gulp.src(paths.appJS)
    .pipe(uglify)
    .pipe($.ngAnnotate())
    .pipe($.directiveReplace({root: 'client'}))
    .pipe($.sourcemaps.init())
    .pipe($.concat('app.js'))
    .pipe(gulp.dest('./build/assets/js/'));
});

// Starts a test server, which you can view at http://localhost:8079
gulp.task('server', ['build'], function() {
  gulp.src('./build')
    .pipe($.webserver({
      port: 8079,
      host: 'localhost',
      fallback: 'index.html',
      livereload: true,
      open: true
    }));
});

// Static Server + watching build and live reload accross all the browsers
gulp.task('browsersync', ['build'], function() {

    browserSync.init({
        server: "./build"
    });

    // gulp.watch("app/scss/*.scss", ['sass']);
    // gulp.watch("app/*.html").on('change', browserSync.reload);
});

//Reloads all the browsers
gulp.task('reloadBrowsers', browserSync.reload);

// Builds your entire app once, without starting a server
gulp.task('build', function(cb) {
  sequence('clean', ['copy', 'copy:foundation', 'sass', 'uglify'], 'copy:templates', 'copy:config', cb);
});

// Default task: builds your app, starts a server, and recompiles assets when they change
gulp.task('default', ['browsersync'], function () {
  // Watch Sass
  gulp.watch(['./client/assets/scss/**/*', './scss/**/*'], ['sass', 'reloadBrowsers']);

  // Watch JavaScript
  gulp.watch(['./client/assets/js/**/*', './js/**/*'], ['uglify:app', 'reloadBrowsers']);

  // Watch Directives
  gulp.watch(['./client/assets/components/**/*'], ['uglify:app', 'copy', 'reloadBrowsers']);

  // Watch static files
  gulp.watch(['./client/**/*.*', '!./client/templates/**/*.*', '!./client/assets/{scss,js}/**/*.*'], ['copy', 'reloadBrowsers']);

  // Watch app templates
  gulp.watch(['./client/templates/**/*.html'], ['copy:templates', 'reloadBrowsers']);

  // Watch config
  gulp.watch(paths.configJS, ['copy:config', 'reloadBrowsers']);
});

gulp.task('serve', ['server'], function () {
  // Watch Sass
  gulp.watch(['./client/assets/scss/**/*', './scss/**/*'], ['sass']);

  // Watch JavaScript
  gulp.watch(['./client/assets/js/**/*', './js/**/*'], ['uglify:app']);

  // Watch static files
  gulp.watch(['./client/**/*.*', '!./client/templates/**/*.*', '!./client/assets/{scss,js,components}/**/*.*'], ['copy']);

  // Watch app templates
  gulp.watch(['./client/templates/**/*.html', './client/assets/components/**/*.html'], ['copy:templates']);

  // Watch config
  gulp.watch(paths.configJS, ['uglify:app', 'reloadBrowsers']);
});
<commit_msg>another cleanup<commit_after>// FOUNDATION FOR APPS TEMPLATE GULPFILE
// -------------------------------------
// This file processes all of the assets in the "client" folder, combines them with the Foundation for Apps assets, and outputs the finished files in the "build" folder as a finished app.

// 1. LIBRARIES
// - - - - - - - - - - - - - - -

var $        = require('gulp-load-plugins')();
var argv     = require('yargs').argv;
var gulp     = require('gulp');
var rimraf   = require('rimraf');
var router   = require('front-router');
var sequence = require('run-sequence');
var browserSync = require('browser-sync').create();

// Check for --production flag
var isProduction = !!(argv.production);

// 2. FILE PATHS
// - - - - - - - - - - - - - - -

var paths = {
  assets: [
    './client/**/*.*',
    '!./client/templates/**/*.*',
    '!./client/assets/{scss,js,components}/**/*.*'
  ],
  // Sass will check these folders for files when you use @import.
  sass: [
    'client/assets/scss',
    'bower_components/foundation-apps/scss',
    'client/assets/components/**/*.scss'
  ],
  // These files include Foundation for Apps and its dependencies
  foundationJS: [
    'bower_components/fastclick/lib/fastclick.js',
    'bower_components/viewport-units-buggyfill/viewport-units-buggyfill.js',
    'bower_components/tether/tether.js',
    'bower_components/hammerjs/hammer.js',
    'bower_components/angular/angular.js',
    'bower_components/angular-animate/angular-animate.js',
    'bower_components/angular-ui-router/release/angular-ui-router.js',
    'bower_components/foundation-apps/js/vendor/**/*.js',
    'bower_components/foundation-apps/js/angular/**/*.js',
    '!bower_components/foundation-apps/js/angular/app.js'
  ],
  // These files are for your app's JavaScript
  appJS: [
    'client/assets/js/app.js',
    'client/assets/js/services/*.js',
    'client/assets/js/utils/*.js',
    'client/assets/components/**/*.js',
  ],
  configJS: [
    './FUSION_CONFIG.js'
  ]
};

// 3. TASKS
// - - - - - - - - - - - - - - -

// Cleans the build directory
gulp.task('clean', function(cb) {
  rimraf('./build', cb);
});

// Copies everything in the client folder except templates, Sass, and JS
gulp.task('copy', function() {
  return gulp.src(paths.assets, {
    base: './client/'
  })
    .pipe(gulp.dest('./build'));
});

// Copies your app's page templates and generates URLs for them
gulp.task('copy:templates', function() {
  return gulp.src('./client/templates/**/*.html')
    .pipe(router({
      path: 'build/assets/js/routes.js',
      root: 'client'
    }))
    .pipe(gulp.dest('./build/templates'));
});

// Copies your app's page templates and generates URLs for them
gulp.task('copy:config', function() {
  return gulp.src(paths.configJS).pipe(gulp.dest('./build/assets/js/'));
});

// Compiles the Foundation for Apps directive partials into a single JavaScript file
gulp.task('copy:foundation', function(cb) {
  gulp.src('bower_components/foundation-apps/js/angular/components/**/*.html')
    .pipe($.ngHtml2js({
      prefix: 'components/',
      moduleName: 'foundation',
      declareModule: false
    }))
    .pipe($.uglify())
    .pipe($.concat('templates.js'))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('./build/assets/js'));

  // Iconic SVG icons
  gulp.src('./bower_components/foundation-apps/iconic/**/*')
    .pipe(gulp.dest('./build/assets/img/iconic/'));

  cb();
});

// Compiles Sass
gulp.task('sass', function () {
  var cssnano = $.if(isProduction, $.cssnano());

  return gulp.src('client/assets/scss/app.scss')
    .pipe($.sass({
      includePaths: paths.sass,
      outputStyle: (isProduction ? 'compressed' : 'nested'),
      errLogToConsole: true
    }))
    .pipe($.autoprefixer({
      browsers: ['last 2 versions', 'ie 10']
    }))
    .pipe(cssnano)
    .pipe(gulp.dest('./build/assets/css/'));
});

// Compiles and copies the Foundation for Apps JavaScript, as well as your app's custom JS
gulp.task('uglify', ['uglify:foundation', 'uglify:app']);

gulp.task('uglify:foundation', function(cb) {
  var uglify = $.if(isProduction, $.uglify()
    .on('error', function (e) {
      console.log(e);
    }));

  return gulp.src(paths.foundationJS)
    .pipe(uglify)
    .pipe($.concat('foundation.js'))
    .pipe(gulp.dest('./build/assets/js/'));
});

gulp.task('uglify:app', function() {
  var uglify = $.if(isProduction, $.uglify()
    .on('error', function (e) {
      console.log(e);
    }));

  return gulp.src(paths.appJS)
    .pipe(uglify)
    .pipe($.ngAnnotate())
    .pipe($.directiveReplace({root: 'client'}))
    .pipe($.sourcemaps.init())
    .pipe($.concat('app.js'))
    .pipe(gulp.dest('./build/assets/js/'));
});

// Starts a test server, which you can view at http://localhost:8079
gulp.task('server', ['build'], function() {
  gulp.src('./build')
    .pipe($.webserver({
      port: 8079,
      host: 'localhost',
      fallback: 'index.html',
      livereload: true,
      open: true
    }));
});

// Static Server + watching build and live reload accross all the browsers
gulp.task('browsersync', ['build'], function() {

    browserSync.init({
        server: "./build"
    });

    // gulp.watch("app/scss/*.scss", ['sass']);
    // gulp.watch("app/*.html").on('change', browserSync.reload);
});

//Reloads all the browsers
gulp.task('reloadBrowsers', browserSync.reload);

// Builds your entire app once, without starting a server
gulp.task('build', function(cb) {
  sequence('clean', ['copy', 'copy:foundation', 'sass', 'uglify'], 'copy:templates', 'copy:config', cb);
});

// Default task: builds your app, starts a server, and recompiles assets when they change
gulp.task('default', ['browsersync'], function () {
  // Watch Sass
  gulp.watch(['./client/assets/scss/**/*', './scss/**/*'], ['sass', 'reloadBrowsers']);

  // Watch JavaScript
  gulp.watch(['./client/assets/js/**/*', './js/**/*'], ['uglify:app', 'reloadBrowsers']);

  // Watch Directives
  gulp.watch(['./client/assets/components/**/*'], ['uglify:app', 'copy', 'reloadBrowsers']);

  // Watch static files
  gulp.watch(['./client/**/*.*', '!./client/templates/**/*.*', '!./client/assets/{scss,js}/**/*.*'], ['copy', 'reloadBrowsers']);

  // Watch app templates
  gulp.watch(['./client/templates/**/*.html'], ['copy:templates', 'reloadBrowsers']);

  // Watch config
  gulp.watch(paths.configJS, ['copy:config', 'reloadBrowsers']);
});

gulp.task('serve', ['server'], function () {
  // Watch Sass
  gulp.watch(['./client/assets/scss/**/*', './scss/**/*'], ['sass']);

  // Watch JavaScript
  gulp.watch(['./client/assets/js/**/*', './js/**/*'], ['uglify:app']);

  // Watch static files
  gulp.watch(['./client/**/*.*', '!./client/templates/**/*.*', '!./client/assets/{scss,js,components}/**/*.*'], ['copy']);

  // Watch app templates
  gulp.watch(['./client/templates/**/*.html', './client/assets/components/**/*.html'], ['copy:templates']);

  // Watch config
  gulp.watch(paths.configJS, ['uglify:app', 'reloadBrowsers']);
});
<|endoftext|>


<commit_before>// Include gulp
var gulp = require('gulp'),
  fs = require('fs'),
  pkg = JSON.parse(fs.readFileSync('./package.json'))
  beep = require('beepbeep'),
  onError = function (err) { beep(); }
;

// Include Our Plugins
var appcache = require('gulp-appcache'),
  clone      = require('gulp-clone'),
  concat     = require('gulp-concat'),
  imageResize= require('gulp-image-resize')
  jshint     = require('gulp-jshint'),
  livereload = require('gulp-livereload'),
  plumber    = require('gulp-plumber'),
  postcss    = require('gulp-postcss'),
  rename     = require("gulp-rename"),
  replace    = require('gulp-replace'),
  sass       = require('gulp-sass'),
  shell      = require('gulp-shell'),
  sourcemaps = require('gulp-sourcemaps'),
  uglify     = require('gulp-uglify')
;

// Lint Task
gulp.task('jshint', function() {
  return gulp.src([
      pkg.directories.js_src + '/**/*.js',
      '!' + pkg.directories.js_src + '/vendor/*.js'
    ])
    .pipe(plumber({errorHandler: onError}))
    .pipe(jshint({ // see https://github.com/jshint/jshint/blob/master/examples/.jshintrc
      browser: true,
      jquery: true,
      strict: true,
      curly: true,
      undef: true
    }))
    .pipe(jshint.reporter('default'))
    .pipe(jshint.reporter('fail'))
  ;
});

// Concatenate & Minify JS
gulp.task('uglify', function() {
  return gulp.src([
      pkg.directories.js_src + '/vendor/*.js', // disable this line by prepending '!' - in case of errors
      pkg.directories.js_src + '/modules/*.js',
      pkg.directories.js_src + '/main.js'
    ])
    .pipe(concat('scripts.js'))
    .pipe(uglify({output: {
      max_line_len: 9000
    }}))
    .pipe(gulp.dest(pkg.directories.js))
    .pipe(livereload());
  ;
});

// Sass
gulp.task('sass', function(cb) {
  return gulp.src(pkg.directories.sass + '/**/*.scss')
    .pipe(plumber({errorHandler: onError}))
    .pipe(sass({outputStyle: 'compact'}).on('error', sass.logError))
    .pipe(gulp.dest(pkg.directories.css))
  ;
  cb(err);
});

// PostCSS
gulp.task('postcss',['sass'], function (cb) {
  return gulp.src(pkg.directories.css + '/styles.css')
    .pipe( postcss([ require('autoprefixer')({browsers: ['last 2 versions', '> 2%', 'ie 8', 'ie 9']})]) )
    .pipe( gulp.dest(pkg.directories.css) )
    .pipe( postcss([ require('rtlcss')]) )
    .pipe(rename('rtl.css'))
    .pipe( gulp.dest(pkg.directories.css) )
  ;
  cb(err);
});

gulp.task('oldie',['postcss'], function () {
  var css = gulp.src(pkg.directories.css + '/*.css')
    .pipe(replace(/(\n)\s*\n/g, '$1'))
  ;

  var oldie = css.pipe(clone())
    .pipe(replace(/\/\*#.+?\*\//g, ''))
    .pipe(replace(/@media[^\{]+tty[^\{]+\{ (.+ \}) \}(\s*)/g, '$1$2'))
    .pipe(replace(/(@media[^\{]+device-pixel-ratio[^\{]+\{ [\s\S]+? \} \}\s*)/g, ''))
    .pipe(replace(/(@media screen) [^\{]+ \(max-width: \d+px\)( \{ [\s\S]+? \} \}\s*)/g, ''))
    .pipe(replace(/(@media screen) and \(.+?\)( \{ [\s\S]+? \} \}\s*)/g, '$1$2'))
    .pipe(replace(/-(moz|webkit)-[^\{]+?:.+?;\s*/g, ''))
    .pipe(replace(/(transition|border-[\S]*radius):.+?;\s*/g, ''))
    .pipe(replace(/opacity: 0;\s*/g, 'visibility: hidden; '))
    .pipe(replace(/opacity: 1;\s*/g, 'visibility: visible; '))
    .pipe(replace(/rgba(\(.+?),\s?[\d\.]+(\))/g, 'rgb$1$2'))
    .pipe(replace(/\s\S+\s?\{\s+\}/g, ''))
    .pipe(replace(/([\d\.]+)vw/g, function (regexMatches) {
      return Math.round(parseFloat(regexMatches[0]) * 10.24) + 'px'; // matches 1024px
    }))
    .pipe(replace(/([\d\.]+)vh/g, function (regexMatches) {
      return Math.round(parseFloat(regexMatches[0]) * 7.68) + 'px'; // matches 768 px
    }))
    .pipe(replace(/([\d\.]+)rem/g, function (regexMatches) {
      return Math.round(parseFloat(regexMatches[0]) * 12) + 'px'; // matches $fontsize-default
    }))
    .pipe( gulp.dest(pkg.directories.css + '/oldie') )
  ;

  return css
    .pipe(replace(/(@media[^\{]+tty[^\{]+\{ [\s\S]+? \} \}\s*)/g, ''))
    .pipe( gulp.dest(pkg.directories.css) )
    .pipe(livereload());
  ;
});

gulp.task('appcache', function(){
  gulp.src([
    pkg.directories.template + '/**/*',
    '!'+pkg.directories.template + '/*.html',
    '!'+pkg.directories.images + '/article*/*',
    '!'+pkg.directories.images + '/originals/*',
    '!'+pkg.directories.css + '/oldie/*'
  ])
  .pipe(appcache({
    //relativePath: pkg.directories.template,
    hash: true,
    preferOnline: true,
    filename: 'manifest.appcache',
    exclude: 'manifest.appcache'
  }))
  .pipe(gulp.dest(pkg.directories.template));
});

gulp.task('logo', function() {
  var logo = gulp.src(pkg.directories.images + '/logo.png');

  [
    {
      width: 32,
      height: 32,
      name: 'favicon.ico',
      directory: pkg.directories.template
    },{
      width: 96,
      height: 96,
      name: 'favicon-96x96.png',
      directory: pkg.directories.template
    },{
      width: 152,
      height: 152,
      name: 'apple-touch-icon-precomposed.png',
      directory: pkg.directories.template
    },{
      width: 196,
      height: 196,
      name: 'favicon-196x196.png',
      directory: pkg.directories.template
    },{
      width: 128,
      height: 128,
      name: 'tile-128x128.png',
      directory: pkg.directories.images
    },{
      width: 270,
      height: 270,
      name: 'tile-270x270.png',
      directory: pkg.directories.images
    },{
      width: 558,
      height: 270,
      name: 'tile-558x270.png',
      directory: pkg.directories.images
    },{
      width: 558,
      height: 558,
      name: 'tile-558x558.png',
      directory: pkg.directories.images
    }
  ].forEach(function(i) {
    logo.pipe(clone())
      .pipe(imageResize({
        width: i.width,
        height: i.height,
        crop: true,
        quality: 0.7,
        gravity: 'Center',
        imageMagick: true
      }))
      .pipe(rename(i.name))
      .pipe(gulp.dest(i.directory))
    ;
  })
  return logo;
});

gulp.task('article_images', function() {
  var article_images = gulp.src(pkg.directories.images + '/originals/*.jpg');

  [{ width: 640, height: 360 },{ width: 1280, height: 720 }].forEach(function(i) {
    article_images.pipe(clone())
      .pipe(imageResize({
        width: i.width,
        height: i.height,
        crop: true,
        quality: 0.7,
        gravity: 'Center',
        imageMagick: true
      }))
      .pipe(gulp.dest(pkg.directories.images + '/articles-'+i.width))
    ;
  });
  return article_images;
});

gulp.task('deploy_live', shell.task([
  pkg.directories.build + '/deploy.sh live'
]));
gulp.task('vagrant_up', shell.task([
  'cd ' + pkg.directories.build + '/vagrant && vagrant up && cd -'
]));
gulp.task('vagrant_suspend', shell.task([
  'cd ' + pkg.directories.build + '/vagrant && vagrant suspend && cd -'
]));

// Watch Files For Changes
gulp.task('watch', function() {
  livereload.listen();
  gulp.watch(pkg.directories.js_src + '/**/*.js', ['build-js']);
  gulp.watch(pkg.directories.sass + '/**/*.scss', ['build-sass']);
  gulp.watch(pkg.directories.images + '/logo.png', ['build-icons']);
  gulp.watch(pkg.directories.images + '/originals/*.jpg', ['build-article-images']);
});

// Default Task
gulp.task('default',     ['build-js','build-sass','build-icons']);
gulp.task('build-sass',  ['sass','postcss','oldie','appcache']);
gulp.task('build-js',    ['jshint','uglify','appcache']);
gulp.task('build-icons', ['logo','appcache']);
gulp.task('build-article-images',    ['article_images','appcache']);
<commit_msg>Fixed gulpfile<commit_after>// Include gulp
var gulp = require('gulp'),
  fs = require('fs'),
  pkg = JSON.parse(fs.readFileSync('./package.json'))
  beep = require('beepbeep'),
  onError = function (err) { beep(); }
;

// Include Our Plugins
var appcache = require('gulp-appcache'),
  clone      = require('gulp-clone'),
  concat     = require('gulp-concat'),
  imageResize= require('gulp-image-resize'),
  jshint     = require('gulp-jshint'),
  livereload = require('gulp-livereload'),
  plumber    = require('gulp-plumber'),
  postcss    = require('gulp-postcss'),
  rename     = require("gulp-rename"),
  replace    = require('gulp-replace'),
  sass       = require('gulp-sass'),
  shell      = require('gulp-shell'),
  sourcemaps = require('gulp-sourcemaps'),
  uglify     = require('gulp-uglify')
;

// Lint Task
gulp.task('jshint', function() {
  return gulp.src([
      pkg.directories.js_src + '/**/*.js',
      '!' + pkg.directories.js_src + '/vendor/*.js'
    ])
    .pipe(plumber({errorHandler: onError}))
    .pipe(jshint({ // see https://github.com/jshint/jshint/blob/master/examples/.jshintrc
      browser: true,
      jquery: true,
      strict: true,
      curly: true,
      undef: true
    }))
    .pipe(jshint.reporter('default'))
    .pipe(jshint.reporter('fail'))
  ;
});

// Concatenate & Minify JS
gulp.task('uglify', function() {
  return gulp.src([
      pkg.directories.js_src + '/vendor/*.js', // disable this line by prepending '!' - in case of errors
      pkg.directories.js_src + '/modules/*.js',
      pkg.directories.js_src + '/main.js'
    ])
    .pipe(concat('scripts.js'))
    .pipe(uglify({output: {
      max_line_len: 9000
    }}))
    .pipe(gulp.dest(pkg.directories.js))
    .pipe(livereload());
  ;
});

// Sass
gulp.task('sass', function(cb) {
  return gulp.src(pkg.directories.sass + '/**/*.scss')
    .pipe(plumber({errorHandler: onError}))
    .pipe(sass({outputStyle: 'compact'}).on('error', sass.logError))
    .pipe(gulp.dest(pkg.directories.css))
  ;
  cb(err);
});

// PostCSS
gulp.task('postcss',['sass'], function (cb) {
  return gulp.src(pkg.directories.css + '/styles.css')
    .pipe( postcss([ require('autoprefixer')({browsers: ['last 2 versions', '> 2%', 'ie 8', 'ie 9']})]) )
    .pipe( gulp.dest(pkg.directories.css) )
    .pipe( postcss([ require('rtlcss')]) )
    .pipe(rename('rtl.css'))
    .pipe( gulp.dest(pkg.directories.css) )
  ;
  cb(err);
});

gulp.task('oldie',['postcss'], function () {
  var css = gulp.src(pkg.directories.css + '/*.css')
    .pipe(replace(/(\n)\s*\n/g, '$1'))
  ;

  var oldie = css.pipe(clone())
    .pipe(replace(/\/\*#.+?\*\//g, ''))
    .pipe(replace(/@media[^\{]+tty[^\{]+\{ (.+ \}) \}(\s*)/g, '$1$2'))
    .pipe(replace(/(@media[^\{]+device-pixel-ratio[^\{]+\{ [\s\S]+? \} \}\s*)/g, ''))
    .pipe(replace(/(@media screen) [^\{]+ \(max-width: \d+px\)( \{ [\s\S]+? \} \}\s*)/g, ''))
    .pipe(replace(/(@media screen) and \(.+?\)( \{ [\s\S]+? \} \}\s*)/g, '$1$2'))
    .pipe(replace(/-(moz|webkit)-[^\{]+?:.+?;\s*/g, ''))
    .pipe(replace(/(transition|border-[\S]*radius):.+?;\s*/g, ''))
    .pipe(replace(/opacity: 0;\s*/g, 'visibility: hidden; '))
    .pipe(replace(/opacity: 1;\s*/g, 'visibility: visible; '))
    .pipe(replace(/rgba(\(.+?),\s?[\d\.]+(\))/g, 'rgb$1$2'))
    .pipe(replace(/\s\S+\s?\{\s+\}/g, ''))
    .pipe(replace(/([\d\.]+)vw/g, function (regexMatches) {
      return Math.round(parseFloat(regexMatches[0]) * 10.24) + 'px'; // matches 1024px
    }))
    .pipe(replace(/([\d\.]+)vh/g, function (regexMatches) {
      return Math.round(parseFloat(regexMatches[0]) * 7.68) + 'px'; // matches 768 px
    }))
    .pipe(replace(/([\d\.]+)rem/g, function (regexMatches) {
      return Math.round(parseFloat(regexMatches[0]) * 12) + 'px'; // matches $fontsize-default
    }))
    .pipe( gulp.dest(pkg.directories.css + '/oldie') )
  ;

  return css
    .pipe(replace(/(@media[^\{]+tty[^\{]+\{ [\s\S]+? \} \}\s*)/g, ''))
    .pipe( gulp.dest(pkg.directories.css) )
    .pipe(livereload());
  ;
});

gulp.task('appcache', function(){
  gulp.src([
    pkg.directories.template + '/**/*',
    '!'+pkg.directories.template + '/*.html',
    '!'+pkg.directories.images + '/article*/*',
    '!'+pkg.directories.images + '/originals/*',
    '!'+pkg.directories.css + '/oldie/*'
  ])
  .pipe(appcache({
    //relativePath: pkg.directories.template,
    hash: true,
    preferOnline: true,
    filename: 'manifest.appcache',
    exclude: 'manifest.appcache'
  }))
  .pipe(gulp.dest(pkg.directories.template));
});

gulp.task('logo', function() {
  var logo = gulp.src(pkg.directories.images + '/logo.png');

  [
    {
      width: 32,
      height: 32,
      name: 'favicon.ico',
      directory: pkg.directories.template
    },{
      width: 96,
      height: 96,
      name: 'favicon-96x96.png',
      directory: pkg.directories.template
    },{
      width: 152,
      height: 152,
      name: 'apple-touch-icon-precomposed.png',
      directory: pkg.directories.template
    },{
      width: 196,
      height: 196,
      name: 'favicon-196x196.png',
      directory: pkg.directories.template
    },{
      width: 128,
      height: 128,
      name: 'tile-128x128.png',
      directory: pkg.directories.images
    },{
      width: 270,
      height: 270,
      name: 'tile-270x270.png',
      directory: pkg.directories.images
    },{
      width: 558,
      height: 270,
      name: 'tile-558x270.png',
      directory: pkg.directories.images
    },{
      width: 558,
      height: 558,
      name: 'tile-558x558.png',
      directory: pkg.directories.images
    }
  ].forEach(function(i) {
    logo.pipe(clone())
      .pipe(imageResize({
        width: i.width,
        height: i.height,
        crop: true,
        quality: 0.7,
        gravity: 'Center',
        imageMagick: true
      }))
      .pipe(rename(i.name))
      .pipe(gulp.dest(i.directory))
    ;
  })
  return logo;
});

gulp.task('article_images', function() {
  var article_images = gulp.src(pkg.directories.images + '/originals/*.jpg');

  [{ width: 640, height: 360 },{ width: 1280, height: 720 }].forEach(function(i) {
    article_images.pipe(clone())
      .pipe(imageResize({
        width: i.width,
        height: i.height,
        crop: true,
        quality: 0.7,
        gravity: 'Center',
        imageMagick: true
      }))
      .pipe(gulp.dest(pkg.directories.images + '/articles-'+i.width))
    ;
  });
  return article_images;
});

gulp.task('deploy_live', shell.task([
  pkg.directories.build + '/deploy.sh live'
]));
gulp.task('vagrant_up', shell.task([
  'cd ' + pkg.directories.build + '/vagrant && vagrant up && cd -'
]));
gulp.task('vagrant_suspend', shell.task([
  'cd ' + pkg.directories.build + '/vagrant && vagrant suspend && cd -'
]));

// Watch Files For Changes
gulp.task('watch', function() {
  livereload.listen();
  gulp.watch(pkg.directories.js_src + '/**/*.js', ['build-js']);
  gulp.watch(pkg.directories.sass + '/**/*.scss', ['build-sass']);
  gulp.watch(pkg.directories.images + '/logo.png', ['build-icons']);
  gulp.watch(pkg.directories.images + '/originals/*.jpg', ['build-article-images']);
});

// Default Task
gulp.task('default',     ['build-js','build-sass','build-icons']);
gulp.task('build-sass',  ['sass','postcss','oldie','appcache']);
gulp.task('build-js',    ['jshint','uglify','appcache']);
gulp.task('build-icons', ['logo','appcache']);
gulp.task('build-article-images',    ['article_images','appcache']);
<|endoftext|>


<commit_before>var gulp = require('gulp');
var del = require('del');
var browserSync = require('browser-sync');
var concat = require('gulp-concat');
var imagemin = require('gulp-imagemin');
var less = require('gulp-less');
var uglify = require('gulp-uglify');
var uglifycss = require('gulp-uglifycss');
var reload = browserSync.reload;

var isDev = function(){
  return process.env.NODE_ENV.trim() === 'development';
}();

var isProd = function(){
  return process.env.NODE_ENV.trim() === 'production';
}();

gulp.task('clean', function(cb){
  var stream = del(['dist/**/*'], cb);
  return stream;
});

gulp.task('copy:html', function(){
  gulp.src('src/**/*.{html,htm}')
      .pipe(gulp.dest('dist/'));
});

gulp.task('copy:lib', function(){
  gulp.src('node_modules/angular/angular.min.js')
      .pipe(gulp.dest('dist/js/angular/'));
  gulp.src('node_modules/angular-toastr/dist/*.{js,css}')
      .pipe(gulp.dest('dist/js/angular-toastr/'));
  gulp.src('node_modules/angular-ui-router/release/angular-ui-router.min.js')
      .pipe(gulp.dest('dist/js/angular-ui-router/'));
  gulp.src('node_modules/ng-dialog/js/ngDialog.min.js')
      .pipe(gulp.dest('dist/js/ng-dialog/'));
  gulp.src('node_modules/ng-dialog/css/**/*.css')
      .pipe(gulp.dest('dist/js/ng-dialog/'));
  gulp.src('node_modules/ng-file-upload/dist/*.*')
      .pipe(gulp.dest('dist/js/ng-file-upload/'));
  gulp.src('node_modules/ngstorage/ngStorage.min.js')
      .pipe(gulp.dest('dist/js/ngstorage/'));
  gulp.src('node_modules/oclazyload/dist/ocLazyLoad.min.js')
      .pipe(gulp.dest('dist/js/oclazyload/'));
});

gulp.task('imagemin', function(){
  gulp.src('src/img/*')
      .pipe(imagemin())
      .pipe(gulp.dest('dist/img/'));
});

gulp.task('less', function(){
  gulp.src('src/less/*')
      .pipe(less())
      .pipe(gulp.dest('dist/css/'))
      .pipe(reload({stream: true}));
});

gulp.task('less:uglifycss', function(){
  gulp.src('src/less/*')
      .pipe(less())
      .pipe(uglifycss())
      .pipe(gulp.dest('dist/css/'));
});

gulp.task('concat:appjs', function(){
  gulp.src(['src/app.config.js', 'src/app.js', 'src/app.filter.js', 'src/app.services.js'])
      .pipe(concat('app.js'))
      .pipe(gulp.dest('dist/'));
});

gulp.task('uglify:concat:appjs', function(){
  gulp.src(['src/app.config.js', 'src/app.js', 'src/app.filter.js', 'src/app.services.js'])
      .pipe(uglify())
      .pipe(concat('app.js'))
      .pipe(gulp.dest('dist/'));
});

gulp.task('copy:pagejs', function(){
  gulp.src(['src/**/*.js', '!src/*.js'])
      .pipe(gulp.dest('dist/'));
});

gulp.task('uglify:pagejs', function(){
  gulp.src(['src/**/*.js', '!src/*.js'])
      .pipe(uglify())
      .pipe(gulp.dest('dist/'));
});

gulp.task('server', ['less'], function(){
  browserSync({
    server: {
      baseDir: 'dist'
    },
    port: 8000
  });
  console.log(reload);
  gulp.watch("app/less/*.less", ['less']);
  gulp.watch(['src/**/*', '!src/less/*.less']).on('change', reload);
});

gulp.task('watch', function(){
  gulp.watch('src/**/*.{html,htm}', ['copy:html']);
  gulp.watch('src/img/*', ['imagemin']);
  gulp.watch('src/less/*', ['less']);
  gulp.watch(['src/app.config.js', 'src/app.js', 'src/app.filter.js', 'src/app.services.js'], ['concat:appjs']);
  gulp.watch(['src/**/*.js', '!src/*.js'], ['copy:pagejs']);
});

var taskList = ['copy:lib', 'copy:html', 'imagemin'];

if (isProd){
  taskList.push('less:uglifycss', 'uglify:concat:appjs', 'uglify:pagejs');
}else {
  taskList.push('less', 'concat:appjs', 'copy:pagejs', 'server', 'watch');
}

gulp.task('default', taskList);<commit_msg>del console<commit_after>var gulp = require('gulp');
var del = require('del');
var browserSync = require('browser-sync');
var concat = require('gulp-concat');
var imagemin = require('gulp-imagemin');
var less = require('gulp-less');
var uglify = require('gulp-uglify');
var uglifycss = require('gulp-uglifycss');
var reload = browserSync.reload;

var isDev = function(){
  return process.env.NODE_ENV.trim() === 'development';
}();

var isProd = function(){
  return process.env.NODE_ENV.trim() === 'production';
}();

gulp.task('clean', function(cb){
  var stream = del(['dist/**/*'], cb);
  return stream;
});

gulp.task('copy:html', function(){
  gulp.src('src/**/*.{html,htm}')
      .pipe(gulp.dest('dist/'));
});

gulp.task('copy:lib', function(){
  gulp.src('node_modules/angular/angular.min.js')
      .pipe(gulp.dest('dist/js/angular/'));
  gulp.src('node_modules/angular-toastr/dist/*.{js,css}')
      .pipe(gulp.dest('dist/js/angular-toastr/'));
  gulp.src('node_modules/angular-ui-router/release/angular-ui-router.min.js')
      .pipe(gulp.dest('dist/js/angular-ui-router/'));
  gulp.src('node_modules/ng-dialog/js/ngDialog.min.js')
      .pipe(gulp.dest('dist/js/ng-dialog/'));
  gulp.src('node_modules/ng-dialog/css/**/*.css')
      .pipe(gulp.dest('dist/js/ng-dialog/'));
  gulp.src('node_modules/ng-file-upload/dist/*.*')
      .pipe(gulp.dest('dist/js/ng-file-upload/'));
  gulp.src('node_modules/ngstorage/ngStorage.min.js')
      .pipe(gulp.dest('dist/js/ngstorage/'));
  gulp.src('node_modules/oclazyload/dist/ocLazyLoad.min.js')
      .pipe(gulp.dest('dist/js/oclazyload/'));
});

gulp.task('imagemin', function(){
  gulp.src('src/img/*')
      .pipe(imagemin())
      .pipe(gulp.dest('dist/img/'));
});

gulp.task('less', function(){
  gulp.src('src/less/*')
      .pipe(less())
      .pipe(gulp.dest('dist/css/'))
      .pipe(reload({stream: true}));
});

gulp.task('less:uglifycss', function(){
  gulp.src('src/less/*')
      .pipe(less())
      .pipe(uglifycss())
      .pipe(gulp.dest('dist/css/'));
});

gulp.task('concat:appjs', function(){
  gulp.src(['src/app.config.js', 'src/app.js', 'src/app.filter.js', 'src/app.services.js'])
      .pipe(concat('app.js'))
      .pipe(gulp.dest('dist/'));
});

gulp.task('uglify:concat:appjs', function(){
  gulp.src(['src/app.config.js', 'src/app.js', 'src/app.filter.js', 'src/app.services.js'])
      .pipe(uglify())
      .pipe(concat('app.js'))
      .pipe(gulp.dest('dist/'));
});

gulp.task('copy:pagejs', function(){
  gulp.src(['src/**/*.js', '!src/*.js'])
      .pipe(gulp.dest('dist/'));
});

gulp.task('uglify:pagejs', function(){
  gulp.src(['src/**/*.js', '!src/*.js'])
      .pipe(uglify())
      .pipe(gulp.dest('dist/'));
});

gulp.task('server', ['less'], function(){
  browserSync({
    server: {
      baseDir: 'dist'
    },
    port: 8000
  });
  gulp.watch("app/less/*.less", ['less']);
  gulp.watch(['src/**/*', '!src/less/*.less']).on('change', reload);
});

gulp.task('watch', function(){
  gulp.watch('src/**/*.{html,htm}', ['copy:html']);
  gulp.watch('src/img/*', ['imagemin']);
  gulp.watch('src/less/*', ['less']);
  gulp.watch(['src/app.config.js', 'src/app.js', 'src/app.filter.js', 'src/app.services.js'], ['concat:appjs']);
  gulp.watch(['src/**/*.js', '!src/*.js'], ['copy:pagejs']);
});

var taskList = ['copy:lib', 'copy:html', 'imagemin'];

if (isProd){
  taskList.push('less:uglifycss', 'uglify:concat:appjs', 'uglify:pagejs');
}else {
  taskList.push('less', 'concat:appjs', 'copy:pagejs', 'server', 'watch');
}

gulp.task('default', taskList);<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');
var watch = require('gulp-watch');
var deploy = require('gulp-gh-pages');
var compass = require('gulp-compass');
var jshint = require('gulp-jshint');
var del = require('del');
var runSequence = require('run-sequence');

var options = {
    branch: 'master'
};

gulp.task('deploy', ['site:build'], function () {
    return gulp.src('./_site/**/*')
        .pipe(deploy(options));
});

gulp.task('jekyll:build', function (gulpCallBack){
    var spawn = require('child_process').spawn;
    var jekyll = spawn('bundle', ['exec', 'jekyll', 'build'], {stdio: 'inherit'});

    jekyll.on('exit', function(code) {
        gulpCallBack(code === 0 ? null : 'ERROR: Jekyll process exited with code: ' + code);
    });
});

gulp.task('site:build', function(callback) {
    runSequence('clean', ['compass:compile', 'js:lint'], 'jekyll:build', callback);
});

gulp.task('compass:compile', function() {
    return gulp.src('./sass/*.scss')
        .pipe(compass({
            config_file: './config.rb',
            sourcemap: true,
            sass: 'sass',
        }))
        .pipe(gulp.dest('css'));
});

gulp.task('js:lint', function() {
    return gulp.src(['./js/*.js', '!./js/lib/*.js'])
        .pipe(jshint())
        .pipe(jshint.reporter('default'));
});

gulp.task('clean', function () {
    return del(['_site/**']);
});

gulp.task('default', function () {
    watch('./sass/*.scss', function () {
        gulp.start('compass:compile');
    });
    watch('./js/*.js', function () {
        gulp.start('js:lint');
    });
});
<commit_msg>Add Gulp task to minify HTML<commit_after>'use strict';

var gulp = require('gulp');
var watch = require('gulp-watch');
var deploy = require('gulp-gh-pages');
var compass = require('gulp-compass');
var jshint = require('gulp-jshint');
var htmlmin = require('gulp-html-minifier');
var del = require('del');
var runSequence = require('run-sequence');

var options = {
    branch: 'master'
};

gulp.task('deploy', ['site:build'], function () {
    return gulp.src('./_site/**/*')
        .pipe(deploy(options));
});

gulp.task('jekyll:build', function (gulpCallBack){
    var spawn = require('child_process').spawn;
    var jekyll = spawn('bundle', ['exec', 'jekyll', 'build'], {stdio: 'inherit'});

    jekyll.on('exit', function(code) {
        gulpCallBack(code === 0 ? null : 'ERROR: Jekyll process exited with code: ' + code);
    });
});

gulp.task('site:build', function(callback) {
    runSequence('clean', ['compass:compile', 'js:lint'], 'jekyll:build', 'minify:html', callback);
});

gulp.task('compass:compile', function() {
    return gulp.src('./sass/*.scss')
        .pipe(compass({
            config_file: './config.rb',
            sourcemap: true,
            sass: 'sass',
        }))
        .pipe(gulp.dest('css'));
});

gulp.task('minify:html', function() {
  gulp.src('./_site/**/*.html')
    .pipe(htmlmin({collapseWhitespace: true }))
    .pipe(gulp.dest('./_site'));
});

gulp.task('js:lint', function() {
    return gulp.src(['./js/*.js', '!./js/lib/*.js'])
        .pipe(jshint())
        .pipe(jshint.reporter('default'));
});

gulp.task('clean', function () {
    return del(['_site/**']);
});

gulp.task('default', function () {
    watch('./sass/*.scss', function () {
        gulp.start('compass:compile');
    });
    watch('./js/*.js', function () {
        gulp.start('js:lint');
    });
});
<|endoftext|>


<commit_before>const gulp       = require('gulp');
const gulpsync   = require('gulp-sync')(gulp);
const requireDir = require('require-dir');
requireDir('./tasks');

gulp.task('build', gulpsync.sync(['clean', ['stylus', 'vendorCss', 'pug', 'assets', 'images']]));
gulp.task('build:final', gulpsync.sync(['clean', ['pug', 'stylus:min', 'vendorCss:min', 'assets'], 'images:build', 'webpack']));

gulp.task('default', gulpsync.sync(['clean', 'build', 'watch', ['webpack', 'browser-sync']]));<commit_msg>Убрал лишний clean<commit_after>const gulp       = require('gulp');
const gulpsync   = require('gulp-sync')(gulp);
const requireDir = require('require-dir');
requireDir('./tasks');

gulp.task('build', gulpsync.sync(['clean', ['stylus', 'vendorCss', 'pug', 'assets', 'images']]));
gulp.task('build:final', gulpsync.sync(['clean', ['pug', 'stylus:min', 'vendorCss:min', 'assets'], 'images:build', 'webpack']));

gulp.task('default', gulpsync.sync(['build', 'watch', ['webpack', 'browser-sync']]));<|endoftext|>


<commit_before>
var gulp         = require('gulp');
var del          = require('del');
var browsersync  = require('browser-sync').create();
var imagemin     = require('gulp-imagemin');
var autoprefixer = require('gulp-autoprefixer');
var sass         = require('gulp-sass');
var cleancss     = require('gulp-clean-css');
var sourcemaps   = require('gulp-sourcemaps');
var uglify       = require('gulp-uglify');
var concat       = require('gulp-concat');
var jshint       = require('gulp-jshint');
var childprocess = require('child_process');
var argv         = require('yargs').argv;
var gulpif       = require('gulp-if');
var runsequence  = require('run-sequence');

var paths = {
  source: {
    css: 'scss/**/*.scss',
    html: 'html/**/*.html',
    js: [
      'node_modules/jquery/dist/jquery.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/affix.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/alert.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/button.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/carousel.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/collapse.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/dropdown.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/modal.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/popover.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/scrollspy.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/tab.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/tooltip.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/transition.js',
      'js/app.js'
    ],
    img: 'img/**/*.{svg,png,gif,jpg,jpeg}'
  },
  deploy: {
    css: 'deploy/css/',
    html: 'deploy/',
    js: 'deploy/js/',
    img: 'deploy/img/'
  }
};

gulp.task('html', function(done) {
  browsersync.notify('Running: jekyll build');
  return childprocess.spawn('jekyll', ['build'], {stdio: 'inherit'})
    .on('close', done);
});

gulp.task('css', function() {
  return gulp.src(paths.source.css)
    .pipe(gulpif(!argv.production, sourcemaps.init()))
    .pipe(sass({ precision: 10 }).on('error', sass.logError))
    // See https://github.com/postcss/autoprefixer
    // and https://github.com/ai/browserslist
    // and http://caniuse.com/usage-table
    .pipe(autoprefixer({ browsers: ['last 2 versions'] }))
    .pipe(cleancss())
    .pipe(gulpif(!argv.production, sourcemaps.write('./')))
    .pipe(gulp.dest(paths.deploy.css));
});

gulp.task('js', ['lint'], function() {
  return gulp.src(paths.source.js)
    .pipe(gulpif(!argv.production, sourcemaps.init()))
    .pipe(concat('app.js'))
    .pipe(uglify())
    .pipe(gulpif(!argv.production, sourcemaps.write('./')))
    .pipe(gulp.dest(paths.deploy.js));
});

gulp.task('lint', function() {
  return gulp.src('js/app.js')
    .pipe(jshint({ lookup: false }))
    .pipe(jshint.reporter('default'));
});

gulp.task('img', function() {
  return gulp.src(paths.source.img)
    .pipe(imagemin())
    .pipe(gulp.dest(paths.deploy.img));
});

gulp.task('serve', function() {
  browsersync.init({
    ui: {
      port: 1337
    },
    open: false,
    notify: true,
    files: [
      'deploy/**/*'
    ],
    server: {
      baseDir: 'deploy/'
    }
  });
});

gulp.task('clean', function() {
  return del('deploy');
});

gulp.task('watch', function() {
  gulp.watch(paths.source.css, ['css']);
  gulp.watch(paths.source.html, ['html']);
  gulp.watch(paths.source.js, ['js']);
  gulp.watch(paths.source.img, ['img']);
});

gulp.task('build', ['clean'], function(callback) {
  runsequence(['html', 'css', 'js', 'img'], callback);
});

gulp.task('default', ['build'], function() {
  runsequence('serve', 'watch');
});
<commit_msg>add todo<commit_after>
var gulp         = require('gulp');
var del          = require('del');
var browsersync  = require('browser-sync').create();
var imagemin     = require('gulp-imagemin');
var autoprefixer = require('gulp-autoprefixer');
var sass         = require('gulp-sass');
var cleancss     = require('gulp-clean-css');
var sourcemaps   = require('gulp-sourcemaps');
var uglify       = require('gulp-uglify');
var concat       = require('gulp-concat');
var jshint       = require('gulp-jshint');
var childprocess = require('child_process');
var argv         = require('yargs').argv;
var gulpif       = require('gulp-if');
var runsequence  = require('run-sequence');

// Add or remove build assets here as needed
// TODO: Add a manifest.json and use wiredep to inject assets dynamically
var paths = {
  source: {
    css: 'scss/**/*.scss',
    html: 'html/**/*.html',
    js: [
      'node_modules/jquery/dist/jquery.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/affix.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/alert.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/button.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/carousel.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/collapse.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/dropdown.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/modal.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/popover.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/scrollspy.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/tab.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/tooltip.js',
      'node_modules/bootstrap-sass/assets/javascripts/bootstrap/transition.js',
      'js/app.js'
    ],
    img: 'img/**/*.{svg,png,gif,jpg,jpeg}'
  },
  deploy: {
    css: 'deploy/css/',
    html: 'deploy/',
    js: 'deploy/js/',
    img: 'deploy/img/'
  }
};

gulp.task('html', function(done) {
  browsersync.notify('Running: jekyll build');
  return childprocess.spawn('jekyll', ['build'], {stdio: 'inherit'})
    .on('close', done);
});

gulp.task('css', function() {
  return gulp.src(paths.source.css)
    .pipe(gulpif(!argv.production, sourcemaps.init()))
    .pipe(sass({ precision: 10 }).on('error', sass.logError))
    // See https://github.com/postcss/autoprefixer
    // and https://github.com/ai/browserslist
    // and http://caniuse.com/usage-table
    .pipe(autoprefixer({ browsers: ['last 2 versions'] }))
    .pipe(cleancss())
    .pipe(gulpif(!argv.production, sourcemaps.write('./')))
    .pipe(gulp.dest(paths.deploy.css));
});

gulp.task('js', ['lint'], function() {
  return gulp.src(paths.source.js)
    .pipe(gulpif(!argv.production, sourcemaps.init()))
    .pipe(concat('app.js'))
    .pipe(uglify())
    .pipe(gulpif(!argv.production, sourcemaps.write('./')))
    .pipe(gulp.dest(paths.deploy.js));
});

gulp.task('lint', function() {
  return gulp.src('js/app.js')
    .pipe(jshint({ lookup: false }))
    .pipe(jshint.reporter('default'));
});

gulp.task('img', function() {
  return gulp.src(paths.source.img)
    .pipe(imagemin())
    .pipe(gulp.dest(paths.deploy.img));
});

gulp.task('serve', function() {
  browsersync.init({
    ui: {
      port: 1337
    },
    open: false,
    notify: true,
    files: [
      'deploy/**/*'
    ],
    server: {
      baseDir: 'deploy/'
    }
  });
});

gulp.task('clean', function() {
  return del('deploy');
});

gulp.task('watch', function() {
  gulp.watch(paths.source.css, ['css']);
  gulp.watch(paths.source.html, ['html']);
  gulp.watch(paths.source.js, ['js']);
  gulp.watch(paths.source.img, ['img']);
});

gulp.task('build', ['clean'], function(callback) {
  runsequence(['html', 'css', 'js', 'img'], callback);
});

gulp.task('default', ['build'], function() {
  runsequence('serve', 'watch');
});
<|endoftext|>


<commit_before>/* eslint-env node */
/* eslint strict: ["error", "global"] */
'use strict';
var coveralls = require('gulp-coveralls'),
    eslint = require('gulp-eslint'),
    excludeGitignore = require('gulp-exclude-gitignore'),
    gulp = require('gulp'),
    istanbul = require('gulp-istanbul'),
    mocha = require('gulp-mocha'),
    nsp = require('gulp-nsp'),
    path = require('path'),
    plumber = require('gulp-plumber');

gulp.task('eslint', function() {
    return gulp.src([
        '**/*.js',
        '!app/templates/gulpfile.js',
        '!app/templates/src/scripts/settings/call_plugins.js'
    ])
    .pipe(excludeGitignore())
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
});

gulp.task('nsp', function(cb) {
    return nsp({package: path.resolve('package.json')}, cb);
});

gulp.task('istanbul', function() {
    return gulp.src('app/index.js')
        .pipe(excludeGitignore())
        .pipe(istanbul({
            includeUntested: true
        }))
        .pipe(istanbul.hookRequire());
});

gulp.task('mocha', ['istanbul'], function(cb) {
    var mochaErr;

    gulp.src('test/**/*.js')
        .pipe(plumber())
        .pipe(mocha({reporter: 'spec'}))
        .on('error', function(err) {
            mochaErr = err;
        })
        .pipe(istanbul.writeReports())
        .on('end', function() {
            cb(mochaErr);
        });
});

gulp.task('coveralls', ['mocha'], function() {
    if (!process.env.CI) {
        return;
    }

    return gulp.src(__dirname + 'coverage/lcov.info')
    .pipe(coveralls());
});

gulp.task('test', ['nsp', 'eslint', 'mocha', 'coveralls']);

gulp.task('watch-test', function() {
    gulp.watch(['app/index.js', 'test/**/*.js'], ['mocha']);
});
<commit_msg>Testing Coveralls<commit_after>/* eslint-env node */
/* eslint strict: ["error", "global"] */
'use strict';
var coveralls = require('gulp-coveralls'),
    eslint = require('gulp-eslint'),
    excludeGitignore = require('gulp-exclude-gitignore'),
    gulp = require('gulp'),
    istanbul = require('gulp-istanbul'),
    mocha = require('gulp-mocha'),
    nsp = require('gulp-nsp'),
    path = require('path'),
    plumber = require('gulp-plumber');

gulp.task('eslint', function() {
    return gulp.src([
        '**/*.js',
        '!app/templates/gulpfile.js',
        '!app/templates/src/scripts/settings/call_plugins.js'
    ])
    .pipe(excludeGitignore())
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
});

gulp.task('nsp', function(cb) {
    return nsp({package: path.resolve('package.json')}, cb);
});

gulp.task('istanbul', function() {
    return gulp.src('app/index.js')
        .pipe(excludeGitignore())
        .pipe(istanbul({
            includeUntested: true
        }))
        .pipe(istanbul.hookRequire());
});

gulp.task('mocha', ['istanbul'], function(cb) {
    var mochaErr;

    gulp.src('test/**/*.js')
        .pipe(plumber())
        .pipe(mocha({reporter: 'spec'}))
        .on('error', function(err) {
            mochaErr = err;
        })
        .pipe(istanbul.writeReports())
        .on('end', function() {
            cb(mochaErr);
        });
});

gulp.task('coveralls', ['mocha'], function() {
    if (!process.env.CI) {
        return;
    }

    return gulp.src(path.join(__dirname, 'coverage/lcov.info'))
    .pipe(coveralls());
});

gulp.task('test', ['nsp', 'eslint', 'mocha', 'coveralls']);

gulp.task('watch-test', function() {
    gulp.watch(['app/index.js', 'test/**/*.js'], ['mocha']);
});
<|endoftext|>