<commit_before>/*
 * grunt-docbase
 * https://github.com/mateus/DocbaseGrunt
 *
 * Copyright (c) 2015 Mateus Freira
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  // Please see the Grunt documentation for more information regarding task
  // creation: http://gruntjs.com/creating-tasks

  grunt.registerMultiTask('docbase', 'Grunt plugin to generate html files from your docbase project.', function() {

    var done = this.async();
    var options = this.options({
      generatePath: 'html/',
      mapFile: 'map.json',
      baseUrl: '',
      checkLoadedSelector: "[role='flatdoc-menu']",
      urlToAccess: "http://localhost:9001/",
      assets: ['bower_components', 'styles', 'scripts', 'images'],
      linksSelector: '[ng-href]:not(.dropdown-toggle)',
      linksVersions: '.version-switcher a',
      rootDocument: 'html',
      generateSearchIndex: true,
      generateHtml: true,
      startDocument: '',
      endDocument: '',
      searchIndexSelector: "h1, h2, h3, p"
    });
    grunt.log.writeln("starting ");
    var util = require("./lib/util.js");
    var termsToBaseURLReplace = ['src="', 'href="', "src=", "href="];
    var urlToFielName = util.urlToFielName;
    var getPageLinks = util.getPageLinks;
    var inQuotes = util.inQuotes;
    var mapFile = grunt.file.readJSON(options.mapFile);
    var versionsLink = util.versionLinks(mapFile);
    var phantom = require('phantom');
    var pages = [];
    var links = [];
    var crawled = {};
    var searchIndex = [];
    var indexdLinks = [];
    var fs = require('fs');
    var moveAssets = function(srcpath) {
      if (grunt.file.isDir(srcpath)) {
        var files = grunt.file.expand(srcpath + "/*");
        files.forEach(moveAssets);
      } else {
        grunt.file.copy(srcpath, options.generatePath + srcpath)
      }
    };
    var clearFolder = function(srcpath) {
      if (grunt.file.isDir(srcpath)) {
        var files = grunt.file.expand(srcpath + "/*");
        files.forEach(clearFolder);
      } else {
        grunt.file.delete(srcpath);
      }
    };
    var prepareAssets = function() {
      options.assets.forEach(function(srcpath) {
        grunt.log.writeln("Moving:", srcpath);
        moveAssets(srcpath);
      });
    }
    var checkQueueProcess = function(page, ph) {
      page.close();
      pages.shift();
      if (pages.length === 0) {
        prepareAssets();
        setTimeout(function() {
          ph.exit();
          done();
        }, 0);
      }
    };
    var replaceBaseUrl = function(documentContent, fileName) {
      var nPaths = (fileName.match(/\//g) || []).length;
      var baseUrl = "";
      for (var i = nPaths - 2; i >= 0; i--) {
        baseUrl += "../";
      }
      var result = documentContent;
      termsToBaseURLReplace.forEach(function(term) {
        result = result.replace(new RegExp(term + '/', 'g'), term + baseUrl);
      });
      return result;
    };
    var replaceLink = function(documentContent, from, to) {
      documentContent = documentContent.replace(new RegExp(inQuotes(from), 'g'), to);
      documentContent = documentContent.replace(new RegExp(from + "\#", 'g'), to + "#");
      return documentContent;
    };
    var replacePageLinks = function(documentContent) {
      versionsLink.forEach(function(version) {
        documentContent = replaceLink(documentContent, version.link, urlToFielName(version.realLink));
        documentContent = replaceLink(documentContent, urlToFielName(version.link), urlToFielName(version.realLink));
      });
      links.forEach(function(link) {
        var url = urlToFielName(link);
        documentContent = replaceLink(documentContent, link, url);
        documentContent = documentContent.replace(new RegExp(options.urlToAccess, 'g'), "");
      });
      return documentContent;
    };
    var makeCrawler = function(findLinks, once) {
      return function(currentLinks) {
        currentLinks.forEach(function(link) {
          if (!once || !crawled[link]) {
            if (once) {
              crawled[link] = true;
            }
            links.push(link);
            crawlPage(options.urlToAccess + link, findLinks);
          }
        });
      };
    };
    var generateSearchIndex = function(page, url) {
      page.evaluate(function(selector, url) {
        var HEADER = ['H2' , 'H1', 'H3'];
        var elements = Array.prototype.slice.call(document.querySelectorAll(selector));
        var h2s = elements.filter(function(element) {
          return HEADER.indexOf(element.tagName) !== -1;
        });
        return h2s.map(function(element, index) {
          var h2Index = elements.indexOf(element);
          var nextH2 = h2s[index + 1];
          var nextH2Index = !!nextH2 ? elements.indexOf(nextH2) : elements.length;
          var elementsBetween = elements.slice(h2Index, nextH2Index);
          var path = url.substr(url.indexOf('#'));
          var link = element.id ?  path + "/#" + element.id : path;
          return {
            link: link,
            title: element.innerText,
            content: elementsBetween.reduce(function(text, current) {
              return text += current.outerHTML;
            }, "")
          }
        });
      }, function(elements) {
        var  missingLinks = elements.filter(function(element){
          var has = !!indexdLinks[element.link];
          if(!has){
            indexdLinks[element.link] = true;
          }
          return !has;
        });
        searchIndex = searchIndex.concat(missingLinks.map(function(link){
          link.link = options.generateHtml ?  urlToFielName(link.link) : link.link;
          return link;
        }));
      }, options.searchIndexSelector, url);
    };
    var generatePage = function(page, url, ph) {
      page.evaluate(function(rootDocument) {
        return document.querySelector(rootDocument).innerHTML;
      }, function(documentContent) {
        var fileName = urlToFielName(url);
        documentContent = replaceBaseUrl(replacePageLinks(documentContent), fileName);
        if(options.generateHtml)
          grunt.file.write(options.generatePath + fileName, options.startDocument + documentContent + options.endDocument, 'w');
        var path = options.generateHtml ? options.generatePath : '';
        grunt.file.write(path + "search-index.json", JSON.stringify(searchIndex), 'w');
        grunt.log.writeln("Generating:", options.generatePath + urlToFielName(url));
        checkQueueProcess(page, ph);
      }, options.rootDocument);

    };
    var crawlPage = function(url, findLinks) {
      pages.push(url);
      phantom.create(function(ph) {
        ph.createPage(function(page) {
          page.set('settings.userAgent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36');
          page.open(url, function() {
            util.waitFor({
              debug: true,
              interval: 100,
              timeout: 50000,
              checkLoadedSelector: options.checkLoadedSelector,
              check: function(check) {
                return !!document.querySelector(check);
              },
              success: function() {
                if (findLinks) {
                  getPageLinks(page, options.linksSelector, makeCrawler(false, false));
                  getPageLinks(page, options.linksVersions, makeCrawler(true, true));
                };
                generatePage(page, url, ph);
                if (options.generateSearchIndex) {
                  generateSearchIndex(page, url);
                }
              },
              error: function(e) {
                  grunt.log.writeln("Erro generating page:", options.generatePath + urlToFielName(url));
                } // optional
            }, page);
          });
        });
      }, {
        parameters: {
          'ignore-ssl-errors': 'yes',
          'ssl-protocol': 'tlsv1',
          'web-security': false,
          //'debug' : 'true'
        }
      });
    };
    clearFolder(options.generatePath);
    crawlPage(options.urlToAccess, true);
  });

};<commit_msg>Use ul as text to search<commit_after>/*
 * grunt-docbase
 * https://github.com/mateus/DocbaseGrunt
 *
 * Copyright (c) 2015 Mateus Freira
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  // Please see the Grunt documentation for more information regarding task
  // creation: http://gruntjs.com/creating-tasks

  grunt.registerMultiTask('docbase', 'Grunt plugin to generate html files from your docbase project.', function() {

    var done = this.async();
    var options = this.options({
      generatePath: 'html/',
      mapFile: 'map.json',
      baseUrl: '',
      checkLoadedSelector: "[role='flatdoc-menu']",
      urlToAccess: "http://localhost:9001/",
      assets: ['bower_components', 'styles', 'scripts', 'images'],
      linksSelector: '[ng-href]:not(.dropdown-toggle)',
      linksVersions: '.version-switcher a',
      rootDocument: 'html',
      generateSearchIndex: true,
      generateHtml: true,
      startDocument: '',
      endDocument: '',
      searchIndexSelector: "h1, h2, h3, p, ul"
    });
    grunt.log.writeln("starting ");
    var util = require("./lib/util.js");
    var termsToBaseURLReplace = ['src="', 'href="', "src=", "href="];
    var urlToFielName = util.urlToFielName;
    var getPageLinks = util.getPageLinks;
    var inQuotes = util.inQuotes;
    var mapFile = grunt.file.readJSON(options.mapFile);
    var versionsLink = util.versionLinks(mapFile);
    var phantom = require('phantom');
    var pages = [];
    var links = [];
    var crawled = {};
    var searchIndex = [];
    var indexdLinks = [];
    var fs = require('fs');
    var moveAssets = function(srcpath) {
      if (grunt.file.isDir(srcpath)) {
        var files = grunt.file.expand(srcpath + "/*");
        files.forEach(moveAssets);
      } else {
        grunt.file.copy(srcpath, options.generatePath + srcpath)
      }
    };
    var clearFolder = function(srcpath) {
      if (grunt.file.isDir(srcpath)) {
        var files = grunt.file.expand(srcpath + "/*");
        files.forEach(clearFolder);
      } else {
        grunt.file.delete(srcpath);
      }
    };
    var prepareAssets = function() {
      options.assets.forEach(function(srcpath) {
        grunt.log.writeln("Moving:", srcpath);
        moveAssets(srcpath);
      });
    }
    var checkQueueProcess = function(page, ph) {
      page.close();
      pages.shift();
      if (pages.length === 0) {
        prepareAssets();
        setTimeout(function() {
          ph.exit();
          done();
        }, 0);
      }
    };
    var replaceBaseUrl = function(documentContent, fileName) {
      var nPaths = (fileName.match(/\//g) || []).length;
      var baseUrl = "";
      for (var i = nPaths - 2; i >= 0; i--) {
        baseUrl += "../";
      }
      var result = documentContent;
      termsToBaseURLReplace.forEach(function(term) {
        result = result.replace(new RegExp(term + '/', 'g'), term + baseUrl);
      });
      return result;
    };
    var replaceLink = function(documentContent, from, to) {
      documentContent = documentContent.replace(new RegExp(inQuotes(from), 'g'), to);
      documentContent = documentContent.replace(new RegExp(from + "\#", 'g'), to + "#");
      return documentContent;
    };
    var replacePageLinks = function(documentContent) {
      versionsLink.forEach(function(version) {
        documentContent = replaceLink(documentContent, version.link, urlToFielName(version.realLink));
        documentContent = replaceLink(documentContent, urlToFielName(version.link), urlToFielName(version.realLink));
      });
      links.forEach(function(link) {
        var url = urlToFielName(link);
        documentContent = replaceLink(documentContent, link, url);
        documentContent = documentContent.replace(new RegExp(options.urlToAccess, 'g'), "");
      });
      return documentContent;
    };
    var makeCrawler = function(findLinks, once) {
      return function(currentLinks) {
        currentLinks.forEach(function(link) {
          if (!once || !crawled[link]) {
            if (once) {
              crawled[link] = true;
            }
            links.push(link);
            crawlPage(options.urlToAccess + link, findLinks);
          }
        });
      };
    };
    var generateSearchIndex = function(page, url) {
      page.evaluate(function(selector, url) {
        var HEADER = ['H2' , 'H1', 'H3'];
        var elements = Array.prototype.slice.call(document.querySelectorAll(selector));
        var h2s = elements.filter(function(element) {
          return HEADER.indexOf(element.tagName) !== -1;
        });
        return h2s.map(function(element, index) {
          var h2Index = elements.indexOf(element);
          var nextH2 = h2s[index + 1];
          var nextH2Index = !!nextH2 ? elements.indexOf(nextH2) : elements.length;
          var elementsBetween = elements.slice(h2Index, nextH2Index);
          var path = url.substr(url.indexOf('#'));
          var link = element.id ?  path + "/#" + element.id : path;
          return {
            link: link,
            title: element.innerText,
            content: elementsBetween.reduce(function(text, current) {
              return text += current.outerHTML;
            }, "")
          }
        });
      }, function(elements) {
        var  missingLinks = elements.filter(function(element){
          var has = !!indexdLinks[element.link];
          if(!has){
            indexdLinks[element.link] = true;
          }
          return !has;
        });
        searchIndex = searchIndex.concat(missingLinks.map(function(link){
          link.link = options.generateHtml ?  urlToFielName(link.link) : link.link;
          return link;
        }));
      }, options.searchIndexSelector, url);
    };
    var generatePage = function(page, url, ph) {
      page.evaluate(function(rootDocument) {
        return document.querySelector(rootDocument).innerHTML;
      }, function(documentContent) {
        var fileName = urlToFielName(url);
        documentContent = replaceBaseUrl(replacePageLinks(documentContent), fileName);
        if(options.generateHtml)
          grunt.file.write(options.generatePath + fileName, options.startDocument + documentContent + options.endDocument, 'w');
        var path = options.generateHtml ? options.generatePath : '';
        grunt.file.write(path + "search-index.json", JSON.stringify(searchIndex), 'w');
        grunt.log.writeln("Generating:", options.generatePath + urlToFielName(url));
        checkQueueProcess(page, ph);
      }, options.rootDocument);

    };
    var crawlPage = function(url, findLinks) {
      pages.push(url);
      phantom.create(function(ph) {
        ph.createPage(function(page) {
          page.set('settings.userAgent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36');
          page.open(url, function() {
            util.waitFor({
              debug: true,
              interval: 100,
              timeout: 50000,
              checkLoadedSelector: options.checkLoadedSelector,
              check: function(check) {
                return !!document.querySelector(check);
              },
              success: function() {
                if (findLinks) {
                  getPageLinks(page, options.linksSelector, makeCrawler(false, false));
                  getPageLinks(page, options.linksVersions, makeCrawler(true, true));
                };
                generatePage(page, url, ph);
                if (options.generateSearchIndex) {
                  generateSearchIndex(page, url);
                }
              },
              error: function(e) {
                  grunt.log.writeln("Erro generating page:", options.generatePath + urlToFielName(url));
                } // optional
            }, page);
          });
        });
      }, {
        parameters: {
          'ignore-ssl-errors': 'yes',
          'ssl-protocol': 'tlsv1',
          'web-security': false,
          //'debug' : 'true'
        }
      });
    };
    clearFolder(options.generatePath);
    crawlPage(options.urlToAccess, true);
  });

};<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var temp = require('temp');
var open = require('open');
var _ = require('lodash');

var util = require('../lib/util');

function monitorChildProcess(child, callback) {
	child.child.stdout.on('data', function(data) {
		if (new RegExp('\\[pid: ' + child.child.pid + '\\][\\n\\r]*$').test(data.toString())) {
			callback();
		}
	});
}

module.exports = function(grunt) {
  var DefaultLiveReloadPort = 35729;
  var watchDir = temp.mkdirSync('express');
  var serverMap = {};
  var parentcwd = process.cwd();

  // get npmTasks from grunt-express, not the parent Gruntfile
  process.chdir(path.join(__dirname, '../'));

  if (!grunt.task._tasks['watch']) {
    grunt.loadNpmTasks('grunt-contrib-watch');
  }

  if (!grunt.task._tasks['parallel']) {
    grunt.loadNpmTasks('grunt-parallel');
  }

  process.chdir(parentcwd);

  grunt.registerMultiTask('express', function() {
    var thisTarget = this.target;
    var options = this.options({
      serverreload: false,
      livereload: false,
      open: false,
    });

    serverMap[thisTarget] = options.serverKey = path.resolve(watchDir, thisTarget + '.server');
    util.touchFile(options.serverKey);

    if (options.bases) {
      if (!Array.isArray(options.bases)) {
        grunt.config.set('express.' + thisTarget + '.options.bases', [options.bases]);
        options.bases = [options.bases];
      }

      // wrap each path in connect.static middleware
      options.bases =_.map(options.bases, function(b) {
        return path.resolve(b);
      });
    }

    if (options.livereload === true) {
      options.livereload = DefaultLiveReloadPort;
    }
    if (options.livereload) {
      // dynamically add `grunt-contrib-watch` task to manage livereload of static `bases`
      grunt.config.set('watch.' + util.makeServerTaskName(thisTarget, 'livereload'), {
        files: _.map(options.bases, function(base) {
          return base + '/**/*.*';
        }),
        options: {
          livereload: options.livereload
        }
      });
    }

    if (options.serverreload) {
      var watcherOptions = {
        interrupt: true,
        atBegin: true,
        event: ['added', 'changed']
      };

      var watching = 'undefined' !== typeof grunt.task._tasks.watch || 'undefined' !== typeof grunt.config.data.watch;
      // make sure `grunt-contrib-watch` task is loaded
      if (!watching) {
        grunt.loadNpmTasks('grunt-contrib-watch');
      }

      // dynamically add `grunt-contrib-watch` task to manage `grunt-express` sub task
      grunt.config.set('watch.' + util.makeServerTaskName(thisTarget, 'server'), {
        files: options.serverKey,
        tasks: [['express-server', thisTarget, options.serverKey].join(':'), 'express-keepalive'],
        options: _.extend({}, options.watch, watcherOptions)
      });

      if (_.filter(grunt.task._queue, function(task) {
        return !task.placeholder && task.task.name === 'watch';
      }).length === 0) {
        grunt.task.run('watch');
      }
    } else {
      grunt.task.run(['express-server', thisTarget].join(':'));
    }
  });

  grunt.registerTask('express-start', 'Start the server (or restart if already started)', function(target) {
    util.touchFile(serverMap[target]);
  });
  // alias, backward compatibility
  grunt.registerTask('express-restart', 'Restart the server (or start if not already started)', ['express-start']);

  grunt.registerTask('express-server', function(target) {
    var self = this;
    var options = _.extend({}, grunt.config.get('express.options'), grunt.config.get('express.' + target + '.options'));
    if (options.livereload === true) {
      options.livereload = DefaultLiveReloadPort;
    }

    if (options.serverreload) {
      util.watchModule(function(oldStat, newStat) {
        if (newStat.mtime.getTime() !== oldStat.mtime.getTime()) {
          util.touchFile(self.args[1]);
        }
      });
    }

    var done = this.async();

    util.runServer(grunt, options).on('startListening', function (server) {
      var address = server.address();
      var serverPort = address.port;
      if (serverPort !== options.port) {
        grunt.config.set('express.' + target + '.options.port', serverPort);
      }

      if (options.open === true) {
        // https://github.com/joyent/node/blob/master/lib/_tls_wrap.js#L464
        var protocol = (!server.pfx && (!server.cert || !server.key)) ? 'http' : 'https';
        console.log(address)
        var hostname = address.address || 'localhost';
        if (hostname === '0.0.0.0') {
          hostname = 'localhost';
        }
        open(protocol + '://' + hostname + ':' + address.port);
      } else if (typeof options.open === 'string') {
        open(options.open);
      }

      grunt.event.emit('express:' + target + ':started');
      done();
    });
  });

  grunt.registerTask('express-keepalive', 'Keep grunt running', function() {
    this.async();
  });
};
<commit_msg>Fixes #32<commit_after>'use strict';

var path = require('path');
var temp = require('temp');
var open = require('open');
var _ = require('lodash');

var util = require('../lib/util');

function monitorChildProcess(child, callback) {
	child.child.stdout.on('data', function(data) {
		if (new RegExp('\\[pid: ' + child.child.pid + '\\][\\n\\r]*$').test(data.toString())) {
			callback();
		}
	});
}

module.exports = function(grunt) {
  var DefaultLiveReloadPort = 35729;
  var watchDir = temp.mkdirSync('express');
  var serverMap = {};
  var parentcwd = process.cwd();

  // get npmTasks from grunt-express, not the parent Gruntfile
  process.chdir(path.join(__dirname, '../'));

  if (!grunt.task._tasks['watch']) {
    grunt.loadNpmTasks('grunt-contrib-watch');
  }

  if (!grunt.task._tasks['parallel']) {
    grunt.loadNpmTasks('grunt-parallel');
  }

  process.chdir(parentcwd);

  grunt.registerMultiTask('express', function() {
    var thisTarget = this.target;
    var options = this.options({
      serverreload: false,
      livereload: false,
      open: false
    });

    serverMap[thisTarget] = options.serverKey = path.resolve(watchDir, thisTarget + '.server');
    util.touchFile(options.serverKey);

    if (options.bases) {
      if (!Array.isArray(options.bases)) {
        grunt.config.set('express.' + thisTarget + '.options.bases', [options.bases]);
        options.bases = [options.bases];
      }

      // wrap each path in connect.static middleware
      options.bases =_.map(options.bases, function(b) {
        return path.resolve(b);
      });
    }

    if (options.livereload === true) {
      options.livereload = DefaultLiveReloadPort;
    }
    if (options.livereload) {
      // dynamically add `grunt-contrib-watch` task to manage livereload of static `bases`
      grunt.config.set('watch.' + util.makeServerTaskName(thisTarget, 'livereload'), {
        files: _.map(options.bases, function(base) {
          return base + '/**/*.*';
        }),
        options: {
          livereload: options.livereload
        }
      });
    }

    if (options.serverreload) {
      var watcherOptions = {
        interrupt: true,
        atBegin: true,
        event: ['added', 'changed']
      };

      var watching = 'undefined' !== typeof grunt.task._tasks.watch || 'undefined' !== typeof grunt.config.data.watch;
      // make sure `grunt-contrib-watch` task is loaded
      if (!watching) {
        grunt.loadNpmTasks('grunt-contrib-watch');
      }

      // dynamically add `grunt-contrib-watch` task to manage `grunt-express` sub task
      grunt.config.set('watch.' + util.makeServerTaskName(thisTarget, 'server'), {
        files: options.serverKey,
        tasks: [['express-server', thisTarget, options.serverKey].join(':'), 'express-keepalive'],
        options: _.extend({}, options.watch, watcherOptions)
      });

      if (_.filter(grunt.task._queue, function(task) {
        return !task.placeholder && task.task.name === 'watch';
      }).length === 0) {
        if (options.livereload) {
          var serverReloadTask = 'express-watch-server:' + thisTarget + ':' + options.serverKey,
              liveReloadTask = 'express-watch-livereload:' + options.bases.join(',') + ':' + thisTarget + ':' + options.livereload,
              parallelTask = 'parallel.' + util.makeServerTaskName(thisTarget, 'server');

          grunt.config.set(parallelTask, {
            tasks: [serverReloadTask, liveReloadTask],
            options: {
              stream: true,
              grunt: true
            }
          });

          grunt.task.run(parallelTask.replace('.', ':'));
        } else {
          grunt.task.run('watch');
        }
      }
    } else {
      grunt.task.run(['express-server', thisTarget].join(':'));
    }
  });

  grunt.registerTask('express-watch-livereload', 'wrapper for watch task, for running with grunt-parallel', function (bases, target, port) {
    // dynamically add `grunt-contrib-watch` task to manage livereload of static `bases`
    var taskName = 'watch.' + util.makeServerTaskName(target, 'livereload');
    bases = bases.split(',');
    port = parseInt(port) || DefaultLiveReloadPort;

    grunt.config.set(taskName, {
      files: _.map(bases, function(base) {
        return base + '/**/*.*';
      }),
      options: {
        livereload: port,
        interrupt: true
      }
    });
    grunt.task.run(taskName.replace('.', ':'));
  });

  grunt.registerTask('express-watch-server', 'wrapper for watch task, for running with grunt-parallel', function (target, serverKey) {
    var taskName = 'watch.' + util.makeServerTaskName(target, 'server'),
        options = grunt.config.get('express');

    var watcherOptions = {
      interrupt: true,
      atBegin: true,
      event: ['added', 'changed']
    };
    // dynamically add `grunt-contrib-watch` task to manage `grunt-express` sub task
    grunt.config.set(taskName, {
      files: serverKey,
      tasks: [['express-server', target, serverKey].join(':'), 'express-keepalive'],
      options: _.extend({}, options.watch, watcherOptions)
    });

    grunt.task.run(taskName.replace('.', ':'));
  });

  grunt.registerTask('express-start', 'Start the server (or restart if already started)', function(target) {
    util.touchFile(serverMap[target]);
  });
  // alias, backward compatibility
  grunt.registerTask('express-restart', 'Restart the server (or start if not already started)', ['express-start']);

  grunt.registerTask('express-server', function(target) {
    var self = this;
    var options = _.extend({}, grunt.config.get('express.options'), grunt.config.get('express.' + target + '.options'));
    if (options.livereload === true) {
      options.livereload = DefaultLiveReloadPort;
    }

    if (options.serverreload) {
      util.watchModule(function(oldStat, newStat) {
        if (newStat.mtime.getTime() !== oldStat.mtime.getTime()) {
          util.touchFile(self.args[1]);
        }
      });
    }

    var done = this.async();

    util.runServer(grunt, options).on('startListening', function (server) {
      var address = server.address();
      var serverPort = address.port;
      if (serverPort !== options.port) {
        grunt.config.set('express.' + target + '.options.port', serverPort);
      }

      if (options.open === true) {
        // https://github.com/joyent/node/blob/master/lib/_tls_wrap.js#L464
        var protocol = (!server.pfx && (!server.cert || !server.key)) ? 'http' : 'https';
        console.log(address)
        var hostname = address.address || 'localhost';
        if (hostname === '0.0.0.0') {
          hostname = 'localhost';
        }
        open(protocol + '://' + hostname + ':' + address.port);
      } else if (typeof options.open === 'string') {
        open(options.open);
      }

      grunt.event.emit('express:' + target + ':started');
      done();
    });
  });

  grunt.registerTask('express-keepalive', 'Keep grunt running', function() {
    this.async();
  });
};
<|endoftext|>


<commit_before>/*
 * grunt-glue-nu
 * https://github.com/MarcDiethelm/grunt-glue-nu
 *
 * Copyright (c) 2013 Marc Diethelm
 * Licensed under the MIT license.
 */

'use strict';

var  log = console.log
	,dir = console.dir
	,os = require('os')
	,path = require('path')
	,wrench = require('wrench')
;

module.exports = function (grunt) {

	// Glue options originally used with grunt-glue
	//'--css=<%=destSpritesCss%> --img=<%=destSpritesImg%> --less --url=<%=staticUriPrefix%><%=baseDirName%> --namespace=s --sprite-namespace= --recursive --crop --optipng --force --debug'

	var defaults = {
			 _process   : true
			,glueArgs   : null
			,tmpDir     : path.join(os.tmpdir(), 'grunt-glue-nu')
			,bundleName : null // default value set to task target inside the task

			,css        : null // default value set to dest inside the task
			,img        : null // default value set to dest inside the task
			,recursive  : true
			,crop       : true
			,force      : true
			,debug      : true
		}

		,extendedOptions = [
			 '_process'
			,'glueArgs'
			,'tmpDir'
			,'bundleName'
		]
	;

	// todo: need to write some tests (bdd?)
	// todo: look at/test conf files use

	grunt.registerMultiTask('glue', 'Create sprites automatically with Glue, but the grunt way!', function() {

		var  bundle, done;

		if (this.filesSrc.length > 0 || (this.data.options && this.data.options.glueArgs) ) {
			bundle = new Bundle();
			done = this.async();
		}
		else {
			grunt.log.warn('No sprites to compile.');
			return true;
		}

		bundle
			.configure(this)
			.make()
			.compile(function compileCb() {
				bundle.clean();
				done(); // tell grunt this task:target is complete
			})
		;

		return true;
	});

	// Constructor

	var Bundle = function() {};

	Bundle.prototype = {

		taskTargetName: ''

		,taskData: {}

		,directToGlue: false

		,expandedSrc: []

		,options: {}

		,aGlueOptions: []

		,glueSrcDir: ''

		,isTmpDirCreated: false

		// controllers
		///////////////////////////

		,configure: function(taskTarget) {
			this.taskData = taskTarget.data;
			this.taskFilesSrcArray = taskTarget.filesSrc;
			this.taskData.options = this.taskData.options || {};
			this.directToGlue = !!this.taskData.options.glueArgs;
			this.taskTargetName = taskTarget.target;

			if (!this.directToGlue) {
				this.checkRequiredInput();
				this.options = this.mergeOptions(defaults, taskTarget);
			}
			return this;
		}

		,make: function() {
			var isSourceSimple = this.isSrcSimpleDir();

			if (!this.directToGlue) {
				// don't copy files if source is simple and bundleName is either not set or the same as task target name
				// why? because Glue has no way to specify the generated file names except through the source folder
				if ( isSourceSimple && (!this.options.bundleName || this.options.bundleName === this.taskTargetName) ) {
					// just pass the location to glue
					this.glueSrcDir = this.taskData.src;
				}
				else {
					// work with complex src (multiple sources, globbing) / copy to force bundle name
					this.glueSrcDir = this.copyFilesToTmpDir();
					this.isTmpDirCreated = true;
				}
			}
			return this;
		}

		,compile: function(compileCb) {
			if (!this.directToGlue) {
				// build the args to glue from options
				this.aGlueOptions = this.createGlueArgs(this.glueSrcDir, this.options);
			}
			else {
				this.aGlueOptions = this.taskData.options.glueArgs.split(' ');
			}

			this.runGlue(function runGlueCb(err, result) {

				if (err) {
					// Glue thinks it's terrible when the src is empty. We don't
					if (err.message.indexOf('No images found') !== -1) {
						grunt.log.warn(err.message.replace(/^Error: /, 'Glue: '));
					}
					else {
						grunt.fail.warn(err.message);
					}
				}

				grunt.log.debug(result.stdout);

				return compileCb();
			});
		}

		,clean: function() {
			// remove the tmpDir and any glueSrcDir it contains, must force because it's outside of working dir.
			this.isTmpDirCreated && grunt.file.delete(this.options.tmpDir, {force: true});
			return true;
		}

		// methods
		///////////////////////////

		,checkRequiredInput: function() {
			!this.taskData.src &&
				grunt.fail.fatal('No src specified.');

			!this.taskData.dest &&
				grunt.fail.fatal('No dest specified.');

			return true;
		}

		,mergeOptions: function(defaults, taskTarget) {
			var filesArray = taskTarget.files;
			// setting grunt task dest as default for css and img args, so they can be overridden with specific options.
			// Glue says: You must choose the output folder using either the output argument or both --img and --css.
			// So we're using --img and --css
			defaults.css = filesArray[0].orig.dest;
			defaults.img = filesArray[0].orig.dest;
			defaults.bundleName = taskTarget.target; // used as tmp dir name. glue uses that as sprite name

			// Merge task-specific and/or target-specific options with defaults.
			return taskTarget.options(defaults);
		}

		,isSrcSimpleDir: function() {
			var  taskDataSrc = this.taskData.src
				,src
			;
			if (typeof taskDataSrc === 'string') {
				src = taskDataSrc;
			}
			// is it an array consisting of one string?
			else if (grunt.util.kindOf(taskDataSrc) === 'array' && taskDataSrc.length === 1) {
				src = taskDataSrc[0];
			}

			if ( src && grunt.file.isDir(src) ) {
				return true;
			}
			else {
				return false;
			}
		}

		,copyFilesToTmpDir: function() {
			var bundleTmpDir = path.join(this.options.tmpDir, this.options.bundleName);

			// copy all files to a tmp folder for glue to work in
			this.taskFilesSrcArray.forEach(function eachSrcFile(file, index, array) {

				var basename = path.basename(file);

				// file
				if (!grunt.file.isDir(file)) {
					grunt.file.copy(file, path.join(bundleTmpDir, basename));
				}
				// folder
				else {
					this.copySubDir(file, bundleTmpDir, basename);
				}
			}, this);
			return bundleTmpDir;
		}

		,copySubDir: function(origDir, bundleTmpDir, subDir) {
			// create bundleTmpDir if needed
			if (!grunt.file.isDir(bundleTmpDir)) {
				grunt.file.mkdir(bundleTmpDir);
			}
			// copy the folder into bundleTmpDir
			wrench.copyDirSyncRecursive(origDir, path.join(bundleTmpDir, subDir), {
				forceDelete     : true,  // Whether to overwrite existing directory or not
				preserveFiles   : false, // If we're overwriting something and the file already exists, keep the existing
				inflateSymlinks : true   // Whether to follow symlinks or not when copying files
			});
		}

		,createGlueArgs: function() {
			var  arg
				,glueArgs = []
			;

			for (arg in this.options) {
				// don't push non-glue options into glue args
				if (extendedOptions.indexOf(arg) !== -1) {
					continue;
				}
				// don't push options that aren't set into glue args
				if (this.options[arg] === null) {
					continue;
				}

				if (typeof this.options[arg] === 'boolean') {
					// only add boolean option if value is true
					this.options[arg] === true && glueArgs.push('--'+ arg);
				}
				else {
					glueArgs.push('--'+ arg +'='+ this.options[arg]);
				}
			}

			glueArgs.push(this.glueSrcDir); // add the source dir last

			return glueArgs;
		}

		,runGlue: function(cb) {
			var options = {
				    cmd: 'glue'
					,args: this.aGlueOptions
				}
			;

			grunt.log.debug('> glue', this.aGlueOptions.join(' '));

			grunt.util.spawn(options, function(err, result, code) {
				cb(err, result)
			});
		}
	};

};

<commit_msg>More --debug logging<commit_after>/*
 * grunt-glue-nu
 * https://github.com/MarcDiethelm/grunt-glue-nu
 *
 * Copyright (c) 2013 Marc Diethelm
 * Licensed under the MIT license.
 */

'use strict';

var  log = console.log
	,dir = console.dir
	,os = require('os')
	,path = require('path')
	,wrench = require('wrench')
;

module.exports = function (grunt) {

	// Glue options originally used with grunt-glue
	//'--css=<%=destSpritesCss%> --img=<%=destSpritesImg%> --less --url=<%=staticUriPrefix%><%=baseDirName%> --namespace=s --sprite-namespace= --recursive --crop --optipng --force --debug'

	var defaults = {
			 _process   : true
			,glueArgs   : null
			,tmpDir     : path.join(os.tmpdir(), 'grunt-glue-nu')
			,bundleName : null // default value set to task target inside the task

			,css        : null // default value set to dest inside the task
			,img        : null // default value set to dest inside the task
			,recursive  : true
			,crop       : true
			,force      : true
			,debug      : true
		}

		,extendedOptions = [
			 '_process'
			,'glueArgs'
			,'tmpDir'
			,'bundleName'
		]
	;

	// todo: need to write some tests (bdd?)
	// todo: look at/test conf files use

	grunt.registerMultiTask('glue', 'Create sprites automatically with Glue, but the grunt way!', function() {

		var  bundle, done;

		if (this.filesSrc.length > 0 || (this.data.options && this.data.options.glueArgs) ) {
			bundle = new Bundle();
			done = this.async();
		}
		else {
			grunt.log.warn('No sprites to compile.');
			return true;
		}

		bundle
			.configure(this)
			.make()
			.compile(function compileCb() {
				bundle.clean();
				done(); // tell grunt this task:target is complete
			})
		;

		return true;
	});

	// Constructor

	var Bundle = function() {};

	Bundle.prototype = {

		taskTargetName: ''

		,taskData: {}

		,directToGlue: false

		,expandedSrc: []

		,options: {}

		,aGlueOptions: []

		,glueSrcDir: ''

		,isTmpDirCreated: false

		// controllers
		///////////////////////////

		,configure: function(taskTarget) {
			this.taskData = taskTarget.data;
			this.taskFilesSrcArray = taskTarget.filesSrc;
			this.taskData.options = this.taskData.options || {};
			this.directToGlue = !!this.taskData.options.glueArgs;
			this.taskTargetName = taskTarget.target;

			if (!this.directToGlue) {
				this.checkRequiredInput();
				this.options = this.mergeOptions(defaults, taskTarget);
			}
			return this;
		}

		,make: function() {
			var isSourceSimple = this.isSrcSimpleDir();

			if (!this.directToGlue) {
				// don't copy files if source is simple and bundleName is either not set or the same as task target name
				// why? because Glue has no way to specify the generated file names except through the source folder
				if ( isSourceSimple && (!this.options.bundleName || this.options.bundleName === this.taskTargetName) ) {
					// just pass the location to glue
					this.glueSrcDir = this.taskData.src;
				}
				else {
					// work with complex src (multiple sources, globbing) / copy to force bundle name
					this.glueSrcDir = this.copyFilesToTmpDir();
					this.isTmpDirCreated = true;
				}
			}
			return this;
		}

		,compile: function(compileCb) {
			if (!this.directToGlue) {
				// build the args to glue from options
				this.aGlueOptions = this.createGlueArgs(this.glueSrcDir, this.options);
			}
			else {
				this.aGlueOptions = this.taskData.options.glueArgs.split(' ');
			}

			this.runGlue(function runGlueCb(err, result) {

				if (err) {
					// Glue thinks it's terrible when the src is empty. We don't
					if (err.message.indexOf('No images found') !== -1) {
						grunt.log.warn(err.message.replace(/^Error: /, 'Glue: '));
					}
					else {
						grunt.fail.warn(err.message);
					}
				}

				grunt.log.debug(result.stdout);

				return compileCb();
			});
		}

		,clean: function() {
			// remove the tmpDir and any glueSrcDir it contains, must force because it's outside of working dir.
			grunt.log.debug('Removing tmp dir %s', this.options.tmpDir);
			this.isTmpDirCreated && grunt.file.delete(this.options.tmpDir, {force: true});
			return true;
		}

		// methods
		///////////////////////////

		,checkRequiredInput: function() {
			!this.taskData.src &&
				grunt.fail.fatal('No src specified.');

			!this.taskData.dest &&
				grunt.fail.fatal('No dest specified.');

			return true;
		}

		,mergeOptions: function(defaults, taskTarget) {
			var filesArray = taskTarget.files;
			// setting grunt task dest as default for css and img args, so they can be overridden with specific options.
			// Glue says: You must choose the output folder using either the output argument or both --img and --css.
			// So we're using --img and --css
			defaults.css = filesArray[0].orig.dest;
			defaults.img = filesArray[0].orig.dest;
			defaults.bundleName = taskTarget.target; // used as tmp dir name. glue uses that as sprite name

			// Merge task-specific and/or target-specific options with defaults.
			return taskTarget.options(defaults);
		}

		,isSrcSimpleDir: function() {
			var  taskDataSrc = this.taskData.src
				,src
			;
			if (typeof taskDataSrc === 'string') {
				src = taskDataSrc;
			}
			// is it an array consisting of one string?
			else if (grunt.util.kindOf(taskDataSrc) === 'array' && taskDataSrc.length === 1) {
				src = taskDataSrc[0];
			}

			if ( src && grunt.file.isDir(src) ) {
				return true;
			}
			else {
				return false;
			}
		}

		,copyFilesToTmpDir: function() {
			var bundleTmpDir = path.join(this.options.tmpDir, this.options.bundleName);

			grunt.log.debug('Creating tmp dir for glue: %s', bundleTmpDir);

			// copy all files to a tmp folder for glue to work in
			this.taskFilesSrcArray.forEach(function eachSrcFile(file, index, array) {

				var basename = path.basename(file);

				// file
				if (!grunt.file.isDir(file)) {
					grunt.log.debug('Copy file %s to tmp dir', file);
					grunt.file.copy(file, path.join(bundleTmpDir, basename));
				}
				// folder
				else {
					grunt.log.debug('Copy folder %s to tmp dir', file);
					this.copySubDir(file, bundleTmpDir, basename);
				}
			}, this);

			return bundleTmpDir;
		}

		,copySubDir: function(origDir, bundleTmpDir, subDir) {
			// create bundleTmpDir if needed
			if (!grunt.file.isDir(bundleTmpDir)) {
				grunt.file.mkdir(bundleTmpDir);
			}
			// copy the folder into bundleTmpDir
			wrench.copyDirSyncRecursive(origDir, path.join(bundleTmpDir, subDir), {
				forceDelete     : true,  // Whether to overwrite existing directory or not
				preserveFiles   : false, // If we're overwriting something and the file already exists, keep the existing
				inflateSymlinks : true   // Whether to follow symlinks or not when copying files
			});
		}

		,createGlueArgs: function() {
			var  arg
				,glueArgs = []
			;

			for (arg in this.options) {
				// don't push non-glue options into glue args
				if (extendedOptions.indexOf(arg) !== -1) {
					continue;
				}
				// don't push options that aren't set into glue args
				if (this.options[arg] === null) {
					continue;
				}

				if (typeof this.options[arg] === 'boolean') {
					// only add boolean option if value is true
					this.options[arg] === true && glueArgs.push('--'+ arg);
				}
				else {
					glueArgs.push('--'+ arg +'='+ this.options[arg]);
				}
			}

			glueArgs.push(this.glueSrcDir); // add the source dir last

			return glueArgs;
		}

		,runGlue: function(cb) {
			var options = {
				    cmd: 'glue'
					,args: this.aGlueOptions
				}
			;

			grunt.log.debug('> glue', this.aGlueOptions.join(' '));

			grunt.util.spawn(options, function(err, result, code) {
				cb(err, result)
			});
		}
	};

};

<|endoftext|>


<commit_before>/*
 * grunt-har-gen
 * https://github.com/james/grunt-har-gen
 *
 * Copyright (c) 2013 James Cryer
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function (grunt) {

  var _ = require('lodash'),
      async = require('async'),
      exec = require('child_process').execFile,
      path = require('path'),
      phantomjs = require('phantomjs'),
      asset = path.join.bind(null, __dirname, '..'),
      netsniff = asset('lib/netsniff.js');

  grunt.registerMultiTask('hargen', 'Grunt plugin for generating HAR files from a series of URLs', function () {

    var options = this.options({
          urls:          {},
          output:        './tmp'
        }),
        urls = _.pairs(options.urls),
        dir = options.output,
        done = this.async();

    async.forEachSeries(urls, function (pair, next) {
      var filename = pair[0],
          url = pair[1];

      grunt.log.writeln('Trying: ' + url);

      exec(phantomjs.path, [netsniff, url], {maxBuffer: 1024 * 1024}, function (err, stdout, stderr) {
        if (err) {
          grunt.log.errorlns('Failed to connect to: ' + url);
          grunt.verbose.writeln(stderr);
        } else {
          grunt.log.writeln('Saving results to: ' + dir + '/' + filename);
          grunt.file.write(dir + '/' + filename, stdout);
        }

        next();
      });
    }, done);

    if (0 === urls.length) {
      grunt.log.error('No urls specified');
      done(false);
    }
  });
};
<commit_msg>Use pipes properly to avoid buffering errors<commit_after>/*
 * grunt-har-gen
 * https://github.com/james/grunt-har-gen
 *
 * Copyright (c) 2013 James Cryer
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function (grunt) {

  var _ = require('lodash'),
      async = require('async'),
      spawn = require('child_process').spawn,
      fs = require('fs'),
      path = require('path'),
      phantomjs = require('phantomjs'),
      asset = path.join.bind(null, __dirname, '..'),
      netsniff = asset('lib/netsniff.js');

  grunt.registerMultiTask(
    'hargen', 'Grunt plugin for generating HAR files from a series of URLs',
    function () {
      var options = this.options({
            urls:   {},
            output: './tmp'
          }),
          urls = _.pairs(options.urls),
          dir = options.output,
          done = this.async();

      async.forEach(urls, function (pair, next) {
        var filename = pair[0],
            url = pair[1];

        grunt.log.writeln('Trying: ' + url);

        var process = spawn(phantomjs.path, [netsniff, url], {
          stdio: [
            'ignore',
            fs.openSync(dir + '/' + filename, 'w'),
            'pipe'
          ]
        });

        process.on('close', function (code) {
          if (code !== 0) {
            grunt.log.errorlns('Failed to connect to: ' + url);
            next(code);
          } else {
            grunt.log.writeln('Saved results to: ' + dir + '/' + filename);
            next();
          }
        })
      }, function (err) {
        done(!err);
      });

      if (0 === urls.length) {
        grunt.log.error('No urls specified');
        done(false);
      }
    });
};
<|endoftext|>


<commit_before>exports.init = function (grunt, silent) {
    'use strict';

    var libPath = 'istanbul/lib/',
        Command = require(libPath + 'command'),
        fs = require('fs'),
        path = require('path');

    require(libPath + 'register-plugins');

    function convertArg(options, key) {
        return '--' + key + '=' + options[key];
    }

    //convert option hash to argument string
    function convertCmdArgs(options) {
        //flatten down the options obj
        var result = Object.keys(options.thresholds).map(function (key) {
            return convertArg(options.thresholds, key);
        });
        delete options.thresholds;
        return result.concat(Object.keys(options).map(function (key) {
            if (key !== 'thresholds') {
                return convertArg(options, key);
            }
        }));
    }

    //make sure we have the required options and that they are valid
    function assertOptions(options, reg) {
        //make sure we have the required options
        reg.forEach(function (key) {
            var opt = options[key];
            if (opt === null || opt === undefined) {
                throw new Error('"' + key + '" option is required.');
            }
        });
        //check if the coverage folder exists
        var folder = path.join(options.root, options.dir);
        var exists = fs.existsSync(folder);
        if (!exists) {
            throw new Error('folder "' + folder + '" does not exist.');
        }
        //check for coverage json files
        var list = fs.readdirSync(folder).filter(function (file) {
            return path.extname(file) === '.json';
        });
        if (list.length === 0) {
            throw new Error('no coverage files found in "' + folder + '".');
        }
    }

    function runCommand(command, args, callback) {
        //create command
        var cmd = Command.create(command);
        //run command
        cmd.run(args, function (err) {
            var passed = false;
            //check result
            if (err) {
                if (!silent) { grunt.fail.warn(err); }
            } else {
                passed = true;
                if (!silent) { grunt.log.ok('Coverage is at or over the minimum thresholds'); }
            }
            callback(passed);
        });
    }

    return {
        checkCoverage: function (options, done) {
            //check to make sure we have what we need
            assertOptions(options, ['thresholds', 'root', 'dir']);

            //get command args from options
            var cmdArgs = convertCmdArgs(options);

            //run istanbul check coverage command
            runCommand('check-coverage', cmdArgs, done);
        }
    };
};<commit_msg>Check for coverage files now uses the same algorithm as the istanbul command.<commit_after>exports.init = function (grunt, silent) {
    'use strict';

    var libPath = 'istanbul/lib/',
        Command = require(libPath + 'command'),
        fs = require('fs'),
        path = require('path');

    require(libPath + 'register-plugins');

    function convertArg(options, key) {
        return '--' + key + '=' + options[key];
    }

    //convert option hash to argument string
    function convertCmdArgs(options) {
        //flatten down the options obj
        var result = Object.keys(options.thresholds).map(function (key) {
            return convertArg(options.thresholds, key);
        });
        delete options.thresholds;
        return result.concat(Object.keys(options).map(function (key) {
            if (key !== 'thresholds') {
                return convertArg(options, key);
            }
        }));
    }

    //make sure we have the required options and that they are valid
    function assertOptions(options, reg) {
        //make sure we have the required options
        reg.forEach(function (key) {
            var opt = options[key];
            if (opt === null || opt === undefined) {
                throw new Error('"' + key + '" option is required.');
            }
        });
        //check if the coverage folder exists
        var folder = path.join(options.root, options.dir);
        var exists = fs.existsSync(folder);
        if (!exists) {
            throw new Error('folder "' + folder + '" does not exist.');
        }
        //check for coverage json files
        var list = grunt.file.expand({ matchBase: true, cwd: folder }, '**/coverage*.json');
        if (list.length === 0) {
            throw new Error('no coverage files found in "' + folder + '".');
        }
    }

    function runCommand(command, args, callback) {
        //create command
        var cmd = Command.create(command);
        //run command
        cmd.run(args, function (err) {
            var passed = false;
            //check result
            if (err) {
                if (!silent) { grunt.fail.warn(err); }
            } else {
                passed = true;
                if (!silent) { grunt.log.ok('Coverage is at or over the minimum thresholds'); }
            }
            callback(passed);
        });
    }

    return {
        checkCoverage: function (options, done) {
            //check to make sure we have what we need
            assertOptions(options, ['thresholds', 'root', 'dir']);

            //get command args from options
            var cmdArgs = convertCmdArgs(options);

            //run istanbul check coverage command
            runCommand('check-coverage', cmdArgs, done);
        }
    };
};
<|endoftext|>


<commit_before>/*
 * grunt-contrib-jasmine
 * http://gruntjs.com/
 *
 * Licensed under the MIT license.
 */

/*jshint node:true, curly:false*/

'use strict';

module.exports = function(grunt) {

  // node api
  var fs   = require('fs'),
      path = require('path');

  // npm lib
  var phantomjs = require('grunt-lib-phantomjs').init(grunt);

  // local lib
  var jasmine = require('./lib/jasmine');

  var status = {
    specs    : 0,
    failed   : 0,
    passed   : 0,
    total    : 0,
    skipped  : 0,
    duration : 0
  };

  var runners = {
    default   : __dirname + '/jasmine/templates/DefaultRunner.tmpl',
    requirejs : __dirname + '/jasmine/templates/RequireJSRunner.tmpl'
  };

  var runnerOptions = {
    requirejs : {
      requirejs : jasmine.getRelativeFileList(__dirname + '/../vendor/require-2.1.1.js')[0]
    }
  };

  grunt.registerMultiTask('jasmine', 'Run jasmine specs headlessly through PhantomJS.', function() {

    // Merge task-specific options with these defaults.
    var options = this.options({
      timeout : 10000,
      specs   : [],
      helpers : [],
      vendor  : [],
      outfile : '_SpecRunner.html',
      host    : '',
      template: 'default',
      templateOptions : {},
      phantomjs : {}
    });

    grunt.util._.defaults(options.templateOptions, runnerOptions[options.template] || {});
    if (!options.template.match(/\.tmpl$/)) options.template = runners[options.template];

    if (grunt.option('debug')) {
      grunt.log.debug(options);
    }

    setup(options);

    var files = grunt.file.expandFiles(grunt.util._.pluck(this.files, 'src'));
    jasmine.buildSpecrunner(files,options);

    // If we're just building (e.g. for web), skip phantom.
    if (this.flags.build) return;

    var done = this.async();
    phantomRunner(options, function(err,status) {
      if (err) grunt.log.error(err);
      if (status.failed === 0) grunt.log.ok('0 failures');
      else grunt.log.error(status.failed + ' failures');
      teardown(options);
      done(!err && status.failed === 0);
    });

  });

  function phantomRunner(options,cb){
    var file = options.outfile;

    if (options.host) {
      file = options.host + options.outfile;
    }

    grunt.verbose.subhead('Testing jasmine specs via phantom').or.writeln('Testing jasmine specs via phantom');

    phantomjs.spawn(file, {
      failCode : 90,
      options  : options,
      done     : function(err){
        cb(err,status);
      }
    });

  }

  function teardown(options) {
    if (fs.statSync(options.outfile).isFile()) fs.unlink(options.outfile);

    // Have to explicitly unregister nested wildcards. Need to file a bug for EventEmitter2
    phantomjs.removeAllListeners('*');
    phantomjs.removeAllListeners('jasmine.*');
    phantomjs.removeAllListeners('error.*');
    phantomjs.removeAllListeners('jasmine.done.*');
  }

  function setup(options) {
    var thisRun = {};

    phantomjs.on('fail.timeout',function(){
      grunt.log.writeln();
      grunt.warn('PhantomJS timed out, possibly due to an unfinished async spec.', 90);
    });

    phantomjs.on('console',console.log.bind(console));
    phantomjs.on('verbose',grunt.verbose.writeln.bind(grunt.verbose));
    phantomjs.on('debug', grunt.log.debug.bind(grunt.log, 'phantomjs'));
    phantomjs.on('write', grunt.log.write.bind(grunt.log));
    phantomjs.on('writeln', grunt.log.writeln.bind(grunt.log));
    phantomjs.on('error.onError',function(string, trace){
      if (trace) {
        grunt.log.error(string.red + ' at ');
        trace.forEach(function(line) {
          var file = line.file.replace(/^file:/,'');
          var message = grunt.util._('%s:%d %s').sprintf(path.relative('.',file), line.line, line.function);
          grunt.log.error(message.red);
        });
      } else {
        grunt.log.error(string.red);
      }
    });

    phantomjs.onAny(function() {
      var args = [this.event].concat(grunt.util.toArray(arguments));
      grunt.event.emit.apply(grunt.event, args);
    });

    phantomjs.on('jasmine.writeFile',function(type,filename, xml){
      var dir = options[type] && options[type].output;
      if (dir) {
        grunt.file.mkdir(dir);
        grunt.file.write(path.join(dir, filename), xml);
      }
    });

    phantomjs.on('jasmine.reportRunnerStarting',function(suites) {
      grunt.verbose.writeln('Starting...');
      thisRun.start_time = (new Date()).getTime();
      thisRun.executed_specs = 0;
      thisRun.passed_specs = 0;
    });

    phantomjs.on('jasmine.reportSpecStarting',function(spec) {
      thisRun.executed_specs++;
      grunt.verbose.write(spec.suite.description + ':' + spec.description + '...');
    });

    phantomjs.on('jasmine.reportSuiteResults',function(suite){
      //grunt.verbose.writeln(suite.description + ": " + suite.results.passedCount + " of " + suite.results.totalCount + " passed.");
    });

    phantomjs.on('jasmine.reportSpecResults',function(specId, result,summary) {
      if (result.passed) thisRun.passed_specs++;

      grunt.verbose.writeln(summary.passed ? result.msg.green : result.msg.red);
      for (var i = 0; i < result.messages.length; i++) {
        var item = result.messages[i];

        if (item.type === 'log') {
          grunt.verbose.writeln(item.toString());
        } else if (item.type === 'expect' && !item.passed_) {
          grunt.log.writeln(summary.description + ':' + result.msg.red);
          phantomjs.emit('onError', item.message, item.trace);
        }
      }
      phantomjs.emit( 'jasmine.testDone', result.totalCount, result.passedCount, result.failedCount, result.skipped );

    });

    phantomjs.on('jasmine.reportRunnerResults',function(){
      grunt.verbose.writeln('Runner finished');
      var dur = (new Date()).getTime() - thisRun.start_time;
      var failed = thisRun.executed_specs - thisRun.passed_specs;
      var spec_str = thisRun.executed_specs + (thisRun.executed_specs === 1 ? " spec, " : " specs, ");
      var fail_str = failed + (failed === 1 ? " failure in " : " failures in ");
      grunt.log.writeln(spec_str + fail_str + (dur/1000) + "s.");
    });

    phantomjs.on('jasmine.testDone',function(totalAssertions, passedAssertions, failedAssertions, skippedAssertions){
      status.specs++;
      status.failed  += failedAssertions;
      status.passed  += passedAssertions;
      status.total   += totalAssertions;
      status.skipped += skippedAssertions;
    });

    phantomjs.on('jasmine.done',function(elapsed){
      phantomjs.halt();
      status.duration = elapsed;
    });

    phantomjs.on('jasmine.done.PhantomReporter',function(){
      phantomjs.emit('jasmine.done');
    });

    phantomjs.on('jasmine.done_fail',function(url){
      grunt.log.error();
      grunt.warn('PhantomJS unable to load "' + url + '" URI.', 90);
    });
  }

};

<commit_msg>remove expandFiles, grunt does it for us now<commit_after>/*
 * grunt-contrib-jasmine
 * http://gruntjs.com/
 *
 * Licensed under the MIT license.
 */

/*jshint node:true, curly:false*/

'use strict';

module.exports = function(grunt) {

  // node api
  var fs   = require('fs'),
      path = require('path');

  // npm lib
  var phantomjs = require('grunt-lib-phantomjs').init(grunt);

  // local lib
  var jasmine = require('./lib/jasmine');

  var status = {
    specs    : 0,
    failed   : 0,
    passed   : 0,
    total    : 0,
    skipped  : 0,
    duration : 0
  };

  var runners = {
    default   : __dirname + '/jasmine/templates/DefaultRunner.tmpl',
    requirejs : __dirname + '/jasmine/templates/RequireJSRunner.tmpl'
  };

  var runnerOptions = {
    requirejs : {
      requirejs : jasmine.getRelativeFileList(__dirname + '/../vendor/require-2.1.1.js')[0]
    }
  };

  grunt.registerMultiTask('jasmine', 'Run jasmine specs headlessly through PhantomJS.', function() {

    // Merge task-specific options with these defaults.
    var options = this.options({
      timeout : 10000,
      specs   : [],
      helpers : [],
      vendor  : [],
      outfile : '_SpecRunner.html',
      host    : '',
      template: 'default',
      templateOptions : {},
      phantomjs : {}
    });

    grunt.util._.defaults(options.templateOptions, runnerOptions[options.template] || {});
    if (!options.template.match(/\.tmpl$/)) options.template = runners[options.template];

    if (grunt.option('debug')) {
      grunt.log.debug(options);
    }

    setup(options);

    var files = this.file.src;
    jasmine.buildSpecrunner(files,options);

    // If we're just building (e.g. for web), skip phantom.
    if (this.flags.build) return;

    var done = this.async();
    phantomRunner(options, function(err,status) {
      if (err) grunt.log.error(err);
      if (status.failed === 0) grunt.log.ok('0 failures');
      else grunt.log.error(status.failed + ' failures');
      teardown(options);
      done(!err && status.failed === 0);
    });

  });

  function phantomRunner(options,cb){
    var file = options.outfile;

    if (options.host) {
      file = options.host + options.outfile;
    }

    grunt.verbose.subhead('Testing jasmine specs via phantom').or.writeln('Testing jasmine specs via phantom');

    phantomjs.spawn(file, {
      failCode : 90,
      options  : options,
      done     : function(err){
        cb(err,status);
      }
    });

  }

  function teardown(options) {
    if (fs.statSync(options.outfile).isFile()) fs.unlink(options.outfile);

    // Have to explicitly unregister nested wildcards. Need to file a bug for EventEmitter2
    phantomjs.removeAllListeners('*');
    phantomjs.removeAllListeners('jasmine.*');
    phantomjs.removeAllListeners('error.*');
    phantomjs.removeAllListeners('jasmine.done.*');
  }

  function setup(options) {
    var thisRun = {};

    phantomjs.on('fail.timeout',function(){
      grunt.log.writeln();
      grunt.warn('PhantomJS timed out, possibly due to an unfinished async spec.', 90);
    });

    phantomjs.on('console',console.log.bind(console));
    phantomjs.on('verbose',grunt.verbose.writeln.bind(grunt.verbose));
    phantomjs.on('debug', grunt.log.debug.bind(grunt.log, 'phantomjs'));
    phantomjs.on('write', grunt.log.write.bind(grunt.log));
    phantomjs.on('writeln', grunt.log.writeln.bind(grunt.log));
    phantomjs.on('error.onError',function(string, trace){
      if (trace) {
        grunt.log.error(string.red + ' at ');
        trace.forEach(function(line) {
          var file = line.file.replace(/^file:/,'');
          var message = grunt.util._('%s:%d %s').sprintf(path.relative('.',file), line.line, line.function);
          grunt.log.error(message.red);
        });
      } else {
        grunt.log.error(string.red);
      }
    });

    phantomjs.onAny(function() {
      var args = [this.event].concat(grunt.util.toArray(arguments));
      grunt.event.emit.apply(grunt.event, args);
    });

    phantomjs.on('jasmine.writeFile',function(type,filename, xml){
      var dir = options[type] && options[type].output;
      if (dir) {
        grunt.file.mkdir(dir);
        grunt.file.write(path.join(dir, filename), xml);
      }
    });

    phantomjs.on('jasmine.reportRunnerStarting',function(suites) {
      grunt.verbose.writeln('Starting...');
      thisRun.start_time = (new Date()).getTime();
      thisRun.executed_specs = 0;
      thisRun.passed_specs = 0;
    });

    phantomjs.on('jasmine.reportSpecStarting',function(spec) {
      thisRun.executed_specs++;
      grunt.verbose.write(spec.suite.description + ':' + spec.description + '...');
    });

    phantomjs.on('jasmine.reportSuiteResults',function(suite){
      //grunt.verbose.writeln(suite.description + ": " + suite.results.passedCount + " of " + suite.results.totalCount + " passed.");
    });

    phantomjs.on('jasmine.reportSpecResults',function(specId, result,summary) {
      if (result.passed) thisRun.passed_specs++;

      grunt.verbose.writeln(summary.passed ? result.msg.green : result.msg.red);
      for (var i = 0; i < result.messages.length; i++) {
        var item = result.messages[i];

        if (item.type === 'log') {
          grunt.verbose.writeln(item.toString());
        } else if (item.type === 'expect' && !item.passed_) {
          grunt.log.writeln(summary.description + ':' + result.msg.red);
          phantomjs.emit('onError', item.message, item.trace);
        }
      }
      phantomjs.emit( 'jasmine.testDone', result.totalCount, result.passedCount, result.failedCount, result.skipped );

    });

    phantomjs.on('jasmine.reportRunnerResults',function(){
      grunt.verbose.writeln('Runner finished');
      var dur = (new Date()).getTime() - thisRun.start_time;
      var failed = thisRun.executed_specs - thisRun.passed_specs;
      var spec_str = thisRun.executed_specs + (thisRun.executed_specs === 1 ? " spec, " : " specs, ");
      var fail_str = failed + (failed === 1 ? " failure in " : " failures in ");
      grunt.log.writeln(spec_str + fail_str + (dur/1000) + "s.");
    });

    phantomjs.on('jasmine.testDone',function(totalAssertions, passedAssertions, failedAssertions, skippedAssertions){
      status.specs++;
      status.failed  += failedAssertions;
      status.passed  += passedAssertions;
      status.total   += totalAssertions;
      status.skipped += skippedAssertions;
    });

    phantomjs.on('jasmine.done',function(elapsed){
      phantomjs.halt();
      status.duration = elapsed;
    });

    phantomjs.on('jasmine.done.PhantomReporter',function(){
      phantomjs.emit('jasmine.done');
    });

    phantomjs.on('jasmine.done_fail',function(url){
      grunt.log.error();
      grunt.warn('PhantomJS unable to load "' + url + '" URI.', 90);
    });
  }

};

<|endoftext|>


<commit_before>module.exports = function(grunt) {

    'use strict';

    var spawn = require('child_process').spawn,
        path = require('path'),
        async = require('async'),
        fs = require('fs');

    var _ = grunt.util._;

    var versions = {
        1.0: '1.0.3705',
        1.1: '1.1.4322',
        2.0: '2.0.50727',
        3.5: '3.5',
        4.0: '4.0.30319',
        12.0: '12.0',
        14.0: '14.0'
    };

    grunt.registerMultiTask('msbuild', 'Run MSBuild tasks', function() {

        var asyncCallback = this.async();

        var options = this.options({
            targets: ['Build'],
            buildParameters: {},
            failOnError: true,
            verbosity: 'normal',
            processor: '',
            nologo: true
        });

        if (!options.projectConfiguration) {
            options.projectConfiguration = 'Release';
        }

        grunt.verbose.writeln('Using Options: ' + JSON.stringify(options, null, 4).cyan);

        var projectFunctions = [];
        var files = this.files;

        if (files.length == 0) {
            files.push({src: ['']});
        }

        files.forEach(function(filePair) {
            filePair.src.forEach(function(src) {
                projectFunctions.push(function(cb) {
                    build(src, options, cb);
                });

                projectFunctions.push(function(cb) {
                    cb();
                });
            });
        });

        async.series(projectFunctions, function() {
            asyncCallback();
        });

    });

    function build(src, options, cb) {

        var projName = src || path.basename(process.cwd());

        grunt.log.writeln('Building ' + projName.cyan);

        var cmd = createCommand(options.version || null, options.processor);
        var args = createCommandArgs(src, options);

        grunt.verbose.writeln('Using cmd:', cmd);
        grunt.verbose.writeln('Using args:', args);

        if (!cmd) {
            return;
        }

        var cp = spawn(cmd, args, {
            stdio: 'inherit'
        });

        cp.on('close', function(code) {
            var success = code === 0;
            grunt.verbose.writeln('close received - code: ', success);

            if (code === 0) {
                grunt.log.writeln('Build complete ' + projName.cyan);
                cb();
            } else {
                grunt.log.writeln(('MSBuild failed with code: ' + code).cyan + projName);
                if (options.failOnError) {
                    grunt.warn('MSBuild exited with a failure code: ' + code);
                }
            }

        });

    }

    function createCommandArgs(src, options) {

        var args = [];

        if (src) {
            var projectPath = path.normalize(path.resolve() + '/' + src);

            args.push(projectPath);
        }

        args.push('/target:' + options.targets);
        args.push('/verbosity:' + options.verbosity);

        if (options.nologo) {
            args.push('/nologo');
        }

        if (options.maxCpuCount) {
            grunt.verbose.writeln('Using maxcpucount:', +options.maxCpuCount);
            args.push('/maxcpucount:' + options.maxCpuCount);
        }

	if (options.consoleLoggerParameters) {
            grunt.verbose.writeln('Using clp:' + options.consoleLoggerParameters);
	    args.push('/clp:' + options.consoleLoggerParameters);
	}

        args.push('/property:Configuration=' + options.projectConfiguration);

        if (options.platform) {
            args.push('/p:Platform=' + options.platform);
        }

        for (var buildArg in options.buildParameters) {
            args.push('/property:' + buildArg + '=' + options.buildParameters[buildArg]);
        }

        return args;
    }

    function createCommand(version, processor) {

        // temp mono xbuild usage for linux / osx - assumes xbuild is in the path, works on my machine...
        if (process.platform === 'linux' || process.platform === 'darwin') {
            return 'xbuild';
        }

        if (!version) {
            var msBuild12x86Path = 'C:\\Program Files (x86)\\MSBuild\\12.0\\Bin\\MSBuild.exe';
            var msBuild12x64Path = 'C:\\Program Files\\MSBuild\\12.0\\Bin\\MSBuild.exe';

            if (fs.existsSync(msBuild12x86Path)) {
                grunt.verbose.writeln('Using MSBuild at:', msBuild12x86Path.cyan);
                return msBuild12x86Path;
            } else if (fs.existsSync(msBuild12x64Path)) {
                grunt.verbose.writeln('Using MSBuild at:', msBuild12x64Path.cyan);
                return msBuild12x64Path;
            } else {
                // Fallback to version 4.0
                version = 4.0;
            }
        }

        processor = 'Framework' + (processor === 64 ? processor : '');

        var specificVersion = versions[version];

        if (!specificVersion) {
            grunt.fatal('Unrecognised MSBuild version "' + version + '"');
        }

        if (version < 12) {
            var buildExecutablePath = path.join(process.env.WINDIR, 'Microsoft.Net', processor, 'v' + specificVersion, 'MSBuild.exe');
        } else {
            var programFiles = process.env['ProgramFiles(x86)'] || process.env.PROGRAMFILES;
            var buildExecutablePath = path.join(programFiles, 'MSBuild', specificVersion, 'Bin', 'MSBuild.exe');
        }

        grunt.verbose.writeln('Using MSBuild at:' + buildExecutablePath.cyan);

        if (!fs.existsSync(buildExecutablePath)) {
            grunt.fatal('Unable to find MSBuild executable');
        }

        return path.normalize(buildExecutablePath);

    }

};
<commit_msg>Find latest installed msbuild version if not set<commit_after>module.exports = function(grunt) {

    'use strict';

    var spawn = require('child_process').spawn,
        path = require('path'),
        async = require('async'),
        fs = require('fs');

    var _ = grunt.util._;

    var versions = {
        1.0: '1.0.3705',
        1.1: '1.1.4322',
        2.0: '2.0.50727',
        3.5: '3.5',
        4.0: '4.0.30319',
        12.0: '12.0',
        14.0: '14.0'
    };

    grunt.registerMultiTask('msbuild', 'Run MSBuild tasks', function() {

        var asyncCallback = this.async();

        var options = this.options({
            targets: ['Build'],
            buildParameters: {},
            failOnError: true,
            verbosity: 'normal',
            processor: '',
            nologo: true
        });

        if (!options.projectConfiguration) {
            options.projectConfiguration = 'Release';
        }

        grunt.verbose.writeln('Using Options: ' + JSON.stringify(options, null, 4).cyan);

        var projectFunctions = [];
        var files = this.files;

        if (files.length == 0) {
            files.push({src: ['']});
        }

        files.forEach(function(filePair) {
            filePair.src.forEach(function(src) {
                projectFunctions.push(function(cb) {
                    build(src, options, cb);
                });

                projectFunctions.push(function(cb) {
                    cb();
                });
            });
        });

        async.series(projectFunctions, function() {
            asyncCallback();
        });

    });

    function build(src, options, cb) {

        var projName = src || path.basename(process.cwd());

        grunt.log.writeln('Building ' + projName.cyan);

        var cmd = createCommand(options.version || null, options.processor);
        var args = createCommandArgs(src, options);

        grunt.verbose.writeln('Using cmd:', cmd);
        grunt.verbose.writeln('Using args:', args);

        if (!cmd) {
            return;
        }

        var cp = spawn(cmd, args, {
            stdio: 'inherit'
        });

        cp.on('close', function(code) {
            var success = code === 0;
            grunt.verbose.writeln('close received - code: ', success);

            if (code === 0) {
                grunt.log.writeln('Build complete ' + projName.cyan);
                cb();
            } else {
                grunt.log.writeln(('MSBuild failed with code: ' + code).cyan + projName);
                if (options.failOnError) {
                    grunt.warn('MSBuild exited with a failure code: ' + code);
                }
            }

        });

    }

    function createCommandArgs(src, options) {

        var args = [];

        if (src) {
            var projectPath = path.normalize(path.resolve() + '/' + src);

            args.push(projectPath);
        }

        args.push('/target:' + options.targets);
        args.push('/verbosity:' + options.verbosity);

        if (options.nologo) {
            args.push('/nologo');
        }

        if (options.maxCpuCount) {
            grunt.verbose.writeln('Using maxcpucount:', +options.maxCpuCount);
            args.push('/maxcpucount:' + options.maxCpuCount);
        }

	if (options.consoleLoggerParameters) {
            grunt.verbose.writeln('Using clp:' + options.consoleLoggerParameters);
	    args.push('/clp:' + options.consoleLoggerParameters);
	}

        args.push('/property:Configuration=' + options.projectConfiguration);

        if (options.platform) {
            args.push('/p:Platform=' + options.platform);
        }

        for (var buildArg in options.buildParameters) {
            args.push('/property:' + buildArg + '=' + options.buildParameters[buildArg]);
        }

        return args;
    }

    function createCommand(version, processor) {

        // temp mono xbuild usage for linux / osx - assumes xbuild is in the path, works on my machine...
        if (process.platform === 'linux' || process.platform === 'darwin') {
            return 'xbuild';
        }

        var programFiles = process.env['ProgramFiles(x86)'] || process.env.PROGRAMFILES;

        if (!version) {
            version = 4.0; // default fallback to version 4.0

            var msbuildDir = path.join(programFiles, 'MSBuild');

            if (fs.existsSync(msbuildDir)) {
                var msbuildVersions = fs.readdirSync(msbuildDir)
                    .filter(function(entryName) {
                        return entryName.indexOf('1') === 0;
                    });

                if (msbuildVersions.length > 0) {
                    // set latest installed msbuild version
                    version = parseInt(msbuildVersions[msbuildVersions.length - 1]);
                }
            }
        }

        processor = 'Framework' + (processor === 64 ? processor : '');

        var specificVersion = versions[version];

        if (!specificVersion) {
            grunt.fatal('Unrecognised MSBuild version "' + version + '"');
        }

        if (version < 12) {
            var buildExecutablePath = path.join(process.env.WINDIR, 'Microsoft.Net', processor, 'v' + specificVersion, 'MSBuild.exe');
        } else {
            var buildExecutablePath = path.join(programFiles, 'MSBuild', specificVersion, 'Bin', 'MSBuild.exe');
        }

        grunt.verbose.writeln('Using MSBuild at:' + buildExecutablePath.cyan);

        if (!fs.existsSync(buildExecutablePath)) {
            grunt.fatal('Unable to find MSBuild executable');
        }

        return path.normalize(buildExecutablePath);

    }

};
<|endoftext|>


<commit_before>var fs = require('fs');

var constants = require('./util/constants');
var common = require('./util/common');

// main
makeCredentialsFile();
makeSetPlotConfigFile();
makeTestImageFolders();
makeRequireJSFixture();

// Create a credentials json file,
// to be required in jasmine test suites and test dashboard
function makeCredentialsFile() {
    var credentials = JSON.stringify({
        MAPBOX_ACCESS_TOKEN: constants.mapboxAccessToken
    }, null, 2);

    common.writeFile(constants.pathToCredentials, credentials);
    logger('make build/credentials.json');
}

// Create a 'set plot config' file,
// to be included in the image test index
function makeSetPlotConfigFile() {
    var setPlotConfig = [
        '\'use strict\';',
        '',
        '/* global Plotly:false */',
        '',
        'Plotly.setPlotConfig({',
        '    mapboxAccessToken: \'' + constants.mapboxAccessToken + '\'',
        '});',
        ''
    ].join('\n');

    common.writeFile(constants.pathToSetPlotConfig, setPlotConfig);
    logger('make build/set_plot_config.js');
}

// Make artifact folders for image tests
function makeTestImageFolders() {

    function makeOne(folderPath, info) {
        if(!common.doesDirExist(folderPath)) {
            fs.mkdirSync(folderPath);
            logger('initialize ' + info);
        }
        else logger(info + ' is present');
    }

    makeOne(constants.pathToTestImages, 'test image folder');
    makeOne(constants.pathToTestImagesDiff, 'test image diff folder');
}

// Make script file that define plotly in a RequireJS context
function makeRequireJSFixture() {
    var bundle = fs.readFileSync(constants.pathToPlotlyDistMin, 'utf-8'),
        template = 'define(\'plotly\', function(require, exports, module) { {{bundle}} });',
        index = template.replace('{{bundle}}', bundle);

    common.writeFile(constants.pathToRequireJSFixture, index);
    logger('make build/requirejs_fixture.js');
}

function logger(task) {
    console.log('ok ' + task);
}
<commit_msg>task: build require.js test fixture with [].join instead of str replace<commit_after>var fs = require('fs');

var constants = require('./util/constants');
var common = require('./util/common');

// main
makeCredentialsFile();
makeSetPlotConfigFile();
makeTestImageFolders();
makeRequireJSFixture();

// Create a credentials json file,
// to be required in jasmine test suites and test dashboard
function makeCredentialsFile() {
    var credentials = JSON.stringify({
        MAPBOX_ACCESS_TOKEN: constants.mapboxAccessToken
    }, null, 2);

    common.writeFile(constants.pathToCredentials, credentials);
    logger('make build/credentials.json');
}

// Create a 'set plot config' file,
// to be included in the image test index
function makeSetPlotConfigFile() {
    var setPlotConfig = [
        '\'use strict\';',
        '',
        '/* global Plotly:false */',
        '',
        'Plotly.setPlotConfig({',
        '    mapboxAccessToken: \'' + constants.mapboxAccessToken + '\'',
        '});',
        ''
    ].join('\n');

    common.writeFile(constants.pathToSetPlotConfig, setPlotConfig);
    logger('make build/set_plot_config.js');
}

// Make artifact folders for image tests
function makeTestImageFolders() {

    function makeOne(folderPath, info) {
        if(!common.doesDirExist(folderPath)) {
            fs.mkdirSync(folderPath);
            logger('initialize ' + info);
        }
        else logger(info + ' is present');
    }

    makeOne(constants.pathToTestImages, 'test image folder');
    makeOne(constants.pathToTestImagesDiff, 'test image diff folder');
}

// Make script file that define plotly in a RequireJS context
function makeRequireJSFixture() {
    var bundle = fs.readFileSync(constants.pathToPlotlyDistMin, 'utf-8');

    var index = [
        'define(\'plotly\', function(require, exports, module) {',
        bundle,
        '});'
    ].join('');

    common.writeFile(constants.pathToRequireJSFixture, index);
    logger('make build/requirejs_fixture.js');
}

function logger(task) {
    console.log('ok ' + task);
}
<|endoftext|>


<commit_before>var irc = require('irc');
var config = require('./config.js');

var bot;
var commands;

var channel_blocks = {
	private_chat: {
		blocked: false,
		kudos_minus: false,
		kudos_plus: false,
		ultrachord: false,
	},
	main_chat: {
		blocked: false,
		// XXX merge these into identify
		botbrname: false,
		botbrpass: false,
		botbrsync: false,
		kudos_minus: false,
		kudos_plus: false,
		update_ip: false,
	}
};

var commands_aliases = {
	b: 'battle',
	chord: 'ultrachord',
	compo: 'battle',
	g: 'google',
	gi: 'image',
	gif: 'giphy',
	h: 'help',
	i: 'imdb',
	images: 'image',
	img: 'imgur',
	imgr: 'imgur',
	l: 'lyceum',
	ohc: 'ohb',
	pic: 'pix',
	uc: 'ultrachord',
	up: 'uptime',
	w: 'wikipedia',
	wiki: 'wikipedia',
	y: 'youtube',
	yt: 'youtube',
};

var commands_alias_filters = {
	'kudos_minus': /^(.+)\-{2}$/i,
	'kudos_plus': /^(.+)\+{2}$/i,
};

alias_check = function(command) {
	if (typeof commands_aliases[command] !== 'undefined') {
		command = commands_aliases[command];
	}
	return command;
};

command_check = function(channel_type, command) {
	if (channel_blocks[channel_type][command] === false) {
		return false;
	}
	if (typeof commands[command] === 'undefined') {
		return false;
	}
	return true;
};

command_parser = function(from, to, text, info) {

	var command = '';

	// break text into words
	var words = text.split(' ').filter(e => e !== '');

	// supplement info
	info.from = from;
	info.command_prefix = config.command_prefix;
	info.words = words;

	// interpret solicitor
	var channel;
	if (to === config.bot_name) {
		console.log('PM <' + from + '> ' + text);
		channel = 'private_chat';
		info.channel = from;
		info.channel_type = channel;
	}
	else if (config.irc.channels.indexOf(to) != -1) {
		console.log(to + ' <' + from + '> ' + text);
		channel = 'main_chat';
		info.channel = info.args[0];
		info.channel_type = channel;
	}

	// check alias filters (command override)
	for (var key in commands_alias_filters) {
		filter = commands_alias_filters[key];
		if (filter.test(text)) {
			commands[key](info, words);
			return;
		}
	};

	// check for command prefix
	if (words[0].substr(0, 1) !== config.command_prefix) {
		if (to === config.bot_name) {
			// XXX something is fukt here
			if (from === config.bot_name) {
				console.log('STOP MESSAGING YERSELF!!');
				return false;
			}
			info.channel = from;
			commands.unknown(info, words);
		}
		return false;
	}

	// remove command prefix
	var command = words[0].substr(1);

	// abort if command is empty or non-alphabetic (likely an emoticon)
	if (command === '' || !command.match(/^[a-zA-Z]/)) {
		return false;
	}

	// check if the command is an alias
	command = alias_check(command);

	// check channel's blocked commands
	if (command_check(channel, command) === false) {
		commands.blocked(info, words);
		console.log('"' + command + '" in #' + channel + ' blocked');
		return false;
	}

	// check for command and call
	if (typeof commands[command] === "function") {
		var response = commands[command](info, words);
	}
};

module.exports = {

	alias_check: function(command) {
		return alias_check(command);
	},

	alias_find: function(command) {
		var alias_list = [];
		for (alias in commands_aliases) {
			if (commands_aliases[alias] === command) {
				alias_list.push(alias);
			}
		}
		return alias_list;
	},

	command_check: function(command, channel_type) {
		return command_check(command, channel_type);
	},

	command_list: function(channel_type) {
		var command_list = [];
		for (command in commands) {
			if (command_check(channel_type, command)) {
				command_list.push(command);
			}
		}
		return command_list;
	},

	initialize: function() {
		bot = new irc.Client(config.irc.server, config.bot_name, {
			channels: config.irc.channels
		});

		//commands.init(this);
		commands = require('./irc_commands.js');

		bot.addListener('join', function(channel, who) {
			console.log(who + ' has joined ' + channel);
		});

		bot.addListener('part', function(channel, who) {
			console.log(who + ' has parted ' + channel);
		});

		bot.addListener('quit', function(channel, who) {
			console.log(who + ' has quit ' + channel);
		});

		bot.addListener('message', function(from, to, text, info) {
			command_parser(from, to, text, info);
		});
	},

	say: function(channel, text) {
		function irc_push(channel, text) {
			text = config.irc.text_color + ' ' + text + config.irc.text_color + ' ';
			bot.say(channel, text);
		}
		// is it an array?
		if (Array.isArray(text)) {
			text.forEach(function(line) {
				irc_push(channel, line);
			});
			return;
		}
		// is it just text?
		irc_push(channel, text);
	}
}
<commit_msg>Don't let command errors crash bot (#51)<commit_after>var irc = require('irc');
var config = require('./config.js');

var bot;
var commands;

var channel_blocks = {
	private_chat: {
		blocked: false,
		kudos_minus: false,
		kudos_plus: false,
		ultrachord: false,
	},
	main_chat: {
		blocked: false,
		// XXX merge these into identify
		botbrname: false,
		botbrpass: false,
		botbrsync: false,
		kudos_minus: false,
		kudos_plus: false,
		update_ip: false,
	}
};

var commands_aliases = {
	b: 'battle',
	chord: 'ultrachord',
	compo: 'battle',
	g: 'google',
	gi: 'image',
	gif: 'giphy',
	h: 'help',
	i: 'imdb',
	images: 'image',
	img: 'imgur',
	imgr: 'imgur',
	l: 'lyceum',
	ohc: 'ohb',
	pic: 'pix',
	uc: 'ultrachord',
	up: 'uptime',
	w: 'wikipedia',
	wiki: 'wikipedia',
	y: 'youtube',
	yt: 'youtube',
};

var commands_alias_filters = {
	'kudos_minus': /^(.+)\-{2}$/i,
	'kudos_plus': /^(.+)\+{2}$/i,
};

alias_check = function(command) {
	if (typeof commands_aliases[command] !== 'undefined') {
		command = commands_aliases[command];
	}
	return command;
};

command_check = function(channel_type, command) {
	if (channel_blocks[channel_type][command] === false) {
		return false;
	}
	if (typeof commands[command] === 'undefined') {
		return false;
	}
	return true;
};

command_parser = function(from, to, text, info) {

	var command = '';

	// break text into words
	var words = text.split(' ').filter(e => e !== '');

	// supplement info
	info.from = from;
	info.command_prefix = config.command_prefix;
	info.words = words;

	// interpret solicitor
	var channel;
	if (to === config.bot_name) {
		console.log('PM <' + from + '> ' + text);
		channel = 'private_chat';
		info.channel = from;
		info.channel_type = channel;
	}
	else if (config.irc.channels.indexOf(to) != -1) {
		console.log(to + ' <' + from + '> ' + text);
		channel = 'main_chat';
		info.channel = info.args[0];
		info.channel_type = channel;
	}

	// check alias filters (command override)
	for (var key in commands_alias_filters) {
		filter = commands_alias_filters[key];
		if (filter.test(text)) {
			commands[key](info, words);
			return;
		}
	};

	// check for command prefix
	if (words[0].substr(0, 1) !== config.command_prefix) {
		if (to === config.bot_name) {
			// XXX something is fukt here
			if (from === config.bot_name) {
				console.log('STOP MESSAGING YERSELF!!');
				return false;
			}
			info.channel = from;
			commands.unknown(info, words);
		}
		return false;
	}

	// remove command prefix
	var command = words[0].substr(1);

	// abort if command is empty or non-alphabetic (likely an emoticon)
	if (command === '' || !command.match(/^[a-zA-Z]/)) {
		return false;
	}

	// check if the command is an alias
	command = alias_check(command);

	// check channel's blocked commands
	if (command_check(channel, command) === false) {
		commands.blocked(info, words);
		console.log('"' + command + '" in #' + channel + ' blocked');
		return false;
	}

	// check for command and call
	if (typeof commands[command] === "function") {
		try {
			var response = commands[command](info, words);
		} catch(err) {
			bot.say(info.channel, 'an error hath occured :X');
			console.log(err);
		}
	}
};

module.exports = {

	alias_check: function(command) {
		return alias_check(command);
	},

	alias_find: function(command) {
		var alias_list = [];
		for (alias in commands_aliases) {
			if (commands_aliases[alias] === command) {
				alias_list.push(alias);
			}
		}
		return alias_list;
	},

	command_check: function(command, channel_type) {
		return command_check(command, channel_type);
	},

	command_list: function(channel_type) {
		var command_list = [];
		for (command in commands) {
			if (command_check(channel_type, command)) {
				command_list.push(command);
			}
		}
		return command_list;
	},

	initialize: function() {
		bot = new irc.Client(config.irc.server, config.bot_name, {
			channels: config.irc.channels
		});

		//commands.init(this);
		commands = require('./irc_commands.js');

		bot.addListener('join', function(channel, who) {
			console.log(who + ' has joined ' + channel);
		});

		bot.addListener('part', function(channel, who) {
			console.log(who + ' has parted ' + channel);
		});

		bot.addListener('quit', function(channel, who) {
			console.log(who + ' has quit ' + channel);
		});

		bot.addListener('message', function(from, to, text, info) {
			command_parser(from, to, text, info);
		});
	},

	say: function(channel, text) {
		function irc_push(channel, text) {
			text = config.irc.text_color + ' ' + text + config.irc.text_color + ' ';
			bot.say(channel, text);
		}
		// is it an array?
		if (Array.isArray(text)) {
			text.forEach(function(line) {
				irc_push(channel, line);
			});
			return;
		}
		// is it just text?
		irc_push(channel, text);
	}
}
<|endoftext|>