<commit_before>/*
 * grunt-dom-munger
 * https://github.com/cgross/grunt-dom-munger
 *
 * Copyright (c) 2013 Chris Gross
 * Licensed under the MIT license.
 */
'use strict';

var path = require('path');
var fs = require('fs');
var cheerio = require('cheerio');

module.exports = function(grunt) {

  var processFile = function(f,dest,options,$,window){

    grunt.log.subhead('Processing ' + f.cyan);

    var updated = false;

    if (options.read){
      if (!options.read.selector || !options.read.attribute || !options.read.writeto){
        grunt.log.error('Read config missing selector, attribute, and/or writeto options');
      } else {

        var vals = $(options.read.selector).map(function(i,elem){
          return $(elem).attr(options.read.attribute);
        });

        vals = vals.filter(function(item){
          return item !== undefined;
        });

        if (options.read.isPath){
          var relativeTo = path.dirname(grunt.file.expand(f));
          vals = vals.map(function(val){
            return path.join(relativeTo,val);
          });
        }

        grunt.config(['dom_munger','data',options.read.writeto],vals);
        grunt.log.writeln('Wrote ' + (options.read.selector + '.' + options.read.attribute).cyan + ' to ' + ('dom_munger.data.'+options.read.writeto).cyan);
      }
    }

    if (options.update){
      if (!options.update.selector || !options.update.attribute || !options.update.value){
        grunt.log.error('Update config missing selector, attribute, and/or value options');
      } else {
        $(options.update.selector).attr(options.update.attribute,options.update.value);
        grunt.log.writeln('Updated ' + options.update.attribute.cyan + ' to ' + options.update.value.cyan);
        updated = true;
      }
    }

    if (options.append){
      if (!options.append.selector || !options.append.html){
        grunt.log.error('Append config missing selector and/or html options');
      } else {
        $(options.append.selector).append(options.append.html);
        grunt.log.writeln("Appended to " + options.append.selector.cyan);
        updated = true;
      }
    }

    if (options.prepend){
      if (!options.prepend.selector || !options.prepend.html){
        grunt.log.error('Prepend config missing selector and/or html options');
      } else {
        $(options.prepend.selector).prepend(options.prepend.html);
        grunt.log.writeln("Prepended to " + options.prepend.selector.cyan);
        updated = true;
      }
    }

    if (options.text){
      if (!options.text.selector || !options.text.text){
        grunt.log.error('Text config missing selector and/or text options');
      } else {
        $(options.text.selector).text(options.text.text);
        grunt.log.writeln('Applied text to ' + options.text.selector.cyan);
        updated = true;
      }
    }

    if (options.remove){
      $(options.remove).remove();
      grunt.log.writeln('Removed ' + options.remove.cyan);
      updated = true;
    }

    if (options.callback){
       options.callback($);
       //just assume its updating something
       updated = true;
    }

    if (updated){
      var updatedContents = $.html()
      grunt.file.write(dest || f,updatedContents);
      grunt.log.writeln('File ' + (dest || f).cyan + ' created/updated.');
    }

  };

  grunt.registerMultiTask('dom_munger', 'Read and manipulate html.', function() {

    var options = this.options({});
    var done = this.async();
    var countdown = 0;

    if (this.filesSrc.length > 1 && this.data.dest){
      grunt.log.error('Dest cannot be specified with multiple src files.');
      done(false);
    }

    this.files.forEach(function(f) {

      var dest = f.dest;

      f.src.filter(function(filepath) {
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      }).forEach(function(f){

        countdown++;

        var srcContents = grunt.file.read(f);

        var $ = cheerio.load(srcContents);
        processFile(f,dest,options,$);

        countdown --;
        if (countdown === 0){
          done();
        }

      });
    });

  });

};
<commit_msg>Avoid calling done() too early<commit_after>/*
 * grunt-dom-munger
 * https://github.com/cgross/grunt-dom-munger
 *
 * Copyright (c) 2013 Chris Gross
 * Licensed under the MIT license.
 */
'use strict';

var path = require('path');
var fs = require('fs');
var cheerio = require('cheerio');

module.exports = function(grunt) {

  var processFile = function(f,dest,options,$,window){

    grunt.log.subhead('Processing ' + f.cyan);

    var updated = false;

    if (options.read){
      if (!options.read.selector || !options.read.attribute || !options.read.writeto){
        grunt.log.error('Read config missing selector, attribute, and/or writeto options');
      } else {

        var vals = $(options.read.selector).map(function(i,elem){
          return $(elem).attr(options.read.attribute);
        });

        vals = vals.filter(function(item){
          return item !== undefined;
        });

        if (options.read.isPath){
          var relativeTo = path.dirname(grunt.file.expand(f));
          vals = vals.map(function(val){
            return path.join(relativeTo,val);
          });
        }

        grunt.config(['dom_munger','data',options.read.writeto],vals);
        grunt.log.writeln('Wrote ' + (options.read.selector + '.' + options.read.attribute).cyan + ' to ' + ('dom_munger.data.'+options.read.writeto).cyan);
      }
    }

    if (options.update){
      if (!options.update.selector || !options.update.attribute || !options.update.value){
        grunt.log.error('Update config missing selector, attribute, and/or value options');
      } else {
        $(options.update.selector).attr(options.update.attribute,options.update.value);
        grunt.log.writeln('Updated ' + options.update.attribute.cyan + ' to ' + options.update.value.cyan);
        updated = true;
      }
    }

    if (options.append){
      if (!options.append.selector || !options.append.html){
        grunt.log.error('Append config missing selector and/or html options');
      } else {
        $(options.append.selector).append(options.append.html);
        grunt.log.writeln("Appended to " + options.append.selector.cyan);
        updated = true;
      }
    }

    if (options.prepend){
      if (!options.prepend.selector || !options.prepend.html){
        grunt.log.error('Prepend config missing selector and/or html options');
      } else {
        $(options.prepend.selector).prepend(options.prepend.html);
        grunt.log.writeln("Prepended to " + options.prepend.selector.cyan);
        updated = true;
      }
    }

    if (options.text){
      if (!options.text.selector || !options.text.text){
        grunt.log.error('Text config missing selector and/or text options');
      } else {
        $(options.text.selector).text(options.text.text);
        grunt.log.writeln('Applied text to ' + options.text.selector.cyan);
        updated = true;
      }
    }

    if (options.remove){
      $(options.remove).remove();
      grunt.log.writeln('Removed ' + options.remove.cyan);
      updated = true;
    }

    if (options.callback){
       options.callback($);
       //just assume its updating something
       updated = true;
    }

    if (updated){
      var updatedContents = $.html()
      grunt.file.write(dest || f,updatedContents);
      grunt.log.writeln('File ' + (dest || f).cyan + ' created/updated.');
    }

  };

  grunt.registerMultiTask('dom_munger', 'Read and manipulate html.', function() {

    var options = this.options({});
    var done = this.async();

    if (this.filesSrc.length > 1 && this.data.dest){
      grunt.log.error('Dest cannot be specified with multiple src files.');
      done(false);
    }

    this.files.forEach(function(f) {

      var dest = f.dest;

      f.src.filter(function(filepath) {
        if (!grunt.file.exists(filepath)) {
          grunt.log.warn('Source file "' + filepath + '" not found.');
          return false;
        } else {
          return true;
        }
      }).forEach(function(f){

        var srcContents = grunt.file.read(f);

        var $ = cheerio.load(srcContents);
        processFile(f,dest,options,$);

      });
    });

    done();
  });

};
<|endoftext|>


<commit_before>/*
 * grunt-contrib-jshint
 * http://gruntjs.com/
 *
 * Copyright (c) 2013 "Cowboy" Ben Alman, contributors
 * Licensed under the MIT license.
 */

'use strict';

var path = require('path');
var jshint = require('jshint').JSHINT;
var jshintcli = require('jshint/src/cli');

exports.init = function(grunt) {
  var exports = {
    usingGruntReporter: false
  };

  var pad = function(msg,length) {
    while (msg.length < length) {
      msg = ' ' + msg;
    }
    return msg;
  };

  // Select a reporter (if not using the default Grunt reporter)
  // Copied from jshint/src/cli/cli.js until that part is exposed
  exports.selectReporter = function(options) {
    switch (true) {
    // JSLint reporter
    case options.reporter === 'jslint':
    case options['jslint-reporter']:
      options.reporter = 'jshint/src/reporters/jslint_xml.js';
      break;

    // CheckStyle (XML) reporter
    case options.reporter === 'checkstyle':
    case options['checkstyle-reporter']:
      options.reporter = 'jshint/src/reporters/checkstyle.js';
      break;

    // Reporter that displays additional JSHint data
    case options['show-non-errors']:
      options.reporter = 'jshint/src/reporters/non_error.js';
      break;

    // Custom reporter
    case options.reporter !== undefined:
      options.reporter = path.resolve(process.cwd(), options.reporter);
    }

    var reporter;
    if (options.reporter) {
      try {
        reporter = require(options.reporter).reporter;
        exports.usingGruntReporter = false;
      } catch (err) {
        grunt.fatal(err);
      }
    }

    // Use the default Grunt reporter if none are found
    if (!reporter) {
      reporter = exports.reporter;
      exports.usingGruntReporter = true;
    }

    return reporter;
  };

  // Default Grunt JSHint reporter
  exports.reporter = function(results, data) {
    // Dont report empty data as its an ignored file
    if (data.length < 1) {
      grunt.log.error('0 files linted. Please check your ignored files.');
      return;
    }

    if (results.length === 0) {
      // Success!
      grunt.verbose.ok();
      return;
    }

    var options = data[0].options;

    grunt.log.writeln();

    var lastfile = null;
    // Iterate over all errors.
    results.forEach(function(result) {

      // Only print file name once per error
      if (result.file !== lastfile) {
        grunt.log.writeln((result.file ? '   ' + result.file : '').bold);
      }
      lastfile = result.file;

      var e = result.error;

      // Sometimes there's no error object.
      if (!e) { return; }

      if (e.evidence) {
        // Manually increment errorcount since we're not using grunt.log.error().
        grunt.fail.errorcount++;

        // No idea why JSHint treats tabs as options.indent # characters wide, but it
        // does. See issue: https://github.com/jshint/jshint/issues/430
        // Replacing tabs with appropriate spaces (i.e. columns) ensures that
        // caret will line up correctly.
        var evidence = e.evidence.replace(/\t/g,grunt.util.repeat(options.indent,' '));

        grunt.log.writeln((pad(e.line.toString(),7) + ' |') + evidence.grey);
        grunt.log.write(grunt.util.repeat(9,' ') + grunt.util.repeat(e.character -1,' ') + '^ ');
        grunt.verbose.write('[' + e.code + '] ');
        grunt.log.writeln(e.reason);

      } else {
        // Generic "Whoops, too many errors" error.
        grunt.log.error(e.reason);
      }
    });
    grunt.log.writeln();
  };

  // Run JSHint on the given files with the given options
  exports.lint = function(files, options, done) {
    var cliOptions = {
      verbose: grunt.option('verbose'),
      extensions: '',
    };

    // A list of non-dot-js extensions to check
    if (options.extensions) {
      cliOptions.extensions = options.extensions;
      delete options.extensions;
    }

    // A list ignored files
    if (options.ignores) {
      if (typeof options.ignores === 'string') {
        options.ignores = [options.ignores];
      }
      cliOptions.ignores = options.ignores;
      delete options.ignores;
    }

    // Option to extract JS from HTML file
    if (options.extract) {
      cliOptions.extract = options.extract;
      delete options.extract;
    }

    // Get reporter output directory for relative paths in reporters
    if (options.reporterOutput) {
      var reporterOutputDir = path.dirname(options.reporterOutput);
      delete options.reporterOutput;
    }

    // Select a reporter to use
    var reporter = exports.selectReporter(options);

    // Remove bad options that may have came in from the cli
    ['reporter', 'jslint-reporter', 'checkstyle-reporter', 'show-non-errors'].forEach(function(opt) {
      if (options.hasOwnProperty(opt)) {
        delete options[opt];
      }
    });

    if (options.jshintrc === true) {
      // let jshint find the options itself
      delete cliOptions.config;
    } else if (options.jshintrc) {
      // Read JSHint options from a specified jshintrc file.
      cliOptions.config = jshintcli.loadConfig(options.jshintrc);
    } else {
      // Enable/disable debugging if option explicitly set.
      if (grunt.option('debug') !== undefined) {
        options.devel = options.debug = grunt.option('debug');
        // Tweak a few things.
        if (grunt.option('debug')) {
          options.maxerr = Infinity;
        }
      }
      // pass all of the remaining options directly to jshint
      cliOptions.config = options;
    }

    // Run JSHint on all file and collect results/data
    var allResults = [];
    var allData = [];
    cliOptions.args = files;
    cliOptions.reporter = function(results, data) {
      results.forEach(function(datum) {
        datum.file = reporterOutputDir ? path.relative(reporterOutputDir, datum.file) : datum.file;
      });
      reporter(results, data, options);
      allResults = allResults.concat(results);
      allData = allData.concat(data);
    };
    jshintcli.run(cliOptions);
    done(allResults, allData);
  };

  return exports;
};
<commit_msg>More robust check for reporterOutput in options<commit_after>/*
 * grunt-contrib-jshint
 * http://gruntjs.com/
 *
 * Copyright (c) 2013 "Cowboy" Ben Alman, contributors
 * Licensed under the MIT license.
 */

'use strict';

var path = require('path');
var jshint = require('jshint').JSHINT;
var jshintcli = require('jshint/src/cli');

exports.init = function(grunt) {
  var exports = {
    usingGruntReporter: false
  };

  var pad = function(msg,length) {
    while (msg.length < length) {
      msg = ' ' + msg;
    }
    return msg;
  };

  // Select a reporter (if not using the default Grunt reporter)
  // Copied from jshint/src/cli/cli.js until that part is exposed
  exports.selectReporter = function(options) {
    switch (true) {
    // JSLint reporter
    case options.reporter === 'jslint':
    case options['jslint-reporter']:
      options.reporter = 'jshint/src/reporters/jslint_xml.js';
      break;

    // CheckStyle (XML) reporter
    case options.reporter === 'checkstyle':
    case options['checkstyle-reporter']:
      options.reporter = 'jshint/src/reporters/checkstyle.js';
      break;

    // Reporter that displays additional JSHint data
    case options['show-non-errors']:
      options.reporter = 'jshint/src/reporters/non_error.js';
      break;

    // Custom reporter
    case options.reporter !== undefined:
      options.reporter = path.resolve(process.cwd(), options.reporter);
    }

    var reporter;
    if (options.reporter) {
      try {
        reporter = require(options.reporter).reporter;
        exports.usingGruntReporter = false;
      } catch (err) {
        grunt.fatal(err);
      }
    }

    // Use the default Grunt reporter if none are found
    if (!reporter) {
      reporter = exports.reporter;
      exports.usingGruntReporter = true;
    }

    return reporter;
  };

  // Default Grunt JSHint reporter
  exports.reporter = function(results, data) {
    // Dont report empty data as its an ignored file
    if (data.length < 1) {
      grunt.log.error('0 files linted. Please check your ignored files.');
      return;
    }

    if (results.length === 0) {
      // Success!
      grunt.verbose.ok();
      return;
    }

    var options = data[0].options;

    grunt.log.writeln();

    var lastfile = null;
    // Iterate over all errors.
    results.forEach(function(result) {

      // Only print file name once per error
      if (result.file !== lastfile) {
        grunt.log.writeln((result.file ? '   ' + result.file : '').bold);
      }
      lastfile = result.file;

      var e = result.error;

      // Sometimes there's no error object.
      if (!e) { return; }

      if (e.evidence) {
        // Manually increment errorcount since we're not using grunt.log.error().
        grunt.fail.errorcount++;

        // No idea why JSHint treats tabs as options.indent # characters wide, but it
        // does. See issue: https://github.com/jshint/jshint/issues/430
        // Replacing tabs with appropriate spaces (i.e. columns) ensures that
        // caret will line up correctly.
        var evidence = e.evidence.replace(/\t/g,grunt.util.repeat(options.indent,' '));

        grunt.log.writeln((pad(e.line.toString(),7) + ' |') + evidence.grey);
        grunt.log.write(grunt.util.repeat(9,' ') + grunt.util.repeat(e.character -1,' ') + '^ ');
        grunt.verbose.write('[' + e.code + '] ');
        grunt.log.writeln(e.reason);

      } else {
        // Generic "Whoops, too many errors" error.
        grunt.log.error(e.reason);
      }
    });
    grunt.log.writeln();
  };

  // Run JSHint on the given files with the given options
  exports.lint = function(files, options, done) {
    var cliOptions = {
      verbose: grunt.option('verbose'),
      extensions: '',
    };

    // A list of non-dot-js extensions to check
    if (options.extensions) {
      cliOptions.extensions = options.extensions;
      delete options.extensions;
    }

    // A list ignored files
    if (options.ignores) {
      if (typeof options.ignores === 'string') {
        options.ignores = [options.ignores];
      }
      cliOptions.ignores = options.ignores;
      delete options.ignores;
    }

    // Option to extract JS from HTML file
    if (options.extract) {
      cliOptions.extract = options.extract;
      delete options.extract;
    }

    // Get reporter output directory for relative paths in reporters
    if (options.hasOwnProperty('reporterOutput')) {
      var reporterOutputDir = path.dirname(options.reporterOutput);
      delete options.reporterOutput;
    }

    // Select a reporter to use
    var reporter = exports.selectReporter(options);

    // Remove bad options that may have came in from the cli
    ['reporter', 'jslint-reporter', 'checkstyle-reporter', 'show-non-errors'].forEach(function(opt) {
      if (options.hasOwnProperty(opt)) {
        delete options[opt];
      }
    });

    if (options.jshintrc === true) {
      // let jshint find the options itself
      delete cliOptions.config;
    } else if (options.jshintrc) {
      // Read JSHint options from a specified jshintrc file.
      cliOptions.config = jshintcli.loadConfig(options.jshintrc);
    } else {
      // Enable/disable debugging if option explicitly set.
      if (grunt.option('debug') !== undefined) {
        options.devel = options.debug = grunt.option('debug');
        // Tweak a few things.
        if (grunt.option('debug')) {
          options.maxerr = Infinity;
        }
      }
      // pass all of the remaining options directly to jshint
      cliOptions.config = options;
    }

    // Run JSHint on all file and collect results/data
    var allResults = [];
    var allData = [];
    cliOptions.args = files;
    cliOptions.reporter = function(results, data) {
      results.forEach(function(datum) {
        datum.file = reporterOutputDir ? path.relative(reporterOutputDir, datum.file) : datum.file;
      });
      reporter(results, data, options);
      allResults = allResults.concat(results);
      allData = allData.concat(data);
    };
    jshintcli.run(cliOptions);
    done(allResults, allData);
  };

  return exports;
};
<|endoftext|>


<commit_before>'use strict';

var inquirer = require('inquirer');
var gitHelper = require('./lib/helpers/git');
var dependenciesHelper = require('./lib/helpers/dependencies');
var messages = require('./lib/messages');
var version = require('./lib/version');

module.exports = function (grunt) {

  grunt.task.loadNpmTasks('grunt-bump');

  // ---

  grunt.registerTask('prepare_sg_release', function () {

    var done = this.async();
    var options = this.options({
      tempReleaseBranch: 'release'
    });

    function checkNpmInstall() {
      dependenciesHelper.checkInstall(grunt, process.cwd(), 'npm', checkBowerInstall);
    }

    function checkBowerInstall() {
      dependenciesHelper.checkInstall(grunt, process.cwd(), 'bower', checkoutTempReleaseBranch);
    }

    function checkoutTempReleaseBranch() {
      gitHelper.checkout(grunt, process.cwd(), '-b ' + options.tempReleaseBranch, getReleaseVersion);
    }

    function getReleaseVersion() {
      version.getRelease(grunt, done);
    }

    (function start() {
      gitHelper.check(grunt);
      checkNpmInstall();
    })();

  });

  // ---

  grunt.registerMultiTask('sg_release', 'The SunGard standard release script for HTML5 projects.', function () {

    grunt.task.run('prepare_sg_release');
    grunt.task.run('bump-only');

  });

};

<commit_msg>Added checkGit as a step on prepare_sg_release<commit_after>'use strict';

var inquirer = require('inquirer');
var gitHelper = require('./lib/helpers/git');
var dependenciesHelper = require('./lib/helpers/dependencies');
var messages = require('./lib/messages');
var version = require('./lib/version');

module.exports = function (grunt) {

  grunt.task.loadNpmTasks('grunt-bump');

  // ---

  grunt.registerTask('prepare_sg_release', function () {

    var done = this.async();
    var options = this.options({
      tempReleaseBranch: 'release'
    });

    function checkGit() {
      gitHelper.check(grunt);
      checkNpmInstall();
    }

    function checkNpmInstall() {
      dependenciesHelper.checkInstall(grunt, process.cwd(), 'npm', checkBowerInstall);
    }

    function checkBowerInstall() {
      dependenciesHelper.checkInstall(grunt, process.cwd(), 'bower', checkoutTempReleaseBranch);
    }

    function checkoutTempReleaseBranch() {
      gitHelper.checkout(grunt, process.cwd(), '-b ' + options.tempReleaseBranch, getReleaseVersion);
    }

    function getReleaseVersion() {
      version.getRelease(grunt, done);
    }

    (function start() {
      checkGit();
    })();

  });

  // ---

  grunt.registerMultiTask('sg_release', 'The SunGard standard release script for HTML5 projects.', function () {

    grunt.task.run('prepare_sg_release');
    grunt.task.run('bump-only');

  });

};

<|endoftext|>


<commit_before>'use strict';

var inquirer = require('inquirer');
var extendGruntPlugin = require('extend-grunt-plugin');

var gitHelper = require('./lib/helpers/git');
var dependenciesHelper = require('./lib/helpers/dependencies');
var messages = require('./lib/messages');
var version = require('./lib/version');

// ---

module.exports = function (grunt) {

  var options;
  var releaseBranchName;

  grunt.registerTask('prepare_sg_release', function () {

    var done = this.async();

    function checkGit() {
      gitHelper.check(grunt);
      checkNpmInstall();
    }

    function checkNpmInstall() {
      dependenciesHelper.checkInstall(grunt, process.cwd(), 'npm', options.skipNpmInstall, checkBowerInstall);
    }

    function checkBowerInstall() {
      dependenciesHelper.checkInstall(grunt, process.cwd(), 'bower', options.skipBowerInstall, getReleaseVersion);
    }

    function getReleaseVersion() {
      version.getRelease(grunt, createTempReleaseBranch);
    }

    function createTempReleaseBranch() {
      releaseBranchName = options.tempReleaseBranch + '/v' + grunt.option('setversion');
      gitHelper.createBranch(grunt, process.cwd(), releaseBranchName, done);
    }

    (function start() {
      checkGit();
    })();

  });

  // ---

  grunt.registerTask('merge_sg_release', function () {

    var done = this.async();

    function checkoutMaster() {
      gitHelper.checkout(grunt, process.cwd(), options.masterBranch, mergeFromTempReleaseBranch);
    }

    function mergeFromTempReleaseBranch() {
      gitHelper.merge(grunt, process.cwd(), releaseBranchName, options.commitMessagePrefix, options.mergeToMasterMsg, checkoutDevelop);
    }

    function checkoutDevelop() {
      gitHelper.checkout(grunt, process.cwd(), options.developBranch, mergeIntoDevelopBranch);
    }

    function mergeIntoDevelopBranch() {
      gitHelper.merge(grunt, process.cwd(), releaseBranchName, options.commitMessagePrefix, options.mergeToDevelopMsg, deleteTempReleaseBranch);
    }

    function deleteTempReleaseBranch() {
      gitHelper.deleteBranch(grunt, process.cwd(), releaseBranchName, options.deleteRemoteBranch === true ? deleteTempRemoteReleaseBranch : getNextVersion);
    }

    function deleteTempRemoteReleaseBranch() {
      gitHelper.deleteRemoteBranch(grunt, process.cwd(), options.pushTo, releaseBranchName, getNextVersion);
    }

    function getNextVersion() {
      version.getNext(grunt, done);
    }

    (function start() {
      checkoutMaster();
    })();

  });

  // ---

  grunt.registerTask('finish_sg_release', function () {

    var done = this.async();

    function commitDevelopmentVersion() {
      gitHelper.commit(grunt, process.cwd(), options.commitMessagePrefix, options.developVersionCommitMsg, pushDevelopBranch);
    }

    function pushDevelopBranch() {
      gitHelper.push(grunt, process.cwd(), options.pushTo, options.developBranch, pushMasterBranch);
    }

    function pushMasterBranch() {
      gitHelper.push(grunt, process.cwd(), options.pushTo, options.masterBranch, pushReleaseTag);
    }

    function pushReleaseTag() {
      var tagNameOption = options.tagName;
      var releaseVersion = grunt.option('releaseVersion');
      var tagName = tagNameOption.replace('%VERSION%', releaseVersion);

      gitHelper.push(grunt, process.cwd(), options.pushTo, tagName, done);
    }

    (function start() {
      commitDevelopmentVersion();
    })();

  });

  // ---

  grunt.registerMultiTask('sg_release', 'The SunGard standard release script for HTML5 projects.', function () {

    options = this.options({
      skipBowerInstall: false,
      skipNpmInstall: false,
      developBranch: 'develop',
      masterBranch: 'master',
      tempReleaseBranch: 'release',
      commitMessagePrefix: '',
      mergeToDevelopMsg: messages.mergeToDevelopMsg,
      mergeToMasterMsg: messages.mergeToMasterMsg,
      developVersionCommitMsg: messages.developVersionCommitMsg,
      tagName: 'v%VERSION%',
      pushTo: 'upstream',
      push: false // By default push should happen only at the end, during finish_sg_release subtask
    });

    extendGruntPlugin(grunt, require('grunt-bump'), {
      'bump': options,
      'bump-only': options
    });

    if (options.finishOnly !== true && options.finishOnly !== "true") {
      grunt.task.run('prepare_sg_release');
      grunt.task.run('bump');
    }

    if (options.finishOnly === true || options.finishOnly === "true") {
      // get the version again since we cannot call prepare_sg_release here
      version.getRelease(grunt, function () {
        releaseBranchName = options.tempReleaseBranch + '/v' + grunt.option('setversion');
      });
    }

    if (options.startOnly !== true && options.startOnly !== "true") {
      grunt.task.run('merge_sg_release');
      grunt.task.run('bump-only');
      grunt.task.run('finish_sg_release');
    }
  });

};

<commit_msg>not using the v here, otherwise we cannot checkout the temp branch anymore<commit_after>'use strict';

var inquirer = require('inquirer');
var extendGruntPlugin = require('extend-grunt-plugin');

var gitHelper = require('./lib/helpers/git');
var dependenciesHelper = require('./lib/helpers/dependencies');
var messages = require('./lib/messages');
var version = require('./lib/version');

// ---

module.exports = function (grunt) {

  var options;
  var releaseBranchName;

  grunt.registerTask('prepare_sg_release', function () {

    var done = this.async();

    function checkGit() {
      gitHelper.check(grunt);
      checkNpmInstall();
    }

    function checkNpmInstall() {
      dependenciesHelper.checkInstall(grunt, process.cwd(), 'npm', options.skipNpmInstall, checkBowerInstall);
    }

    function checkBowerInstall() {
      dependenciesHelper.checkInstall(grunt, process.cwd(), 'bower', options.skipBowerInstall, getReleaseVersion);
    }

    function getReleaseVersion() {
      version.getRelease(grunt, createTempReleaseBranch);
    }

    function createTempReleaseBranch() {
      releaseBranchName = options.tempReleaseBranch + '/' + grunt.option('setversion');
      gitHelper.createBranch(grunt, process.cwd(), releaseBranchName, done);
    }

    (function start() {
      checkGit();
    })();

  });

  // ---

  grunt.registerTask('merge_sg_release', function () {

    var done = this.async();

    function checkoutMaster() {
      gitHelper.checkout(grunt, process.cwd(), options.masterBranch, mergeFromTempReleaseBranch);
    }

    function mergeFromTempReleaseBranch() {
      gitHelper.merge(grunt, process.cwd(), releaseBranchName, options.commitMessagePrefix, options.mergeToMasterMsg, checkoutDevelop);
    }

    function checkoutDevelop() {
      gitHelper.checkout(grunt, process.cwd(), options.developBranch, mergeIntoDevelopBranch);
    }

    function mergeIntoDevelopBranch() {
      gitHelper.merge(grunt, process.cwd(), releaseBranchName, options.commitMessagePrefix, options.mergeToDevelopMsg, deleteTempReleaseBranch);
    }

    function deleteTempReleaseBranch() {
      gitHelper.deleteBranch(grunt, process.cwd(), releaseBranchName, options.deleteRemoteBranch === true ? deleteTempRemoteReleaseBranch : getNextVersion);
    }

    function deleteTempRemoteReleaseBranch() {
      gitHelper.deleteRemoteBranch(grunt, process.cwd(), options.pushTo, releaseBranchName, getNextVersion);
    }

    function getNextVersion() {
      version.getNext(grunt, done);
    }

    (function start() {
      checkoutMaster();
    })();

  });

  // ---

  grunt.registerTask('finish_sg_release', function () {

    var done = this.async();

    function commitDevelopmentVersion() {
      gitHelper.commit(grunt, process.cwd(), options.commitMessagePrefix, options.developVersionCommitMsg, pushDevelopBranch);
    }

    function pushDevelopBranch() {
      gitHelper.push(grunt, process.cwd(), options.pushTo, options.developBranch, pushMasterBranch);
    }

    function pushMasterBranch() {
      gitHelper.push(grunt, process.cwd(), options.pushTo, options.masterBranch, pushReleaseTag);
    }

    function pushReleaseTag() {
      var tagNameOption = options.tagName;
      var releaseVersion = grunt.option('releaseVersion');
      var tagName = tagNameOption.replace('%VERSION%', releaseVersion);

      gitHelper.push(grunt, process.cwd(), options.pushTo, tagName, done);
    }

    (function start() {
      commitDevelopmentVersion();
    })();

  });

  // ---

  grunt.registerMultiTask('sg_release', 'The SunGard standard release script for HTML5 projects.', function () {

    options = this.options({
      skipBowerInstall: false,
      skipNpmInstall: false,
      developBranch: 'develop',
      masterBranch: 'master',
      tempReleaseBranch: 'release',
      commitMessagePrefix: '',
      mergeToDevelopMsg: messages.mergeToDevelopMsg,
      mergeToMasterMsg: messages.mergeToMasterMsg,
      developVersionCommitMsg: messages.developVersionCommitMsg,
      tagName: 'v%VERSION%',
      pushTo: 'upstream',
      push: false // By default push should happen only at the end, during finish_sg_release subtask
    });

    extendGruntPlugin(grunt, require('grunt-bump'), {
      'bump': options,
      'bump-only': options
    });

    if (options.finishOnly !== true && options.finishOnly !== "true") {
      grunt.task.run('prepare_sg_release');
      grunt.task.run('bump');
    }

    if (options.finishOnly === true || options.finishOnly === "true") {
      // get the version again since we cannot call prepare_sg_release here
      version.getRelease(grunt, function () {
        releaseBranchName = options.tempReleaseBranch + '/v' + grunt.option('setversion');
      });
    }

    if (options.startOnly !== true && options.startOnly !== "true") {
      grunt.task.run('merge_sg_release');
      grunt.task.run('bump-only');
      grunt.task.run('finish_sg_release');
    }
  });

};

<|endoftext|>


<commit_before>var _ = require('lodash');

module.exports = {
  marked: require('marked').setOptions({
    gfm: true,
    tables: true,
    breaks: true,
    pedantic: true,
    sanitize: false,
    smartLists: true,
    smartypants: true
  }),
  javaKeywords: ['for', 'switch'], // TODO: if it's necessary add other keywords as well
  findBehavior: function(name) {
    for (var i = 0; name && i < global.parsed.length; i++) {
      var item = global.parsed[i];
      if (this.isBehavior(item) && this.className(item.is) == this.className(name)) {
        return global.parsed[i];
      }
    }
  },
  findElement: function(name) {
    for (var i = 0; name && i < global.parsed.length; i++) {
      var item = global.parsed[i];
      if (!this.isBehavior(item) && this.className(item.is) == this.className(name)) {
        return global.parsed[i];
      }
    }
  },
  isBehavior: function(item) {
    return ((item && item.type) || this.type) == 'behavior';
  },
  getNestedBehaviors: function(item, name) {
    var _this = this;
    var properties = [];

    var events = [];

    var behavior = this.findBehavior(name)
    if (behavior) {
      events = behavior.events;

      behavior.properties.forEach(function(prop) {
        prop.isBehavior = true;
        prop.behavior = _this.className(item.is);
        prop.signature = _this.signParamString(prop);
        properties.push(prop);
      });

      if(behavior.behaviors) {
        behavior.behaviors.forEach(function(b) {
          var nestedBehaviors = _this.getNestedBehaviors(item, b);
          properties = _.union(properties, nestedBehaviors.properties);
          events = _.union(events, nestedBehaviors.events);
        });
      }
    }

    return {properties: properties, events: events};
  },
  className: function (name) {
    return this.camelCase(name || this['name']);
  },
  elementClassName: function(name) {
    return this.className(name) + (this.isBehavior() ? '' : 'Element');
  },
  baseClassName: function () {
    var _this = this;
    // Always extend native HTMLElement
    var e = ['HTMLElement'];
    if (this.behaviors && this.behaviors.length) {
      this.behaviors.forEach(function(name){
        // CoreResizable -> CoreResizableElement, core-input -> CoreInputElment
        if (name && name.match(/[A-Z\-]/)) {
          if (_this.findBehavior(name)) {
            e.push(_this.camelCase(name));
          } else {
            console.log("NOT FOUND: " + name + " " + _this.camelCase(name));
          }
        } else {
          // input -> HTMLInputElement, table -> HTMLTableElement
          e.push('HTML' + _this.elementClassName(name));
        }
      });
    }
    return "extends " + e.join(',');
  },
  camelCase: function(s) {
    return (s || '').replace(/^Polymer\./, '').replace(/[^\-\w\.]/g,'').replace(/(\b|-|\.)\w/g, function (m) {
      return m.toUpperCase().replace(/[-\.]/g, '');
    });
  },
  hyphenize: function(s) {
    return s.replace(/([A-Z])/g, "-$1").toLowerCase();
  },
  computeMethodName: function(s) {
    return (s || '').replace(/-\w/g, function (m) {
      return m.toUpperCase().replace(/-/, '');
    });
  },
  computeName: function(s) {
    return (s || '').replace(/[^\w\-\.:]/g, '');
  },
  computeType: function(t) {
    if (!t) return 'Object';
    // TODO: Sometimes type have a syntax like: (number|string)
    // We should be able to overload those methods instead of using
    // Object, but JsInterop does not support well overloading
    if (/.*\|.*/.test(t)) return 'Object';
    if (/^string/i.test(t)) return 'String';
    if (/^boolean/i.test(t)) return 'boolean';
    if (/^array/i.test(t)) return 'JsArray';
    if (/^element/i.test(t)) return 'Element';
    if (/^number/i.test(t)) return 'double';
    if (/^function/i.test(t)) return 'Function';
    if (this.findBehavior(t)) {
      return this.camelCase(t);
    }
    if (this.findElement(t)) {
      return this.camelCase(t) + 'Element';
    }

    return "JavaScriptObject";
  },
  sortProperties: function(properties) {
  },
  getGettersAndSetters: function(properties) {
    // Sorting properties so no-typed and String methods are at end
    properties.sort(function(a, b) {
      var t1 = this.computeType(a.type);
      var t2 = this.computeType(b.type);
      return t1 == t2 ? 0: !a.type && b.type ? 1 : a.type && !b.type ? -1: t1 == 'String' ? 1 : -1;
    }.bind(this));
    var ret = [];
    // We use done hash to avoid generate same property with different signature (unsupported in JsInterop)
    var done = {};
    // We use cache to catch especial cases of getter/setter no defined in the
    // properties block but as 'set foo:{}, get foo:{}' pairs. The hack is that
    // first we see a method with the a valid type (setter) and then we visit
    // a method with the same name but empty type (getter).
    var cache = {};

    _.forEach(properties, function(item) {
      // We consider as properties:
      if (
          // Items with the published tag (those defined in the properties section)
          item.published ||
          // Non function items
          !item.private && item.type && !/function/i.test(item.type) ||
          // Properties defined with customized get/set syntax
          !item.type && cache[item.name] && cache[item.name].type) {

        // defined with customized get/set, if we are here is because
        // this item.type is undefined and cached one has the correct type
        item = cache[item.name] ? cache[item.name] : item;

        item.getter = item.getter || this.computeGetterWithPrefix(item);
        item.setter = item.setter || (this.computeSetterWithPrefix(item) + '(' + this.computeType(item.type) + ' value)');

        // JsInterop does not support a property with two signatures
        if (!done[item.getter]) {
          ret.push(item);
          done[item.getter] = true;
        }
      } else {
        cache[item.name] = item;
      }
    }.bind(this));
    return ret;
  },
  getStringSetters: function(properties) {
    var ret = [];
    var arr = this.getGettersAndSetters(properties);
    _.forEach(arr, function(item) {
      var itType = this.computeType(item.type) ;
      if (!/(Function|String|boolean)/.test(itType)) {
        for (var j = 0; j< arr.length; j++) {
          if (arr[j].name == item.name && arr[j].type == 'String') {
            return;
          }
        }
        ret.push(item);
      }
    }.bind(this));
    return ret;
  },
  getMethods: function(properties) {
    // Sorting properties so Object methods are at first
    properties.sort(function(a, b) {
      var t1 = this.typedParamsString(a);
      var t2 = this.typedParamsString(b);
      return t1 == t2 ? 0: /^Object/.test(t1) ? -1 : 1;
    }.bind(this));

    // Skip functions with name equal to a getter/setter
    var gsetters = {};
    _.forEach(properties, function(item) {
      if (item.getter) {
        gsetters[item.getter] = true;
        gsetters[item.setter] = true;
        gsetters[item.name] = true;
      }
    }.bind(this));

    var ret = [];
    var done = {};
    _.forEach(properties, function(item) {
      if (!gsetters[item.name] && !item.getter && !item.private && !item.published && /function/i.test(item.type)) {
        item.method = item.method || item.name + '(' + this.typedParamsString(item) + ')';
        // JsInterop + SDM do not support method overloading if one signature is object
        var other = item.method.replace(/String/, 'Object');
        if (!gsetters[item.method] && !done[other] && !done[item.method]) {
          ret.push(item);
          done[item.method] = true;
        }
      }
    }.bind(this));
    return ret;
  },
  removePrivateApi: function(arr, prop) {
    for (var i = arr.length - 1; i >= 0; i--) {
      if (/^(_.*|ready|created)$/.test(arr[i][prop])) {
        arr.splice(i, 1);
      }
    }
  },
  hasItems: function(array) {
    return array && array.length > 0;
  },
  hasEvents: function() {
    return this.hasItems(this.events);
  },
  hasProperties: function() {
    return this.hasItems(this.properties);
  },
  hasParams: function() {
    return this.hasItems(this.params);
  },
  capitalizeFirstLetter: function(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
  },
  computeGetterWithPrefix: function(item) {
    var name = item.name.replace(/^detail\./,'');
    // replaced isXXX methods with getXXX temporary because of bug in JsInterop
    // because in the case of isNarrow, the JS generated is something like $object.arrow
    //var prefix = /^boolean/i.test(item.type) ? 'is' : 'get';
    var prefix = 'get';
    if (this.startsWith(name, prefix)) {
      return name;
    } else {
      return prefix + this.capitalizeFirstLetter(this.computeMethodName(name));
    }
  },
  computeSetterWithPrefix: function(item) {
    return 'set' + this.capitalizeFirstLetter(this.computeMethodName(item.name));
  },
  startsWith: function (str, substr){
    return str.indexOf(substr) === 0;
  },
  signParamString: function(method) {
    if (method.type != 'Function') {
      return method.type;
    }
    var result = [];
    if (method.params) {
      method.params.forEach(function(param) {
        var type = this.computeType(param.type);
        result.push(type);
      }, this);
    }
    return result.join(',');
  },
  typedParamsString: function(method) {
    var result = [];
    if (method.params) {
      method.params.forEach(function(param) {
        var type = this.computeType(param.type);
        result.push(type + ' ' + this.computeMethodName(param.name));
      }, this);
    }
    return result.join(', ');
  },
  paramsString: function(method) {
    var result = [];
    if (method.params) {
      method.params.forEach(function(param) {
        result.push(this.computeMethodName(param.name));
      }, this);
    }
    return result.join(', ');
  },
  returnString: function(method) {
    if (method['return'] && method['return']['type']) {
      return this.computeType(method['return']['type'])
    }
    return 'void';
  },
  getDescription: function(spaces, o) {
    o = o || this;
    var desc = o.description || o.desc || '';
    desc = this.marked(desc);
    return (desc).trim().split('\n').join('\n' + spaces + '* ').replace(/\*\//g, "* /");
  },
  disclaimer: function() {
    var projectName = this.bowerData.name || "unknown";
    var projectLicense = this.bowerData.license || "unknown";

    var projectAuthors = this.bowerData.authors || this.bowerData.author;
    if (projectAuthors && projectAuthors.map) {
      projectAuthors = projectAuthors.map(function(author) {
        return author.name ? author.name : author;
      }).toString();
    }
    projectAuthors = projectAuthors || "unknown author";

    return "/*\n" +
    " * This code was generated with Vaadin Web Component GWT API Generator, \n" +
    " * from " + projectName + " project by " + projectAuthors + "\n" +
    " * that is licensed with " + projectLicense + " license.\n" +
    " */";
  },
  j2s: function(json, msg) {
    msg = msg || '';
    var cache = [];
    console.log(msg + JSON.stringify(json, function(key, value) {
        if (typeof value === 'object' && value !== null) {
            if (cache.indexOf(value) !== -1) {
                return;
            }
            cache.push(value);
        }
        return value;
    }));
  }
};
<commit_msg>Avoid override methods when defined with the same signature and different parameter name<commit_after>var _ = require('lodash');

module.exports = {
  marked: require('marked').setOptions({
    gfm: true,
    tables: true,
    breaks: true,
    pedantic: true,
    sanitize: false,
    smartLists: true,
    smartypants: true
  }),
  javaKeywords: ['for', 'switch'], // TODO: if it's necessary add other keywords as well
  findBehavior: function(name) {
    for (var i = 0; name && i < global.parsed.length; i++) {
      var item = global.parsed[i];
      if (this.isBehavior(item) && this.className(item.is) == this.className(name)) {
        return global.parsed[i];
      }
    }
  },
  findElement: function(name) {
    for (var i = 0; name && i < global.parsed.length; i++) {
      var item = global.parsed[i];
      if (!this.isBehavior(item) && this.className(item.is) == this.className(name)) {
        return global.parsed[i];
      }
    }
  },
  isBehavior: function(item) {
    return ((item && item.type) || this.type) == 'behavior';
  },
  getNestedBehaviors: function(item, name) {
    var _this = this;
    var properties = [];

    var events = [];

    var behavior = this.findBehavior(name)
    if (behavior) {
      events = behavior.events;

      behavior.properties.forEach(function(prop) {
        prop.isBehavior = true;
        prop.behavior = _this.className(item.is);
        prop.signature = _this.signParamString(prop);
        properties.push(prop);
      });

      if(behavior.behaviors) {
        behavior.behaviors.forEach(function(b) {
          var nestedBehaviors = _this.getNestedBehaviors(item, b);
          properties = _.union(properties, nestedBehaviors.properties);
          events = _.union(events, nestedBehaviors.events);
        });
      }
    }

    return {properties: properties, events: events};
  },
  className: function (name) {
    return this.camelCase(name || this['name']);
  },
  elementClassName: function(name) {
    return this.className(name) + (this.isBehavior() ? '' : 'Element');
  },
  baseClassName: function () {
    var _this = this;
    // Always extend native HTMLElement
    var e = ['HTMLElement'];
    if (this.behaviors && this.behaviors.length) {
      this.behaviors.forEach(function(name){
        // CoreResizable -> CoreResizableElement, core-input -> CoreInputElment
        if (name && name.match(/[A-Z\-]/)) {
          if (_this.findBehavior(name)) {
            e.push(_this.camelCase(name));
          } else {
            console.log("NOT FOUND: " + name + " " + _this.camelCase(name));
          }
        } else {
          // input -> HTMLInputElement, table -> HTMLTableElement
          e.push('HTML' + _this.elementClassName(name));
        }
      });
    }
    return "extends " + e.join(',');
  },
  camelCase: function(s) {
    return (s || '').replace(/^Polymer\./, '').replace(/[^\-\w\.]/g,'').replace(/(\b|-|\.)\w/g, function (m) {
      return m.toUpperCase().replace(/[-\.]/g, '');
    });
  },
  hyphenize: function(s) {
    return s.replace(/([A-Z])/g, "-$1").toLowerCase();
  },
  computeMethodName: function(s) {
    return (s || '').replace(/-\w/g, function (m) {
      return m.toUpperCase().replace(/-/, '');
    });
  },
  computeName: function(s) {
    return (s || '').replace(/[^\w\-\.:]/g, '');
  },
  computeType: function(t) {
    if (!t) return 'Object';
    // TODO: Sometimes type have a syntax like: (number|string)
    // We should be able to overload those methods instead of using
    // Object, but JsInterop does not support well overloading
    if (/.*\|.*/.test(t)) return 'Object';
    if (/^string/i.test(t)) return 'String';
    if (/^boolean/i.test(t)) return 'boolean';
    if (/^array/i.test(t)) return 'JsArray';
    if (/^element/i.test(t)) return 'Element';
    if (/^number/i.test(t)) return 'double';
    if (/^function/i.test(t)) return 'Function';
    if (this.findBehavior(t)) {
      return this.camelCase(t);
    }
    if (this.findElement(t)) {
      return this.camelCase(t) + 'Element';
    }

    return "JavaScriptObject";
  },
  sortProperties: function(properties) {
  },
  getGettersAndSetters: function(properties) {
    // Sorting properties so no-typed and String methods are at end
    properties.sort(function(a, b) {
      var t1 = this.computeType(a.type);
      var t2 = this.computeType(b.type);
      return t1 == t2 ? 0: !a.type && b.type ? 1 : a.type && !b.type ? -1: t1 == 'String' ? 1 : -1;
    }.bind(this));
    var ret = [];
    // We use done hash to avoid generate same property with different signature (unsupported in JsInterop)
    var done = {};
    // We use cache to catch especial cases of getter/setter no defined in the
    // properties block but as 'set foo:{}, get foo:{}' pairs. The hack is that
    // first we see a method with the a valid type (setter) and then we visit
    // a method with the same name but empty type (getter).
    var cache = {};

    _.forEach(properties, function(item) {
      // We consider as properties:
      if (
          // Items with the published tag (those defined in the properties section)
          item.published ||
          // Non function items
          !item.private && item.type && !/function/i.test(item.type) ||
          // Properties defined with customized get/set syntax
          !item.type && cache[item.name] && cache[item.name].type) {

        // defined with customized get/set, if we are here is because
        // this item.type is undefined and cached one has the correct type
        item = cache[item.name] ? cache[item.name] : item;

        item.getter = item.getter || this.computeGetterWithPrefix(item);
        item.setter = item.setter || (this.computeSetterWithPrefix(item) + '(' + this.computeType(item.type) + ' value)');

        // JsInterop does not support a property with two signatures
        if (!done[item.getter]) {
          ret.push(item);
          done[item.getter] = true;
        }
      } else {
        cache[item.name] = item;
      }
    }.bind(this));
    return ret;
  },
  getStringSetters: function(properties) {
    var ret = [];
    var arr = this.getGettersAndSetters(properties);
    _.forEach(arr, function(item) {
      var itType = this.computeType(item.type) ;
      if (!/(Function|String|boolean)/.test(itType)) {
        for (var j = 0; j< arr.length; j++) {
          if (arr[j].name == item.name && arr[j].type == 'String') {
            return;
          }
        }
        ret.push(item);
      }
    }.bind(this));
    return ret;
  },
  computeSignature: function(method) {
    return method.replace(/\s+\w+\s*([,\)])/g, '$1');
  },
  getMethods: function(properties) {
    // Sorting properties so Object methods are at first
    properties.sort(function(a, b) {
      var t1 = this.typedParamsString(a);
      var t2 = this.typedParamsString(b);
      return t1 == t2 ? 0: /^Object/.test(t1) ? -1 : 1;
    }.bind(this));

    // Skip functions with name equal to a getter/setter
    var gsetters = {};
    _.forEach(properties, function(item) {
      if (item.getter) {
        gsetters[item.getter] = true;
        gsetters[item.setter] = true;
        gsetters[item.name] = true;
      }
    }.bind(this));

    var ret = [];
    var done = {};
    _.forEach(properties, function(item) {
      if (!gsetters[item.name] && !item.getter && !item.private && !item.published && /function/i.test(item.type)) {
        item.method = item.method || item.name + '(' + this.typedParamsString(item) + ')';
        // JsInterop + SDM do not support method overloading if one signature is object
        var other = item.method.replace(/String/, 'Object');
        var signature = this.computeSignature(item.method);
        var other_sig = this.computeSignature(other);
        if (!gsetters[signature] && !done[signature] && !done[other_sig]) {
          ret.push(item);
          done[signature] = true;
        }
      }
    }.bind(this));
    return ret;
  },
  removePrivateApi: function(arr, prop) {
    for (var i = arr.length - 1; i >= 0; i--) {
      if (/^(_.*|ready|created)$/.test(arr[i][prop])) {
        arr.splice(i, 1);
      }
    }
  },
  hasItems: function(array) {
    return array && array.length > 0;
  },
  hasEvents: function() {
    return this.hasItems(this.events);
  },
  hasProperties: function() {
    return this.hasItems(this.properties);
  },
  hasParams: function() {
    return this.hasItems(this.params);
  },
  capitalizeFirstLetter: function(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
  },
  computeGetterWithPrefix: function(item) {
    var name = item.name.replace(/^detail\./,'');
    // replaced isXXX methods with getXXX temporary because of bug in JsInterop
    // because in the case of isNarrow, the JS generated is something like $object.arrow
    //var prefix = /^boolean/i.test(item.type) ? 'is' : 'get';
    var prefix = 'get';
    if (this.startsWith(name, prefix)) {
      return name;
    } else {
      return prefix + this.capitalizeFirstLetter(this.computeMethodName(name));
    }
  },
  computeSetterWithPrefix: function(item) {
    return 'set' + this.capitalizeFirstLetter(this.computeMethodName(item.name));
  },
  startsWith: function (str, substr){
    return str.indexOf(substr) === 0;
  },
  signParamString: function(method) {
    if (method.type != 'Function') {
      return method.type;
    }
    var result = [];
    if (method.params) {
      method.params.forEach(function(param) {
        var type = this.computeType(param.type);
        result.push(type);
      }, this);
    }
    return result.join(',');
  },
  typedParamsString: function(method) {
    var result = [];
    if (method.params) {
      method.params.forEach(function(param) {
        var type = this.computeType(param.type);
        result.push(type + ' ' + this.computeMethodName(param.name));
      }, this);
    }
    return result.join(', ');
  },
  paramsString: function(method) {
    var result = [];
    if (method.params) {
      method.params.forEach(function(param) {
        result.push(this.computeMethodName(param.name));
      }, this);
    }
    return result.join(', ');
  },
  returnString: function(method) {
    if (method['return'] && method['return']['type']) {
      return this.computeType(method['return']['type'])
    }
    return 'void';
  },
  getDescription: function(spaces, o) {
    o = o || this;
    var desc = o.description || o.desc || '';
    desc = this.marked(desc);
    return (desc).trim().split('\n').join('\n' + spaces + '* ').replace(/\*\//g, "* /");
  },
  disclaimer: function() {
    var projectName = this.bowerData.name || "unknown";
    var projectLicense = this.bowerData.license || "unknown";

    var projectAuthors = this.bowerData.authors || this.bowerData.author;
    if (projectAuthors && projectAuthors.map) {
      projectAuthors = projectAuthors.map(function(author) {
        return author.name ? author.name : author;
      }).toString();
    }
    projectAuthors = projectAuthors || "unknown author";

    return "/*\n" +
    " * This code was generated with Vaadin Web Component GWT API Generator, \n" +
    " * from " + projectName + " project by " + projectAuthors + "\n" +
    " * that is licensed with " + projectLicense + " license.\n" +
    " */";
  },
  j2s: function(json, msg) {
    msg = msg || '';
    var cache = [];
    console.log(msg + JSON.stringify(json, function(key, value) {
        if (typeof value === 'object' && value !== null) {
            if (cache.indexOf(value) !== -1) {
                return;
            }
            cache.push(value);
        }
        return value;
    }));
  }
};
<|endoftext|>


<commit_before><commit_msg>Refactor (clean).<commit_after><|endoftext|>


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

const debug = require('debug')('strider-template:worker');

module.exports = {
  // Initialize the plugin for a job
  //   config: the config for this job, made by extending the DB config
  //           with any flat-file config
  //   job:    see strider-runner-core for a description of that object
  //   context: currently only defines "dataDir"
  //   cb(err, initializedPlugin)
  init: function (config, job, context, cb) {
    return cb(null, {
      // any extra env variables. Will be available during all phases
      env: {
        test_results: {},
        error: false
      },
      listen: function (emitter, context) {
      },
      test: function (context, done) {
        var self = this;
        context.cmd({
          cmd: "istanbul cover -x '**/node_modules/**' _mocha --  -R mocha-spec-json-reporter"
        }, function (err, stdout) {
          if(err){
            self.env.error = true;
          }
          fs.readFile('mocha-output.json', function (err, data) {
            console.log('DATA', data);
            var jsonObject = JSON.parse(data);
            self.env.test_results = jsonObject;
            if(self.env.error) return done(err);
            done();
          });
        });
      }
    });
  }
};
<commit_msg>changes<commit_after>'use strict';
var fs = require('fs');

const debug = require('debug')('strider-template:worker');

module.exports = {
  // Initialize the plugin for a job
  //   config: the config for this job, made by extending the DB config
  //           with any flat-file config
  //   job:    see strider-runner-core for a description of that object
  //   context: currently only defines "dataDir"
  //   cb(err, initializedPlugin)
  init: function (config, job, context, cb) {
    return cb(null, {
      // any extra env variables. Will be available during all phases
      env: {
        test_results: {},
        error: false
      },
      listen: function (emitter, context) {
      },
      test: function (context, done) {
        var self = this;
        context.cmd({
          cmd: "istanbul cover -x '**/node_modules/**' _mocha --  -R mocha-spec-json-reporter"
        }, function (err, stdout) {
          if(err){
            self.env.error = true;
          }
          fs.readFile('./mocha-output.json', function (err, data) {
            console.log('DATA', data);
            var jsonObject = JSON.parse(data);
            self.env.test_results = jsonObject;
            if(self.env.error) return done(err);
            done();
          });
        });
      }
    });
  }
};
<|endoftext|>


<commit_before>/**
 * @author bhouston / http://exocortex.com
 */

THREE.Ray = function ( origin, direction ) {

	this.origin = ( origin !== undefined ) ? origin : new THREE.Vector3();
	this.direction = ( direction !== undefined ) ? direction : new THREE.Vector3();

};

THREE.Ray.prototype = {

	constructor: THREE.Ray,

	set: function ( origin, direction ) {

		this.origin.copy( origin );
		this.direction.copy( direction );

		return this;

	},

	copy: function ( ray ) {

		this.origin.copy( ray.origin );
		this.direction.copy( ray.direction );

		return this;

	},

	at: function ( t, optionalTarget ) {

		var result = optionalTarget || new THREE.Vector3();

		return result.copy( this.direction ).multiplyScalar( t ).add( this.origin );

	},

	recast: function () {

		var v1 = new THREE.Vector3();

		return function ( t ) {

			this.origin.copy( this.at( t, v1 ) );

			return this;

		};

	}(),

	closestPointToPoint: function ( point, optionalTarget ) {

		var result = optionalTarget || new THREE.Vector3();
		result.subVectors( point, this.origin );
		var directionDistance = result.dot( this.direction );

		if ( directionDistance < 0 ) {

			return result.copy( this.origin );

		}

		return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );

	},

	distanceToPoint: function () {

		var v1 = new THREE.Vector3();

		return function ( point ) {

			var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );

			// point behind the ray

			if ( directionDistance < 0 ) {

				return this.origin.distanceTo( point );

			}

			v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );

			return v1.distanceTo( point );

		};

	}(),

	distanceSqToSegment: function( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {

		// from http://www.geometrictools.com/LibMathematics/Distance/Wm5DistRay3Segment3.cpp
		// It returns the min distance between the ray and the segment
		// defined by v0 and v1
		// It can also set two optional targets :
		// - The closest point on the ray
		// - The closest point on the segment

		var segCenter = v0.clone().add( v1 ).multiplyScalar( 0.5 );
		var segDir = v1.clone().sub( v0 ).normalize();
		var segExtent = v0.distanceTo( v1 ) * 0.5;
		var diff = this.origin.clone().sub( segCenter );
		var a01 = - this.direction.dot( segDir );
		var b0 = diff.dot( this.direction );
		var b1 = - diff.dot( segDir );
		var c = diff.lengthSq();
		var det = Math.abs( 1 - a01 * a01 );
		var s0, s1, sqrDist, extDet;

		if ( det >= 0 ) {

			// The ray and segment are not parallel.

			s0 = a01 * b1 - b0;
			s1 = a01 * b0 - b1;
			extDet = segExtent * det;

			if ( s0 >= 0 ) {

				if ( s1 >= - extDet ) {

					if ( s1 <= extDet ) {

						// region 0
						// Minimum at interior points of ray and segment.

						var invDet = 1 / det;
						s0 *= invDet;
						s1 *= invDet;
						sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;

					} else {

						// region 1

						s1 = segExtent;
						s0 = Math.max( 0, - ( a01 * s1 + b0) );
						sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;

					}

				} else {

					// region 5

					s1 = - segExtent;
					s0 = Math.max( 0, - ( a01 * s1 + b0) );
					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;

				}

			} else {

				if ( s1 <= - extDet) {

					// region 4

					s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
					s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;

				} else if ( s1 <= extDet ) {

					// region 3

					s0 = 0;
					s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
					sqrDist = s1 * ( s1 + 2 * b1 ) + c;

				} else {

					// region 2

					s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
					s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;

				}

			}

		} else {

			// Ray and segment are parallel.

			s1 = ( a01 > 0 ) ? - segExtent : segExtent;
			s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
			sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;

		}

		if ( optionalPointOnRay ) {

			optionalPointOnRay.copy( this.direction.clone().multiplyScalar( s0 ).add( this.origin ) );

		}

		if ( optionalPointOnSegment ) {

			optionalPointOnSegment.copy( segDir.clone().multiplyScalar( s1 ).add( segCenter ) );

		}

		return sqrDist;

	},

	isIntersectionSphere: function ( sphere ) {

		return this.distanceToPoint( sphere.center ) <= sphere.radius;

	},

	intersectSphere: function () {

		// from http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-sphere-intersection/

		var v1 = new THREE.Vector3();

		return function ( sphere, optionalTarget ) {

			v1.subVectors( sphere.center, this.origin );

			var tca = v1.dot( this.direction );

			if ( tca < 0 ) return null;

			var d2 = v1.dot( v1 ) - tca * tca;

			var radius2 = sphere.radius * sphere.radius;

			if ( d2 > radius2 ) return null;

			var thc = Math.sqrt( radius2 - d2 );

			// t0 = first intersect point - entrance on front of sphere
			var t0 = tca - thc;

			// t1 = second intersect point - exit point on back of sphere
			var t1 = tca + thc;

			// test to see if t0 is behind the ray:
			// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
			// in order to always return an intersect point that is in front of the ray.
			if (t0 < 0) return this.at( t1, optionalTarget );

			// else t0 is in front of the ray, so return the first collision point scaled by t0
			return this.at( t0, optionalTarget );

		}

	}(),

	isIntersectionPlane: function ( plane ) {

		// check if the ray lies on the plane first

		var distToPoint = plane.distanceToPoint( this.origin );

		if ( distToPoint === 0 ) {

			return true;

		}

		var denominator = plane.normal.dot( this.direction );

		if ( denominator * distToPoint < 0 ) {

			return true;

		}

		// ray origin is behind the plane (and is pointing behind it)

		return false;

	},

	distanceToPlane: function ( plane ) {

		var denominator = plane.normal.dot( this.direction );
		if ( denominator == 0 ) {

			// line is coplanar, return origin
			if( plane.distanceToPoint( this.origin ) == 0 ) {

				return 0;

			}

			// Null is preferable to undefined since undefined means.... it is undefined

			return null;

		}

		var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;

		// Return if the ray never intersects the plane

		return t >= 0 ? t :  null;

	},

	intersectPlane: function ( plane, optionalTarget ) {

		var t = this.distanceToPlane( plane );

		if ( t === null ) {

			return null;
		}

		return this.at( t, optionalTarget );

	},

	isIntersectionBox: function () {

		var v = new THREE.Vector3();

		return function ( box ) {

			return this.intersectBox( box, v ) !== null;

		};

	}(),

	intersectBox: function ( box , optionalTarget ) {

		// http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-box-intersection/

		var tmin,tmax,tymin,tymax,tzmin,tzmax;

		var invdirx = 1/this.direction.x,
			invdiry = 1/this.direction.y,
			invdirz = 1/this.direction.z;

		var origin = this.origin;

		if (invdirx >= 0) {

			tmin = (box.min.x - origin.x) * invdirx;
			tmax = (box.max.x - origin.x) * invdirx;

		} else {

			tmin = (box.max.x - origin.x) * invdirx;
			tmax = (box.min.x - origin.x) * invdirx;
		}

		if (invdiry >= 0) {

			tymin = (box.min.y - origin.y) * invdiry;
			tymax = (box.max.y - origin.y) * invdiry;

		} else {

			tymin = (box.max.y - origin.y) * invdiry;
			tymax = (box.min.y - origin.y) * invdiry;
		}

		if ((tmin > tymax) || (tymin > tmax)) return null;

		// These lines also handle the case where tmin or tmax is NaN
		// (result of 0 * Infinity). x !== x returns true if x is NaN

		if (tymin > tmin || tmin !== tmin ) tmin = tymin;

		if (tymax < tmax || tmax !== tmax ) tmax = tymax;

		if (invdirz >= 0) {

			tzmin = (box.min.z - origin.z) * invdirz;
			tzmax = (box.max.z - origin.z) * invdirz;

		} else {

			tzmin = (box.max.z - origin.z) * invdirz;
			tzmax = (box.min.z - origin.z) * invdirz;
		}

		if ((tmin > tzmax) || (tzmin > tmax)) return null;

		if (tzmin > tmin || tmin !== tmin ) tmin = tzmin;

		if (tzmax < tmax || tmax !== tmax ) tmax = tzmax;

		//return point closest to the ray (positive side)

		if ( tmax < 0 ) return null;

		return this.at( tmin >= 0 ? tmin : tmax, optionalTarget );

	},

	intersectTriangle: function() {

		// Compute the offset origin, edges, and normal.
		var diff = new THREE.Vector3();
		var edge1 = new THREE.Vector3();
		var edge2 = new THREE.Vector3();
		var normal = new THREE.Vector3();

		return function ( a, b, c, backfaceCulling, optionalTarget ) {

			// from http://www.geometrictools.com/LibMathematics/Intersection/Wm5IntrRay3Triangle3.cpp

			edge1.subVectors( b, a );
			edge2.subVectors( c, a );
			normal.crossVectors( edge1, edge2 );

			// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
			// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
			//   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
			//   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
			//   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
			var DdN = this.direction.dot( normal );
			var sign;

			if ( DdN > 0 ) {

				if ( backfaceCulling ) return null;
				sign = 1;

			} else if ( DdN < 0 ) {

				sign = - 1;
				DdN = - DdN;

			} else {

				return null;

			}

			diff.subVectors( this.origin, a );
			var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );

			// b1 < 0, no intersection
			if ( DdQxE2 < 0 ) {

				return null;

			}

			var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );

			// b2 < 0, no intersection
			if ( DdE1xQ < 0 ) {

				return null;

			}

			// b1+b2 > 1, no intersection
			if ( DdQxE2 + DdE1xQ > DdN ) {

				return null;

			}

			// Line intersects triangle, check if ray does.
			var QdN = - sign * diff.dot( normal );

			// t < 0, no intersection
			if ( QdN < 0 ) {

				return null;

			}

			// Ray intersects triangle.
			return this.at( QdN / DdN, optionalTarget );

		};

	}(),

	applyMatrix4: function ( matrix4 ) {

		this.direction.add( this.origin ).applyMatrix4( matrix4 );
		this.origin.applyMatrix4( matrix4 );
		this.direction.sub( this.origin );
		this.direction.normalize();

		return this;
	},

	equals: function ( ray ) {

		return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );

	},

	clone: function () {

		return new THREE.Ray().copy( this );

	}

};
<commit_msg>whitespace<commit_after>/**
 * @author bhouston / http://exocortex.com
 */

THREE.Ray = function ( origin, direction ) {

	this.origin = ( origin !== undefined ) ? origin : new THREE.Vector3();
	this.direction = ( direction !== undefined ) ? direction : new THREE.Vector3();

};

THREE.Ray.prototype = {

	constructor: THREE.Ray,

	set: function ( origin, direction ) {

		this.origin.copy( origin );
		this.direction.copy( direction );

		return this;

	},

	copy: function ( ray ) {

		this.origin.copy( ray.origin );
		this.direction.copy( ray.direction );

		return this;

	},

	at: function ( t, optionalTarget ) {

		var result = optionalTarget || new THREE.Vector3();

		return result.copy( this.direction ).multiplyScalar( t ).add( this.origin );

	},

	recast: function () {

		var v1 = new THREE.Vector3();

		return function ( t ) {

			this.origin.copy( this.at( t, v1 ) );

			return this;

		};

	}(),

	closestPointToPoint: function ( point, optionalTarget ) {

		var result = optionalTarget || new THREE.Vector3();
		result.subVectors( point, this.origin );
		var directionDistance = result.dot( this.direction );

		if ( directionDistance < 0 ) {

			return result.copy( this.origin );

		}

		return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );

	},

	distanceToPoint: function () {

		var v1 = new THREE.Vector3();

		return function ( point ) {

			var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );

			// point behind the ray

			if ( directionDistance < 0 ) {

				return this.origin.distanceTo( point );

			}

			v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );

			return v1.distanceTo( point );

		};

	}(),

	distanceSqToSegment: function( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {

		// from http://www.geometrictools.com/LibMathematics/Distance/Wm5DistRay3Segment3.cpp
		// It returns the min distance between the ray and the segment
		// defined by v0 and v1
		// It can also set two optional targets :
		// - The closest point on the ray
		// - The closest point on the segment

		var segCenter = v0.clone().add( v1 ).multiplyScalar( 0.5 );
		var segDir = v1.clone().sub( v0 ).normalize();
		var segExtent = v0.distanceTo( v1 ) * 0.5;
		var diff = this.origin.clone().sub( segCenter );
		var a01 = - this.direction.dot( segDir );
		var b0 = diff.dot( this.direction );
		var b1 = - diff.dot( segDir );
		var c = diff.lengthSq();
		var det = Math.abs( 1 - a01 * a01 );
		var s0, s1, sqrDist, extDet;

		if ( det >= 0 ) {

			// The ray and segment are not parallel.

			s0 = a01 * b1 - b0;
			s1 = a01 * b0 - b1;
			extDet = segExtent * det;

			if ( s0 >= 0 ) {

				if ( s1 >= - extDet ) {

					if ( s1 <= extDet ) {

						// region 0
						// Minimum at interior points of ray and segment.

						var invDet = 1 / det;
						s0 *= invDet;
						s1 *= invDet;
						sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;

					} else {

						// region 1

						s1 = segExtent;
						s0 = Math.max( 0, - ( a01 * s1 + b0) );
						sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;

					}

				} else {

					// region 5

					s1 = - segExtent;
					s0 = Math.max( 0, - ( a01 * s1 + b0) );
					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;

				}

			} else {

				if ( s1 <= - extDet) {

					// region 4

					s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
					s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;

				} else if ( s1 <= extDet ) {

					// region 3

					s0 = 0;
					s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
					sqrDist = s1 * ( s1 + 2 * b1 ) + c;

				} else {

					// region 2

					s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
					s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;

				}

			}

		} else {

			// Ray and segment are parallel.

			s1 = ( a01 > 0 ) ? - segExtent : segExtent;
			s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
			sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;

		}

		if ( optionalPointOnRay ) {

			optionalPointOnRay.copy( this.direction.clone().multiplyScalar( s0 ).add( this.origin ) );

		}

		if ( optionalPointOnSegment ) {

			optionalPointOnSegment.copy( segDir.clone().multiplyScalar( s1 ).add( segCenter ) );

		}

		return sqrDist;

	},

	isIntersectionSphere: function ( sphere ) {

		return this.distanceToPoint( sphere.center ) <= sphere.radius;

	},

	intersectSphere: function () {

		// from http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-sphere-intersection/

		var v1 = new THREE.Vector3();

		return function ( sphere, optionalTarget ) {

			v1.subVectors( sphere.center, this.origin );

			var tca = v1.dot( this.direction );

			if ( tca < 0 ) return null;

			var d2 = v1.dot( v1 ) - tca * tca;

			var radius2 = sphere.radius * sphere.radius;

			if ( d2 > radius2 ) return null;

			var thc = Math.sqrt( radius2 - d2 );

			// t0 = first intersect point - entrance on front of sphere
			var t0 = tca - thc;

			// t1 = second intersect point - exit point on back of sphere
			var t1 = tca + thc;

			// test to see if t0 is behind the ray:
			// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
			// in order to always return an intersect point that is in front of the ray.
			if ( t0 < 0 ) return this.at( t1, optionalTarget );

			// else t0 is in front of the ray, so return the first collision point scaled by t0
			return this.at( t0, optionalTarget );

		}

	}(),

	isIntersectionPlane: function ( plane ) {

		// check if the ray lies on the plane first

		var distToPoint = plane.distanceToPoint( this.origin );

		if ( distToPoint === 0 ) {

			return true;

		}

		var denominator = plane.normal.dot( this.direction );

		if ( denominator * distToPoint < 0 ) {

			return true;

		}

		// ray origin is behind the plane (and is pointing behind it)

		return false;

	},

	distanceToPlane: function ( plane ) {

		var denominator = plane.normal.dot( this.direction );
		if ( denominator == 0 ) {

			// line is coplanar, return origin
			if( plane.distanceToPoint( this.origin ) == 0 ) {

				return 0;

			}

			// Null is preferable to undefined since undefined means.... it is undefined

			return null;

		}

		var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;

		// Return if the ray never intersects the plane

		return t >= 0 ? t :  null;

	},

	intersectPlane: function ( plane, optionalTarget ) {

		var t = this.distanceToPlane( plane );

		if ( t === null ) {

			return null;
		}

		return this.at( t, optionalTarget );

	},

	isIntersectionBox: function () {

		var v = new THREE.Vector3();

		return function ( box ) {

			return this.intersectBox( box, v ) !== null;

		};

	}(),

	intersectBox: function ( box , optionalTarget ) {

		// http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-box-intersection/

		var tmin,tmax,tymin,tymax,tzmin,tzmax;

		var invdirx = 1/this.direction.x,
			invdiry = 1/this.direction.y,
			invdirz = 1/this.direction.z;

		var origin = this.origin;

		if (invdirx >= 0) {

			tmin = (box.min.x - origin.x) * invdirx;
			tmax = (box.max.x - origin.x) * invdirx;

		} else {

			tmin = (box.max.x - origin.x) * invdirx;
			tmax = (box.min.x - origin.x) * invdirx;
		}

		if (invdiry >= 0) {

			tymin = (box.min.y - origin.y) * invdiry;
			tymax = (box.max.y - origin.y) * invdiry;

		} else {

			tymin = (box.max.y - origin.y) * invdiry;
			tymax = (box.min.y - origin.y) * invdiry;
		}

		if ((tmin > tymax) || (tymin > tmax)) return null;

		// These lines also handle the case where tmin or tmax is NaN
		// (result of 0 * Infinity). x !== x returns true if x is NaN

		if (tymin > tmin || tmin !== tmin ) tmin = tymin;

		if (tymax < tmax || tmax !== tmax ) tmax = tymax;

		if (invdirz >= 0) {

			tzmin = (box.min.z - origin.z) * invdirz;
			tzmax = (box.max.z - origin.z) * invdirz;

		} else {

			tzmin = (box.max.z - origin.z) * invdirz;
			tzmax = (box.min.z - origin.z) * invdirz;
		}

		if ((tmin > tzmax) || (tzmin > tmax)) return null;

		if (tzmin > tmin || tmin !== tmin ) tmin = tzmin;

		if (tzmax < tmax || tmax !== tmax ) tmax = tzmax;

		//return point closest to the ray (positive side)

		if ( tmax < 0 ) return null;

		return this.at( tmin >= 0 ? tmin : tmax, optionalTarget );

	},

	intersectTriangle: function() {

		// Compute the offset origin, edges, and normal.
		var diff = new THREE.Vector3();
		var edge1 = new THREE.Vector3();
		var edge2 = new THREE.Vector3();
		var normal = new THREE.Vector3();

		return function ( a, b, c, backfaceCulling, optionalTarget ) {

			// from http://www.geometrictools.com/LibMathematics/Intersection/Wm5IntrRay3Triangle3.cpp

			edge1.subVectors( b, a );
			edge2.subVectors( c, a );
			normal.crossVectors( edge1, edge2 );

			// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
			// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
			//   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
			//   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
			//   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
			var DdN = this.direction.dot( normal );
			var sign;

			if ( DdN > 0 ) {

				if ( backfaceCulling ) return null;
				sign = 1;

			} else if ( DdN < 0 ) {

				sign = - 1;
				DdN = - DdN;

			} else {

				return null;

			}

			diff.subVectors( this.origin, a );
			var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );

			// b1 < 0, no intersection
			if ( DdQxE2 < 0 ) {

				return null;

			}

			var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );

			// b2 < 0, no intersection
			if ( DdE1xQ < 0 ) {

				return null;

			}

			// b1+b2 > 1, no intersection
			if ( DdQxE2 + DdE1xQ > DdN ) {

				return null;

			}

			// Line intersects triangle, check if ray does.
			var QdN = - sign * diff.dot( normal );

			// t < 0, no intersection
			if ( QdN < 0 ) {

				return null;

			}

			// Ray intersects triangle.
			return this.at( QdN / DdN, optionalTarget );

		};

	}(),

	applyMatrix4: function ( matrix4 ) {

		this.direction.add( this.origin ).applyMatrix4( matrix4 );
		this.origin.applyMatrix4( matrix4 );
		this.direction.sub( this.origin );
		this.direction.normalize();

		return this;
	},

	equals: function ( ray ) {

		return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );

	},

	clone: function () {

		return new THREE.Ray().copy( this );

	}

};
<|endoftext|>


<commit_before>describe('proxies', function(){

  describe('making proxies', function(){

    it('adds a bound() function to the global scope', function(){
      expect(B).to.be.a('function');
    });

    it('provides a helper to identify bound methods', function(){
      expect(bound.isBoundMethod(function(){})).to.be(false);
      expect(bound.isBoundMethod(B({}))).to.be(true);
    });

    it('should return the input object as a result of calling bound()', function(){
      expect(B(alice)).to.equal(alice.bound);
    });

    it('should augment objects passed into B() with a .bound() method', function(){
      expect( B({}) ).to.be.a('function');
    });

    it('should throw an error if a non bound method is already stored at the key "bound" and B() is called on it', function(){
      expect(function(){
        B({bound:3});
      }).to.throwException();
    });

    it('should not throw an error if a bound method is already stored at the key "bound" and bound is called on it', function(){
      expect(function(){
        B(alice);
        B(alice);
      }).not.to.throwException();
    });

    // regression test
    it('should not throw an error if you try to proxy an object that has a target property', function(){
      expect(function() {
        B({target:3});
      }).not.to.throwException();
    });

    it('should put a unique bound method on each proxied object', function(){
      expect(B({})).not.to.be(B({}));
    });

    it('should provide the same method if the same object is passed in twice', function(){
      expect(B(alice)).to.equal(B(alice));
    });

    it('should not provide the same bound method for a child as the one available on its prototype', function(){
      expect(B(child)).not.to.equal(B(parent));
    });

    it('should not add any properties to a object other than .bound()', function(){
      var object = {};
      B(object);
      expect(object).to.only.have.keys(['bound']);
    });

    it('should not allow proxying proxy objects', function(){
      expect(function() {
        var proxy = B(empty);
        B(proxy);
      }).to.throwException();
    });

  });

  describe('iteration', function(){

    xit('skips .bound methods');

    xit('does not skip .bound properties that are not bound methods');

    xit('does not skip bound methods stored at keys besides .bound');

  });

  describe('applying to bound method between contexts', function(){

    it('should not allow the bound method of one object to be called in the context of another object', function(){
      // todo: long term, this should actually just have the effect of calling the bound method of the target object instead
      expect(function(){
        B(alice).apply(bob);
      }).to.throwException();
    });

    it('throws an error when a .bound() method is called on its associated object, but the method is not found on the target at the key \'bound\'', function(){
      var removedMethod = B(alice);
      delete alice.bound;
      expect(function(){
        removedMethod.apply(alice);
      }).to.throwException();

      alice.bound = function(){};
      expect(function(){
        removedMethod.apply(alice);
      }).to.throwException();

      alice.wrongkey = removedMethod;
      expect(function(){
        alice.wrongKey();
      }).to.throwException();
    });

    it('should augment child objects with their own .bound() property when a call to .bound() delegates through to the prototype object', function(){
      B(parent);
      expect(parent.bound).to.equal(child.bound);
      child.bound(); // delegates to parent.bound()
      expect(parent.bound).not.to.equal(child.bound);
    });

  });

  describe('bound proxy object methods', function(){

    it('should allow access to a proxy object by calling the "getProxy" command', function(){
      var proxy = B({}).getProxy();
      var proxyMethods = 'get set del has owns run exec pub sub getProxy meta'.split(' ');
      _.each(proxyMethods, function(methodName){
        var randomNumber = Math.random();
        expect(proxy[methodName]).to.be.a('function');
        sinon.spy(proxy, methodName);
        proxy[methodName](randomNumber);
        expect(proxy[methodName].calledWith(randomNumber)).to.be(true);
      });
    });

    it('should get the value of properties from the target object when you run the get command', function(){
      var object = B(alice);
      expect(B(alice).get('name')).to.equal('alice');
    });

    it('should set the value of properties from the target object when you run the set command', function(){
      B(alice);
      B(alice).set('name', 'al');
      expect(alice.name).to.equal('al');
    });

    it('should delete properties from the target object when you run the del command', function(){
      B(alice);
      B(alice).del('name');
      expect(B(alice).get('name')).to.equal(undefined);
      expect(alice.hasOwnProperty('setThing')).not.to.be(true);
    });

    xit('should re-run work that was dependent on calls to "has" after deleting properties that used to exist');

    xit('should re-run work that was dependent on calls to "has" after setting properties that didnt\'t used to exist');

    it('should return the presence or absence of a property on the target object when you run the has command', function(){
      B(message);
      expect(B(message).has('text')).to.be(true);
      expect(B(message).has('unicorns')).to.be(false);
    });

    it('should return the immediate presence or absence of a property (not prototype-inherited) on the target object when you run the owns command', function(){
      B(parent).set('prop', 2);
      expect(B(child).owns('prop')).to.be(false);
      B(child).set('prop', 2);
      expect(B(child).owns('prop')).to.be(true);
    });

    xit('todo: need to provide a way for users to run a function or a method in an arbitrary context');

    xit('should run the specified method (in the context of the target object) when you run the run command, and should return the result');

    xit('should run the target function object (in the context of window) when you run the exec command, and should return the result');

    xit('todo: should provide an eventing system, including publish and subscribe');

    xit('should add meta data about the target object to the proxy object when you call the meta command');
  });

  describe('updates to depended-upon properties', function(){

    xit('should let you invalidate listeners for one key by exposing a bound() command "changed"', function(){
      var runCount = 0;
      bound.autorun(function() {
        B(alice).get('name');
        runCount++;
      });
      expect(runCount).to.equal(1);
      alice.name = 'al';
      B(alice).changed('name');
      clock.tick(0);
      expect(runCount).to.equal(2);
      alice.age = 21;
      B(alice).changed('age');
      clock.tick(0);
      expect(runCount).to.equal(2);
    });

    xit('should update only the values associated with specified keys', function(){
    });

    xit('should expire all dependent computations when called with no command name', function(){
    });

    xit('should not result in re-runs of dependent contexts for setting properties to the same value they already hold', function(){

    });

    it('should not re-run properties dependent on key inclusion when only the property value has changed, not its presence in the object', function(){
      // todo: tursify
      B(alice);
      var runCount1 = 0;
      bound.autorun(function(){
        B(alice).has('hamburger');
        runCount1 += 1;
      });
      var runCount2 = 0;
      bound.autorun(function(){
        B(alice).get('name');
        runCount2 += 1;
      });
      B(alice).set('name', 'al');
      clock.tick(0);
      expect([runCount1, runCount2]).to.eql([1, 2]);
    });

    it('errors when passed an invalid command name', function(){
      expect(function(){
        B({}).invalidCommand();
      }).to.throwException();
    });

  });

});
<commit_msg>Replaced test object with fixture<commit_after>describe('proxies', function(){

  describe('making proxies', function(){

    it('adds a bound() function to the global scope', function(){
      expect(B).to.be.a('function');
    });

    it('provides a helper to identify bound methods', function(){
      expect(bound.isBoundMethod(function(){})).to.be(false);
      expect(bound.isBoundMethod(B({}))).to.be(true);
    });

    it('should return the input object as a result of calling bound()', function(){
      expect(B(alice)).to.equal(alice.bound);
    });

    it('should augment objects passed into B() with a .bound() method', function(){
      expect( B({}) ).to.be.a('function');
    });

    it('should throw an error if a non bound method is already stored at the key "bound" and B() is called on it', function(){
      expect(function(){
        B({bound:3});
      }).to.throwException();
    });

    it('should not throw an error if a bound method is already stored at the key "bound" and bound is called on it', function(){
      expect(function(){
        B(alice);
        B(alice);
      }).not.to.throwException();
    });

    // regression test
    it('should not throw an error if you try to proxy an object that has a target property', function(){
      expect(function() {
        B({target:3});
      }).not.to.throwException();
    });

    it('should put a unique bound method on each proxied object', function(){
      expect(B({})).not.to.be(B({}));
    });

    it('should provide the same method if the same object is passed in twice', function(){
      expect(B(alice)).to.equal(B(alice));
    });

    it('should not provide the same bound method for a child as the one available on its prototype', function(){
      expect(B(child)).not.to.equal(B(parent));
    });

    it('should not add any properties to a object other than .bound()', function(){
      B(empty);
      expect(empty).to.only.have.keys(['bound']);
    });

    it('should not allow proxying proxy objects', function(){
      expect(function() {
        var proxy = B(empty);
        B(proxy);
      }).to.throwException();
    });

  });

  describe('iteration', function(){

    xit('skips .bound methods');

    xit('does not skip .bound properties that are not bound methods');

    xit('does not skip bound methods stored at keys besides .bound');

  });

  describe('applying to bound method between contexts', function(){

    it('should not allow the bound method of one object to be called in the context of another object', function(){
      // todo: long term, this should actually just have the effect of calling the bound method of the target object instead
      expect(function(){
        B(alice).apply(bob);
      }).to.throwException();
    });

    it('throws an error when a .bound() method is called on its associated object, but the method is not found on the target at the key \'bound\'', function(){
      var removedMethod = B(alice);
      delete alice.bound;
      expect(function(){
        removedMethod.apply(alice);
      }).to.throwException();

      alice.bound = function(){};
      expect(function(){
        removedMethod.apply(alice);
      }).to.throwException();

      alice.wrongkey = removedMethod;
      expect(function(){
        alice.wrongKey();
      }).to.throwException();
    });

    it('should augment child objects with their own .bound() property when a call to .bound() delegates through to the prototype object', function(){
      B(parent);
      expect(parent.bound).to.equal(child.bound);
      child.bound(); // delegates to parent.bound()
      expect(parent.bound).not.to.equal(child.bound);
    });

  });

  describe('bound proxy object methods', function(){

    it('should allow access to a proxy object by calling the "getProxy" command', function(){
      var proxy = B({}).getProxy();
      var proxyMethods = 'get set del has owns run exec pub sub getProxy meta'.split(' ');
      _.each(proxyMethods, function(methodName){
        var randomNumber = Math.random();
        expect(proxy[methodName]).to.be.a('function');
        sinon.spy(proxy, methodName);
        proxy[methodName](randomNumber);
        expect(proxy[methodName].calledWith(randomNumber)).to.be(true);
      });
    });

    it('should get the value of properties from the target object when you run the get command', function(){
      var object = B(alice);
      expect(B(alice).get('name')).to.equal('alice');
    });

    it('should set the value of properties from the target object when you run the set command', function(){
      B(alice);
      B(alice).set('name', 'al');
      expect(alice.name).to.equal('al');
    });

    it('should delete properties from the target object when you run the del command', function(){
      B(alice);
      B(alice).del('name');
      expect(B(alice).get('name')).to.equal(undefined);
      expect(alice.hasOwnProperty('setThing')).not.to.be(true);
    });

    xit('should re-run work that was dependent on calls to "has" after deleting properties that used to exist');

    xit('should re-run work that was dependent on calls to "has" after setting properties that didnt\'t used to exist');

    it('should return the presence or absence of a property on the target object when you run the has command', function(){
      B(message);
      expect(B(message).has('text')).to.be(true);
      expect(B(message).has('unicorns')).to.be(false);
    });

    it('should return the immediate presence or absence of a property (not prototype-inherited) on the target object when you run the owns command', function(){
      B(parent).set('prop', 2);
      expect(B(child).owns('prop')).to.be(false);
      B(child).set('prop', 2);
      expect(B(child).owns('prop')).to.be(true);
    });

    xit('todo: need to provide a way for users to run a function or a method in an arbitrary context');

    xit('should run the specified method (in the context of the target object) when you run the run command, and should return the result');

    xit('should run the target function object (in the context of window) when you run the exec command, and should return the result');

    xit('todo: should provide an eventing system, including publish and subscribe');

    xit('should add meta data about the target object to the proxy object when you call the meta command');
  });

  describe('updates to depended-upon properties', function(){

    xit('should let you invalidate listeners for one key by exposing a bound() command "changed"', function(){
      var runCount = 0;
      bound.autorun(function() {
        B(alice).get('name');
        runCount++;
      });
      expect(runCount).to.equal(1);
      alice.name = 'al';
      B(alice).changed('name');
      clock.tick(0);
      expect(runCount).to.equal(2);
      alice.age = 21;
      B(alice).changed('age');
      clock.tick(0);
      expect(runCount).to.equal(2);
    });

    xit('should update only the values associated with specified keys', function(){
    });

    xit('should expire all dependent computations when called with no command name', function(){
    });

    xit('should not result in re-runs of dependent contexts for setting properties to the same value they already hold', function(){

    });

    it('should not re-run properties dependent on key inclusion when only the property value has changed, not its presence in the object', function(){
      // todo: tursify
      B(alice);
      var runCount1 = 0;
      bound.autorun(function(){
        B(alice).has('hamburger');
        runCount1 += 1;
      });
      var runCount2 = 0;
      bound.autorun(function(){
        B(alice).get('name');
        runCount2 += 1;
      });
      B(alice).set('name', 'al');
      clock.tick(0);
      expect([runCount1, runCount2]).to.eql([1, 2]);
    });

    it('errors when passed an invalid command name', function(){
      expect(function(){
        B({}).invalidCommand();
      }).to.throwException();
    });

  });

});
<|endoftext|>