<commit_before>var request = require('request');
var fs = require('fs');
var _ = require('underscore');
var q = require('q');
/*
 * grunt-jenkins
 * https://github.com/sghill/grunt-jenkins
 *
 * Copyright (c) 2012 sghill
 * Licensed under the MIT license.
 */

module.exports = function(grunt) {

  // Please see the grunt documentation for more information regarding task and
  // helper creation: https://github.com/gruntjs/grunt/blob/master/docs/toc.md

  // ==========================================================================
  // TASKS
  // ==========================================================================

  var SERVER = 'http://192.168.241.137';
  var PIPELINE_DIRECTORY = 'pipeline';

  function logJobName(job) {
    grunt.log.writeln(job.name);
  }

  function logError(e) {
    grunt.log.error(e);
  }

  function isLast(item, collection) {
    return _.isEqual(item, _.last(collection));
  }

  grunt.registerTask('jenkins-list-projects', 'list projects on jenkins server', function() {
    var done = this.async();
    grunt.helper('getProjectNames', logJobName, done);
 });

  grunt.registerTask('jenkins-backup-configs', 'backup listed projects on jenkins server', function() {
    var done = this.async();
    request(SERVER + '/api/json', function(e, r, body) {
      var isSuccess = !e && r.statusCode === 200;
      if(isSuccess) {
        var jobs = JSON.parse(body).jobs;

        _.each(jobs, function(job) {
          var jobConfigurationUrl = [job.url, 'config.xml'].join('/');

          request(jobConfigurationUrl, function(e, r, body) {
            var directoryName = [PIPELINE_DIRECTORY, job.name].join('/');
            var filename = [PIPELINE_DIRECTORY, job.name, 'config.xml'].join('/');

            if(!fs.existsSync(PIPELINE_DIRECTORY)) {
              fs.mkdirSync(PIPELINE_DIRECTORY);
            }

            if(!fs.existsSync(directoryName)) {
              fs.mkdirSync(directoryName);
            }

            fs.writeFile(filename, body, 'utf8', function(err) {
              if(err) { throw err; }

              grunt.log.writeln('created file: ' + filename);
              if(isLast(job, jobs)) {
                done(isSuccess);
              }
            });

          });
        });

      }
    });
  });

  function withDot(filename) {
    return /\./.test(filename);
  }

  function fetchDirectoriesOf(directory) {
    var deferred = q.defer();
    fs.readdir(directory, function(e, contents) {
      if(e) {
        return deferred.reject(e);
      }
      // assumption: we don't have periods in our job names
      var directories = _.reject(contents, withDot);
      return deferred.resolve(directories);
    });
    return deferred.promise;
  }

  function fetchJobConfigurationStrategy(job) {
    var deferred = q.defer();
    var url = [SERVER, 'job', job, 'config.xml'].join('/');
    request(url, function(e, r, b) {
      var strategy = r.statusCode === 200 ? 'update' : 'create';
      grunt.log.writeln(strategy + ': ' + job);
      deferred.resolve({strategy: strategy, jobName: job});
    });
    return deferred.promise;
  }

  function fetchFileContents (fileAndJob) {
    var deferred = q.defer();
    fs.readFile(fileAndJob.fileName, function(e, contents) {
      if(e) {
        return deferred.reject(e);
      }
      return deferred.resolve({fileContents: contents, jobName: fileAndJob.jobName });
    })
    return deferred.promise;
  }

  function createJob (config) {
    var deferred = q.defer();
    var options = {
      url: [SERVER, 'createItem'].join('/'),
      method: 'POST',
      qs: {
        name: config.jobName
      },
      headers: {
        'Content-Type': 'text/xml'
      },
      body: config.fileContents
    };
    request(options, function(e, r, b) {
      if(e) { return deferred.reject(e); }
      return deferred.resolve(r.statusCode === 200);
    })
    return deferred.promise;
  }

  function updateJob (config) {
    var deferred = q.defer();
    var options = {
      url: [SERVER, 'job', config.jobName, 'config.xml'].join('/'),
      method: 'POST',
      body: config.fileContents
    }
    request(options, function(e, r, b) {
      if(e) { return deferred.reject(e); }
      return deferred.resolve(r.statusCode === 200);
    });

    return deferred.promise;
  }

  function applyStrategy (strategyObj) {
    var deferred = q.defer();
    var filename = [PIPELINE_DIRECTORY, strategyObj.jobName, 'config.xml'].join('/');
    var fileStrategy = {fileName: filename, jobName: strategyObj.jobName};
    if(strategyObj.strategy === 'create') {
      return fetchFileContents(fileStrategy).
        then(createJob).
        then(function(val) {
          return deferred.resolve(val);
        });
    } else if (strategyObj.strategy === 'update') {
      return fetchFileContents(fileStrategy).
        then(updateJob).
        then(function(val) {
          return deferred.resolve(val);
        });
    }
    return deferred.promise;
  }

  function createOrUpdateJobs(directories) {
    var deferred = q.defer();

    _.each(directories, function(folder) {
      var url = [SERVER, 'job', folder, 'config.xml'].join('/');
      return fetchJobConfigurationStrategy(folder).
        then(applyStrategy).
        then(function(val) {
          return deferred.resolve(val);
        });
    });

    return deferred.promise;
  }

  grunt.registerTask('jenkins-install-jobs', 'good mode', function() {
    var done = this.async();
    fetchDirectoriesOf(PIPELINE_DIRECTORY).
      then(createOrUpdateJobs).
      then(function() {
        done(true);
      }, logError).
      end();
  });

  grunt.registerTask('jenkins-install-configs', 'install backed up configurations to jenkins', function() {
    var done = this.async();
    fs.readdir(PIPELINE_DIRECTORY, function(err, files) {
      var statusCodes = [];
      _.each(files, function(folder) {
        var filename = [PIPELINE_DIRECTORY, folder, 'config.xml'].join('/');
        var url = [SERVER, 'job', folder, 'config.xml'].join('/');

        fs.stat([PIPELINE_DIRECTORY, folder].join('/'), function(e, stats) {
          if(e) { throw e; }
          if(stats.isDirectory()) {
            request(url, function(e, r, body) {
              if(r.statusCode === 200) {
                grunt.log.writeln('job ' + folder + ' exists. Will be updating at ' + url);
                fs.readFile(filename, function (err, data) {
                  if (err) throw err;
                  request({url: url, method: 'POST', body: data}, function(e, res, body) {
                    statusCodes.push(res.statusCode);
                    if(isLast(folder, files)) {
                      done(_.all(statusCodes, function(code) { return code === 200; }));
                    }
                  });
                });
              } else if(r.statusCode === 404) {
                grunt.log.writeln('job ' + folder + ' does not exist. creating it.');
                fs.readFile(filename, function (err, data) {
                  if (err) throw err;
                  var srvr =(SERVER + '/createItem');
                  request({url: srvr, method: 'POST', qs: { name: folder }, headers: { "Content-Type": "text/xml" }, body: data}, function(e, res, body) {
                    statusCodes.push(res.statusCode);
                    if(isLast(folder, files)) {
                      done(_.all(statusCodes, function(code) { return code === 200; }));
                    }
                  });
                });
              } else {
                grunt.log.error('server error? no response from ' + SERVER);
              }
            });
          } else {
            return;
          }
        });
      });
    });
  });

  // ==========================================================================
  // HELPERS
  // ==========================================================================

  grunt.registerHelper('getProjectNames', function(callback, done) {
    request(SERVER + '/api/json', function(e, r, body) {
      var isSuccess = !e & r.statusCode === 200;
      if(isSuccess) {
        var jobs = JSON.parse(body).jobs;
        jobs.forEach(callback);
      }
      done(isSuccess);
    });
  });

};
<commit_msg>not returning deferred.resolve and deferred.reject<commit_after>var request = require('request');
var fs = require('fs');
var _ = require('underscore');
var q = require('q');
/*
 * grunt-jenkins
 * https://github.com/sghill/grunt-jenkins
 *
 * Copyright (c) 2012 sghill
 * Licensed under the MIT license.
 */

module.exports = function(grunt) {

  // Please see the grunt documentation for more information regarding task and
  // helper creation: https://github.com/gruntjs/grunt/blob/master/docs/toc.md

  // ==========================================================================
  // TASKS
  // ==========================================================================

  var SERVER = 'http://192.168.241.137';
  var PIPELINE_DIRECTORY = 'pipeline';

  function logJobName(job) {
    grunt.log.writeln(job.name);
  }

  function logError(e) {
    grunt.log.error(e);
  }

  function isLast(item, collection) {
    return _.isEqual(item, _.last(collection));
  }

  grunt.registerTask('jenkins-list-projects', 'list projects on jenkins server', function() {
    var done = this.async();
    grunt.helper('getProjectNames', logJobName, done);
 });

  grunt.registerTask('jenkins-backup-configs', 'backup listed projects on jenkins server', function() {
    var done = this.async();
    request(SERVER + '/api/json', function(e, r, body) {
      var isSuccess = !e && r.statusCode === 200;
      if(isSuccess) {
        var jobs = JSON.parse(body).jobs;

        _.each(jobs, function(job) {
          var jobConfigurationUrl = [job.url, 'config.xml'].join('/');

          request(jobConfigurationUrl, function(e, r, body) {
            var directoryName = [PIPELINE_DIRECTORY, job.name].join('/');
            var filename = [PIPELINE_DIRECTORY, job.name, 'config.xml'].join('/');

            if(!fs.existsSync(PIPELINE_DIRECTORY)) {
              fs.mkdirSync(PIPELINE_DIRECTORY);
            }

            if(!fs.existsSync(directoryName)) {
              fs.mkdirSync(directoryName);
            }

            fs.writeFile(filename, body, 'utf8', function(err) {
              if(err) { throw err; }

              grunt.log.writeln('created file: ' + filename);
              if(isLast(job, jobs)) {
                done(isSuccess);
              }
            });

          });
        });

      }
    });
  });

  function withDot(filename) {
    return /\./.test(filename);
  }

  function fetchDirectoriesOf(directory) {
    var deferred = q.defer();
    fs.readdir(directory, function(e, contents) {
      if(e) { deferred.reject(e); }
      // assumption: we don't have periods in our job names
      var directories = _.reject(contents, withDot);
      deferred.resolve(directories);
    });
    return deferred.promise;
  }

  function fetchJobConfigurationStrategy(job) {
    var deferred = q.defer();
    var url = [SERVER, 'job', job, 'config.xml'].join('/');
    request(url, function(e, r, b) {
      var strategy = r.statusCode === 200 ? 'update' : 'create';
      grunt.log.writeln(strategy + ': ' + job);
      deferred.resolve({strategy: strategy, jobName: job});
    });
    return deferred.promise;
  }

  function fetchFileContents (fileAndJob) {
    var deferred = q.defer();
    fs.readFile(fileAndJob.fileName, function(e, contents) {
      if(e) { deferred.reject(e); }
      deferred.resolve({fileContents: contents, jobName: fileAndJob.jobName });
    })
    return deferred.promise;
  }

  function createJob (config) {
    var deferred = q.defer();
    var options = {
      url: [SERVER, 'createItem'].join('/'),
      method: 'POST',
      qs: {
        name: config.jobName
      },
      headers: {
        'Content-Type': 'text/xml'
      },
      body: config.fileContents
    };

    request(options, function(e, r, b) {
      if(e) { deferred.reject(e); }
      deferred.resolve(r.statusCode === 200);
    })

    return deferred.promise;
  }

  function updateJob (config) {
    var deferred = q.defer(),
        options = {
      url: [SERVER, 'job', config.jobName, 'config.xml'].join('/'),
      method: 'POST',
      body: config.fileContents
    };

    request(options, function(e, r, b) {
      if(e) { deferred.reject(e); }
      deferred.resolve(r.statusCode === 200);
    });

    return deferred.promise;
  }

  function applyStrategy (strategyObj) {
    var deferred = q.defer(),
        filename = [PIPELINE_DIRECTORY, strategyObj.jobName, 'config.xml'].join('/'),
        fileStrategy = {fileName: filename, jobName: strategyObj.jobName};

    function resolve (val) {
      deferred.resolve(val);
    }

    if(strategyObj.strategy === 'create') {
      fetchFileContents(fileStrategy).
        then(createJob).
        then(resolve);
    } else if (strategyObj.strategy === 'update') {
      fetchFileContents(fileStrategy).
        then(updateJob).
        then(resolve);
    }

    return deferred.promise;
  }

  function createOrUpdateJobs(directories) {
    var deferred = q.defer();

    function resolve (val) {
      deferred.resolve(val);
    }

    _.each(directories, function(folder) {
      fetchJobConfigurationStrategy(folder).
        then(applyStrategy).
        then(resolve);
    });

    return deferred.promise;
  }

  grunt.registerTask('jenkins-install-jobs', 'good mode', function() {
    var done = this.async();
    fetchDirectoriesOf(PIPELINE_DIRECTORY).
      then(createOrUpdateJobs).
      then(function() {
        done(true);
      }, logError).
      end();
  });

  // ==========================================================================
  // HELPERS
  // ==========================================================================

  grunt.registerHelper('getProjectNames', function(callback, done) {
    request(SERVER + '/api/json', function(e, r, body) {
      var isSuccess = !e & r.statusCode === 200;
      if(isSuccess) {
        var jobs = JSON.parse(body).jobs;
        jobs.forEach(callback);
      }
      done(isSuccess);
    });
  });

};
<|endoftext|>


<commit_before>
exports = {
    AggregateRoot : require("../lib/AggregateRoot"),
    DomainRepository : require("../lib/DomainRepository")
}

<commit_msg>Trying another<commit_after>
module.exports = exports = {
    AggregateRoot : require("../lib/AggregateRoot"),
    DomainRepository : require("../lib/DomainRepository")
}

<|endoftext|>


<commit_before>/**
* Generates button objects
* @param {array} collection coll of strings from which to create text buttons
* @return {array} array of messenger button objects
*/
function generateButtonObject(collection) {
  return collection.map((element) => ({
    content_type: 'text',
    title: element,
    payload: element,
  }));
}

/**
* Splits a locale into language and region but only returns language
* @param {string} locale a string of language_region for example: "en_GB"
* @return {string} the language part of a locale
*/
function extractLanguageFromLocale(locale) {
  const [language] = locale.split('_');
  return language;
}

// TO DO: generalise the generateButtonobjec
/**
 * Generate button template for quick Yes/No answers
 * @param {string} text the question
 * @param {string} yesTitle yes text (needed for translations)
 * @param {string} noTitle no text (needed for translations)
 * @param {string} yesPayload payload for a yes answer
 * @param {string} noPayload payload for a yes answer
 * @return {object} a messenger button template object
*/
function generateYesNoButtonTemplate(text,
                                     yesTitle,
                                     noTitle,
                                     yesPayload,
                                     noPayload) {
  return {
    attachment: {
      type: 'template',
      payload: {
        template_type: 'button',
        text,
        buttons: [{
          type: 'postback',
          title: yesTitle,
          payload: yesPayload,
        }, {
          type: 'postback',
          title: noTitle,
          payload: noPayload,
        }],
      },
    },
  };
}

/**
* Generate a messenger quick reply
* @param {string} text the question text
* @param {array} replyArray an array of up to 11 objects that is, the answers
* @return {object} a quick reply object
*/
function generateQuickReply(text, replyArray) {
  return {
    text,
    quick_replies: replyArray,
  };
}

/**
* Handle breaks in the currently running conversation
* @param {object} response the response object
* @param {object} conversation the conversation object
* @param {function} callback default function to call
* @return {function} the function to direct the conversation
*/
function conversationSwitch(response, conversation, callback) {
  switch (response.text) {
    case 'restart':
      conversation.stop('interrupted');
      return conversation.next();
    default:
      return callback;
  }
}

/**
* Go to the next conversation.
* @param {object} response the response object
* @param {object} conversation the conversation object
* @return {function} calling converationSwitch with conversation.next()
*/
function nextConversation(response, conversation) {
  return conversationSwitch(response, conversation, conversation.next());
}

/**
* Which conversation thread to go to
* @param {string} threadName the name of the thread to go to next
* @return {function} result of calling conversationSwitch with the threadName
*/
function goto(threadName) {
  return (response, conversation) => {
    conversationSwitch(response,
                         conversation,
                         conversation.gotoThread(threadName));
  };
}

/**
* Send a message to a facebookId, they have to have opted in
* @param {object} bot a bot returned from calling `spawn`
* @param {string} facebookId messenger id
* @param {function} messagecallback callback to pass to startConversation
*/
function sendMessage(bot, facebookId, messageCallback) {
  bot.startConversation({user: facebookId, channel: facebookId},
                        messageCallback);
}

module.exports = {
  extractLanguageFromLocale,
  generateButtonObject,
  nextConversation,
  goto,
  generateYesNoButtonTemplate,
  generateQuickReply,
  sendMessage,
};
<commit_msg>add more text to interrupt the conversation<commit_after>/**
* Generates button objects
* @param {array} collection coll of strings from which to create text buttons
* @return {array} array of messenger button objects
*/
function generateButtonObject(collection) {
  return collection.map((element) => ({
    content_type: 'text',
    title: element,
    payload: element,
  }));
}

/**
* Splits a locale into language and region but only returns language
* @param {string} locale a string of language_region for example: "en_GB"
* @return {string} the language part of a locale
*/
function extractLanguageFromLocale(locale) {
  const [language] = locale.split('_');
  return language;
}

// TO DO: generalise the generateButtonobjec
/**
 * Generate button template for quick Yes/No answers
 * @param {string} text the question
 * @param {string} yesTitle yes text (needed for translations)
 * @param {string} noTitle no text (needed for translations)
 * @param {string} yesPayload payload for a yes answer
 * @param {string} noPayload payload for a yes answer
 * @return {object} a messenger button template object
*/
function generateYesNoButtonTemplate(text,
                                     yesTitle,
                                     noTitle,
                                     yesPayload,
                                     noPayload) {
  return {
    attachment: {
      type: 'template',
      payload: {
        template_type: 'button',
        text,
        buttons: [{
          type: 'postback',
          title: yesTitle,
          payload: yesPayload,
        }, {
          type: 'postback',
          title: noTitle,
          payload: noPayload,
        }],
      },
    },
  };
}

/**
* Generate a messenger quick reply
* @param {string} text the question text
* @param {array} replyArray an array of up to 11 objects that is, the answers
* @return {object} a quick reply object
*/
function generateQuickReply(text, replyArray) {
  return {
    text,
    quick_replies: replyArray,
  };
}

/**
* Handle breaks in the currently running conversation
* @param {object} response the response object
* @param {object} conversation the conversation object
* @param {function} callback default function to call
* @return {function} the function to direct the conversation
*/
function conversationSwitch(response, conversation, callback) {
  if (['restart', 'hello', 'hi', 'start'].includes(response.text)) {
    conversation.stop('interrupted');
    return conversation.next();
  } else {
    return callback;
  }
}

/**
* Go to the next conversation.
* @param {object} response the response object
* @param {object} conversation the conversation object
* @return {function} calling converationSwitch with conversation.next()
*/
function nextConversation(response, conversation) {
  return conversationSwitch(response, conversation, conversation.next());
}

/**
* Which conversation thread to go to
* @param {string} threadName the name of the thread to go to next
* @return {function} result of calling conversationSwitch with the threadName
*/
function goto(threadName) {
  return (response, conversation) => {
    conversationSwitch(response,
                         conversation,
                         conversation.gotoThread(threadName));
  };
}

/**
* Send a message to a facebookId, they have to have opted in
* @param {object} bot a bot returned from calling `spawn`
* @param {string} facebookId messenger id
* @param {function} messagecallback callback to pass to startConversation
*/
function sendMessage(bot, facebookId, messageCallback) {
  bot.startConversation({user: facebookId, channel: facebookId},
                        messageCallback);
}

module.exports = {
  extractLanguageFromLocale,
  generateButtonObject,
  nextConversation,
  goto,
  generateYesNoButtonTemplate,
  generateQuickReply,
  sendMessage,
};
<|endoftext|>


<commit_before>/* Modernizr 2.8.3 (Custom Build) | MIT & BSD
 * Build: http://modernizr.com/download/#-shiv-cssclasses
 */
;window.Modernizr=function(a,b,c){function u(a){j.cssText=a}function v(a,b){return u(prefixes.join(a+";")+(b||""))}function w(a,b){return typeof a===b}function x(a,b){return!!~(""+a).indexOf(b)}function y(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:w(f,"function")?f.bind(d||b):f}return!1}var d="2.8.3",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m={},n={},o={},p=[],q=p.slice,r,s={}.hasOwnProperty,t;!w(s,"undefined")&&!w(s.call,"undefined")?t=function(a,b){return s.call(a,b)}:t=function(a,b){return b in a&&w(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=q.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(q.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(q.call(arguments)))};return e});for(var z in m)t(m,z)&&(r=z.toLowerCase(),e[r]=m[z](),p.push((e[r]?"":"no-")+r));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)t(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},u(""),i=k=null,function(a,b){function l(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function m(){var a=s.elements;return typeof a=="string"?a.split(" "):a}function n(a){var b=j[a[h]];return b||(b={},i++,a[h]=i,j[i]=b),b}function o(a,c,d){c||(c=b);if(k)return c.createElement(a);d||(d=n(c));var g;return d.cache[a]?g=d.cache[a].cloneNode():f.test(a)?g=(d.cache[a]=d.createElem(a)).cloneNode():g=d.createElem(a),g.canHaveChildren&&!e.test(a)&&!g.tagUrn?d.frag.appendChild(g):g}function p(a,c){a||(a=b);if(k)return a.createDocumentFragment();c=c||n(a);var d=c.frag.cloneNode(),e=0,f=m(),g=f.length;for(;e<g;e++)d.createElement(f[e]);return d}function q(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return s.shivMethods?o(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/[\w\-]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(s,b.frag)}function r(a){a||(a=b);var c=n(a);return s.shivCSS&&!g&&!c.hasCSS&&(c.hasCSS=!!l(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),k||q(a,c),a}var c="3.7.0",d=a.html5||{},e=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,f=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,g,h="_html5shiv",i=0,j={},k;(function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",g="hidden"in a,k=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){g=!0,k=!0}})();var s={elements:d.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:c,shivCSS:d.shivCSS!==!1,supportsUnknownElements:k,shivMethods:d.shivMethods!==!1,type:"default",shivDocument:r,createElement:o,createDocumentFragment:p};a.html5=s,r(b)}(this,b),e._version=d,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+p.join(" "):""),e}(this,this.document);
<commit_msg>Update Modernizr build.<commit_after>/*! modernizr 3.3.1 (Custom Build) | MIT *
 * http://modernizr.com/download/?-setclasses-shiv !*/
!function(e,n,t){function a(e,n){return typeof e===n}function o(){var e,n,t,o,r,s,l;for(var f in i)if(i.hasOwnProperty(f)){if(e=[],n=i[f],n.name&&(e.push(n.name.toLowerCase()),n.options&&n.options.aliases&&n.options.aliases.length))for(t=0;t<n.options.aliases.length;t++)e.push(n.options.aliases[t].toLowerCase());for(o=a(n.fn,"function")?n.fn():n.fn,r=0;r<e.length;r++)s=e[r],l=s.split("."),1===l.length?Modernizr[l[0]]=o:(!Modernizr[l[0]]||Modernizr[l[0]]instanceof Boolean||(Modernizr[l[0]]=new Boolean(Modernizr[l[0]])),Modernizr[l[0]][l[1]]=o),c.push((o?"":"no-")+l.join("-"))}}function r(e){var n=l.className,t=Modernizr._config.classPrefix||"";if(f&&(n=n.baseVal),Modernizr._config.enableJSClass){var a=new RegExp("(^|\\s)"+t+"no-js(\\s|$)");n=n.replace(a,"$1"+t+"js$2")}Modernizr._config.enableClasses&&(n+=" "+t+e.join(" "+t),f?l.className.baseVal=n:l.className=n)}var i=[],s={_version:"3.3.1",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,n){var t=this;setTimeout(function(){n(t[e])},0)},addTest:function(e,n,t){i.push({name:e,fn:n,options:t})},addAsyncTest:function(e){i.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=s,Modernizr=new Modernizr;var c=[],l=n.documentElement,f="svg"===l.nodeName.toLowerCase();f||!function(e,n){function t(e,n){var t=e.createElement("p"),a=e.getElementsByTagName("head")[0]||e.documentElement;return t.innerHTML="x<style>"+n+"</style>",a.insertBefore(t.lastChild,a.firstChild)}function a(){var e=E.elements;return"string"==typeof e?e.split(" "):e}function o(e,n){var t=E.elements;"string"!=typeof t&&(t=t.join(" ")),"string"!=typeof e&&(e=e.join(" ")),E.elements=t+" "+e,l(n)}function r(e){var n=y[e[g]];return n||(n={},v++,e[g]=v,y[v]=n),n}function i(e,t,a){if(t||(t=n),u)return t.createElement(e);a||(a=r(t));var o;return o=a.cache[e]?a.cache[e].cloneNode():p.test(e)?(a.cache[e]=a.createElem(e)).cloneNode():a.createElem(e),!o.canHaveChildren||h.test(e)||o.tagUrn?o:a.frag.appendChild(o)}function s(e,t){if(e||(e=n),u)return e.createDocumentFragment();t=t||r(e);for(var o=t.frag.cloneNode(),i=0,s=a(),c=s.length;c>i;i++)o.createElement(s[i]);return o}function c(e,n){n.cache||(n.cache={},n.createElem=e.createElement,n.createFrag=e.createDocumentFragment,n.frag=n.createFrag()),e.createElement=function(t){return E.shivMethods?i(t,e,n):n.createElem(t)},e.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+a().join().replace(/[\w\-:]+/g,function(e){return n.createElem(e),n.frag.createElement(e),'c("'+e+'")'})+");return n}")(E,n.frag)}function l(e){e||(e=n);var a=r(e);return!E.shivCSS||f||a.hasCSS||(a.hasCSS=!!t(e,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),u||c(e,a),e}var f,u,d="3.7.3",m=e.html5||{},h=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,g="_html5shiv",v=0,y={};!function(){try{var e=n.createElement("a");e.innerHTML="<xyz></xyz>",f="hidden"in e,u=1==e.childNodes.length||function(){n.createElement("a");var e=n.createDocumentFragment();return"undefined"==typeof e.cloneNode||"undefined"==typeof e.createDocumentFragment||"undefined"==typeof e.createElement}()}catch(t){f=!0,u=!0}}();var E={elements:m.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:d,shivCSS:m.shivCSS!==!1,supportsUnknownElements:u,shivMethods:m.shivMethods!==!1,type:"default",shivDocument:l,createElement:i,createDocumentFragment:s,addElements:o};e.html5=E,l(n),"object"==typeof module&&module.exports&&(module.exports=E)}("undefined"!=typeof e?e:this,n),o(),r(c),delete s.addTest,delete s.addAsyncTest;for(var u=0;u<Modernizr._q.length;u++)Modernizr._q[u]();e.Modernizr=Modernizr}(window,document);<|endoftext|>


<commit_before>'use strict';

(function(module){

  var complaintsView = {};

  var render = function(article) {
    var template = Handlebars.compile($('#company-name-template').text());

    article.daysAgo =
      parseInt((new Date() - new Date(article.publishedOn))/60/60/24/1000);
    article.publishStatus =
      article.publishedOn ? 'published ' +
      article.daysAgo + ' days ago' : '(draft)';
    article.body = marked(article.body);

    return template(article);
  };

  complaintsView.autoCompleteName = function() {
    $('#business_name').autocomplete({
      source: Complaint.selectUniqueInColumn('business')
    });
  };

  complaintsView.autoCompleteCategory = function() {
    $('#category_name').autocomplete({
      source: Complaint.selectUniqueInColumn('businesscategory')
    });
  };

  complaintsView.getQuery = function(){
    $('search-form').on('submit', function(){
      if($('business_name').val()){
        var query = $('business_name').val();
        // var returnedResults = searchByName(query);
        var returnedResults = Complaint.allComplaints;
        var viewObject = {
          total_results: returnedResults.length,
          total_complaints: 888,//Complaint.sumOfComplaints(returnedResults),
          open_claims: '100%'//Complaint.openComplaintsRatio(returnedResults),
        };

      }
    });
    //eventhandeler for search form. calls methods based on query and renders results.
  };

  complaintsView.render = function(){
    complaintsView.autoCompleteName();
    complaintsView.autoCompleteCategory();
  };

  Complaint.updateData(complaintsView.render);

  module.complaintsView = complaintsView;
})(window);
<commit_msg>setting up template<commit_after>'use strict';

(function(module){

  var complaintsView = {};

  complaintsView.renderWithHandlebars = function(templateid, data) {
    var template = Handlebars.compile($(templateid).text());
    return template(data);
  };

  complaintsView.autoCompleteName = function() {
    $('#business_name').autocomplete({
      source: Complaint.selectUniqueInColumn('business')
    });
  };

  complaintsView.autoCompleteCategory = function() {
    $('#category_name').autocomplete({
      source: Complaint.selectUniqueInColumn('businesscategory')
    });
  };

  complaintsView.getQuery = function(){
    $('search-form').on('submit', function(){
      if($('business_name').val()){
        var query = $('business_name').val();
        // var returnedResults = searchByName(query);
        var returnedResults = Complaint.allComplaints;
        var viewObject = {
          total_results: returnedResults.length,
          total_complaints: 888,//Complaint.sumOfComplaints(returnedResults),
          open_claims: '100%'//Complaint.openComplaintsRatio(returnedResults),
        };
        complaintsView.renderWithHandlebars('#renderWithHandlebars', viewObject);
      }
    });
    //eventhandeler for search form. calls methods based on query and renders results.
  };

  complaintsView.renderIndexPage = function(){
    complaintsView.autoCompleteName();
    complaintsView.autoCompleteCategory();
  };

  Complaint.updateData(complaintsView.renderIndexPage);

  module.complaintsView = complaintsView;
})(window);
<|endoftext|>


<commit_before>// ==UserScript==
// @name           豆瓣电台dbscrobbler
// @namespace      http://gmscrobber.whosemind.net
// @description    记录 douban.fm 到last.fm
// @include        http://douban.fm/
// @include        http://douban.fm/?*
// @require        https://raw.githubusercontent.com/justan/lrc/master/lrc.js
// @require        https://raw.githubusercontent.com/justan/gmscrobber/gh-pages/simple_scrobbler_user.js
// @version        0.2.3
// @uso:script     98833
// @initiative     false
// @grant          GM_getValue
// @grant          GM_setValue
// @grant          GM_deleteValue
// @grant          GM_xmlhttpRequest
// @grant          GM_registerMenuCommand
// @grant          GM_log
// @grant          unsafeWindow
// ==/UserScript==

var meta = uso.metaParse(GM_info.scriptMetaStr);
uso.check(meta.version, meta.uso.script);

(function(){
var douban = function(){
	var ready = function(){
		var ex = unsafeWindow.extStatusHandler,
			cmds = {start:"start", end:"e", next:"s", like: "r", unlike: "u", ban: 'b', pause: "pause", gotoplay: "gotoplay"};

		if(!sc.sk){
			return;
		}
		exportFunction(function(info){
			var song, albuminfo, o = info;
			log(o);
			o = JSON.parse(o);
			song = o.song || {};

      albuminfo = song.album;
			song.album = song.albumtitle;
			song.duration = song.len || 180;

			setTimeout(function(){
				if(song.ssid === null || song.subtype == "T"){
					log("无效歌曲, 跳过...");
					return;
				}
				var conn = "&";
				switch(o.type){
				case cmds.start:
					if(/\.{3}$/.test(song.album)){
						if(o.type == cmds.start){
							//song.album = "";
							getAlbum(albuminfo, function(at){
								sc.song.album = at;
								log("一个省略的专辑名...新的专辑名是: " + at);
							});
						}
					}
					//song.artist = song.artist.replace(/\s+\/\s+.+$/,"");//多个歌手，就保留第一个
					//song.artist = song.artist.replace(/\s*[\/\&]\s*/, " & ");

					song.artist = song.artist.split(/\s*[\/\&\;]\s*/);
					for(var i = 0, l = song.artist.length; i < l; i++){
						if(/\w/.test(song.artist)){
							conn = " & ";//英文名用" & "分割
							break;
						}
					}
					song.artist = song.artist.join(conn);
          song._doubanuname = unsafeWindow.$("#fm-user").text();
					sc.nowPlaying(song);
					sc.getInfo(song, function(p){
						log(JSON.stringify(p));
						if(song.like != p.islove){
							if(p.islove){
								log("love " + song.title + "in douban.fm");
								o.type = cmds.like;
								ex(JSON.stringify(o));
								o.type = cmds.start;
								xhr({
									method: "GET",
									url: "http://douban.fm/j/mine/playlist?type=r&sid=" + o.song.sid + "&channel=0",
									onload: function(data){
										log("同步红星至豆瓣电台成功");
									},
									onerror: function(e){
										log("同步红星至豆瓣电台失败.. \n" + JSON.stringify(e));
									}
								});
							}
						}
						document.getElementById("radioplayer").parentNode.title = "在last.fm中记录 " + p.len + " 次";
					});
					break;
				case cmds.end:
					sc.scrobble();
					break;
				case cmds.like:
					sc.love();
					break;
				case cmds.unlike:
					sc.unlove();
					break;
        case cmds.pause:
          sc.pause();
          break;
        case cmds.gotoplay:
          sc.play();
          break;
				default:
					break;
				}

			}, 0);

			return ex.apply(this, arguments);
			//ex(o);
		}, unsafeWindow, {defineAs: 'extStatusHandler'});
	},
	sc = new Scrobbler({name: "豆瓣电台", type: 1, ready: ready}),
	getAlbum = function(info, cb){
		var url = "http://api.douban.com/music" + info.replace(/\/$/, '') + "?alt=json";
		xhr({
			method: "GET",
			url: url,
			onload: function(d){
				cb(JSON.parse(d.responseText)["title"]["$t"]);
			},
			onerror: function(e){
				log("专辑信息获取失败.. \n" + JSON.stringify(e));
			}
		});
	};
};

exportFunction(function() {
	setTimeout(function(){
		unsafeWindow.extStatusHandler ? douban() : log("init error");
	}, 0);
}, unsafeWindow, {defineAs: '__gmready'});
unsafeWindow.Do.ready(unsafeWindow.__gmready);
})();
<commit_msg>Update dbscrobbler.user.js<commit_after>// ==UserScript==
// @name           豆瓣电台dbscrobbler
// @namespace      http://gmscrobber.whosemind.net
// @description    记录 douban.fm 到last.fm
// @include        http://douban.fm/*
// @include        https://douban.fm/*
// @require        https://raw.githubusercontent.com/justan/lrc/master/lrc.js
// @require        https://raw.githubusercontent.com/justan/gmscrobber/gh-pages/simple_scrobbler_user.js
// @version        0.3.0
// @uso:script     98833
// @initiative     false
// @grant          GM_getValue
// @grant          GM_setValue
// @grant          GM_deleteValue
// @grant          unsafeWindow
// @grant          GM_log
// @grant          GM_xmlhttpRequest
// @grant          GM_registerMenuCommand
// ==/UserScript==

var hasStarSync = false

var scrobber = new Scrobbler({name: "豆瓣电台", ready: function() {
   this.on('nowplaying', function() {
      this.getInfo(this.song, function(info) {
        q('.app').title = '在 last.fm 中记录: ' + info.len + ' 次';
        var localInfo = getSongInfo()
        if(info.islove === '1' && !localInfo.isLove || info.islove === '0' && localInfo.isLove) {
            FindReact(q('.buttons>label')).props.onClick()
        }
      });

      hasStarSync || starSync()
    })

    this.setSongInfoFN(getSongInfo);
}})

var starSync = function() {
  q('.buttons>label').addEventListener('click', function() {
  var info = getSongInfo();
     if(!info.isLove){
        scrobber.love();
     }else{
        scrobber.unlove();
      }
  }, false)
  hasStarSync = true
}

var getSongInfo = function() {
  var currentSong = FindReact(q('.player-wrapper').firstElementChild).props.currentSong.attributes
  var song = {
    title: currentSong.title
  , artist: currentSong.artist
  , album: currentSong.albumtitle
  , playTime: currentSong.length - uso.timeParse(q('.time').innerHTML.slice(1))
  , duration: currentSong.length
  , isLove: !!currentSong.like
  }
  return song
}

var FindReact = function(dom) {
    for (var key in dom) {
        if (key.startsWith("__reactInternalInstance$")) {
            var compInternals = dom[key]._currentElement;
            var compWrapper = compInternals._owner;
            var comp = compWrapper._instance;
            return comp;
        }
    }
    return null;
};

var q = function() {
  return document.querySelector.apply(document, arguments);
};
<|endoftext|>


<commit_before>const got = require('got');
const parseLinkHeader = require('parse-link-header');

module.exports = {
  getDigest,
  getTags,
};

function massageRegistry(input) {
  let registry = input;
  if (!registry || registry === 'docker.io') {
    registry = 'index.docker.io'; // eslint-disable-line no-param-reassign
  }
  if (!registry.match('$https?://')) {
    registry = `https://${registry}`; // eslint-disable-line no-param-reassign
  }
  return registry;
}

function getRepository(pkgName) {
  return pkgName.includes('/') ? pkgName : `amd64/${pkgName}`;
}

async function getAuthHeaders(registry, repository) {
  // istanbul ignore if
  if (registry !== 'https://index.docker.io') {
    return {};
  }
  try {
    const authUrl = `https://auth.docker.io/token?service=registry.docker.io&scope=repository:${repository}:pull`;
    logger.debug(`Obtaining docker registry token for ${repository}`);
    const { token } = (await got(authUrl, { json: true })).body;
    if (!token) {
      logger.warn('Failed to obtain docker registry token');
      return null;
    }
    return {
      Authorization: `Bearer ${token}`,
      Accept: 'application/vnd.docker.distribution.manifest.v2+json',
    };
  } catch (err) /* istanbul ignore next */ {
    if (err.statusCode === 401) {
      logger.info({ registry, repository }, 'Unauthorized docker lookup');
      logger.debug({
        err,
        message: err.message,
        body: err.response ? err.response.body : undefined,
      });
      return null;
    }
    if (err.statusCode >= 500 && err.statusCode < 600) {
      logger.warn({ err }, 'docker registry failure: internal error');
      throw new Error('registry-failure');
    }
    logger.warn('Error obtaining docker token');
    return null;
  }
}

async function getDigest(registry, name, tag = 'latest') {
  logger.debug(`getDigest(${registry}, ${name}, ${tag})`);
  const massagedRegistry = massageRegistry(registry);
  const repository = getRepository(name);
  try {
    const url = `${massagedRegistry}/v2/${repository}/manifests/${tag}`;
    const headers = await getAuthHeaders(massagedRegistry, repository);
    if (!headers) {
      logger.info('No docker auth found - returning');
      return null;
    }
    headers.accept = 'application/vnd.docker.distribution.manifest.v2+json';
    const digest = (await got(url, { json: true, headers, timeout: 10000 }))
      .headers['docker-content-digest'];
    logger.debug({ digest }, 'Got docker digest');
    return digest;
  } catch (err) /* istanbul ignore next */ {
    if (err.message === 'registry-failure') {
      throw err;
    }
    if (err.statusCode === 401) {
      logger.info({ registry, repository }, 'Unauthorized docker lookup');
      logger.debug({
        err,
        message: err.message,
        body: err.response ? err.response.body : undefined,
      });
      return null;
    }
    if (err.statusCode === 404) {
      logger.info(
        { err, body: err.response ? err.response.body : undefined, name, tag },
        'Docker Manifest is unknown'
      );
      return null;
    }
    if (err.statusCode >= 500 && err.statusCode < 600) {
      logger.warn(
        { err, body: err.response ? err.response.body : undefined, name, tag },
        'docker registry failure: internal error'
      );
      throw new Error('registry-failure');
    }
    if (err.code === 'ETIMEDOUT') {
      logger.info(
        { massagedRegistry },
        'Timeout when attempting to connect to docker registry'
      );
      logger.debug({ err });
      return null;
    }
    logger.info(
      { err, body: err.response ? err.response.body : undefined, name, tag },
      'Unknown Error looking up docker image digest'
    );
    return null;
  }
}

async function getTags(registry, name) {
  logger.debug(`getTags(${registry}, ${name})`);
  const massagedRegistry = massageRegistry(registry);
  const repository = getRepository(name);
  try {
    let url = `${massagedRegistry}/v2/${repository}/tags/list?n=10000`;
    const headers = await getAuthHeaders(massagedRegistry, repository);
    if (!headers) {
      return null;
    }
    let tags = [];
    let page = 1;
    do {
      const res = await got(url, { json: true, headers, timeout: 10000 });
      tags = tags.concat(res.body.tags);
      const linkHeader = parseLinkHeader(res.headers.link);
      url = linkHeader && linkHeader.next ? linkHeader.next.url : null;
      page += 1;
    } while (url && page < 20);
    logger.debug({ length: tags.length }, 'Got docker tags');
    logger.trace({ tags });
    return tags;
  } catch (err) /* istanbul ignore next */ {
    logger.debug(
      {
        err,
        name,
        message: err.message,
        body: err.response ? err.response.body : undefined,
      },
      'docker.getTags() error'
    );
    if (err.statusCode === 401) {
      logger.info('Not authorised to look up docker tags');
      return null;
    }
    if (err.statusCode >= 500 && err.statusCode < 600) {
      logger.warn({ err }, 'docker registry failure: internal error');
      throw new Error('registry-failure');
    }
    if (err.code === 'ETIMEDOUT') {
      logger.info(
        { massagedRegistry },
        'Timeout when attempting to connect to docker registry'
      );
      logger.debug({ err });
      return null;
    }
    logger.warn('Error getting docker image tags');
    return null;
  }
}
<commit_msg>refactor: docker getTags filter suffix and version<commit_after>const got = require('got');
const parseLinkHeader = require('parse-link-header');
const { isVersion } = require('../versioning/docker');

module.exports = {
  getDigest,
  getTags,
};

function massageRegistry(input) {
  let registry = input;
  if (!registry || registry === 'docker.io') {
    registry = 'index.docker.io'; // eslint-disable-line no-param-reassign
  }
  if (!registry.match('$https?://')) {
    registry = `https://${registry}`; // eslint-disable-line no-param-reassign
  }
  return registry;
}

function getRepository(pkgName) {
  return pkgName.includes('/') ? pkgName : `amd64/${pkgName}`;
}

async function getAuthHeaders(registry, repository) {
  // istanbul ignore if
  if (registry !== 'https://index.docker.io') {
    return {};
  }
  try {
    const authUrl = `https://auth.docker.io/token?service=registry.docker.io&scope=repository:${repository}:pull`;
    logger.debug(`Obtaining docker registry token for ${repository}`);
    const { token } = (await got(authUrl, { json: true })).body;
    if (!token) {
      logger.warn('Failed to obtain docker registry token');
      return null;
    }
    return {
      Authorization: `Bearer ${token}`,
      Accept: 'application/vnd.docker.distribution.manifest.v2+json',
    };
  } catch (err) /* istanbul ignore next */ {
    if (err.statusCode === 401) {
      logger.info({ registry, repository }, 'Unauthorized docker lookup');
      logger.debug({
        err,
        message: err.message,
        body: err.response ? err.response.body : undefined,
      });
      return null;
    }
    if (err.statusCode >= 500 && err.statusCode < 600) {
      logger.warn({ err }, 'docker registry failure: internal error');
      throw new Error('registry-failure');
    }
    logger.warn('Error obtaining docker token');
    return null;
  }
}

async function getDigest(registry, name, tag = 'latest') {
  logger.debug(`getDigest(${registry}, ${name}, ${tag})`);
  const massagedRegistry = massageRegistry(registry);
  const repository = getRepository(name);
  try {
    const url = `${massagedRegistry}/v2/${repository}/manifests/${tag}`;
    const headers = await getAuthHeaders(massagedRegistry, repository);
    if (!headers) {
      logger.info('No docker auth found - returning');
      return null;
    }
    headers.accept = 'application/vnd.docker.distribution.manifest.v2+json';
    const digest = (await got(url, { json: true, headers, timeout: 10000 }))
      .headers['docker-content-digest'];
    logger.debug({ digest }, 'Got docker digest');
    return digest;
  } catch (err) /* istanbul ignore next */ {
    if (err.message === 'registry-failure') {
      throw err;
    }
    if (err.statusCode === 401) {
      logger.info({ registry, repository }, 'Unauthorized docker lookup');
      logger.debug({
        err,
        message: err.message,
        body: err.response ? err.response.body : undefined,
      });
      return null;
    }
    if (err.statusCode === 404) {
      logger.info(
        { err, body: err.response ? err.response.body : undefined, name, tag },
        'Docker Manifest is unknown'
      );
      return null;
    }
    if (err.statusCode >= 500 && err.statusCode < 600) {
      logger.warn(
        { err, body: err.response ? err.response.body : undefined, name, tag },
        'docker registry failure: internal error'
      );
      throw new Error('registry-failure');
    }
    if (err.code === 'ETIMEDOUT') {
      logger.info(
        { massagedRegistry },
        'Timeout when attempting to connect to docker registry'
      );
      logger.debug({ err });
      return null;
    }
    logger.info(
      { err, body: err.response ? err.response.body : undefined, name, tag },
      'Unknown Error looking up docker image digest'
    );
    return null;
  }
}

async function getTags(registry, name, suffix) {
  logger.debug(`getTags(${registry}, ${name}, ${suffix})`);
  const massagedRegistry = massageRegistry(registry);
  const repository = getRepository(name);
  try {
    let url = `${massagedRegistry}/v2/${repository}/tags/list?n=10000`;
    const headers = await getAuthHeaders(massagedRegistry, repository);
    if (!headers) {
      return null;
    }
    let tags = [];
    let page = 1;
    do {
      const res = await got(url, { json: true, headers, timeout: 10000 });
      tags = tags.concat(res.body.tags);
      const linkHeader = parseLinkHeader(res.headers.link);
      url = linkHeader && linkHeader.next ? linkHeader.next.url : null;
      page += 1;
    } while (url && page < 20);
    logger.debug({ length: tags.length }, 'Got docker tags');
    logger.trace({ tags });
    return tags
      .filter(tag => !suffix || tag.endsWith(`-${suffix}`))
      .filter(isVersion);
  } catch (err) /* istanbul ignore next */ {
    logger.debug(
      {
        err,
        name,
        message: err.message,
        body: err.response ? err.response.body : undefined,
      },
      'docker.getTags() error'
    );
    if (err.statusCode === 401) {
      logger.info('Not authorised to look up docker tags');
      return null;
    }
    if (err.statusCode >= 500 && err.statusCode < 600) {
      logger.warn({ err }, 'docker registry failure: internal error');
      throw new Error('registry-failure');
    }
    if (err.code === 'ETIMEDOUT') {
      logger.info(
        { massagedRegistry },
        'Timeout when attempting to connect to docker registry'
      );
      logger.debug({ err });
      return null;
    }
    logger.warn('Error getting docker image tags');
    return null;
  }
}
<|endoftext|>


<commit_before>import React from "react";
import withSideEffect from "react-side-effect";
import deepEqual from "deep-equal";
import {
    TAG_NAMES,
    TAG_PROPERTIES,
    REACT_TAG_MAP
} from "./HelmetConstants.js";
import PlainComponent from "./PlainComponent";

const HELMET_ATTRIBUTE = "data-react-helmet";

const encodeSpecialCharacters = (str) => {
    return String(str)
            .replace(/&/g, "&")
            .replace(/</g, "<")
            .replace(/>/g, ">")
            .replace(/"/g, """)
            .replace(/'/g, "'");
};

const getInnermostProperty = (propsList, property) => {
    for (const props of [...propsList].reverse()) {
        if (props[property]) {
            return props[property];
        }
    }

    return null;
};

const getTitleFromPropsList = (propsList) => {
    const innermostTitle = getInnermostProperty(propsList, "title");
    const innermostTemplate = getInnermostProperty(propsList, "titleTemplate");

    if (innermostTemplate && innermostTitle) {
        return innermostTemplate.replace(/\%s/g, innermostTitle);
    }

    return innermostTitle || "";
};

const getOnChangeClientState = (propsList) => {
    return getInnermostProperty(propsList, "onChangeClientState") || () => {};
};

const getBaseTagFromPropsList = (validTags, propsList) => {
    return propsList
        .filter(props => typeof props[TAG_NAMES.BASE] !== "undefined")
        .map(props => props[TAG_NAMES.BASE])
        .reverse()
        .reduce((innermostBaseTag, tag) => {
            if (!innermostBaseTag.length) {
                for (const attributeKey of Object.keys(tag)) {
                    const lowerCaseAttributeKey = attributeKey.toLowerCase();

                    if (validTags.indexOf(lowerCaseAttributeKey) !== -1) {
                        return innermostBaseTag.concat(tag);
                    }
                }
            }

            return innermostBaseTag;
        }, []);
};

const getTagsFromPropsList = (tagName, validTags, propsList) => {
    // Calculate list of tags, giving priority innermost component (end of the propslist)
    const approvedSeenTags = {};

    const tagList = propsList
        .filter(props => typeof props[tagName] !== "undefined")
        .map(props => props[tagName])
        .reverse()
        .reduce((approvedTags, instanceTags) => {
            const instanceSeenTags = {};

            instanceTags.filter(tag => {
                let validAttributeKey;
                for (const attributeKey of Object.keys(tag)) {
                    const lowerCaseAttributeKey = attributeKey.toLowerCase();

                    // Special rule with link tags, since rel and href are both valid tags, rel takes priority
                    if (validTags.indexOf(lowerCaseAttributeKey) !== -1
                        && !(validAttributeKey === TAG_PROPERTIES.REL && tag[validAttributeKey].toLowerCase() === "canonical")
                        && !(lowerCaseAttributeKey === TAG_PROPERTIES.REL && tag[lowerCaseAttributeKey].toLowerCase() === "stylesheet")) {
                        validAttributeKey = lowerCaseAttributeKey;
                    }
                }

                if (!validAttributeKey) {
                    return false;
                }

                const value = tag[validAttributeKey].toLowerCase();

                if (!approvedSeenTags[validAttributeKey]) {
                    approvedSeenTags[validAttributeKey] = new Set();
                }

                if (!instanceSeenTags[validAttributeKey]) {
                    instanceSeenTags[validAttributeKey] = new Set();
                }

                if (!approvedSeenTags[validAttributeKey].has(value)) {
                    instanceSeenTags[validAttributeKey].add(value);
                    return true;
                }

                return false;
            })
            .reverse()
            .forEach(tag => approvedTags.push(tag));

            // Update seen tags with tags from this instance
            for (const attributeKey of Object.keys(instanceSeenTags)) {
                const tagUnion = new Set([
                    ...approvedSeenTags[attributeKey],
                    ...instanceSeenTags[attributeKey]
                ]);

                approvedSeenTags[attributeKey] = tagUnion;
            }

            return approvedTags;
        }, [])
        .reverse();

    return tagList;
};

const updateTitle = title => {
    document.title = title || document.title;
};

const updateTags = (type, tags) => {
    const headElement = document.head || document.querySelector("head");
    const oldTags = [...headElement.querySelectorAll(`${type}[${HELMET_ATTRIBUTE}]`)];
    const newTags = [];
    let indexToDelete;

    if (tags && tags.length) {
        tags
        .forEach(tag => {
            const newElement = document.createElement(type);

            for (const attribute in tag) {
                if (tag.hasOwnProperty(attribute)) {
                    newElement.setAttribute(attribute, tag[attribute]);
                }
            }

            newElement.setAttribute(HELMET_ATTRIBUTE, "true");

            // Remove a duplicate tag from domTagstoRemove, so it isn't cleared.
            if (oldTags.some((existingTag, index) => {
                indexToDelete = index;
                return newElement.isEqualNode(existingTag);
            })) {
                oldTags.splice(indexToDelete, 1);
            } else {
                newTags.push(newElement);
            }
        });
    }

    oldTags.forEach(tag => tag.parentNode.removeChild(tag));
    newTags.forEach(tag => headElement.appendChild(tag));

    return {
        oldTags,
        newTags
    };
};

const generateTitleAsString = (type, title) => {
    const stringifiedMarkup = `<${type} ${HELMET_ATTRIBUTE}="true">${encodeSpecialCharacters(title)}</${type}>`;

    return stringifiedMarkup;
};

const generateTagsAsString = (type, tags) => {
    const stringifiedMarkup = tags.map(tag => {
        const attributeHtml = Object.keys(tag)
            .map((attribute) => {
                const encodedValue = encodeSpecialCharacters(tag[attribute]);
                return `${attribute}="${encodedValue}"`;
            })
            .join(" ");

        return `<${type} ${HELMET_ATTRIBUTE}="true" ${attributeHtml}${type === TAG_NAMES.SCRIPT ? `></${type}>` : `/>`}`;
    }).join("");

    return stringifiedMarkup;
};

const generateTitleAsReactComponent = (type, title) => {
    // assigning into an array to define toString function on it
    const component = [
        React.createElement(
            TAG_NAMES.TITLE,
            {
                key: title,
                [HELMET_ATTRIBUTE]: true
            },
            title
        )
    ];

    return component;
};

const generateTagsAsReactComponent = (type, tags) => {
    /* eslint-disable react/display-name */
    const component = [...tags].map((tag, i) => {
        const mappedTag = {
            key: i,
            [HELMET_ATTRIBUTE]: true
        };

        Object.keys(tag).forEach((attribute) => {
            const mappedAttribute = REACT_TAG_MAP[attribute] || attribute;

            mappedTag[mappedAttribute] = tag[attribute];
        });

        return React.createElement(type, mappedTag);
    });

    return component;
    /* eslint-enable react/display-name */
};

const getMethodsForTag = (type, tags) => ({
    toComponent: (type === TAG_NAMES.TITLE) ? () => generateTitleAsReactComponent(type, tags) : () => generateTagsAsReactComponent(type, tags),
    toString: (type === TAG_NAMES.TITLE) ? () => generateTitleAsString(type, tags) : () => generateTagsAsString(type, tags)
});

const mapStateOnServer = ({title, baseTag, metaTags, linkTags, scriptTags}) => ({
    title: getMethodsForTag(TAG_NAMES.TITLE, title),
    base: getMethodsForTag(TAG_NAMES.BASE, baseTag),
    meta: getMethodsForTag(TAG_NAMES.META, metaTags),
    link: getMethodsForTag(TAG_NAMES.LINK, linkTags),
    script: getMethodsForTag(TAG_NAMES.SCRIPT, scriptTags)
});

const Helmet = (Component) => {
    /* eslint-disable react/no-multi-comp */
    class HelmetWrapper extends React.Component {
        /**
         * @param {String} title: "Title"
         * @param {Function} onChangeClientState: "(newState) => console.log(newState)"
         * @param {String} titleTemplate: "MySite.com - %s"
         * @param {Object} base: {"target": "_blank", "href": "http://mysite.com/"}
         * @param {Array} meta: [{"name": "description", "content": "Test description"}]
         * @param {Array} link: [{"rel": "canonical", "href": "http://mysite.com/example"}]
         * @param {Array} script: [{"src": "http://mysite.com/js/test.js", "type": "text/javascript"}]
         */
        static propTypes = {
            title: React.PropTypes.string,
            onChangeClientState: React.PropTypes.func,
            titleTemplate: React.PropTypes.string,
            base: React.PropTypes.object,
            meta: React.PropTypes.arrayOf(React.PropTypes.object),
            link: React.PropTypes.arrayOf(React.PropTypes.object),
            script: React.PropTypes.arrayOf(React.PropTypes.object)
        }

        shouldComponentUpdate(nextProps) {
            return !deepEqual(this.props, nextProps);
        }

        static peek = Component.peek
        static rewind = () => {
            let mappedState = Component.rewind();
            if (!mappedState) {
                // provide fallback if mappedState is undefined
                mappedState = mapStateOnServer({
                    title: "",
                    baseTag: "",
                    metaTags: "",
                    linkTags: "",
                    scriptTags: ""
                });
            }

            return mappedState;
        }

        static set canUseDOM(canUseDOM) {
            Component.canUseDOM = canUseDOM;
        }

        render() {
            return <Component {...this.props} />;
        }
    }
    /* eslint-enable react/no-multi-comp */

    return HelmetWrapper;
};

const reducePropsToState = (propsList) => ({
    title: getTitleFromPropsList(propsList),
    onChangeClientState: getOnChangeClientState(propsList),
    baseTag: getBaseTagFromPropsList([TAG_PROPERTIES.HREF], propsList),
    metaTags: getTagsFromPropsList(TAG_NAMES.META, [TAG_PROPERTIES.NAME, TAG_PROPERTIES.CHARSET, TAG_PROPERTIES.HTTPEQUIV, TAG_PROPERTIES.PROPERTY], propsList),
    linkTags: getTagsFromPropsList(TAG_NAMES.LINK, [TAG_PROPERTIES.REL, TAG_PROPERTIES.HREF], propsList),
    scriptTags: getTagsFromPropsList(TAG_NAMES.SCRIPT, [TAG_PROPERTIES.SRC], propsList)
});

const handleClientStateChange = (newState) => {
    const {title, baseTag, metaTags, linkTags, scriptTags, onChangeClientState} = newState;

    updateTitle(title);

    const tagUpdates = {
        scriptTags: updateTags(TAG_NAMES.SCRIPT, scriptTags),
        linkTags: updateTags(TAG_NAMES.LINK, linkTags),
        metaTags: updateTags(TAG_NAMES.META, metaTags),
        baseTag: updateTags(TAG_NAMES.BASE, baseTag)
    };

    const addedTags = {};
    const removedTags = {};

    Object.keys(tagUpdates).forEach(tagType => {
        const {newTags, oldTags} = tagUpdates[tagType];

        if (newTags.length) {
            addedTags[tagType] = newTags;
        }
        if (oldTags.length) {
            removedTags[tagType] = tagUpdates[tagType].oldTags;
        }
    });

    onChangeClientState(newState, addedTags, removedTags);
};

const SideEffect = withSideEffect(
    reducePropsToState,
    handleClientStateChange,
    mapStateOnServer
);

// PlainComponent is used to be a blank component decorated by react-side-effect
export default Helmet(SideEffect(PlainComponent));
<commit_msg>Remove use of Set<commit_after>import React from "react";
import withSideEffect from "react-side-effect";
import deepEqual from "deep-equal";
import {
    TAG_NAMES,
    TAG_PROPERTIES,
    REACT_TAG_MAP
} from "./HelmetConstants.js";
import PlainComponent from "./PlainComponent";

const HELMET_ATTRIBUTE = "data-react-helmet";

const encodeSpecialCharacters = (str) => {
    return String(str)
            .replace(/&/g, "&")
            .replace(/</g, "<")
            .replace(/>/g, ">")
            .replace(/"/g, """)
            .replace(/'/g, "'");
};

const getInnermostProperty = (propsList, property) => {
    for (const props of [...propsList].reverse()) {
        if (props[property]) {
            return props[property];
        }
    }

    return null;
};

const getTitleFromPropsList = (propsList) => {
    const innermostTitle = getInnermostProperty(propsList, "title");
    const innermostTemplate = getInnermostProperty(propsList, "titleTemplate");

    if (innermostTemplate && innermostTitle) {
        return innermostTemplate.replace(/\%s/g, innermostTitle);
    }

    return innermostTitle || "";
};

const getOnChangeClientState = (propsList) => {
    return getInnermostProperty(propsList, "onChangeClientState") || () => {};
};

const getBaseTagFromPropsList = (validTags, propsList) => {
    return propsList
        .filter(props => typeof props[TAG_NAMES.BASE] !== "undefined")
        .map(props => props[TAG_NAMES.BASE])
        .reverse()
        .reduce((innermostBaseTag, tag) => {
            if (!innermostBaseTag.length) {
                for (const attributeKey of Object.keys(tag)) {
                    const lowerCaseAttributeKey = attributeKey.toLowerCase();

                    if (validTags.indexOf(lowerCaseAttributeKey) !== -1) {
                        return innermostBaseTag.concat(tag);
                    }
                }
            }

            return innermostBaseTag;
        }, []);
};

const getTagsFromPropsList = (tagName, validTags, propsList) => {
    // Calculate list of tags, giving priority innermost component (end of the propslist)
    const approvedSeenTags = {};

    const tagList = propsList
        .filter(props => typeof props[tagName] !== "undefined")
        .map(props => props[tagName])
        .reverse()
        .reduce((approvedTags, instanceTags) => {
            const instanceSeenTags = {};

            instanceTags.filter(tag => {
                let validAttributeKey;
                for (const attributeKey of Object.keys(tag)) {
                    const lowerCaseAttributeKey = attributeKey.toLowerCase();

                    // Special rule with link tags, since rel and href are both valid tags, rel takes priority
                    if (validTags.indexOf(lowerCaseAttributeKey) !== -1
                        && !(validAttributeKey === TAG_PROPERTIES.REL && tag[validAttributeKey].toLowerCase() === "canonical")
                        && !(lowerCaseAttributeKey === TAG_PROPERTIES.REL && tag[lowerCaseAttributeKey].toLowerCase() === "stylesheet")) {
                        validAttributeKey = lowerCaseAttributeKey;
                    }
                }

                if (!validAttributeKey) {
                    return false;
                }

                const value = tag[validAttributeKey].toLowerCase();

                if (!approvedSeenTags[validAttributeKey]) {
                    approvedSeenTags[validAttributeKey] = {};
                }

                if (!instanceSeenTags[validAttributeKey]) {
                    instanceSeenTags[validAttributeKey] = {};
                }

                if (!approvedSeenTags[validAttributeKey][value]) {
                    instanceSeenTags[validAttributeKey][value] = true;
                    return true;
                }

                return false;
            })
            .reverse()
            .forEach(tag => approvedTags.push(tag));

            // Update seen tags with tags from this instance
            for (const attributeKey of Object.keys(instanceSeenTags)) {
                const tagUnion = {
                    ...approvedSeenTags[attributeKey],
                    ...instanceSeenTags[attributeKey]
                };

                approvedSeenTags[attributeKey] = tagUnion;
            }

            return approvedTags;
        }, [])
        .reverse();

    return tagList;
};

const updateTitle = title => {
    document.title = title || document.title;
};

const updateTags = (type, tags) => {
    const headElement = document.head || document.querySelector("head");
    const oldTags = [...headElement.querySelectorAll(`${type}[${HELMET_ATTRIBUTE}]`)];
    const newTags = [];
    let indexToDelete;

    if (tags && tags.length) {
        tags
        .forEach(tag => {
            const newElement = document.createElement(type);

            for (const attribute in tag) {
                if (tag.hasOwnProperty(attribute)) {
                    newElement.setAttribute(attribute, tag[attribute]);
                }
            }

            newElement.setAttribute(HELMET_ATTRIBUTE, "true");

            // Remove a duplicate tag from domTagstoRemove, so it isn't cleared.
            if (oldTags.some((existingTag, index) => {
                indexToDelete = index;
                return newElement.isEqualNode(existingTag);
            })) {
                oldTags.splice(indexToDelete, 1);
            } else {
                newTags.push(newElement);
            }
        });
    }

    oldTags.forEach(tag => tag.parentNode.removeChild(tag));
    newTags.forEach(tag => headElement.appendChild(tag));

    return {
        oldTags,
        newTags
    };
};

const generateTitleAsString = (type, title) => {
    const stringifiedMarkup = `<${type} ${HELMET_ATTRIBUTE}="true">${encodeSpecialCharacters(title)}</${type}>`;

    return stringifiedMarkup;
};

const generateTagsAsString = (type, tags) => {
    const stringifiedMarkup = tags.map(tag => {
        const attributeHtml = Object.keys(tag)
            .map((attribute) => {
                const encodedValue = encodeSpecialCharacters(tag[attribute]);
                return `${attribute}="${encodedValue}"`;
            })
            .join(" ");

        return `<${type} ${HELMET_ATTRIBUTE}="true" ${attributeHtml}${type === TAG_NAMES.SCRIPT ? `></${type}>` : `/>`}`;
    }).join("");

    return stringifiedMarkup;
};

const generateTitleAsReactComponent = (type, title) => {
    // assigning into an array to define toString function on it
    const component = [
        React.createElement(
            TAG_NAMES.TITLE,
            {
                key: title,
                [HELMET_ATTRIBUTE]: true
            },
            title
        )
    ];

    return component;
};

const generateTagsAsReactComponent = (type, tags) => {
    /* eslint-disable react/display-name */
    const component = [...tags].map((tag, i) => {
        const mappedTag = {
            key: i,
            [HELMET_ATTRIBUTE]: true
        };

        Object.keys(tag).forEach((attribute) => {
            const mappedAttribute = REACT_TAG_MAP[attribute] || attribute;

            mappedTag[mappedAttribute] = tag[attribute];
        });

        return React.createElement(type, mappedTag);
    });

    return component;
    /* eslint-enable react/display-name */
};

const getMethodsForTag = (type, tags) => ({
    toComponent: (type === TAG_NAMES.TITLE) ? () => generateTitleAsReactComponent(type, tags) : () => generateTagsAsReactComponent(type, tags),
    toString: (type === TAG_NAMES.TITLE) ? () => generateTitleAsString(type, tags) : () => generateTagsAsString(type, tags)
});

const mapStateOnServer = ({title, baseTag, metaTags, linkTags, scriptTags}) => ({
    title: getMethodsForTag(TAG_NAMES.TITLE, title),
    base: getMethodsForTag(TAG_NAMES.BASE, baseTag),
    meta: getMethodsForTag(TAG_NAMES.META, metaTags),
    link: getMethodsForTag(TAG_NAMES.LINK, linkTags),
    script: getMethodsForTag(TAG_NAMES.SCRIPT, scriptTags)
});

const Helmet = (Component) => {
    /* eslint-disable react/no-multi-comp */
    class HelmetWrapper extends React.Component {
        /**
         * @param {String} title: "Title"
         * @param {Function} onChangeClientState: "(newState) => console.log(newState)"
         * @param {String} titleTemplate: "MySite.com - %s"
         * @param {Object} base: {"target": "_blank", "href": "http://mysite.com/"}
         * @param {Array} meta: [{"name": "description", "content": "Test description"}]
         * @param {Array} link: [{"rel": "canonical", "href": "http://mysite.com/example"}]
         * @param {Array} script: [{"src": "http://mysite.com/js/test.js", "type": "text/javascript"}]
         */
        static propTypes = {
            title: React.PropTypes.string,
            onChangeClientState: React.PropTypes.func,
            titleTemplate: React.PropTypes.string,
            base: React.PropTypes.object,
            meta: React.PropTypes.arrayOf(React.PropTypes.object),
            link: React.PropTypes.arrayOf(React.PropTypes.object),
            script: React.PropTypes.arrayOf(React.PropTypes.object)
        }

        shouldComponentUpdate(nextProps) {
            return !deepEqual(this.props, nextProps);
        }

        static peek = Component.peek
        static rewind = () => {
            let mappedState = Component.rewind();
            if (!mappedState) {
                // provide fallback if mappedState is undefined
                mappedState = mapStateOnServer({
                    title: "",
                    baseTag: "",
                    metaTags: "",
                    linkTags: "",
                    scriptTags: ""
                });
            }

            return mappedState;
        }

        static set canUseDOM(canUseDOM) {
            Component.canUseDOM = canUseDOM;
        }

        render() {
            return <Component {...this.props} />;
        }
    }
    /* eslint-enable react/no-multi-comp */

    return HelmetWrapper;
};

const reducePropsToState = (propsList) => ({
    title: getTitleFromPropsList(propsList),
    onChangeClientState: getOnChangeClientState(propsList),
    baseTag: getBaseTagFromPropsList([TAG_PROPERTIES.HREF], propsList),
    metaTags: getTagsFromPropsList(TAG_NAMES.META, [TAG_PROPERTIES.NAME, TAG_PROPERTIES.CHARSET, TAG_PROPERTIES.HTTPEQUIV, TAG_PROPERTIES.PROPERTY], propsList),
    linkTags: getTagsFromPropsList(TAG_NAMES.LINK, [TAG_PROPERTIES.REL, TAG_PROPERTIES.HREF], propsList),
    scriptTags: getTagsFromPropsList(TAG_NAMES.SCRIPT, [TAG_PROPERTIES.SRC], propsList)
});

const handleClientStateChange = (newState) => {
    const {title, baseTag, metaTags, linkTags, scriptTags, onChangeClientState} = newState;

    updateTitle(title);

    const tagUpdates = {
        scriptTags: updateTags(TAG_NAMES.SCRIPT, scriptTags),
        linkTags: updateTags(TAG_NAMES.LINK, linkTags),
        metaTags: updateTags(TAG_NAMES.META, metaTags),
        baseTag: updateTags(TAG_NAMES.BASE, baseTag)
    };

    const addedTags = {};
    const removedTags = {};

    Object.keys(tagUpdates).forEach(tagType => {
        const {newTags, oldTags} = tagUpdates[tagType];

        if (newTags.length) {
            addedTags[tagType] = newTags;
        }
        if (oldTags.length) {
            removedTags[tagType] = tagUpdates[tagType].oldTags;
        }
    });

    onChangeClientState(newState, addedTags, removedTags);
};

const SideEffect = withSideEffect(
    reducePropsToState,
    handleClientStateChange,
    mapStateOnServer
);

// PlainComponent is used to be a blank component decorated by react-side-effect
export default Helmet(SideEffect(PlainComponent));
<|endoftext|>


<commit_before>import React from 'react';
import css from './Layout.css';

function Layout(props) {

  function getClassName() {
    let classString = props.className;
    let classArray = classString.split(" ");
    const scopedArray = classArray.map(c => css[c]);
    return scopedArray.join(" ");
  }

  return (

{props.children}

  )
}

export default Layout;
<commit_msg>semicolon cleanup. see STRPCOMP-21<commit_after>import React from 'react';
import css from './Layout.css';

function Layout(props) {

  function getClassName() {
    let classString = props.className;
    let classArray = classString.split(" ");
    const scopedArray = classArray.map(c => css[c]);
    return scopedArray.join(" ");
  }

  return (

{props.children}

  );
}

export default Layout;
<|endoftext|>


<commit_before>const { Subject } = require('rxjs')
const corrie = require('corrie')
const wildcardMatch = require('wildcard-match')
const HookStore = require('./HookStore')

const MODES = ['auto', 'asIs', 'sync', 'async']

class Hooter extends Subject {
  constructor(settings) {
    super()
    this.corrie = settings ? corrie(settings) : corrie
    this.hookStoreBefore = new HookStore(this.match)
    this.hookStore = new HookStore(this.match)
    this.hookStoreAfter = new HookStore(this.match, true)
    this.events = {}
  }

  match(a, b) {
    return wildcardMatch('.', a, b)
  }

  lift(operator) {
    // Rxjs subjects return an AnonymousSubject on lifting,
    // but we want to return an instance of Hooter

    let instance = new this.constructor()

    if (operator) {
      instance.operator = operator
    }

    instance.source = this
    return instance
  }

  _subscribe(subscriber) {
    if (this.source) {
      return this.source.subscribe(subscriber)
    }

    return super._subscribe(subscriber)
  }

  error(err) {
    if (this.source && this.source.error) {
      return this.source.error(err)
    }

    super.error(err)
  }

  complete() {
    if (this.source && this.source.complete) {
      return this.source.complete()
    }

    super.complete()
  }

  _hook(eventType, hook, hookStore) {
    if (arguments.length === 1) {
      hook = eventType
      eventType = '**'
    } else if (typeof eventType !== 'string') {
      throw new TypeError('An event type must be a string')
    }

    if (typeof hook !== 'function') {
      throw new TypeError('A hook must be a function')
    }

    return hookStore.put(eventType, hook)
  }

  hook(eventType, hook) {
    return this._hook(eventType, hook, this.hookStore)
  }

  hookBefore(eventType, hook) {
    return this._hook(eventType, hook, this.hookStoreBefore)
  }

  hookAfter(eventType, hook) {
    return this._hook(eventType, hook, this.hookStoreAfter)
  }

  unhook(needle) {
    this.hookStoreBefore.del(needle)
    this.hookStore.del(needle)
    this.hookStoreAfter.del(needle)
  }

  next(event) {
    if (!event || typeof event !== 'object') {
      throw new TypeError('An event must be an object')
    }

    if (typeof event.type !== 'string') {
      throw new TypeError('An event type must be a string')
    }

    if (!['auto', 'asIs', 'sync', 'async'].includes(event.mode)) {
      throw new Error(
        'An event mode must be either "auto", asIs", "sync" or "async"'
      )
    }

    if (event.cb && typeof event.cb !== 'function') {
      throw new TypeError('An event callback must be a function')
    }

    if (this._prefix) {
      event = Object.assign({}, event)
      event.type = `${this._prefix}.${event.type}`
    }

    if (this.source && this.source.next) {
      return this.source.next(event)
    }

    super.next(event)

    let beforeHooks = this.hookStoreBefore.get(event.type)
    let hooks = this.hookStore.get(event.type)
    let afterHooks = this.hookStoreAfter.get(event.type)
    let handlers = beforeHooks
      .concat(hooks)
      .concat(afterHooks)
      .map((hook) => hook.fn.bind(event))

    if (event.cb) {
      handlers.push(event.cb)
    }

    if (handlers.length === 0) {
      return
    } else if (event.mode === 'auto') {
      return this.corrie(...handlers)(...event.args)
    } else {
      return this.corrie[event.mode](...handlers)(...event.args)
    }
  }

  _toot(eventType, mode, args, cb) {
    let registeredEvent = this.events[eventType]

    if (registeredEvent) {
      if (mode) {
        throw new Error(
          `Event "${eventType}" is a registered event` +
            'and shouldn\'t be tooted with a custom mode'
        )
      }

      mode = registeredEvent.mode
    } else {
      mode = mode || 'auto'
    }

    let event = createEvent(eventType, mode, args, cb)
    return this.next(event)
  }

  toot(eventType, ...args) {
    return this._toot(eventType, null, args)
  }

  tootAuto(eventType, ...args) {
    return this._toot(eventType, 'auto', args)
  }

  tootAsIs(eventType, ...args) {
    return this._toot(eventType, 'asIs', args)
  }

  tootSync(eventType, ...args) {
    return this._toot(eventType, 'sync', args)
  }

  tootAsync(eventType, ...args) {
    return this._toot(eventType, 'async', args)
  }

  tootWith(eventType, cb, ...args) {
    return this._toot(eventType, null, args, cb)
  }

  tootAutoWith(eventType, cb, ...args) {
    return this._toot(eventType, 'auto', args, cb)
  }

  tootAsIsWith(eventType, cb, ...args) {
    return this._toot(eventType, 'asIs', args, cb)
  }

  tootSyncWith(eventType, cb, ...args) {
    return this._toot(eventType, 'sync', args, cb)
  }

  tootAsyncWith(eventType, cb, ...args) {
    return this._toot(eventType, 'async', args, cb)
  }

  register(eventType, mode) {
    if (typeof eventType !== 'string' || !eventType.length) {
      throw new Error('An event type must be a non-empty string')
    }

    if (this.events[eventType]) {
      throw new Error(`Event "${eventType}" is already registered`)
    }

    if (!MODES.includes(mode)) {
      throw new Error('A mode must be one of the following:', MODES.join(', '))
    }

    this.events[eventType] = { mode }
  }

  prefix(prefix) {
    if (typeof prefix !== 'string') {
      throw new TypeError('A prefix must be a string')
    }

    let instance = this.lift()
    instance._prefix = prefix
    return instance
  }

  filter(predicate) {
    if (typeof predicate === 'string') {
      let eventType = predicate
      predicate = (e) => this.match(e.type, eventType)
    }

    return super.filter(predicate)
  }
}

function createEvent(type, mode, args, cb) {
  args = args || []
  let event = { type, mode, args }

  if (cb) {
    event.cb = cb
  }

  return event
}

module.exports = Hooter
<commit_msg>hookBefore → hookStart, hookAfter → hookEnd<commit_after>const { Subject } = require('rxjs')
const corrie = require('corrie')
const wildcardMatch = require('wildcard-match')
const HookStore = require('./HookStore')

const MODES = ['auto', 'asIs', 'sync', 'async']

class Hooter extends Subject {
  constructor(settings) {
    super()
    this.corrie = settings ? corrie(settings) : corrie
    this.hookStoreBefore = new HookStore(this.match)
    this.hookStore = new HookStore(this.match)
    this.hookStoreAfter = new HookStore(this.match, true)
    this.events = {}
  }

  match(a, b) {
    return wildcardMatch('.', a, b)
  }

  lift(operator) {
    // Rxjs subjects return an AnonymousSubject on lifting,
    // but we want to return an instance of Hooter

    let instance = new this.constructor()

    if (operator) {
      instance.operator = operator
    }

    instance.source = this
    return instance
  }

  _subscribe(subscriber) {
    if (this.source) {
      return this.source.subscribe(subscriber)
    }

    return super._subscribe(subscriber)
  }

  error(err) {
    if (this.source && this.source.error) {
      return this.source.error(err)
    }

    super.error(err)
  }

  complete() {
    if (this.source && this.source.complete) {
      return this.source.complete()
    }

    super.complete()
  }

  _hook(eventType, hook, hookStore) {
    if (arguments.length === 1) {
      hook = eventType
      eventType = '**'
    } else if (typeof eventType !== 'string') {
      throw new TypeError('An event type must be a string')
    }

    if (typeof hook !== 'function') {
      throw new TypeError('A hook must be a function')
    }

    return hookStore.put(eventType, hook)
  }

  hook(eventType, hook) {
    return this._hook(eventType, hook, this.hookStore)
  }

  hookStart(eventType, hook) {
    return this._hook(eventType, hook, this.hookStoreBefore)
  }

  hookEnd(eventType, hook) {
    return this._hook(eventType, hook, this.hookStoreAfter)
  }

  unhook(needle) {
    this.hookStoreBefore.del(needle)
    this.hookStore.del(needle)
    this.hookStoreAfter.del(needle)
  }

  next(event) {
    if (!event || typeof event !== 'object') {
      throw new TypeError('An event must be an object')
    }

    if (typeof event.type !== 'string') {
      throw new TypeError('An event type must be a string')
    }

    if (!['auto', 'asIs', 'sync', 'async'].includes(event.mode)) {
      throw new Error(
        'An event mode must be either "auto", asIs", "sync" or "async"'
      )
    }

    if (event.cb && typeof event.cb !== 'function') {
      throw new TypeError('An event callback must be a function')
    }

    if (this._prefix) {
      event = Object.assign({}, event)
      event.type = `${this._prefix}.${event.type}`
    }

    if (this.source && this.source.next) {
      return this.source.next(event)
    }

    super.next(event)

    let beforeHooks = this.hookStoreBefore.get(event.type)
    let hooks = this.hookStore.get(event.type)
    let afterHooks = this.hookStoreAfter.get(event.type)
    let handlers = beforeHooks
      .concat(hooks)
      .concat(afterHooks)
      .map((hook) => hook.fn.bind(event))

    if (event.cb) {
      handlers.push(event.cb)
    }

    if (handlers.length === 0) {
      return
    } else if (event.mode === 'auto') {
      return this.corrie(...handlers)(...event.args)
    } else {
      return this.corrie[event.mode](...handlers)(...event.args)
    }
  }

  _toot(eventType, mode, args, cb) {
    let registeredEvent = this.events[eventType]

    if (registeredEvent) {
      if (mode) {
        throw new Error(
          `Event "${eventType}" is a registered event` +
            'and shouldn\'t be tooted with a custom mode'
        )
      }

      mode = registeredEvent.mode
    } else {
      mode = mode || 'auto'
    }

    let event = createEvent(eventType, mode, args, cb)
    return this.next(event)
  }

  toot(eventType, ...args) {
    return this._toot(eventType, null, args)
  }

  tootAuto(eventType, ...args) {
    return this._toot(eventType, 'auto', args)
  }

  tootAsIs(eventType, ...args) {
    return this._toot(eventType, 'asIs', args)
  }

  tootSync(eventType, ...args) {
    return this._toot(eventType, 'sync', args)
  }

  tootAsync(eventType, ...args) {
    return this._toot(eventType, 'async', args)
  }

  tootWith(eventType, cb, ...args) {
    return this._toot(eventType, null, args, cb)
  }

  tootAutoWith(eventType, cb, ...args) {
    return this._toot(eventType, 'auto', args, cb)
  }

  tootAsIsWith(eventType, cb, ...args) {
    return this._toot(eventType, 'asIs', args, cb)
  }

  tootSyncWith(eventType, cb, ...args) {
    return this._toot(eventType, 'sync', args, cb)
  }

  tootAsyncWith(eventType, cb, ...args) {
    return this._toot(eventType, 'async', args, cb)
  }

  register(eventType, mode) {
    if (typeof eventType !== 'string' || !eventType.length) {
      throw new Error('An event type must be a non-empty string')
    }

    if (this.events[eventType]) {
      throw new Error(`Event "${eventType}" is already registered`)
    }

    if (!MODES.includes(mode)) {
      throw new Error('A mode must be one of the following:', MODES.join(', '))
    }

    this.events[eventType] = { mode }
  }

  prefix(prefix) {
    if (typeof prefix !== 'string') {
      throw new TypeError('A prefix must be a string')
    }

    let instance = this.lift()
    instance._prefix = prefix
    return instance
  }

  filter(predicate) {
    if (typeof predicate === 'string') {
      let eventType = predicate
      predicate = (e) => this.match(e.type, eventType)
    }

    return super.filter(predicate)
  }
}

function createEvent(type, mode, args, cb) {
  args = args || []
  let event = { type, mode, args }

  if (cb) {
    event.cb = cb
  }

  return event
}

module.exports = Hooter
<|endoftext|>


<commit_before>mini.Module(
	"engine/map/entity"
)
.requires(
	"engine/map/entityrepository",
	"engine/rendering/animation",
	"engine/rendering/texture",
	"behaviour/trait"
)
.defines(function(
	EntityRepository,
	Animation,
	Texture,
	Trait
) {
	var Entity = mini.Class.subclass({
		initialize: function(x, y, settings) {
			this.stateAnimations = {};

			this.aabb = new Jello.AABB(
				new Jello.Vector2(x, y),
				new Jello.Vector2(x + 4, y + 4)
			);

			this.pos = Vector2.Zero.copy();
			this.offset = Vector2.Zero.copy();

			// Process settings.
			settings = settings || {};
			for( var s in settings ) {
				if(!settings.hasOwnProperty(s)) continue;

				this[s] = settings[s];
			}

			this.setState("idle");
		},

		addToLayer: function (layer) {
			layer.addEntity(this);

			return this;
		},

		/*
		 *  State
		 */
		state: function(name) {
			if(typeof name === "undefined") return this.__state__;
			if(typeof name === "string") {
				this.__state__ = name;
			} else if(typeof name === "function") {
				this.__state__ = name(this);
			} else {
				throw "incompatible state data type";
			};

			if(typeof this.stateAnimations[name] !== "undefined")
				this.animation = this.stateAnimations[name];
		},

		setState: function(name) {
			this.state(name);
		},

		getState: function() {
			return this.state();
		},

		/*
		 * Rendering/Animation
		 */
		addStateAnimation: function(name, sheet, frameTime, order) {
			this.stateAnimations[name] = new Animation(sheet, frameTime, order);
		},

		setTexture: function(texture) {
			this.texture = texture;
		},

		getTexture: function() {
			return this.texture;
		},

		drawTexture: function(renderer) {
			this.getTexture().drawOn(this.getBody(), renderer);
		},

		/*
		 * Physics
		 */
		setBody: function(body) {
			this.body = body;
		},

		getBody: function() {
			return this.body;
		},

		// TODO: replace with bodies aabb.
		// TODO: check for actual inclusion, not just aabb.
		contains: function(point) {
			return this.aabb.contains(point);
		},

		/*
		 * Behavior
		 */
		setTrait: function(trait) {
			this.trait = trait;
		},

		getTrait: function() {
			return this.trait;
		},

		/*
		 *  Updating
		 */
		update: function() {
			var trait = this.getTrait();
			if(typeof trait !== "undefined")
				trait.update(this);

			if(typeof this.animation !== "undefined")
				this.animation.update();
		},

		draw: function(renderer) {
			if(typeof this.getTexture() !== "undefined")
				this.drawTexture(renderer);
		},

		debugDraw: function(debugDraw) {
			if(typeof this.animation !== "undefined")
				this.animation.draw(this.aabb);
		}

	});

	EntityRepository.addClass("Entity", Entity);

	return Entity;
});
<commit_msg>implemented arbitrary drawCallbacks<commit_after>mini.Module(
	"engine/map/entity"
)
.requires(
	"engine/map/entityrepository",
	"engine/rendering/animation",
	"engine/rendering/texture",
	"behaviour/trait"
)
.defines(function(
	EntityRepository,
	Animation,
	Texture,
	Trait
) {
	var Entity = mini.Class.subclass({
		initialize: function(x, y, settings) {
			this.stateAnimations = {};

			this.aabb = new Jello.AABB(
				new Jello.Vector2(x, y),
				new Jello.Vector2(x + 4, y + 4)
			);

			this.pos = Vector2.Zero.copy();
			this.offset = Vector2.Zero.copy();

			// Process settings.
			settings = settings || {};
			for( var s in settings ) {
				if(!settings.hasOwnProperty(s)) continue;

				this[s] = settings[s];
			}

			this.setState("idle");

			// Draw callbacks
			this.drawCallbacks = [];
		},

		addToLayer: function (layer) {
			layer.addEntity(this);

			return this;
		},

		/*
		 *  State
		 */
		state: function(name) {
			if(typeof name === "undefined") return this.__state__;
			if(typeof name === "string") {
				this.__state__ = name;
			} else if(typeof name === "function") {
				this.__state__ = name(this);
			} else {
				throw "incompatible state data type";
			};

			if(typeof this.stateAnimations[name] !== "undefined")
				this.animation = this.stateAnimations[name];
		},

		setState: function(name) {
			this.state(name);
		},

		getState: function() {
			return this.state();
		},

		/*
		 * Rendering/Animation
		 */
		addStateAnimation: function(name, sheet, frameTime, order) {
			this.stateAnimations[name] = new Animation(sheet, frameTime, order);
		},

		// Texturing
		setTexture: function(texture) {
			this.texture = texture;
		},

		getTexture: function() {
			return this.texture;
		},

		drawTexture: function(renderer) {
			this.getTexture().drawOn(this.getBody(), renderer);
		},

		// DrawCallbacks
		addDrawCallback: function(callback) {
			this.drawCallbacks.push(callback);
		},

		clearDrawCallbacks: function() {
			this.drawCallbacks.length = 0;
		},

		applyDrawCallbacks: function(renderer) {
			for(var drawCallbackIndex in this.drawCallbacks) {
				this.drawCallbacks[drawCallbackIndex].call(this, renderer);
			}
		},

		/*
		 * Physics
		 */
		setBody: function(body) {
			this.body = body;
		},

		getBody: function() {
			return this.body;
		},

		// TODO: replace with bodies aabb.
		// TODO: check for actual inclusion, not just aabb.
		contains: function(point) {
			return this.aabb.contains(point);
		},

		/*
		 * Behavior
		 */
		setTrait: function(trait) {
			this.trait = trait;
		},

		getTrait: function() {
			return this.trait;
		},

		/*
		 *  Updating
		 */
		update: function() {
			var trait = this.getTrait();
			if(typeof trait !== "undefined")
				trait.update(this);

			if(typeof this.animation !== "undefined")
				this.animation.update();
		},

		draw: function(renderer) {
			if(typeof this.getTexture() !== "undefined")
				this.drawTexture(renderer);
			this.applyDrawCallbacks(renderer);
		},

		debugDraw: function(debugDraw) {
			if(typeof this.animation !== "undefined")
				this.animation.draw(this.aabb);
		}

	});

	EntityRepository.addClass("Entity", Entity);

	return Entity;
});
<|endoftext|>


<commit_before>mini.Module(
	"engine/map/entity"
)
.requires(
	"engine/map/entityrepository",
	"engine/rendering/animation",
	"engine/time/tween"
)
.defines(function(
	EntityRepository,
	Animation,
	Tween
) {
	var Entity = mini.Class.subclass({
		initialize: function() {
			this.stateAnimations = {};
			this.aabb = new Jello.AABB(
				Jello.Vector2.Zero.copy(),
				Jello.Vector2.One.copy()
			);
		},
		state: function(name) {
			if(typeof this.stateAnimations[name] !== "undefined")
				this.animation = this.stateAnimations[name];
		},
		addStateAnimation: function(name, sheet, frameTime, order) {
			this.stateAnimations[name] = new Animation(sheet, frameTime, order);
		},

		// Updating.
		update: function(timePassed) {
			if(typeof this.animation !== "undefined")
				this.animation.update(timePassed);
		},
		draw: function() {

		},
		debugDraw: function(debugDraw) {
			if(typeof this.animation !== "undefined")
				this.animation.draw(this.aabb);
		}
	});

	EntityRepository.addClass("Entity", Entity);

	return Entity;
});
<commit_msg>initialize Entity with position and settings<commit_after>mini.Module(
	"engine/map/entity"
)
.requires(
	"engine/map/entityrepository",
	"engine/rendering/animation",
	"engine/time/tween"
)
.defines(function(
	EntityRepository,
	Animation,
	Tween
) {
	var Entity = mini.Class.subclass({
		initialize: function(x, y, settings) {
			this.stateAnimations = {};
			this.aabb = new Jello.AABB(
				Jello.Vector2.Zero.copy(),
				Jello.Vector2.One.copy()
			);

			this.pos = Vector2.Zero.copy();
			this.offset = Vector2.Zero.copy();

			// Process settings.
			settings = settings || {};
			for( var s in settings ) {
				this[s] = settings[s];
			}
		},
		state: function(name) {
			if(typeof this.stateAnimations[name] !== "undefined")
				this.animation = this.stateAnimations[name];
		},
		addStateAnimation: function(name, sheet, frameTime, order) {
			this.stateAnimations[name] = new Animation(sheet, frameTime, order);
		},

		// Updating.
		update: function(timePassed) {
			if(typeof this.animation !== "undefined")
				this.animation.update(timePassed);
		},
		draw: function() {

		},
		debugDraw: function(debugDraw) {
			if(typeof this.animation !== "undefined")
				this.animation.draw(this.aabb);
		}
	});

	EntityRepository.addClass("Entity", Entity);

	return Entity;
});
<|endoftext|>


<commit_before>// style.js
const path = require('path');

function Style(file){
	this.file = file;
}

Style.create = function(file){
	return new Style(file);
}

Style.prototype.toTag = function(){
	let ext = path.parse(this.file);

	if (ext === '.js'){
		return this.toJSTag();
	} else {
		return this.toLinkTag();
	}
}

Style.prototype.toLinkTag = function(){
	return `<link rel="stylesheet" href="/css/${this.file}">`
}

Style.prototype.toJSTag = function(){
	return `<script src="${this.file}"></script>`;
}

var item2tag = item => Style.create(item).toTag();

let styleTable = {
	home: [
		'home.css'
	],
	cate: [
		'cate.css'
	],
	cates: [
		'cates.css'
	],
	blog: [
		'blog.css'
	]
}

let publicFiles = [

].map(item2tag)

module.exports = function(name){
	let fileArr = styleTable[name];

	return fileArr.map(item2tag).join('') + publicFiles.join('');
}
<commit_msg>!!BUG!!<commit_after>// style.js
const path = require('path');

function Style(file){
	this.file = file;
}

Style.create = function(file){
	return new Style(file);
}

Style.prototype.toTag = function(){
	let ext = path.parse(this.file);

	if (ext === '.js'){
		return this.toJSTag();
	} else {
		return this.toLinkTag();
	}
}

Style.prototype.toLinkTag = function(){
	return `<link rel="stylesheet" href="/css/${this.file}">`
}

Style.prototype.toJSTag = function(){
	return `<script src="/js/${this.file}"></script>`;
}

var item2tag = item => Style.create(item).toTag();

let styleTable = {
	home: [
		'home.css'
	],
	cate: [
		'cate.css'
	],
	cates: [
		'cates.css'
	],
	blog: [
		'blog.css'
	]
}

let publicFiles = [
	'flexible.min.js',
	'__________.css'
].map(item2tag)

module.exports = function(name){
	let fileArr = styleTable[name];

	return publicFiles.join('') + fileArr.map(item2tag).join('');
}
<|endoftext|>