<commit_before>/*
 * grunt-docs
 * https://github.com/shama/grunt-docs
 *
 * Copyright (c) 2012 Kyle Robinson Young
 * Licensed under the MIT license.
 */

module.exports = function(grunt) {
  'use strict';

  var docpad = require('docpad');
  var path = require('path');

  // TODO: ditch this when grunt v0.4 is released
  grunt.util = grunt.util || grunt.utils;

  var _ = grunt.util._;
  var async = grunt.util.async;

  var docpadError = function(e) {
    var pos = '[' + 'L' + e.line + ':' + ('C' + e.column) + ']';
    grunt.log.error(e.filename + ': ' + pos + ' ' + e.message);
    grunt.fail.warn("Error compiling with docpad.", 1);
  };

  var resolveDest = function(base, file) {
    return _.difference(
      file.split(path.sep),
      base.split(path.sep)
    ).join(path.sep);
  };

  var resolveExt = function(file) {
    return file.substr(0, file.lastIndexOf(path.extname(file)));
  };

  grunt.registerMultiTask('docs', 'Produce docs with docpad', function() {
    var files = this.file.src;
    var dest = this.file.dest;

    var done = this.async();

    async.forEachSeries(files, function(file, next) {
      var srcBase = grunt.helper('_docs-findbase', file);
      var srcFiles = grunt.file.expandFiles(file);

      grunt.helper('docpad', srcFiles, {}, function(result) {
        for (var resultPath in result) {
          var resultData = result[resultPath];
          var destPath = resolveExt(dest + resolveDest(srcBase, resultPath));
          grunt.file.write(destPath, resultData);
          grunt.log.writeln("File '" + destPath + "' created.");
        }
        next();
      });

    }, function() {
      done();
    });

  });

  grunt.registerHelper('docpad', function(files, docpadConfig, callback) {
    docpad.createInstance(docpadConfig, function(err, inst) {
      if (err) {
        docpadError(err);
      }

      var output = {};

      if (_.isString(files)) {
        files = [files];
      }

      async.forEachSeries(files, function(file, next) {
        var options = {
          path: file,
          renderSingleExtensions: true
        };
        inst.action('render', options, function(err, result) {
          if (err) {
            docpadError(err);
          }
          output[file] = result;

          next();
        });
      }, function() {
        callback(output);
      });

    });
  });

  grunt.registerHelper('_docs-findbase', function(file) {
    var base;
    if (file.indexOf('*') !== -1) {
      base = file.substr(0, file.indexOf('*'));
    } else {
      base = path.dirname(file) + path.sep;
    }
    return base;
  });

};
<commit_msg>Refactor findbase<commit_after>/*
 * grunt-docs
 * https://github.com/shama/grunt-docs
 *
 * Copyright (c) 2012 Kyle Robinson Young
 * Licensed under the MIT license.
 */

module.exports = function(grunt) {
  'use strict';

  var docpad = require('docpad');
  var path = require('path');

  // TODO: ditch this when grunt v0.4 is released
  grunt.util = grunt.util || grunt.utils;

  var _ = grunt.util._;
  var async = grunt.util.async;

  var docpadError = function(e) {
    var pos = '[' + 'L' + e.line + ':' + ('C' + e.column) + ']';
    grunt.log.error(e.filename + ': ' + pos + ' ' + e.message);
    grunt.fail.warn("Error compiling with docpad.", 1);
  };

  var resolveDest = function(base, file) {
    return _.difference(
      file.split(path.sep),
      base.split(path.sep)
    ).join(path.sep);
  };

  var resolveExt = function(file) {
    return file.substr(0, file.lastIndexOf(path.extname(file)));
  };

  grunt.registerMultiTask('docs', 'Produce docs with docpad', function() {
    var files = this.file.src;
    var dest = this.file.dest;

    var done = this.async();

    async.forEachSeries(files, function(file, next) {
      var srcBase = grunt.helper('_docs-findbase', file);
      var srcFiles = grunt.file.expandFiles(file);

      grunt.helper('docpad', srcFiles, {}, function(result) {
        for (var resultPath in result) {
          var resultData = result[resultPath];
          var destPath = resolveExt(dest + resolveDest(srcBase, resultPath));
          grunt.file.write(destPath, resultData);
          grunt.log.writeln("File '" + destPath + "' created.");
        }
        next();
      });

    }, function() {
      done();
    });

  });

  grunt.registerHelper('docpad', function(files, docpadConfig, callback) {
    docpad.createInstance(docpadConfig, function(err, inst) {
      if (err) {
        docpadError(err);
      }

      var output = {};

      if (_.isString(files)) {
        files = [files];
      }

      async.forEachSeries(files, function(file, next) {
        var options = {
          path: file,
          renderSingleExtensions: true
        };
        inst.action('render', options, function(err, result) {
          if (err) {
            docpadError(err);
          }
          output[file] = result;

          next();
        });
      }, function() {
        callback(output);
      });

    });
  });

  grunt.registerHelper('_docs-findbase', function(file) {
    if (file.indexOf('*') !== -1) {
      return file.substr(0, file.indexOf('*'));
    } else {
      return path.dirname(file) + path.sep;
    }
  });

};
<|endoftext|>


<commit_before>const store = redis.getClient()

module.exports = function (req, res, next) {
  const method = req.raw.method && req.raw.method.toUpperCase && req.raw.method.toUpperCase()
  if (method === 'OPTIONS') {
    // OPTIONS for cors pre-flight.
    return next()
  }
  var key, max, expire
  if (req.raw.url.match(/^\/auth\//)) {
    key = 'rate:auth:' + req.raw.ip
    max = 30
    expire = 3600
  }
  else {
    key = 'rate:wago:' + req.raw.ip
    max = 500
    expire = 60
  }
  store.incr(key, (err, count) => {
    if (err) {
      console.error('RATE LIMIT ERROR', err)
    }
    else if (count <= 5) {
      store.expire(key, expire)
    }
    else if (count > max) {
      return res.code(429).send({error: "Rate limit exceeded"})
    }
  })

  store.get('stream:method:' + req.raw.ip, (err, val) => {
    if (!err && val) {
      store.expire('stream:method:' + req.raw.ip, 70)
    }
  })

  return next()
}<commit_msg>update embed activity tracking<commit_after>const store = redis.getClient()

module.exports = function (req, res, next) {
  const method = req.raw.method && req.raw.method.toUpperCase && req.raw.method.toUpperCase()
  if (method === 'OPTIONS') {
    // OPTIONS for cors pre-flight.
    return next()
  }
  var key, max, expire
  if (req.raw.url.match(/^\/auth\//)) {
    key = 'rate:auth:' + req.raw.ip
    max = 30
    expire = 3600
  }
  else {
    key = 'rate:wago:' + req.raw.ip
    max = 500
    expire = 60
  }
  store.incr(key, (err, count) => {
    if (err) {
      console.error('RATE LIMIT ERROR', err)
    }
    else if (count <= 5) {
      store.expire(key, expire)
    }
    else if (count > max) {
      return res.code(429).send({error: "Rate limit exceeded"})
    }
  })

  const channel = (global.EmbeddedStream || {}).channel || 'method'
  store.get(`stream:${channel}:${req.raw.ip}`, (err, val) => {
    if (!err && val) {
      store.expire(`stream:${channel}:${req.raw.ip}`, 70)
    }
  })

  return next()
}<|endoftext|>


<commit_before>module.exports = exports = function login(config) {
  if(!config.serializeUser) config.serializeUser = function (id, done) { done(null, id); };
  if(!config.deserializeUser) config.deserializeUser = function (id, done) { done(null, { id: id, email: id }); };
  if(config.password) {
    config.test = function (username, password, done) {
      if(password === config.password && (username === (config.username || config.email))) {
        return done(null, username);
      }
      return done(null, false, 'invalid details');
    }
  }
  if(!config.test) throw new Error('missing test(username, password, done) function.');
  return loginModule;

  function loginModule(atman) {
    var app = atman.app;
    var passport = app.get('passport');
    var Strategy = require('passport-local').Strategy;
    passport.serializeUser(config.serializeUser);
    passport.deserializeUser(config.deserializeUser);
    passport.use('atman', config.strategy || new Strategy(config.test));

    app.post('/auth/login', function (req, res, next) {
      res.redirect('/');
    });

    app.public.post('/auth/login', function (req, res, next) {
      passport.authenticate('atman', function (err, user, info) {
        if(err) return next(err);
        if(!user) return res.redirect(app.resolve('/?failed=' + (info||'')));
        req.login(user, function (err) {
          if(err) return next(err);
          return res.redirect(app.path());
        });
      })(req, res, next);
    });

    app.public.get('/', function (req, res) {
      res.render(__dirname + '/views/login', {
        failed: req.query.failed,
        config: {
          root: app.path(),
          title: app.get('title'),
        }
      });
    });
  }
}

<commit_msg>correct resolve in login<commit_after>module.exports = exports = function login(config) {
  if(!config.serializeUser) config.serializeUser = function (id, done) { done(null, id); };
  if(!config.deserializeUser) config.deserializeUser = function (id, done) { done(null, { id: id, email: id }); };
  if(config.password) {
    config.test = function (username, password, done) {
      if(password === config.password && (username === (config.username || config.email))) {
        return done(null, username);
      }
      return done(null, false, 'invalid details');
    }
  }
  if(!config.test) throw new Error('missing test(username, password, done) function.');
  return loginModule;

  function loginModule(atman) {
    var app = atman.app;
    var passport = app.get('passport');
    var Strategy = require('passport-local').Strategy;
    passport.serializeUser(config.serializeUser);
    passport.deserializeUser(config.deserializeUser);
    passport.use('atman', config.strategy || new Strategy(config.test));

    app.post('/auth/login', function (req, res, next) {
      res.redirect(app.resolve('/'));
    });

    app.public.post('/auth/login', function (req, res, next) {
      passport.authenticate('atman', function (err, user, info) {
        if(err) return next(err);
        if(!user) return res.redirect(app.resolve('/?failed=' + (info||'')));
        req.login(user, function (err) {
          if(err) return next(err);
          return res.redirect(app.path());
        });
      })(req, res, next);
    });

    app.public.get('/', function (req, res) {
      res.render(__dirname + '/views/login', {
        failed: req.query.failed,
        config: {
          root: app.path(),
          title: app.get('title'),
        }
      });
    });
  }
}

<|endoftext|>


<commit_before>'use strict';

const colors = require('colors'),
  shell = require('shelljs/global'),
  fs = require('fs'),
  emoji = require('node-emoji'),
  del = require('del'),
  copydir = require('copy-dir'),
  noEmoji = /^win/.test(process.platform);

let config;

if (noEmoji) {
  lib.emoji.get = () => '';
}

function logComplete(task) {
  console.log('['.green + task.green + ' ' + emoji.get('white_check_mark') + ' ]\n'.green);
}

function folderExists(src) {
  return fs.existsSync(src);
}

function deleteFiles(deleteArray) {
  return new Promise((resolve, reject) => {
    if (deleteArray === null) {
      resolve()
    } else {
      console.log(`Deleting files ${deleteArray}...`);
      del.sync(deleteArray);

      resolve();
    }
  });
}

function readConfigFiles() {
  return new Promise((resolve, reject) => {
    try {
      // Uncomment me
      // config = JSON.parse(fs.readFileSync('./config.json', 'utf8'));
      // Delete me
      config = {
        "delete": {
          "dependencies": [
            "normalize.css"
          ],
          "vendorScss": [
            "@import '../../node_modules/normalize.css/normalize';"
          ]
        },
        "add": {
          "dependencies": {
            "jquery": "~2.2.4",
            "bootstrap-sass": "^3.3.7"
          },
          "vendorJs": [
            "./node_modules/bootstrap-sass/assets/javascripts/bootstrap.min.js"
          ],
          "vendorScss": [
            "@import '../scss/abstracts/_bootstrap-variables.scss';",
            "@import '../../node_modules/bootstrap-sass/assets/stylesheets/_bootstrap.scss';"
          ]
        }
      };
      del.sync(['./config.json']);
      resolve();
    } catch (e) {
      console.log(e);
      reject();
    };
  });
}

function configurePackageJson() {
  return new Promise((resolve, reject) => {
    let packageFile;

    try {
      // Uncomment me
      // packageFile = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
      // Delete me
      packageFile = {
        "name": "web-starter-jc",
        "version": "1.0.0",
        "description": "Starter kit for markup projects",
        "repository": {
          "type": "git",
          "url": "git+https://github.com/justcoded/web-starter-kit"
        },
        "keywords": [
          "starter",
          "markup",
          "JustCoded",
          "jc"
        ],
        "author": "JustCoded",
        "license": "MIT",
        "bugs": {
          "url": "https://github.com/justcoded/web-starter-kit/issues"
        },
        "homepage": "https://github.com/justcoded/web-starter-kit",
        "devDependencies": {
          "babel-preset-es2015": "^6.24.0",
          "babelify": "^7.3.0",
          "browser-sync": "^2.18.0",
          "browserify": "^14.0.0",
          "del": "^2.2.2",
          "files-exist": "^1.0.2",
          "gulp": "^3.9.1",
          "gulp-autoprefixer": "^3.1.1",
          "gulp-concat": "^2.6.1",
          "gulp-cssimport": "^5.0.0",
          "gulp-cssnano": "^2.1.2",
          "gulp-debug": "^3.1.0",
          "gulp-group-css-media-queries": "^1.2.0",
          "gulp-htmlhint": "^0.3.1",
          "gulp-imagemin": "^3.1.1",
          "gulp-jshint": "^2.0.4",
          "gulp-newer": "^1.3.0",
          "gulp-notify": "^3.0.0",
          "gulp-rename": "^1.2.2",
          "gulp-sass": "^3.1.0",
          "gulp-sourcemaps": "^2.4.1",
          "gulp-uglify": "^2.1.0",
          "gulp-util": "^3.0.8",
          "gulp-watch": "^4.3.11",
          "htmlhint-stylish": "^1.0.3",
          "imagemin-pngquant": "^5.0.0",
          "jshint": "^2.9.4",
          "node-notifier": "^5.0.2",
          "path": "^0.12.7",
          "run-sequence": "^1.2.2",
          "vinyl-buffer": "^1.0.0",
          "vinyl-source-stream": "^1.1.0"
        },
        "engines": {
          "node": ">=4.0.0"
        },
        "scripts": {
          "test": "gulp production",
          "start": "gulp"
        },
        "dependencies": {
          "include-media": "~1.4.9",
          "jquery": "~2.2.4",
          "normalize.css": "~5.0.0"
        }
      };
    } catch (e) {
      console.error('There was an error reading the file!');
    }

    if ('delete' in config) {
      if (typeof packageFile === 'undefined') {
        console.log('package.json was not loaded!');
        reject();
      }
      // Change dependencies in package.json file
      changeDependencies(packageFile, config.delete, 'delete')
        .then(() => {
          if ('add' in config) {
            changeDependencies(packageFile, config.add, 'add')
              .then(() => {
                try {
                  fs.writeFileSync('./package.json', JSON.stringify(packageFile, null, 2), 'utf8');
                  resolve();
                } catch (e) {
                  console.log(e);
                  reject();
                }
              });
          }
        })
        .catch(e => {
          console.log(e);
          reject();
        });
    }
  });
}

function changeDependencies(packageFile, config, method) {
  return new Promise((resolve, reject) => {
    let instructions;

    if (method === 'delete') {
      instructions = (object, field) => {
        // Change to object
        return new Promise((resolve, reject) => {
          console.log(`Delete dependencies: ${typeof object[field] === 'undefined'}`.red);
          if (typeof object[field] === 'undefined') {
            resolve();
          } else {
            for (let item of object[field]) {
              if (field in packageFile && item in packageFile[field]) {
                delete packageFile[field][item];
              }
            }

            resolve();
          }
        });
      };
    } else {
      instructions = (object, field) => {
        // Change to object
        return new Promise((resolve, reject) => {
          console.log(`Add dependencies: ${typeof object[field] === 'undefined'}`.red);
          if (typeof object[field] === 'undefined') {
            resolve();
          } else {
            for (let item in object[field]) {
              packageFile[field][item] = object[field][item];
            }

            resolve();
          }
        });
      }
    }

    console.log(`${config}`.red);

    instructions(config, 'dependencies')
      .then(instructions.bind(null, config, 'devDependencies'))
      .then(resolve);
  });
}

function changeVendorScss() {
  return new Promise((resolve, reject) => {
    let path = './src/vendor_entries/vendor.scss',
      vendorScss,
      addVendor,
      deleteVendor;

    try {
      vendorScss = fs.readFileSync(path, 'utf8').toString().split('\n');
    } catch (e) {
      console.log(e)
      reject();
    }

    addVendor = () => {
      return new Promise((resolve, reject) => {
        if (typeof config.add.vendorScss === 'undefined') {
          resolve();
        } else {
          for (let item of config.add.vendorScss) {
            vendorScss.push(item);
          }
          for (let i = 0; i < vendorScss.length; i++) {
            vendorScss[i] = vendorScss[i] + '\n';
          }

          try {
            fs.writeFileSync(path, vendorScss.join().replace(/,/g, ''), 'utf8');
            resolve();
          } catch (e) {
            console.log(e);
            reject();
          }
        }
      });
    }

    deleteVendor = () => {
      return new Promise((resolve, reject) => {
        if (typeof config.delete.vendorScss === 'undefined') {
          resolve();
        } else {
          for (let item of config.delete.vendorScss) {
            let lastChar = vendorScss[4].substr(vendorScss[4].length - 1),
              index;
            if (lastChar === '\n') {
              index = vendorScss.indexOf(item + '\n');
            } else {
              index = vendorScss.indexOf(item);
            }

            if (index > 1) {
              vendorScss.splice(index, 1);
              try {
                fs.writeFileSync(path, vendorScss.join().replace(/,/g, ''), 'utf8');
                resolve();
              } catch (e) {
                console.log(e);
                reject();
              }
            }
          }
          resolve();
        }
      });
    };

    addVendor()
      .then(deleteVendor)
      .then(resolve);
  });
}

function createTmpFolder() {
  return new Promise((resolve, reject) => {
    if (folderExists('tmp')) {
      console.log('Destination path already exists and is not an empty directory. '.red + emoji.get('cry'));
      return;
    }
    exec('mkdir tmp');
    cd('tmp');

    resolve();
  });
}

function gitClone(repo) {
  return new Promise((resolve, reject) => {
    console.log('Clone from ' + repo.url + ' ' + repo.branch);
    exec('git clone ' + repo.url + ' ./ -b ' + repo.branch);
    del.sync(['.git']);
    logComplete('Git cloning has been completed');

    resolve();
  });
}

function moveFiles() {
  return new Promise((resolve, reject) => {
    console.log('Copying files...');
    copydir('../tmp', '../', (err) => {
      if (err) {
        console.log(err);
        return;
      }
      cd('..');
      del.sync(['tmp']);
      logComplete('Copying files has been completed');

      resolve();
    });
  });
}

function installDependencies() {
  return new Promise((resolve, reject) => {
    console.log('Installing npm dependencies...');
    exec('npm install');
    logComplete('Dependencies have been installed');

    resolve();
  });
}

function finish() {
  console.log('Starter has been successfully installed. Good luck '.green +
    emoji.get('wink') + ' \n\u00A9 JustCoded'.green);
  exec('gulp');
}

function build(repositories) {
  return new Promise((resolve, reject) => {

    let chain = Promise.resolve();

    for (var i = 0; i < repositories.length; i++) {
      chain = chain
        .then(deleteFiles.bind(null, repositories[i].filesToDelete || null))
        .then(createTmpFolder)
        .then(gitClone.bind(null, repositories[i]))
        .then(moveFiles);

      if (i !== 0) {
        chain = chain
          .then(readConfigFiles)
          .then(configurePackageJson)
          .then(changeVendorScss);
      }

      if (i == repositories.length - 1) {
        chain = chain
          .then(installDependencies)
          .then(finish);
      }
    }

    resolve();
  });
}

module.exports = {
  init: function (repositories) {
    console.log('\nGetting starter files... ' + emoji.get('runner'));

    build(repositories);
  },
  emoji: emoji
}<commit_msg>Delete debug console logs<commit_after>'use strict';

const colors = require('colors'),
  shell = require('shelljs/global'),
  fs = require('fs'),
  emoji = require('node-emoji'),
  del = require('del'),
  copydir = require('copy-dir'),
  noEmoji = /^win/.test(process.platform);

let config;

if (noEmoji) {
  lib.emoji.get = () => '';
}

function logComplete(task) {
  console.log('['.green + task.green + ' ' + emoji.get('white_check_mark') + ' ]\n'.green);
}

function folderExists(src) {
  return fs.existsSync(src);
}

function deleteFiles(deleteArray) {
  return new Promise((resolve, reject) => {
    if (deleteArray === null) {
      resolve()
    } else {
      console.log(`Deleting files ${deleteArray}...`);
      del.sync(deleteArray);

      resolve();
    }
  });
}

function readConfigFiles() {
  return new Promise((resolve, reject) => {
    try {
      // Uncomment me
      // config = JSON.parse(fs.readFileSync('./config.json', 'utf8'));
      // Delete me
      config = {
        "delete": {
          "dependencies": [
            "normalize.css"
          ],
          "vendorJs": [
            "./node_modules/EXAMPLE1",
            "./node_modules/EXAMPLE2"
          ],
          "vendorScss": [
            "@import '../../node_modules/normalize.css/normalize';"
          ]
        },
        "add": {
          "dependencies": {
            "jquery": "~2.2.4",
            "bootstrap-sass": "^3.3.7"
          },
          "vendorJs": [
            "./node_modules/bootstrap-sass/assets/javascripts/bootstrap.min.js"
          ],
          "vendorScss": [
            "@import '../scss/abstracts/_bootstrap-variables.scss';",
            "@import '../../node_modules/bootstrap-sass/assets/stylesheets/_bootstrap.scss';"
          ]
        }
      };
      del.sync(['./config.json']);
      resolve();
    } catch (e) {
      console.log(e);
      reject();
    };
  });
}

function configurePackageJson() {
  return new Promise((resolve, reject) => {
    let packageFile;

    try {
      // Uncomment me
      // packageFile = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
      // Delete me
      packageFile = {
        "name": "web-starter-jc",
        "version": "1.0.0",
        "description": "Starter kit for markup projects",
        "repository": {
          "type": "git",
          "url": "git+https://github.com/justcoded/web-starter-kit"
        },
        "keywords": [
          "starter",
          "markup",
          "JustCoded",
          "jc"
        ],
        "author": "JustCoded",
        "license": "MIT",
        "bugs": {
          "url": "https://github.com/justcoded/web-starter-kit/issues"
        },
        "homepage": "https://github.com/justcoded/web-starter-kit",
        "devDependencies": {
          "babel-preset-es2015": "^6.24.0",
          "babelify": "^7.3.0",
          "browser-sync": "^2.18.0",
          "browserify": "^14.0.0",
          "del": "^2.2.2",
          "files-exist": "^1.0.2",
          "gulp": "^3.9.1",
          "gulp-autoprefixer": "^3.1.1",
          "gulp-concat": "^2.6.1",
          "gulp-cssimport": "^5.0.0",
          "gulp-cssnano": "^2.1.2",
          "gulp-debug": "^3.1.0",
          "gulp-group-css-media-queries": "^1.2.0",
          "gulp-htmlhint": "^0.3.1",
          "gulp-imagemin": "^3.1.1",
          "gulp-jshint": "^2.0.4",
          "gulp-newer": "^1.3.0",
          "gulp-notify": "^3.0.0",
          "gulp-rename": "^1.2.2",
          "gulp-sass": "^3.1.0",
          "gulp-sourcemaps": "^2.4.1",
          "gulp-uglify": "^2.1.0",
          "gulp-util": "^3.0.8",
          "gulp-watch": "^4.3.11",
          "htmlhint-stylish": "^1.0.3",
          "imagemin-pngquant": "^5.0.0",
          "jshint": "^2.9.4",
          "node-notifier": "^5.0.2",
          "path": "^0.12.7",
          "run-sequence": "^1.2.2",
          "vinyl-buffer": "^1.0.0",
          "vinyl-source-stream": "^1.1.0"
        },
        "engines": {
          "node": ">=4.0.0"
        },
        "scripts": {
          "test": "gulp production",
          "start": "gulp"
        },
        "dependencies": {
          "include-media": "~1.4.9",
          "jquery": "~2.2.4",
          "normalize.css": "~5.0.0"
        }
      };
    } catch (e) {
      console.error('There was an error reading the file!');
    }

    if ('delete' in config) {
      if (typeof packageFile === 'undefined') {
        console.log('package.json was not loaded!');
        reject();
      }
      // Change dependencies in package.json file
      changeDependencies(packageFile, config.delete, 'delete')
        .then(() => {
          if ('add' in config) {
            changeDependencies(packageFile, config.add, 'add')
              .then(() => {
                try {
                  fs.writeFileSync('./package.json', JSON.stringify(packageFile, null, 2), 'utf8');
                  resolve();
                } catch (e) {
                  console.log(e);
                  reject();
                }
              });
          }
        })
        .catch(e => {
          console.log(e);
          reject();
        });
    }
  });
}

function changeDependencies(packageFile, config, method) {
  return new Promise((resolve, reject) => {
    let instructions;

    if (method === 'delete') {
      instructions = (object, field) => {
        // Change to object
        return new Promise((resolve, reject) => {
          if (typeof object[field] === 'undefined') {
            resolve();
          } else {
            for (let item of object[field]) {
              if (field in packageFile && item in packageFile[field]) {
                delete packageFile[field][item];
              }
            }

            resolve();
          }
        });
      };
    } else {
      instructions = (object, field) => {
        // Change to object
        return new Promise((resolve, reject) => {
          if (typeof object[field] === 'undefined') {
            resolve();
          } else {
            for (let item in object[field]) {
              packageFile[field][item] = object[field][item];
            }

            resolve();
          }
        });
      }
    }

    instructions(config, 'dependencies')
      .then(instructions.bind(null, config, 'devDependencies'))
      .then(resolve);
  });
}

function changeVendorScss() {
  return new Promise((resolve, reject) => {
    let path = './src/vendor_entries/vendor.scss',
      vendorScss,
      addVendor,
      deleteVendor;

    try {
      vendorScss = fs.readFileSync(path, 'utf8').toString().split('\n');
    } catch (e) {
      console.log(e)
      reject();
    }

    addVendor = () => {
      return new Promise((resolve, reject) => {
        if (typeof config.add.vendorScss === 'undefined') {
          resolve();
        } else {
          for (let item of config.add.vendorScss) {
            vendorScss.push(item);
          }
          for (let i = 0; i < vendorScss.length; i++) {
            vendorScss[i] = vendorScss[i] + '\n';
          }

          try {
            fs.writeFileSync(path, vendorScss.join().replace(/,/g, ''), 'utf8');
            resolve();
          } catch (e) {
            console.log(e);
            reject();
          }
        }
      });
    }

    deleteVendor = () => {
      return new Promise((resolve, reject) => {
        if (typeof config.delete.vendorScss === 'undefined') {
          resolve();
        } else {
          for (let item of config.delete.vendorScss) {
            let lastChar = vendorScss[4].substr(vendorScss[4].length - 1),
              index;
            if (lastChar === '\n') {
              index = vendorScss.indexOf(item + '\n');
            } else {
              index = vendorScss.indexOf(item);
            }

            if (index > 1) {
              vendorScss.splice(index, 1);
              try {
                fs.writeFileSync(path, vendorScss.join().replace(/,/g, ''), 'utf8');
                resolve();
              } catch (e) {
                console.log(e);
                reject();
              }
            }
          }
          resolve();
        }
      });
    };

    addVendor()
      .then(deleteVendor)
      .then(resolve);
  });
}

function createTmpFolder() {
  return new Promise((resolve, reject) => {
    if (folderExists('tmp')) {
      console.log('Destination path already exists and is not an empty directory. '.red + emoji.get('cry'));
      return;
    }
    exec('mkdir tmp');
    cd('tmp');

    resolve();
  });
}

function gitClone(repo) {
  return new Promise((resolve, reject) => {
    console.log('Clone from ' + repo.url + ' ' + repo.branch);
    exec('git clone ' + repo.url + ' ./ -b ' + repo.branch);
    del.sync(['.git']);
    logComplete('Git cloning has been completed');

    resolve();
  });
}

function moveFiles() {
  return new Promise((resolve, reject) => {
    console.log('Copying files...');
    copydir('../tmp', '../', (err) => {
      if (err) {
        console.log(err);
        return;
      }
      cd('..');
      del.sync(['tmp']);
      logComplete('Copying files has been completed');

      resolve();
    });
  });
}

function installDependencies() {
  return new Promise((resolve, reject) => {
    console.log('Installing npm dependencies...');
    exec('npm install');
    logComplete('Dependencies have been installed');

    resolve();
  });
}

function finish() {
  console.log('Starter has been successfully installed. Good luck '.green +
    emoji.get('wink') + ' \n\u00A9 JustCoded'.green);
  exec('gulp');
}

function build(repositories) {
  return new Promise((resolve, reject) => {

    let chain = Promise.resolve();

    for (var i = 0; i < repositories.length; i++) {
      chain = chain
        .then(deleteFiles.bind(null, repositories[i].filesToDelete || null))
        .then(createTmpFolder)
        .then(gitClone.bind(null, repositories[i]))
        .then(moveFiles);

      if (i !== 0) {
        chain = chain
          .then(readConfigFiles)
          .then(configurePackageJson)
          .then(changeVendorScss);
      }

      if (i == repositories.length - 1) {
        chain = chain
          .then(installDependencies)
          .then(finish);
      }
    }

    resolve();
  });
}

module.exports = {
  init: function (repositories) {
    console.log('\nGetting starter files... ' + emoji.get('runner'));

    build(repositories);
  },
  emoji: emoji
}<|endoftext|>


<commit_before>/* ************************************ */
/* Define helper functions */
/* ************************************ */
function evalAttentionChecks() {
  var check_percent = 1
  if (run_attention_checks) {
    var attention_check_trials = jsPsych.data.getTrialsOfType('attention-check')
    var checks_passed = 0
    for (var i = 0; i < attention_check_trials.length; i++) {
      if (attention_check_trials[i].correct === true) {
        checks_passed += 1
      }
    }
    check_percent = checks_passed / attention_check_trials.length
  }
  return check_percent
}

function assessPerformance() {
	/* Function to calculate the "credit_var", which is a boolean used to
	credit individual experiments in expfactory. */
	var experiment_data = jsPsych.data.getTrialsOfType('poldrack-single-stim')
	var missed_count = 0
	var trial_count = 0
	var rt_array = []
	var rt = 0
		//record choices participants made
	var choice_counts = {}
	choice_counts[-1] = 0
	for (var k = 0; k < choices.length; k++) {
    choice_counts[choices[k]] = 0
  }
	for (var i = 0; i < experiment_data.length; i++) {
		trial_count += 1
		rt = experiment_data[i].rt
		key = experiment_data[i].key_press
		choice_counts[key] += 1
		if (rt == -1) {
			missed_count += 1
		} else {
			rt_array.push(rt)
		}
	}
	//calculate average rt
	var sum = 0
	for (var j = 0; j < rt_array.length; j++) {
		sum += rt_array[j]
	}
	var avg_rt = sum / rt_array.length
		//calculate whether response distribution is okay
	var responses_ok = true
	Object.keys(choice_counts).forEach(function(key, index) {
		if (choice_counts[key] > trial_count * 0.85) {
			responses_ok = false
		}
	})
	credit_var = (avg_rt > 200) && responses_ok
}

var getInstructFeedback = function() {
  return '

' + feedback_instruct_text +
    '

'
}

var post_trial_gap = function() {
  gap = Math.floor(Math.random() * 500) + 500
  return gap;
}

/* Append gap and current trial to data and then recalculate for next trial*/
var appendData = function() {
  jsPsych.data.addDataToLastTrial({
    trial_num: current_trial
  })
  current_trial = current_trial + 1
}

/* ************************************ */
/* Define experimental variables */
/* ************************************ */
// generic task variables
var run_attention_checks = false
var attention_check_thresh = 0.65
var sumInstructTime = 0 //ms
var instructTimeThresh = 0 ///in seconds
var credit_var = true

// task specific variables
var exp_len = 100
var practice_len = 20
var gap = 0
var current_trial = 0
  //set stim/response mapping
var correct_responses = jsPsych.randomization.shuffle([
    ['"M"', 77],
    ['"Z"', 90]
  ])

var choices = [correct_responses[0][1], correct_responses[1][1]]

//set up block stim. correct_responses indexed by [block][stim][type]
var practice_stimuli = [{
  stimulus: '

',
  data: {
    stim_id: 1,
    correct_response: correct_responses[0][1],
    trial_id: 'stim',
    exp_stage: 'practice'
  },
  key_answer: correct_responses[0][1]
}, {
  stimulus: '

',
  data: {
    stim_id: 2,
    correct_response: correct_responses[1][1],
    trial_id: 'stim',
    exp_stage: 'practice'
  },
  key_answer: correct_responses[1][1]
}];

var test_stimuli_block = [{
  stimulus: '

',
  data: {
    stim_id: 1,
    correct_response: correct_responses[0][1],
    trial_id: 'stim',
    exp_stage: 'test'
  }
}, {
  stimulus: '

',
  data: {
    stim_id: 2,
    correct_response: correct_responses[1][1],
    trial_id: 'stim',
    exp_stage: 'test'
  }
}];

var practice_trials = jsPsych.randomization.repeat(practice_stimuli, 5);
var test_trials = jsPsych.randomization.repeat(test_stimuli_block, 25);

/* ************************************ */
/* Set up jsPsych blocks */
/* ************************************ */
// Set up attention check node
var attention_check_block = {
  type: 'attention-check',
  data: {
    trial_id: 'attention_check'
  },
  timing_response: 180000,
  response_ends_trial: true,
  timing_post_trial: 200
}

var attention_node = {
  timeline: [attention_check_block],
  conditional_function: function() {
    return run_attention_checks
  }
}

//Set up post task questionnaire
var post_task_block = {
   type: 'survey-text',
   data: {
       trial_id: "post task questions"
   },
   questions: ['
Please summarize what you were asked to do in this task.
',
              '
Do you have any comments about this task?
'],
   rows: [15, 15],
   columns: [60,60]
};

/* define static blocks */
var feedback_instruct_text =
  'Welcome to the experiment. This task will take about 5 minutes. Press enter to begin.'
var feedback_instruct_block = {
  type: 'poldrack-text',
  cont_key: [13],
  data: {
    trial_id: 'instruction'
  },
  text: getInstructFeedback,
  timing_post_trial: 0,
  timing_response: 180000
};
/// This ensures that the subject does not read through the instructions too quickly.  If they do it too quickly, then we will go over the loop again.
var instructions_block = {
  type: 'poldrack-instructions',
  pages: [
    '

In this experiment blue and orange squares will appear on the screen. You will be told to respond to one of the colored squares by pressing the "M" key and to the other by pressing the "Z" key.
' +
    '
We will begin with practice. If you see the orange square you should press the ' +
    correct_responses[0][0] +
    ' key. If you see the blue square you should press the ' +
    correct_responses[1][0] +
    ' key.

You should respond as quickly and accurately as possible. You will get feedback telling you if you were correct.

'
  ],
  allow_keys: false,
  data: {
    trial_id: 'instruction'
  },
  show_clickable_nav: true,
  timing_post_trial: 1000
};

var instruction_node = {
  timeline: [feedback_instruct_block, instructions_block],
  /* This function defines stopping criteria */
  loop_function: function(data) {
    for (i = 0; i < data.length; i++) {
      if ((data[i].trial_type == 'poldrack-instructions') && (data[i].rt != -1)) {
        rt = data[i].rt
        sumInstructTime = sumInstructTime + rt
      }
    }
    if (sumInstructTime <= instructTimeThresh * 1000) {
      feedback_instruct_text =
        'Read through instructions too quickly.  Please take your time and make sure you understand the instructions.  Press enter to continue.'
      return true
    } else if (sumInstructTime > instructTimeThresh * 1000) {
      feedback_instruct_text =
        'Done with instructions. Press enter to continue.'
      return false
    }
  }
}

var end_block = {
  type: 'poldrack-text',
  timing_response: 180000,
  data: {
    trial_id: 'end',
    exp_id: 'choice_reaction_time'
  },
  text: '

Thanks for completing this task!

Press enter to continue.

',
  cont_key: [13],
  timing_post_trial: 0,
  on_finish: assessPerformance
};

var reset_block = {
  type: 'call-function',
  data: {
    trial_id: 'reset trial'
  },
  func: function() {
    current_trial = 0
  },
  timing_post_trial: 0
}

var start_practice_block = {
  type: 'poldrack-text',
  timing_response: 60000,
  data: {exp_id: 'choice_reaction_time', trial_id: 'practice_intro'},
  text: '

We will begin with practice. If you see the orange square you should press the ' + correct_responses[0][0] + ' key. If you see the blue square you should press the ' + correct_responses[1][0] + ' key.

You will receive feedback telling you if you were correct. Press enter to begin.

',
  cont_key: [13],
  timing_post_trial: 1000
};

var start_test_block = {
  type: 'poldrack-text',
  timing_response: 60000,
  data: {exp_id: 'choice_reaction_time', trial_id: 'practice_intro'},
  text: '

We will now begin the first test block. You will no longer receive feedback about your responses.

If you see the orange square you should press the ' + correct_responses[0][0] + ' key. If you see the blue square you should press the ' + correct_responses[1][0] + ' key. Press enter to begin.

',
  cont_key: [13],
  timing_post_trial: 1000
};

/* define practice block */
var practice_block = {
  type: 'poldrack-categorize',
  timeline: practice_trials,
  is_html: true,
  data: {
    trial_id: 'stim',
    exp_stage: 'practice'
  },
  correct_text: '

Correct!

',
  incorrect_text: '

Incorrect

',
  timeout_message: '

Respond Faster!

',
  choices: choices,
  timing_response: 2000,
  timing_stim: 2000,
  timing_feedback_duration: 1000,
  show_stim_with_feedback: false,
  timing_post_trial: post_trial_gap,
  on_finish: appendData
}

/* define test block */
var test_block = {
  type: 'poldrack-single-stim',
  timeline: test_trials,
  is_html: true,
  data: {
    trial_id: 'stim',
    exp_stage: 'test'
  },
  choices: choices,
  timing_response: 2000,
  timing_post_trial: post_trial_gap,
  on_finish: appendData
};

/* create experiment definition array */
var choice_reaction_time_experiment = [];
choice_reaction_time_experiment.push(instruction_node);
choice_reaction_time_experiment.push(practice_block);
choice_reaction_time_experiment.push(reset_block)
choice_reaction_time_experiment.push(start_test_block);
choice_reaction_time_experiment.push(test_block);
choice_reaction_time_experiment.push(attention_node)
choice_reaction_time_experiment.push(post_task_block)
choice_reaction_time_experiment.push(end_block)<commit_msg>added credit to choice RT<commit_after>/* ************************************ */
/* Define helper functions */
/* ************************************ */
function evalAttentionChecks() {
  var check_percent = 1
  if (run_attention_checks) {
    var attention_check_trials = jsPsych.data.getTrialsOfType('attention-check')
    var checks_passed = 0
    for (var i = 0; i < attention_check_trials.length; i++) {
      if (attention_check_trials[i].correct === true) {
        checks_passed += 1
      }
    }
    check_percent = checks_passed / attention_check_trials.length
  }
  return check_percent
}

function assessPerformance() {
	/* Function to calculate the "credit_var", which is a boolean used to
	credit individual experiments in expfactory. */
	var experiment_data = jsPsych.data.getTrialsOfType('poldrack-single-stim')
	var missed_count = 0
	var trial_count = 0
	var rt_array = []
	var rt = 0
		//record choices participants made
	var choice_counts = {}
	choice_counts[-1] = 0
	for (var k = 0; k < choices.length; k++) {
    choice_counts[choices[k]] = 0
  }
	for (var i = 0; i < experiment_data.length; i++) {
		trial_count += 1
		rt = experiment_data[i].rt
		key = experiment_data[i].key_press
		choice_counts[key] += 1
		if (rt == -1) {
			missed_count += 1
		} else {
			rt_array.push(rt)
		}
	}
	//calculate average rt
	var sum = 0
	for (var j = 0; j < rt_array.length; j++) {
		sum += rt_array[j]
	}
	var avg_rt = sum / rt_array.length
		//calculate whether response distribution is okay
	var responses_ok = true
	Object.keys(choice_counts).forEach(function(key, index) {
		if (choice_counts[key] > trial_count * 0.85) {
			responses_ok = false
		}
	})
	credit_var = (avg_rt > 200) && responses_ok
	jsPsych.data.addDataToLastTrial({"credit_var": credit_var})
}

var getInstructFeedback = function() {
  return '

' + feedback_instruct_text +
    '

'
}

var post_trial_gap = function() {
  gap = Math.floor(Math.random() * 500) + 500
  return gap;
}

/* Append gap and current trial to data and then recalculate for next trial*/
var appendData = function() {
  jsPsych.data.addDataToLastTrial({
    trial_num: current_trial
  })
  current_trial = current_trial + 1
}

/* ************************************ */
/* Define experimental variables */
/* ************************************ */
// generic task variables
var run_attention_checks = false
var attention_check_thresh = 0.65
var sumInstructTime = 0 //ms
var instructTimeThresh = 0 ///in seconds
var credit_var = true

// task specific variables
var exp_len = 100
var practice_len = 20
var gap = 0
var current_trial = 0
  //set stim/response mapping
var correct_responses = jsPsych.randomization.shuffle([
    ['"M"', 77],
    ['"Z"', 90]
  ])

var choices = [correct_responses[0][1], correct_responses[1][1]]

//set up block stim. correct_responses indexed by [block][stim][type]
var practice_stimuli = [{
  stimulus: '

',
  data: {
    stim_id: 1,
    correct_response: correct_responses[0][1],
    trial_id: 'stim',
    exp_stage: 'practice'
  },
  key_answer: correct_responses[0][1]
}, {
  stimulus: '

',
  data: {
    stim_id: 2,
    correct_response: correct_responses[1][1],
    trial_id: 'stim',
    exp_stage: 'practice'
  },
  key_answer: correct_responses[1][1]
}];

var test_stimuli_block = [{
  stimulus: '

',
  data: {
    stim_id: 1,
    correct_response: correct_responses[0][1],
    trial_id: 'stim',
    exp_stage: 'test'
  }
}, {
  stimulus: '

',
  data: {
    stim_id: 2,
    correct_response: correct_responses[1][1],
    trial_id: 'stim',
    exp_stage: 'test'
  }
}];

var practice_trials = jsPsych.randomization.repeat(practice_stimuli, 5);
var test_trials = jsPsych.randomization.repeat(test_stimuli_block, 25);

/* ************************************ */
/* Set up jsPsych blocks */
/* ************************************ */
// Set up attention check node
var attention_check_block = {
  type: 'attention-check',
  data: {
    trial_id: 'attention_check'
  },
  timing_response: 180000,
  response_ends_trial: true,
  timing_post_trial: 200
}

var attention_node = {
  timeline: [attention_check_block],
  conditional_function: function() {
    return run_attention_checks
  }
}

//Set up post task questionnaire
var post_task_block = {
   type: 'survey-text',
   data: {
       trial_id: "post task questions"
   },
   questions: ['
Please summarize what you were asked to do in this task.
',
              '
Do you have any comments about this task?
'],
   rows: [15, 15],
   columns: [60,60]
};

/* define static blocks */
var feedback_instruct_text =
  'Welcome to the experiment. This task will take about 5 minutes. Press enter to begin.'
var feedback_instruct_block = {
  type: 'poldrack-text',
  cont_key: [13],
  data: {
    trial_id: 'instruction'
  },
  text: getInstructFeedback,
  timing_post_trial: 0,
  timing_response: 180000
};
/// This ensures that the subject does not read through the instructions too quickly.  If they do it too quickly, then we will go over the loop again.
var instructions_block = {
  type: 'poldrack-instructions',
  pages: [
    '

In this experiment blue and orange squares will appear on the screen. You will be told to respond to one of the colored squares by pressing the "M" key and to the other by pressing the "Z" key.
' +
    '
We will begin with practice. If you see the orange square you should press the ' +
    correct_responses[0][0] +
    ' key. If you see the blue square you should press the ' +
    correct_responses[1][0] +
    ' key.

You should respond as quickly and accurately as possible. You will get feedback telling you if you were correct.

'
  ],
  allow_keys: false,
  data: {
    trial_id: 'instruction'
  },
  show_clickable_nav: true,
  timing_post_trial: 1000
};

var instruction_node = {
  timeline: [feedback_instruct_block, instructions_block],
  /* This function defines stopping criteria */
  loop_function: function(data) {
    for (i = 0; i < data.length; i++) {
      if ((data[i].trial_type == 'poldrack-instructions') && (data[i].rt != -1)) {
        rt = data[i].rt
        sumInstructTime = sumInstructTime + rt
      }
    }
    if (sumInstructTime <= instructTimeThresh * 1000) {
      feedback_instruct_text =
        'Read through instructions too quickly.  Please take your time and make sure you understand the instructions.  Press enter to continue.'
      return true
    } else if (sumInstructTime > instructTimeThresh * 1000) {
      feedback_instruct_text =
        'Done with instructions. Press enter to continue.'
      return false
    }
  }
}

var end_block = {
  type: 'poldrack-text',
  timing_response: 180000,
  data: {
    trial_id: 'end',
    exp_id: 'choice_reaction_time'
  },
  text: '

Thanks for completing this task!

Press enter to continue.

',
  cont_key: [13],
  timing_post_trial: 0,
  on_finish: assessPerformance
};

var reset_block = {
  type: 'call-function',
  data: {
    trial_id: 'reset trial'
  },
  func: function() {
    current_trial = 0
  },
  timing_post_trial: 0
}

var start_practice_block = {
  type: 'poldrack-text',
  timing_response: 60000,
  data: {exp_id: 'choice_reaction_time', trial_id: 'practice_intro'},
  text: '

We will begin with practice. If you see the orange square you should press the ' + correct_responses[0][0] + ' key. If you see the blue square you should press the ' + correct_responses[1][0] + ' key.

You will receive feedback telling you if you were correct. Press enter to begin.

',
  cont_key: [13],
  timing_post_trial: 1000
};

var start_test_block = {
  type: 'poldrack-text',
  timing_response: 60000,
  data: {exp_id: 'choice_reaction_time', trial_id: 'practice_intro'},
  text: '

We will now begin the first test block. You will no longer receive feedback about your responses.

If you see the orange square you should press the ' + correct_responses[0][0] + ' key. If you see the blue square you should press the ' + correct_responses[1][0] + ' key. Press enter to begin.

',
  cont_key: [13],
  timing_post_trial: 1000
};

/* define practice block */
var practice_block = {
  type: 'poldrack-categorize',
  timeline: practice_trials,
  is_html: true,
  data: {
    trial_id: 'stim',
    exp_stage: 'practice'
  },
  correct_text: '

Correct!

',
  incorrect_text: '

Incorrect

',
  timeout_message: '

Respond Faster!

',
  choices: choices,
  timing_response: 2000,
  timing_stim: 2000,
  timing_feedback_duration: 1000,
  show_stim_with_feedback: false,
  timing_post_trial: post_trial_gap,
  on_finish: appendData
}

/* define test block */
var test_block = {
  type: 'poldrack-single-stim',
  timeline: test_trials,
  is_html: true,
  data: {
    trial_id: 'stim',
    exp_stage: 'test'
  },
  choices: choices,
  timing_response: 2000,
  timing_post_trial: post_trial_gap,
  on_finish: appendData
};

/* create experiment definition array */
var choice_reaction_time_experiment = [];
choice_reaction_time_experiment.push(instruction_node);
choice_reaction_time_experiment.push(practice_block);
choice_reaction_time_experiment.push(reset_block)
choice_reaction_time_experiment.push(start_test_block);
choice_reaction_time_experiment.push(test_block);
choice_reaction_time_experiment.push(attention_node)
choice_reaction_time_experiment.push(post_task_block)
choice_reaction_time_experiment.push(end_block)<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var Schema = mongoose.Schema;

module.exports = {
    def: {
        _owner: {
            type: Schema.Types.ObjectId,
            ref: 'muser',
            required:true
        },
        _users:[{
            type:Schema.Types.ObjectId,
            ref:'meetfulEventUser'
        }],
        _messages:[{
            type:Schema.Types.ObjectId,
            ref:'meetfulEventMessages',
            default:[]
        }],
        name: {
            type: String,
            required: true
        },
        short_description: {
            type: String,
            required: true
        },
        description: {
            type: String,
            required: true
        },
        tags: {
            type: {},
            required: true
        }
    }
};
<commit_msg>meetful-xxx-event-schema-change<commit_after>var mongoose = require('mongoose');
var Schema = mongoose.Schema;

module.exports = {
    name: 'mevent',
    def: {
        _owner: {
            type: Schema.Types.ObjectId,
            ref: 'muser',
            required: true
        },
        _users: [{
            type: Schema.Types.ObjectId,
            ref: 'muser'
        }],
        _messages: [{
            type: Schema.Types.ObjectId,
            ref: 'meetfulEventMessages',
            default: []
        }],
        name: {
            type: String,
            required: true
        },
        short_description: {
            type: String,
            required: true
        },
        description: {
            type: String,
            required: true
        },
        address: {
            type: String,
            required: false
        },
        date: {
            type: String,
            required: false
        },
        tags: {
            type: {},
            required: true
        },
        status: {
            type: String,
            required: true
        }
    }
};
<|endoftext|>


<commit_before>/*
 * grunt-flow-type-check
 * https://github.com/isuttell/grunt-flow-type-check
 *
 * Copyright (c) 2014 Isaac Suttell
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  var flow = require('./lib/flow').init(grunt);

  grunt.registerMultiTask('flow', 'Facebook\'s Flow static type checking', function() {
    var options = this.options({
      configFile: '.',
      json: false,
      background: false
    });

    // This task is asynchronous
    var callback = this.async();

    // Default args and process options
    var args = [options.configFile];
    var opts = {
      stdio: 'inherit'
    };

    if (options.json) {
      // Enable json output - mostly for testing
      args.push('--json');
      delete opts.stdio;
    }

    // Watch tasks
    if (options.background === true) {
      var availableArgs = ['start', 'status', 'stop'];
      if (availableArgs.indexOf(this.args[0]) > -1) {
        args.push(this.args);
        args = [this.args, options.configFile];
        flow.run(args, opts, function(err, output) {
          if (err) {
            callback(err);
          }
        });
      }

      // When we catch CTRL+C kill the flow server
      process.on('SIGINT', function() {
        args.push('stop');
        flow.run(args, opts, function(err, output) {
          process.kill();
        });
      });

    } else {

      // By default we run a full check
      args = ['check', options.configFile];
      flow.run(args, opts, function(err, output) {
        if (output) {
          grunt.log.writeln(JSON.stringify(output));
        }
        callback(err);
      });
    }
  });

};
<commit_msg>refactor code so itis more DRY<commit_after>/*
 * grunt-flow-type-check
 * https://github.com/isuttell/grunt-flow-type-check
 *
 * Copyright (c) 2014 Isaac Suttell
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  // Flow control library
  var flow = require('./lib/flow').init(grunt);

  grunt.registerMultiTask('flow', 'Facebook\'s Flow static type checking', function() {
    // Default options
    var options = this.options({
      configFile: '.',
      json: false,
      background: false
    });

    // This task is asynchronous
    var callback = this.async();

    // Default args and process options
    var args = [];
    var opts = {
      stdio: 'inherit'
    };

    // Figure out what command to run
    var commands = ['start', 'status', 'stop', 'check'];
    if (commands.indexOf(this.args[0]) > -1) {
      args.push(this.args);
    } else {
      // Default to a basic full check
      args.push('check');
    }

    // Where is `.flowconfig`
    args.push(options.configFile);

    // Enable json output - mostly for testing
    if (options.json) {
      args.push('--json');
      delete opts.stdio;
    }

    // Run it
    flow.run(args, opts, function(err, output) {
      if (output) {
        grunt.log.writeln(JSON.stringify(output));
      }
      callback(err);
    });

    // Stop the server
    if (options.background === true) {
      // When we catch CTRL+C kill the flow server
      process.on('SIGINT', function() {
        args.push('stop');
        flow.run(args, opts, function(err, output) {
          process.kill();
        });
      });
    }

  });

};
<|endoftext|>


<commit_before>// VCE Project - Particle class
//
// A simple class to store particle information and apply
// various transformations to simulate particle movement.
//
// Requires:
// - p5.js or p5.min.js
//
// Andrew D. McGuire 2017
// a.mcguire227@gmail.com
//----------------------------------------------------------

function Particle(x,y,r) {

    /* Initialise the particle with a random velocity
       and zero acceleration.

       args:
       x - particle initial x position
       y - particle in ital y position
       r - particle radius
    */
    this.initVelocity = function() {

	// intialise a random velocity based on the size
	// of the particles (all particles have equal energy)
	var v1 = Math.random()*4.0-2.0;
	var k1 = Math.pow(125.0/Math.pow(this.radius,3),0.5);
	var vel = createVector(k1*v1,k1*v1);
	return vel

    }

    // Particle attributes
    this.pos = createVector(x,y); // position vector
    this.radius = r;              // radius
    this.vel = this.initVelocity();     // velocity vector
    this.acc = createVector(0,0); // current acceleration vector
    this.acc_old = this.acc;      // previous acceleration vector
    this.mass = 1;                // mass (fixed for now)

    // Particle Methods
    this.update = function(dt) {

	/* Compute the new acceleration, position and
	   velocity vectors using the Velocity Verlet algorithm
	   with time-step dt. Constant acceleration is
	   assumed for the moment. */

	this.update_acc(dt)
	this.update_pos(dt)
	this.update_vel(dt)

    }

    this.show = function() {

	/* Draw the particle as an circle on
	   the canvas. Size is controlled by
	   the particle radius. */

	fill(46,138,222);
	noStroke();
	ellipse(this.pos.x,this.pos.y,2.0*this.radius);
    }

    this.highlight = function() {

	// Highlight the particle red.

	fill(256,1,1);
	noStroke();
	ellipse(this.pos.x,this.pos.y,2.0*this.radius);
    }

    this.update_acc = function(dt) {

	/* Update acceleration term. Constant
	   acceleration for now so no change.*/

	this.acc_old = this.acc
	this.acc = this.acc
    }

    this.update_pos = function(dt) {

	/* Update the particle position
	   according to a time-step of size dt.*/

	var pos_1 = this.pos
	pos_1.add(p5.Vector.mult(this.vel, dt));
	var pos_2 = p5.Vector.mult(this.acc, 0.5*Math.pow(dt,2.0));
	this.pos = p5.Vector.add(pos_1, pos_2);

    }

    this.update_vel = function(dt) {

	/* Update the velocity according to
	   and its accelerate over time
	   interval dt. */

	var v_1 = this.vel;
	var a_sum = p5.Vector.add(this.acc, this.acc);
	var v_2 = p5.Vector.mult(a_sum, 0.5*dt);
	this.vel = p5.Vector.add(v_1, v_2);
    }

    this.reflect_side = function() {
	// Invert the x velocity component
	this.vel.x = - this.vel.x;
    }

    this.reflect_top = function() {
	// Invert the y velocity component
	this.vel.y = - this.vel.y;
    }

    this.apply_boundary_cond = function(xmax,ymax) {

	/* Update the particle position to
	   simulate periodic boundary conditions
	   with box bounds (0,xmax), (0,ymax)*/

	if (this.pos.x >= xmax) {
	    this.pos.x = this.pos.x - xmax
	}
	if (this.pos.x < 0) {
	    this.pos.x = this.pos.x + xmax
	}
	if (this.pos.y >= ymax) {
	    this.pos.y = this.pos.y - ymax
	}
	if (this.pos.y < 0) {
	    this.pos.y = this.pos.y + ymax
	}
    }

    this.apply_impulse = function(Jx,Jy) {

	/*
	   Compute and apply velocity change due to
	   an impulse applied to the particle.

	   args:
	   Jx - scalar x-component of the impulse vector
	   Jy - scalar y-component of the impulse vector
	*/

	this.vel.x = this.vel.x + (Jx/this.mass);
	this.vel.y = this.vel.y + (Jy/this.mass);
    }

} // end of Particle class
<commit_msg>MD module: particle mass now based on radius and all particles initialised with the same energy<commit_after>// VCE Project - Particle class
//
// A simple class to store particle information and apply
// various transformations to simulate particle movement.
//
// Requires:
// - p5.js or p5.min.js
//
// Andrew D. McGuire 2017
// a.mcguire227@gmail.com
//----------------------------------------------------------

function Particle(x,y,r) {

    /* Initialise the particle with a random velocity
       and zero acceleration.

       args:
       x - particle initial x position
       y - particle in ital y position
       r - particle radius
    */
    this.initVelocity = function() {

	// return a random velocity vector based on particle energy
	var Ex = this.energy*Math.random();
	var Ey = this.energy - Ex;
	var dir = [-1,1];
	var vx = dir[Math.floor(Math.random() * dir.length)]*Math.pow(2.0*Ex/this.mass, 0.5);
	var vy = dir[Math.floor(Math.random() * dir.length)]*Math.pow(2.0*Ey/this.mass, 0.5);
	var v = createVector(vx,vy);
	return v

    }

    // Particle attributes
    this.pos = createVector(x,y); // position vector
    this.radius = r;              // radius
    this.acc = createVector(0,0); // current acceleration vector
    this.acc_old = this.acc;      // previous acceleration vector
    this.mass = Math.pow(this.radius,3.0)/125.0; // mass
    this.energy = 1.0;                    // total particle energy
    this.vel = this.initVelocity();     // velocity vector

    // Particle Methods
    this.update = function(dt) {

	/* Compute the new acceleration, position and
	   velocity vectors using the Velocity Verlet algorithm
	   with time-step dt. Constant acceleration is
	   assumed for the moment. */

	this.update_acc(dt)
	this.update_pos(dt)
	this.update_vel(dt)

    }

    this.show = function() {

	/* Draw the particle as an circle on
	   the canvas. Size is controlled by
	   the particle radius. */

	fill(46,138,222);
	noStroke();
	ellipse(this.pos.x,this.pos.y,2.0*this.radius);
    }

    this.highlight = function() {

	// Highlight the particle red.

	fill(256,1,1);
	noStroke();
	ellipse(this.pos.x,this.pos.y,2.0*this.radius);
    }

    this.update_acc = function(dt) {

	/* Update acceleration term. Constant
	   acceleration for now so no change.*/

	this.acc_old = this.acc
	this.acc = this.acc
    }

    this.update_pos = function(dt) {

	/* Update the particle position
	   according to a time-step of size dt.*/

	var pos_1 = this.pos
	pos_1.add(p5.Vector.mult(this.vel, dt));
	var pos_2 = p5.Vector.mult(this.acc, 0.5*Math.pow(dt,2.0));
	this.pos = p5.Vector.add(pos_1, pos_2);

    }

    this.update_vel = function(dt) {

	/* Update the velocity according to
	   and its accelerate over time
	   interval dt. */

	var v_1 = this.vel;
	var a_sum = p5.Vector.add(this.acc, this.acc);
	var v_2 = p5.Vector.mult(a_sum, 0.5*dt);
	this.vel = p5.Vector.add(v_1, v_2);
    }

    this.reflect_side = function() {
	// Invert the x velocity component
	this.vel.x = - this.vel.x;
    }

    this.reflect_top = function() {
	// Invert the y velocity component
	this.vel.y = - this.vel.y;
    }

    this.apply_boundary_cond = function(xmax,ymax) {

	/* Update the particle position to
	   simulate periodic boundary conditions
	   with box bounds (0,xmax), (0,ymax)*/

	if (this.pos.x >= xmax) {
	    this.pos.x = this.pos.x - xmax
	}
	if (this.pos.x < 0) {
	    this.pos.x = this.pos.x + xmax
	}
	if (this.pos.y >= ymax) {
	    this.pos.y = this.pos.y - ymax
	}
	if (this.pos.y < 0) {
	    this.pos.y = this.pos.y + ymax
	}
    }

    this.apply_impulse = function(Jx,Jy) {

	/*
	   Compute and apply velocity change due to
	   an impulse applied to the particle.

	   args:
	   Jx - scalar x-component of the impulse vector
	   Jy - scalar y-component of the impulse vector
	*/

	this.vel.x = this.vel.x + (Jx/this.mass);
	this.vel.y = this.vel.y + (Jy/this.mass);
    }

} // end of Particle class
<|endoftext|>


<commit_before><commit_msg>lib/network is not used<commit_after><|endoftext|>


<commit_before>/*
 * NOTICE: Most of this code is from grunt-contrib-less
 * but it has been modified to concat the LESS
 * files first, then compile them into a CSS
 * file. This plugin allows for "requiring" LESS files
 * and also for easily building out individual components.
 *
 * grunt-contrib-less
 * http://gruntjs.com/
 * Copyright (c) 2012 Tyler Kellen, contributors
 * Licensed under the MIT license.
 *
 * assemble-less
 * http://assemble.github.com/assemble-less
 * Copyright (c) 2013 Brian Woodward, contributors
 * Licensed under the MIT license.
 *
 */

module.exports = function(grunt) {

  var path = require('path');
  var util = require('util');
  var _    = grunt.util._;
  var less = false;

  var lessOptions = {
    parse: [
      'paths',
      'filename',
      'optimization',
      'processImports',
      'dumpLineNumbers',
      'strictImports'
    ],
    render: [
      'silent',
      'verbose',
      'compress',
      'yuicompress',
      'strictMaths',
      'strictUnits',
      'ieCompat'
    ]
  };

  grunt.registerMultiTask('less', 'Compile LESS to CSS using underscore and JSON.', function() {
    var done = this.async();

    // Default options.
    var options = this.options({
      version: 'less',
      globals: [],
      concat: true,
      imports: '',
      banner: '',
      process: false,

      // Less.js defaults
      processImports: true,
      strictMaths: false,
      strictUnits: false
    });

    // Load less version specified in options, else load default
    grunt.verbose.writeln('Loading less from ' + options.version);
    try {
      less = require(options.version);
    } catch (err) {
      var lessPath = path.join(process.cwd(), options.version);
      grunt.verbose.writeln('lessPath: ', lessPath);
      less = require(lessPath);
      grunt.log.success('\nRunning Less.js v', path.basename(options.version) + '\n');
    }
    grunt.verbose.writeln('Less loaded');

    // Normalize boolean options that accept options objects.
    if (options.process === true) { options.process = {}; }

    // Define the callback function.
    // function ShowResults(value, index, ar) {
    //   return "SLSLSLSLSLS: " + value + " index: " + index + "<br />";
    // }

    // Process imports and any templates.
    var imports = [];
    var prependImport = '@import ' ;
    // var appendImport = "\n/* this is a test */\n";

    for(var directive in options.imports) {
      if(options.imports.hasOwnProperty(directive)) {
        var list = options.imports[directive];
        if(!Array.isArray(list)) {
          list = [list];
        }
        var directiveString = '(' + directive + ') ';
        _.each(list, function(item) {
          imports.push(prependImport + directiveString + '"' + grunt.template.process(item) + '.less";');
        });
      }
    }

    imports = imports.join('\n');
    // if (Array.isArray(options.imports)) {
    //   // var letters = options.imports;
    //   // letters.forEach(ShowResults);
    //   // var imports = grunt.template.process(letters.join(appendImport));
    //   imports = prependImport + grunt.template.process(options.imports.join(appendImport));
    // } else {
    //   imports = grunt.template.process(options.imports) + appendImport;
    // }

    // Process banner.
    var banner = grunt.template.process(options.banner);

    grunt.util.async.forEachSeries(this.files, function(f, nextFileObj) {
      var destFile = f.dest;

      var files = f.src.filter(function(filepath) {
        // Warn on and remove invalid source files.
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      });

      // No src files, goto next target.
      // Warn would have been issued above.
      if (files.length === 0) {
        nextFileObj();
      }

      var compiled = [];
      var dependencies = [];
      var srcCode = [];

      // Compile multiple concatenated LESS files.
      var concatCompile = function(file, next) {
        grunt.log.writeln('Compiling: ' + file.magenta);
        grunt.util.async.concatSeries(options.globals, function(file, next) {
          if(grunt.util._.contains(dependencies, file) === false) {
            srcCode.push(grunt.file.read(file));
            dependencies.push(file);
          }
          next(null);
        }, function() {});
        srcCode.push(grunt.file.read(file));
        next(null);
      };

      // Render multiple concatenated LESS files.
      var concatRender = function() {
        var lessCode = banner + imports + srcCode.join(grunt.util.normalizelf(grunt.util.linefeed));
        if (options.process) {
           lessCode = grunt.template.process(lessCode, options.process);
        }
        compileLess(destFile, lessCode, options, function(css, err) {
          if(!err) {
            grunt.file.write(destFile, css);
            grunt.log.ok('Concat/compiled ' + ((srcCode.length) - 3) + ' LESS files into ' + destFile.cyan);
            grunt.verbose.writeln('File ' + destFile.cyan + ' created.');
            nextFileObj();
          } else {
            nextFileObj(false);
          }
        });
      };

      // Compile individual LESS files.
      var singleCompile = function(file, next) {

        if(fs.existsSync(destFile)) {
          var dirStats = fs.statSync(destFile);
          if(dirStats.isDirectory() === false) {
            grunt.log.warn('Destination must be a directory when compiling to single css files.');
            nextFileObj(false);
          }
        }
        var singleSrcCode = [];
        grunt.util.async.concatSeries(options.globals, function(file, next) {
          singleSrcCode.push(grunt.file.read(file));
          next(null);
        }, function() {});

        singleSrcCode.push(grunt.file.read(file));
        singleSrcCode = banner + imports + singleSrcCode.join(grunt.util.normalizelf(grunt.util.linefeed));

        compileLess(file, singleSrcCode, options, function(css, err) {
          if(!err) {
            // write the file out directly
            var singleDestFile = path.join(destFile, path.basename(file, path.extname(file))) + '.css';
            grunt.file.write(singleDestFile, css);
            grunt.log.ok('File ' + singleDestFile.cyan + ' created.' + ' ok '.green);
            next(null);
          } else {
            nextFileObj(false);
          }
        });
      };

      // Render individual LESS files.
      var singleRender = function() {
        nextFileObj();
      };

      if(options.concat) {
        grunt.util.async.concatSeries(files, concatCompile, concatRender);
      } else {
        grunt.util.async.concatSeries(files, singleCompile, singleRender);
      }
    }, done);
  });

  var compileLess = function(filename, srcCode, options, callback) {
    options = grunt.util._.extend({filename: filename}, options);
    options.paths = options.paths || [path.dirname(filename)];

    var css;
    var parser = new less.Parser(grunt.util._.pick(options, lessOptions.parse));

    grunt.verbose.writeln('before parse');
    parser.parse(srcCode, function(parse_err, tree) {
      if (parse_err) {
        lessError(parse_err);
        callback('',true);
      }
      try {
        grunt.verbose.writeln('parsed...');
        css = tree.toCSS(grunt.util._.pick(options, lessOptions.render));
        grunt.verbose.writeln('rendered...');
        callback(css, null);
      } catch (e) {
        lessError(e);
        callback(css, true);
      }
    });
  };

  _.mixin({

    /* Read optional JSON from Ben Alman, https://gist.github.com/2876125 */
    readOptionalJSON: function(filepath) {
      var data = {};
      try {
        data = grunt.file.readJSON(filepath);
      } catch (e) {}
      return data;
    },
    /* Function from assemble https://github.com/assemble/assemble */
    mergeOptionsArrays: function(target, name) {
      var globalArray = grunt.config(['lessrc', 'options', name]) || [];
      var targetArray = grunt.config(['lessrc', target, 'options', name]) || [];
      return _.union(globalArray, targetArray);
    }
  });

  var formatLessError = function(e) {
    var pos = '[' + 'L' + e.line + ':' + ('C' + e.column) + ']';
    return e.filename + ': ' + pos + ' ' + e.message;
  };

  var lessError = function(e) {
    var message = less.formatError ? less.formatError(e) : formatLessError(e);

    grunt.log.error(message);
    grunt.fail.warn('Error compiling LESS.');
  };
};
<commit_msg>add missing require('fs') statement<commit_after>/*
 * NOTICE: Most of this code is from grunt-contrib-less
 * but it has been modified to concat the LESS
 * files first, then compile them into a CSS
 * file. This plugin allows for "requiring" LESS files
 * and also for easily building out individual components.
 *
 * grunt-contrib-less
 * http://gruntjs.com/
 * Copyright (c) 2012 Tyler Kellen, contributors
 * Licensed under the MIT license.
 *
 * assemble-less
 * http://assemble.github.com/assemble-less
 * Copyright (c) 2013 Brian Woodward, contributors
 * Licensed under the MIT license.
 *
 */

module.exports = function(grunt) {

  var fs   = require('fs');
  var path = require('path');
  var util = require('util');
  var _    = grunt.util._;
  var less = false;

  var lessOptions = {
    parse: [
      'paths',
      'filename',
      'optimization',
      'processImports',
      'dumpLineNumbers',
      'strictImports'
    ],
    render: [
      'silent',
      'verbose',
      'compress',
      'yuicompress',
      'strictMaths',
      'strictUnits',
      'ieCompat'
    ]
  };

  grunt.registerMultiTask('less', 'Compile LESS to CSS using underscore and JSON.', function() {
    var done = this.async();

    // Default options.
    var options = this.options({
      version: 'less',
      globals: [],
      concat: true,
      imports: '',
      banner: '',
      process: false,

      // Less.js defaults
      verbose: true,
      processImports: true,
      strictMaths: false,
      strictUnits: false
    });

    // Load less version specified in options, else load default
    grunt.verbose.writeln('Loading less from ' + options.version);
    try {
      less = require(options.version);
    } catch (err) {
      var lessPath = path.join(process.cwd(), options.version);
      grunt.verbose.writeln('lessPath: ', lessPath);
      less = require(lessPath);
      grunt.log.success('\nRunning Less.js v', path.basename(options.version) + '\n');
    }
    grunt.verbose.writeln('Less loaded');

    // Normalize boolean options that accept options objects.
    if (options.process === true) { options.process = {}; }

    // Process imports and any templates.
    var imports = [];
    var prependImport = '@import ' ;
    // var appendImport = "\n/* this is a test */\n";

    for(var directive in options.imports) {
      if(options.imports.hasOwnProperty(directive)) {
        var list = options.imports[directive];
        if(!Array.isArray(list)) {
          list = [list];
        }
        var directiveString = '(' + directive + ') ';
        _.each(list, function(item) {
          imports.push(prependImport + directiveString + '"' + grunt.template.process(item) + '";');
        });
      }
    }

    // var ref = options.variables;
    // for (name in ref) {
    //   var value = ref[name];
    //   output += '@' + name + ': ' + value + ';\n';
    // }
    // output += '\n';

    imports = imports.join('\n');

    // Process banner.
    var banner = grunt.template.process(options.banner);

    grunt.util.async.forEachSeries(this.files, function(f, nextFileObj) {
      var destFile = f.dest;

      var files = f.src.filter(function(filepath) {
        // Warn on and remove invalid source files.
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      });

      // No src files, goto next target.
      // Warn would have been issued above.
      if (files.length === 0) {
        nextFileObj();
      }

      var compiled = [];
      var dependencies = [];
      var srcCode = [];

      // Compile multiple concatenated LESS files.
      var concatCompile = function(file, next) {
        grunt.verbose.writeln('Compiling: ' + file.magenta);
        grunt.util.async.concatSeries(options.globals, function(file, next) {
          if(grunt.util._.contains(dependencies, file) === false) {
            srcCode.push(grunt.file.read(file));
            dependencies.push(file);
          }
          next(null);
        }, function() {});
        srcCode.push(grunt.file.read(file));
        next(null);
      };

      // Render multiple concatenated LESS files.
      var concatRender = function() {
        var lessCode = banner + imports + srcCode.join(grunt.util.normalizelf(grunt.util.linefeed));
        if (options.process) {
           lessCode = grunt.template.process(lessCode, options.process);
        }
        compileLess(destFile, lessCode, options, function(css, err) {
          if(!err) {
            grunt.file.write(destFile, css);
            grunt.log.notverbose.ok('Compiled "' + destFile.cyan + '"...' + 'OK'.green);
            nextFileObj();
          } else {
            nextFileObj(false);
          }
        });
      };

      // Compile individual LESS files.
      var singleCompile = function(file, next) {

        if(fs.existsSync(destFile)) {
          var dirStats = fs.statSync(destFile);
          if(dirStats.isDirectory() === false) {
            grunt.log.warn('Destination must be a directory when compiling to single css files.');
            nextFileObj(false);
          }
        }
        var singleSrcCode = [];
        grunt.util.async.concatSeries(options.globals, function(file, next) {
          singleSrcCode.push(grunt.file.read(file));
          next(null);
        }, function() {});

        singleSrcCode.push(grunt.file.read(file));
        singleSrcCode = banner + imports + singleSrcCode.join(grunt.util.normalizelf(grunt.util.linefeed));

        compileLess(file, singleSrcCode, options, function(css, err) {
          if(!err) {
            // write the file out directly
            var singleDestFile = path.join(destFile, path.basename(file, path.extname(file))) + '.css';
            grunt.file.write(singleDestFile, css);
            grunt.log.ok('File ' + singleDestFile.cyan + ' created.' + ' ok '.green);
            next(null);
          } else {
            nextFileObj(false);
          }
        });
      };

      // Render individual LESS files.
      var singleRender = function() {
        nextFileObj();
      };

      grunt.verbose.writeflags(options, 'assemble-less options');

      if(options.concat) {
        grunt.util.async.concatSeries(files, concatCompile, concatRender);
      } else {
        grunt.util.async.concatSeries(files, singleCompile, singleRender);
      }
    }, done);
  });

  var compileLess = function(filename, srcCode, options, callback) {
    options = grunt.util._.extend({filename: filename}, options);
    options.paths = options.paths || [path.dirname(filename)];

    var css;
    var parser = new less.Parser(grunt.util._.pick(options, lessOptions.parse));

    grunt.verbose.ok('Attempting to parse...' + 'OK'.green);
    parser.parse(srcCode, function(parse_err, tree) {
      if (parse_err) {
        lessError(parse_err);
        callback('',true);
      }
      try {
        grunt.verbose.ok('File(s) parsed...' + 'OK'.green);
        css = tree.toCSS(grunt.util._.pick(options, lessOptions.render));
        grunt.verbose.ok('File(s) rendered...' + 'OK'.green);
        callback(css, null);
      } catch (e) {
        lessError(e);
        callback(css, true);
      }
    });
  };

  _.mixin({

    /* Read optional JSON from Ben Alman, https://gist.github.com/2876125 */
    readOptionalJSON: function(filepath) {
      var data = {};
      try {
        data = grunt.file.readJSON(filepath);
      } catch (e) {}
      return data;
    },
    /* Function from assemble https://github.com/assemble/assemble */
    mergeOptionsArrays: function(target, name) {
      var globalArray = grunt.config(['lessrc', 'options', name]) || [];
      var targetArray = grunt.config(['lessrc', target, 'options', name]) || [];
      return _.union(globalArray, targetArray);
    }
  });

  var formatLessError = function(e) {
    var pos = '[' + 'L' + e.line + ':' + ('C' + e.column) + ']';
    return e.filename + ': ' + pos + ' ' + e.message;
  };

  var lessError = function(e) {
    var message = less.formatError ? less.formatError(e) : formatLessError(e);

    grunt.log.error(message);
    grunt.fail.warn('Error compiling LESS.');
  };
};
<|endoftext|>