<commit_before>var Fluxxor = require('fluxxor');
var Immutable = require('immutable');
var Cursor = require('immutable/contrib/cursor');

var BATCH_SIZE = 300;
var EMIT_INTERVAL = 300;

var constants = {
  ADD_LOG: 'ADD_LOG',
  ADD_RESOURCE: 'ADD_RESOURCE',
  ADD_ERROR: 'ADD_ERROR',
  SET_RESOURCE_RUNNING: 'SET_RESOURCE_RUNNING',
  SET_RESOURCE_ERRORED: 'SET_RESOURCE_ERRORED',
  TOGGLE_RESOURCE_LOGS: 'TOGGLE_RESOURCE_LOGS',
}

function LogsModel() {
  this.carriageReturned = false;
  this.lines = Immutable.fromJS([[[]]]);
  this.batchCursor = Cursor.from(this.lines, function(newLines) {
    this.lines = newLines;
  }.bind(this));
  this.linesCursor = this.batchCursor.last();

  this.addLog = function(line) {
    var sequence = ansiparse(line);

    for (var i = 0; i < sequence.length; i++) {
      if (sequence[i].cr) {
        this.carriageReturned = true;
      } else if (sequence[i].linebreak) {
        this.pushLine(Immutable.List())
        this.refreshCursor();
        this.carriageReturned = false;
        this.changed = true;
      } else if (this.carriageReturned) {
        if (sequence[i].text) {
          this.pushSequence(sequence[i]);
          var textLen = sequence[i].text.length;

          this.cursor.forEach(function(e, i) {
            if(e.text.length >= textLen) {
              e.text = e.text.substr(textLen);
              this.cursor = this.cursor.set(i, e);
              return false;
            } else {
              e.text = ''
              textLen -= e.text.length;
              this.cursor = this.cursor.set(i, e);
            }
          }, this);

          this.refreshLineCursor();
          this.changed = true;
        }
      } else {
        this.pushSequence(sequence[i]);
        this.refreshLineCursor();
      }
    };
  };

  this.addError = function(message) {
    this.pushLine(Immutable.List())
    this.refreshCursor();
    this.pushSequence({
      text: message,
      error: true,
    });
    this.refreshLineCursor();
    this.carriageReturned = false;
    this.changed = true;
  };

  this.refreshLineCursor = function() {
    this.linesCursor = this.linesCursor.set(this.linesCursor.count() - 1, this.cursor);
  };

  this.refreshCursor = function() {
    this.cursor = this.linesCursor.last();
  };

  this.pushLine = function(line) {
    if (this.linesCursor.count() >= BATCH_SIZE) {
      this.batchCursor = this.batchCursor.set(this.batchCursor.count() - 1, this.linesCursor);
      this.batchCursor = this.batchCursor.update(function(batches) {
        return batches.push(Immutable.List.of(line));
      });
      this.linesCursor = this.batchCursor.last();
    } else {
      this.linesCursor = this.linesCursor.update(function(lines) {
        return lines.push(line);
      });
    }
  };

  this.pushSequence = function(sequence) {
    this.cursor = this.cursor.update(function(line) {
      return line.push(sequence);
    });
  };

  this.refreshCursor();
  this.changed = false;
}

var LogStore = Fluxxor.createStore({
  initialize: function() {
    this.logs = {};
    this.bindActions(
      constants.ADD_LOG, this.onAddLog,
      constants.ADD_ERROR, this.onAddError
    );
    setInterval(this.emitEvents.bind(this), EMIT_INTERVAL);
  },

  getLogs: function(type) {
    if (this.logs[type] === undefined) {
      this.logs[type] = new LogsModel();
    }
    return this.logs[type];
  },

  onAddLog: function(data) {
    this.getLogs(data.type).addLog(data.line);
  },

  onAddError: function(data) {
    this.getLogs(data.type).addError(data.line);
  },

  emitEvents: function() {
    var shouldEmit = false;

    for (var k in this.logs) {
      if (this.logs.hasOwnProperty(k)) {
        if (this.logs[k].changed) {
          shouldEmit = true;
          break;
        }
      }
    }

    if (shouldEmit) {
      this.emit("change");

      for (var k in this.logs) {
        if (this.logs.hasOwnProperty(k)) {
          this.logs[k].changed = false
        }
      }
    }
  },

  getState: function() {
    var state = {};
    for (var k in this.logs) {
      if (this.logs.hasOwnProperty(k)) {
        state[k] = this.logs[k].lines;
      }
    }
    return Immutable.fromJS(state);
  },
});

var ResourceStore = Fluxxor.createStore({
  initialize: function() {
    this.resources = {};
    this.bindActions(
      constants.ADD_RESOURCE, this.onAddResource,
      constants.SET_RESOURCE_RUNNING, this.onSetResourceRunning,
      constants.SET_RESOURCE_ERRORED, this.onSetResourceErrored,
      constants.TOGGLE_RESOURCE_LOGS, this.onToggleResourceLogs
    );
  },

  addResource: function(type, resource) {
    if (this.resources[type] === undefined) {
      this.resources[type] = Immutable.Map();
    }
    resource.kind = type;
    var newResource = Immutable.fromJS(resource);
    if (this.resources[type].has(resource.name)) {
      newResource = this.resources[type].get(resource.name).merge(newResource);
    }
    this.setResource(type, resource.name, newResource);
    this.emit("change");
    return this.resources[type].get(resource.name);
  },

  updateResource: function(type, name, attributes) {
    attributes.name = name;
    this.addResource(type, attributes);
  },

  setResource: function(type, name, resource) {
    this.resources[type] = this.resources[type].set(name, resource);
  },

  onAddResource: function(data) {
    this.addResource(data.type, data.resource);
  },

  onSetResourceRunning: function(data) {
    this.updateResource(data.type, data.name, { running: data.value });
  },

  onSetResourceErrored: function(data) {
    this.updateResource(data.type, data.name, { errored: data.value });
  },

  onToggleResourceLogs: function(data) {
    var resource = this.resources[data.type].get(data.name);
    this.updateResource(data.type, data.name, { showLogs: !resource.get('showLogs') });
  },

  getState: function() {
    return Immutable.fromJS(this.resources);
  },
});

var actions = {
  addLog: function(type, line) {
    this.dispatch(constants.ADD_LOG, { type: type, line: line });
  },

  addError: function(type, line) {
    this.dispatch(constants.ADD_ERROR, { type: type, line: line });
  },

  addResource: function(type, resource) {
    this.dispatch(constants.ADD_RESOURCE, { type: type, resource: resource });
  },

  setResourceRunning: function(type, name, value) {
    this.dispatch(constants.SET_RESOURCE_RUNNING, { type: type, name: name, value: value });
  },

  setResourceErrored: function(type, name, value) {
    this.dispatch(constants.SET_RESOURCE_ERRORED, { type: type, name: name, value: value });
  },

  toggleResourceLogs: function(type, name) {
    this.dispatch(constants.TOGGLE_RESOURCE_LOGS, { type: type, name: name });
  },
}

var stores = {
  LogStore: new LogStore(),
  ResourceStore: new ResourceStore(),
};

module.exports = new Fluxxor.Flux(stores, actions);
<commit_msg>Improve ansi rendering, fixes \r parsing<commit_after>var Fluxxor = require('fluxxor');
var Immutable = require('immutable');
var Cursor = require('immutable/contrib/cursor');

var BATCH_SIZE = 300;
var EMIT_INTERVAL = 300;

var constants = {
  ADD_LOG: 'ADD_LOG',
  ADD_RESOURCE: 'ADD_RESOURCE',
  ADD_ERROR: 'ADD_ERROR',
  SET_RESOURCE_RUNNING: 'SET_RESOURCE_RUNNING',
  SET_RESOURCE_ERRORED: 'SET_RESOURCE_ERRORED',
  TOGGLE_RESOURCE_LOGS: 'TOGGLE_RESOURCE_LOGS',
}

function LogsModel() {
  this.carriageReturned = false;
  this.lines = Immutable.fromJS([[[]]]);
  this.batchCursor = Cursor.from(this.lines, function(newLines) {
    this.lines = newLines;
  }.bind(this));
  this.linesCursor = this.batchCursor.last();
  this.carriage = 0;

  this.addLog = function(line) {
    var sequence = ansiparse(line);

    for (var i = 0; i < sequence.length; i++) {
      if (sequence[i].cr) {
        this.carriage = 0;
      } else if (sequence[i].linebreak) {
        this.pushLine(Immutable.List())
        this.refreshCursor();
        this.carriage = 0;
        this.changed = true;
      } else if (sequence[i].text) {
        var textLen = sequence[i].text.length;
        var carriage = this.carriage;
        var cursor = this.cursor.update(function(line) {
          return line.slice(carriage);
        });
        this.cursor = this.cursor.update(function(line) {
          return line.slice(0, carriage);
        });
        this.pushSequence(sequence[i]);
        this.carriage++;

        cursor.forEach(function(e, i) {
          if(e.text.length >= textLen) {
            e.text = e.text.substr(textLen);
            textLen -= e.text.length;
            this.pushSequence(e);
            return false;
          }
        }, this);

        this.refreshLineCursor();
        this.changed = true;
      }
    };
  };

  this.addError = function(message) {
    this.pushLine(Immutable.List())
    this.refreshCursor();
    this.pushSequence({
      text: message,
      error: true,
    });
    this.refreshLineCursor();
    this.carriageReturned = false;
    this.changed = true;
  };

  this.refreshLineCursor = function() {
    this.linesCursor = this.linesCursor.set(this.linesCursor.count() - 1, this.cursor);
  };

  this.refreshCursor = function() {
    this.cursor = this.linesCursor.last();
  };

  this.pushLine = function(line) {
    if (this.linesCursor.count() >= BATCH_SIZE) {
      this.batchCursor = this.batchCursor.set(this.batchCursor.count() - 1, this.linesCursor);
      this.batchCursor = this.batchCursor.update(function(batches) {
        return batches.push(Immutable.List.of(line));
      });
      this.linesCursor = this.batchCursor.last();
    } else {
      this.linesCursor = this.linesCursor.update(function(lines) {
        return lines.push(line);
      });
    }
  };

  this.pushSequence = function(sequence) {
    this.cursor = this.cursor.update(function(line) {
      return line.push(sequence);
    });
  };

  this.refreshCursor();
  this.changed = false;
}

var LogStore = Fluxxor.createStore({
  initialize: function() {
    this.logs = {};
    this.bindActions(
      constants.ADD_LOG, this.onAddLog,
      constants.ADD_ERROR, this.onAddError
    );
    setInterval(this.emitEvents.bind(this), EMIT_INTERVAL);
  },

  getLogs: function(type) {
    if (this.logs[type] === undefined) {
      this.logs[type] = new LogsModel();
    }
    return this.logs[type];
  },

  onAddLog: function(data) {
    this.getLogs(data.type).addLog(data.line);
  },

  onAddError: function(data) {
    this.getLogs(data.type).addError(data.line);
  },

  emitEvents: function() {
    var shouldEmit = false;

    for (var k in this.logs) {
      if (this.logs.hasOwnProperty(k)) {
        if (this.logs[k].changed) {
          shouldEmit = true;
          break;
        }
      }
    }

    if (shouldEmit) {
      this.emit("change");

      for (var k in this.logs) {
        if (this.logs.hasOwnProperty(k)) {
          this.logs[k].changed = false
        }
      }
    }
  },

  getState: function() {
    var state = {};
    for (var k in this.logs) {
      if (this.logs.hasOwnProperty(k)) {
        state[k] = this.logs[k].lines;
      }
    }
    return Immutable.fromJS(state);
  },
});

var ResourceStore = Fluxxor.createStore({
  initialize: function() {
    this.resources = {};
    this.bindActions(
      constants.ADD_RESOURCE, this.onAddResource,
      constants.SET_RESOURCE_RUNNING, this.onSetResourceRunning,
      constants.SET_RESOURCE_ERRORED, this.onSetResourceErrored,
      constants.TOGGLE_RESOURCE_LOGS, this.onToggleResourceLogs
    );
  },

  addResource: function(type, resource) {
    if (this.resources[type] === undefined) {
      this.resources[type] = Immutable.Map();
    }
    resource.kind = type;
    var newResource = Immutable.fromJS(resource);
    if (this.resources[type].has(resource.name)) {
      newResource = this.resources[type].get(resource.name).merge(newResource);
    }
    this.setResource(type, resource.name, newResource);
    this.emit("change");
    return this.resources[type].get(resource.name);
  },

  updateResource: function(type, name, attributes) {
    attributes.name = name;
    this.addResource(type, attributes);
  },

  setResource: function(type, name, resource) {
    this.resources[type] = this.resources[type].set(name, resource);
  },

  onAddResource: function(data) {
    this.addResource(data.type, data.resource);
  },

  onSetResourceRunning: function(data) {
    this.updateResource(data.type, data.name, { running: data.value });
  },

  onSetResourceErrored: function(data) {
    this.updateResource(data.type, data.name, { errored: data.value });
  },

  onToggleResourceLogs: function(data) {
    var resource = this.resources[data.type].get(data.name);
    this.updateResource(data.type, data.name, { showLogs: !resource.get('showLogs') });
  },

  getState: function() {
    return Immutable.fromJS(this.resources);
  },
});

var actions = {
  addLog: function(type, line) {
    this.dispatch(constants.ADD_LOG, { type: type, line: line });
  },

  addError: function(type, line) {
    this.dispatch(constants.ADD_ERROR, { type: type, line: line });
  },

  addResource: function(type, resource) {
    this.dispatch(constants.ADD_RESOURCE, { type: type, resource: resource });
  },

  setResourceRunning: function(type, name, value) {
    this.dispatch(constants.SET_RESOURCE_RUNNING, { type: type, name: name, value: value });
  },

  setResourceErrored: function(type, name, value) {
    this.dispatch(constants.SET_RESOURCE_ERRORED, { type: type, name: name, value: value });
  },

  toggleResourceLogs: function(type, name) {
    this.dispatch(constants.TOGGLE_RESOURCE_LOGS, { type: type, name: name });
  },
}

var stores = {
  LogStore: new LogStore(),
  ResourceStore: new ResourceStore(),
};

module.exports = new Fluxxor.Flux(stores, actions);
<|endoftext|>


<commit_before>const { parse } = require('../util/purl');

const docker = require('./docker');
const github = require('./github');
const npm = require('./npm');
const nuget = require('./nuget');
const packagist = require('./packagist');
const pypi = require('./pypi');

const datasources = {
  docker,
  github,
  npm,
  nuget,
  packagist,
  pypi,
};

function getPkgReleases(purlStr, config) {
  const purl = parse(purlStr);
  if (!purl) {
    return null;
  }
  if (!datasources[purl.type]) {
    logger.warn('Unknown purl type: ' + purl.type);
    return null;
  }
  return datasources[purl.type].getPkgReleases(purl, config);
}

function supportsDigests(purlStr) {
  const purl = parse(purlStr);
  return !!datasources[purl.type].getPkgReleases;
}

function getDigest(config, value) {
  const purl = parse(config.purl);
  return datasources[purl.type].getDigest(config, value);
}

module.exports = {
  getPkgReleases,
  supportsDigests,
  getDigest,
};
<commit_msg>fix: supportsDigests<commit_after>const { parse } = require('../util/purl');

const docker = require('./docker');
const github = require('./github');
const npm = require('./npm');
const nuget = require('./nuget');
const packagist = require('./packagist');
const pypi = require('./pypi');

const datasources = {
  docker,
  github,
  npm,
  nuget,
  packagist,
  pypi,
};

function getPkgReleases(purlStr, config) {
  const purl = parse(purlStr);
  if (!purl) {
    return null;
  }
  if (!datasources[purl.type]) {
    logger.warn('Unknown purl type: ' + purl.type);
    return null;
  }
  return datasources[purl.type].getPkgReleases(purl, config);
}

function supportsDigests(purlStr) {
  const purl = parse(purlStr);
  return !!datasources[purl.type].getDigest;
}

function getDigest(config, value) {
  const purl = parse(config.purl);
  return datasources[purl.type].getDigest(config, value);
}

module.exports = {
  getPkgReleases,
  supportsDigests,
  getDigest,
};
<|endoftext|>


<commit_before>const assert = require('assert');
const React = require('react');
const parse = require('../');
const { data, render } = require('./helpers/');

describe('html-to-react', () => {
  describe('parser', () => {
    [undefined, null, {}, [], 42].forEach(value => {
      it(`throws an error if first argument is ${value}`, () => {
        assert.throws(() => {
          parse(value);
        }, TypeError);
      });
    });

    it('returns string if it cannot be parsed as HTML', () => {
      assert.equal(parse('foo'), 'foo');
    });

    it('converts single HTML element to React', () => {
      const html = data.html.single;
      const reactElement = parse(html);
      assert.equal(render(reactElement), html);
    });

    it('converts single HTML element and ignores comment', () => {
      const html = data.html.single;
      // comment should be ignored
      const reactElement = parse(html + data.html.comment);
      assert.equal(render(reactElement), html);
    });

    it('converts multiple HTML elements to React', () => {
      const html = data.html.multiple;
      const reactElements = parse(html);
      assert.equal(
        render(React.createElement('div', {}, reactElements)),
        '
' + html + '
'
      );
    });

    it('converts complex HTML to React', () => {
      const html = data.html.complex;
      const reactElement = parse(data.html.doctype + html);
      assert.equal(render(reactElement), html);
    });

    it('converts empty ';
      const reactElement = Parser(html);
      assert.equal(render(reactElement), html);
    });

    it('converts empty ';
      const reactElement = parse(html);
      assert.equal(render(reactElement), html);
    });

    it('converts SVG to React', () => {
      const svg = data.svg.complex;
      const reactElement = parse(svg);
      assert.equal(render(reactElement), svg);
    });

    it('decodes HTML entities', () => {
      const encodedEntities = 'asdf & ÿ ü '';
      const decodedEntities = "asdf & ÿ ü '";
      const reactElement = parse('' + encodedEntities + '');
      assert.equal(reactElement.props.children, decodedEntities);
    });
  });

  describe('options', () => {
    describe('replace', () => {
      it('overrides the element if replace is valid', () => {
        const html = data.html.complex;
        const reactElement = parse(html, {
          replace: node => {
            if (node.name === 'title') {
              return React.createElement('title', {}, 'Replaced Title');
            }
          }
        });
        assert.equal(
          render(reactElement),
          html.replace('<title>Title</title>', '<title>Replaced Title</title>')
        );
      });

      it('does not override the element if replace is invalid', () => {
        const html = data.html.complex;
        const reactElement = parse(html, {
          replace: node => {
            if (node.attribs && node.attribs.id === 'header') {
              return {
                type: 'h1',
                props: { children: 'Heading' }
              };
            }
          }
        });
        assert.notEqual(
          render(reactElement),
          html.replace(
            'Header',
            '
Heading
'
          )
        );
      });
    });
  });
});

describe('dom-to-react', () => {
  it('exports domToReact', () => {
    assert.equal(parse.domToReact, require('../lib/dom-to-react'));
  });
});
<commit_msg>test(html-to-react): update variable name to fix test<commit_after>const assert = require('assert');
const React = require('react');
const parse = require('../');
const { data, render } = require('./helpers/');

describe('html-to-react', () => {
  describe('parser', () => {
    [undefined, null, {}, [], 42].forEach(value => {
      it(`throws an error if first argument is ${value}`, () => {
        assert.throws(() => {
          parse(value);
        }, TypeError);
      });
    });

    it('returns string if it cannot be parsed as HTML', () => {
      assert.equal(parse('foo'), 'foo');
    });

    it('converts single HTML element to React', () => {
      const html = data.html.single;
      const reactElement = parse(html);
      assert.equal(render(reactElement), html);
    });

    it('converts single HTML element and ignores comment', () => {
      const html = data.html.single;
      // comment should be ignored
      const reactElement = parse(html + data.html.comment);
      assert.equal(render(reactElement), html);
    });

    it('converts multiple HTML elements to React', () => {
      const html = data.html.multiple;
      const reactElements = parse(html);
      assert.equal(
        render(React.createElement('div', {}, reactElements)),
        '
' + html + '
'
      );
    });

    it('converts complex HTML to React', () => {
      const html = data.html.complex;
      const reactElement = parse(data.html.doctype + html);
      assert.equal(render(reactElement), html);
    });

    it('converts empty ';
      const reactElement = parse(html);
      assert.equal(render(reactElement), html);
    });

    it('converts empty ';
      const reactElement = parse(html);
      assert.equal(render(reactElement), html);
    });

    it('converts SVG to React', () => {
      const svg = data.svg.complex;
      const reactElement = parse(svg);
      assert.equal(render(reactElement), svg);
    });

    it('decodes HTML entities', () => {
      const encodedEntities = 'asdf & ÿ ü '';
      const decodedEntities = "asdf & ÿ ü '";
      const reactElement = parse('' + encodedEntities + '');
      assert.equal(reactElement.props.children, decodedEntities);
    });
  });

  describe('options', () => {
    describe('replace', () => {
      it('overrides the element if replace is valid', () => {
        const html = data.html.complex;
        const reactElement = parse(html, {
          replace: node => {
            if (node.name === 'title') {
              return React.createElement('title', {}, 'Replaced Title');
            }
          }
        });
        assert.equal(
          render(reactElement),
          html.replace('<title>Title</title>', '<title>Replaced Title</title>')
        );
      });

      it('does not override the element if replace is invalid', () => {
        const html = data.html.complex;
        const reactElement = parse(html, {
          replace: node => {
            if (node.attribs && node.attribs.id === 'header') {
              return {
                type: 'h1',
                props: { children: 'Heading' }
              };
            }
          }
        });
        assert.notEqual(
          render(reactElement),
          html.replace(
            'Header',
            '
Heading
'
          )
        );
      });
    });
  });
});

describe('dom-to-react', () => {
  it('exports domToReact', () => {
    assert.equal(parse.domToReact, require('../lib/dom-to-react'));
  });
});
<|endoftext|>


<commit_before>/*global desc, task, jake, fail, complete */
(function(){
  "use strict";

  desc("build and test");
  task("default", ["lint", "test"]);

  desc("Lint everything");
  task("lint", [], function(){
    var lint = require("./build/lint/lint_runner.js");

    var files = new jake.FileList();
    files.include("**/*.js");
    files.exclude("node_modules");

    var options = nodeLintOptions();
    var passed = lint.validateFileList(files.toArray(), options, {});
    if (!passed)  fail("Lint failed");
  });

  desc("integrate");
  task("integrate", ["default"], function(){
    console.log("integration logic goes here");
  });

  desc("Test everything");
  task("test", [], function(){
    var reporter = require("nodeunit").reporters['default'];
    reporter.run(['src/server/_server_test.js']);
  });

  desc("Integrate");
  task("integrate", ["default"], function(){
    console.log("1. Make sure git status is clean.");
    console.log("2. Build on integration box");
    console.log("   a. walk over to integration box.");
    console.log("   b. 'git pull'");
    console.log("   c. 'jake'");
    console.log("   d. If jake fails, stop! Try again after fixing the issue");
    console.log("3. 'git checkout integration'");
    console.log("4. 'git merge master --no-ff, --log'");
    console.log("5. 'git checkout master'");
  });

  function nodeLintOptions(){
    return {
      bitwise: true,
      curly: false,
      eqeqeq: true,
      forin: true,
      immed: true,
      latedef: true,
      newcap: true,
      noarg: true,
      noempty: true,
      nonew: true,
      regexp: true,
      undef: true,
      strict: true,
      trailing: true,
      node: true
    };
  }
})();
<commit_msg>Build now fails if tests fails; also tests run in correct order; also color 'pass/ fail'<commit_after>/*global desc, task, jake, fail, complete */
(function(){
  "use strict";

  var red, green, reset;
  red   = '\u001b[31m';
  green  = '\u001b[32m';
  reset = '\u001b[0m';

  desc("build and test");
  task("default", ["lint", "test"]);

  desc("Lint everything");
  task("lint", [], function(){
    var lint = require("./build/lint/lint_runner.js");

    var files = new jake.FileList();
    files.include("**/*.js");
    files.exclude("node_modules");

    var options = nodeLintOptions();
    var passed = lint.validateFileList(files.toArray(), options, {});
    if (!passed)  fail("Lint failed");
  });

  desc("integrate");
  task("integrate", ["default"], function(){
    console.log("integration logic goes here");
  });

  desc("Test everything");
  task("test", [], function(){
    var reporter = require("nodeunit").reporters['default'];
    reporter.run(['src/server/_server_test.js'], null, function(failures){
      if(failures){
        fail(red + "Tests failed" + reset);
      }else{
        console.log(green + "Tests Passed" + reset);
      }
      complete();
    });
  }, { async: true });

  desc("Integrate");
  task("integrate", ["default"], function(){
    console.log("1. Make sure git status is clean.");
    console.log("2. Build on integration box");
    console.log("   a. walk over to integration box.");
    console.log("   b. 'git pull'");
    console.log("   c. 'jake'");
    console.log("   d. If jake fails, stop! Try again after fixing the issue");
    console.log("3. 'git checkout integration'");
    console.log("4. 'git merge master --no-ff, --log'");
    console.log("5. 'git checkout master'");
  });

  function nodeLintOptions(){
    return {
      bitwise: true,
      curly: false,
      eqeqeq: true,
      forin: true,
      immed: true,
      latedef: true,
      newcap: true,
      noarg: true,
      noempty: true,
      nonew: true,
      regexp: true,
      undef: true,
      strict: true,
      trailing: true,
      node: true
    };
  }
})();
<|endoftext|>


<commit_before>/* See license.txt for terms of usage */

/*
 * Formatter-wide preferences
 */
pref("extensions.firebug.fireformatHtmlFormatter.wrapSize", 80);    // Only affects attribute lists
pref("extensions.firebug.fireformatHtmlFormatter.indentChar", ' ');
pref("extensions.firebug.fireformatHtmlFormatter.indentCount", 2);
pref("extensions.firebug.fireformatHtmlFormatter.tabSize", 2);

/*
 * XML Doc Type formatter preferences
 */
pref("extensions.firebug.fireformatHtmlFormatter.xmlDocType.separatorBeforeVersion", " ");
pref("extensions.firebug.fireformatHtmlFormatter.xmlDocType.separatorBeforeEncoding", " ");
pref("extensions.firebug.fireformatHtmlFormatter.xmlDocType.separatorBeforeStandalone", " ");
pref("extensions.firebug.fireformatHtmlFormatter.xmlDocType.separatorBeforeClose", " ");

/*
 * Doc Type formatter preferences
 */
pref("extensions.firebug.fireformatHtmlFormatter.docType.separatorBeforeName", " ");
pref("extensions.firebug.fireformatHtmlFormatter.docType.separatorBeforeExternalId", " ");
pref("extensions.firebug.fireformatHtmlFormatter.docType.separatorBeforePublicId", " ");
pref("extensions.firebug.fireformatHtmlFormatter.docType.separatorBeforeSystemId", " ");
pref("extensions.firebug.fireformatHtmlFormatter.docType.separatorBeforeInternalSubset", " ");
pref("extensions.firebug.fireformatHtmlFormatter.docType.separatorBeforeClose", "");

/*
 * Processing Instruction formatter preferences
 */
pref("extensions.firebug.fireformatHtmlFormatter.pi.separatorBeforeData", "");

/*
 * Element formatter preferences
 */
pref("extensions.firebug.fireformatHtmlFormatter.element.htmlNameToLower", true);
pref("extensions.firebug.fireformatHtmlFormatter.element.separatorBeforeAttributes", "");
pref("extensions.firebug.fireformatHtmlFormatter.element.separatorBeforeClose", "");
pref("extensions.firebug.fireformatHtmlFormatter.element.separatorBeforeSelfClose", " ");

/*
 * Attribute list formatting
 */
pref("extensions.firebug.fireformatHtmlFormatter.attribute.attrsPerLine", 5);
pref("extensions.firebug.fireformatHtmlFormatter.attribute.indentLevel", 1);
pref("extensions.firebug.fireformatHtmlFormatter.attribute.listSeparator", " ");
pref("extensions.firebug.fireformatHtmlFormatter.attribute.separatorBeforeEquals", "");
pref("extensions.firebug.fireformatHtmlFormatter.attribute.separatorBeforeValue", "");
<commit_msg>Update defaults for non-blank preferences.<commit_after>/* See license.txt for terms of usage */

/*
 * Formatter-wide preferences
 */
pref("extensions.firebug.fireformatHtmlFormatter.wrapSize", 80);    // Only affects attribute lists
pref("extensions.firebug.fireformatHtmlFormatter.indentChar", ' ');
pref("extensions.firebug.fireformatHtmlFormatter.indentCount", 2);
pref("extensions.firebug.fireformatHtmlFormatter.tabSize", 2);

/*
 * XML Doc Type formatter preferences
 */
pref("extensions.firebug.fireformatHtmlFormatter.xmlDocType.separatorBeforeVersion", " ");
pref("extensions.firebug.fireformatHtmlFormatter.xmlDocType.separatorBeforeEncoding", " ");
pref("extensions.firebug.fireformatHtmlFormatter.xmlDocType.separatorBeforeStandalone", " ");
pref("extensions.firebug.fireformatHtmlFormatter.xmlDocType.separatorBeforeClose", " ");

/*
 * Doc Type formatter preferences
 */
pref("extensions.firebug.fireformatHtmlFormatter.docType.separatorBeforeName", " ");
pref("extensions.firebug.fireformatHtmlFormatter.docType.separatorBeforeExternalId", " ");
pref("extensions.firebug.fireformatHtmlFormatter.docType.separatorBeforePublicId", " ");
pref("extensions.firebug.fireformatHtmlFormatter.docType.separatorBeforeSystemId", " ");
pref("extensions.firebug.fireformatHtmlFormatter.docType.separatorBeforeInternalSubset", " ");
pref("extensions.firebug.fireformatHtmlFormatter.docType.separatorBeforeClose", "");

/*
 * Processing Instruction formatter preferences
 */
pref("extensions.firebug.fireformatHtmlFormatter.pi.separatorBeforeData", " ");

/*
 * Element formatter preferences
 */
pref("extensions.firebug.fireformatHtmlFormatter.element.htmlNameToLower", true);
pref("extensions.firebug.fireformatHtmlFormatter.element.separatorBeforeAttributes", " ");
pref("extensions.firebug.fireformatHtmlFormatter.element.separatorBeforeClose", "");
pref("extensions.firebug.fireformatHtmlFormatter.element.separatorBeforeSelfClose", " ");

/*
 * Attribute list formatting
 */
pref("extensions.firebug.fireformatHtmlFormatter.attribute.attrsPerLine", 5);
pref("extensions.firebug.fireformatHtmlFormatter.attribute.indentLevel", 1);
pref("extensions.firebug.fireformatHtmlFormatter.attribute.listSeparator", " ");
pref("extensions.firebug.fireformatHtmlFormatter.attribute.separatorBeforeEquals", "");
pref("extensions.firebug.fireformatHtmlFormatter.attribute.separatorBeforeValue", "");
<|endoftext|>


<commit_before>'use strict'

describe('View details for flashcardlist', function() {
    var LIST1_COUNT = 2;

    beforeEach(function() {
        browser().navigateTo('/');
        restartDB();
        sleep(0.3);
        browser().navigateTo('/#/FlashcardList/someFlashcardListId1');
    });

    it('should not redirect when going to the page', function() {
        // then
        expect(browser().window().hash()).toBe('/FlashcardList/someFlashcardListId1');
    });

    it('should show the proper title when going to the page', function() {
        expect(element('.page-header > h1').text()).toBe("Spanish for beginners");
    });

    it('should show a friendly message when there is no flashcards', function() {
        // given
        browser().navigateTo("/#/FlashcardList/someFlashcardListId3");

        // then
        expect(element('.page-header > h1').text()).toBe("List with no flashcards");
        expect(element('.flashcards-container > tr').count()).toBe(0);
        expect(element('.no-flashcards-message').count()).toBe(1);
    });

    it('should not show a message when entering the non-empty list', function() {
        expect(element('.no-flashcards-message').count()).toBe(0);
    });

    it('should display list of flashcards when entering the non-empty list', function() {
        // then
        expect(element('.flashcards-container > div').count()).toBe(LIST1_COUNT);

        expect(element('.flashcards-container > div:nth-child(1) > .front').text()).toMatch('front 1');
        expect(element('.flashcards-container > div:nth-child(1) > .back').text()).toMatch('back 1');

        expect(element('.flashcards-container > div:nth-child(2) > .front').text()).toMatch('front 2');
        expect(element('.flashcards-container > div:nth-child(2) > .back').text()).toMatch('back 2');
    });
});<commit_msg>e2e test for displaying the markdown<commit_after>'use strict'

describe('View details for flashcardlist', function() {
    var LIST1_COUNT = 2;

    beforeEach(function() {
        browser().navigateTo('/');
        restartDB();
        sleep(0.3);
        browser().navigateTo('/#/FlashcardList/someFlashcardListId1');
    });

    it('should not redirect when going to the page', function() {
        // then
        expect(browser().window().hash()).toBe('/FlashcardList/someFlashcardListId1');
    });

    it('should show the proper title when going to the page', function() {
        expect(element('.page-header > h1').text()).toBe("Spanish for beginners");
    });

    it('should show a friendly message when there is no flashcards', function() {
        // given
        browser().navigateTo("/#/FlashcardList/someFlashcardListId3");

        // then
        expect(element('.page-header > h1').text()).toBe("List with no flashcards");
        expect(element('.flashcards-container > tr').count()).toBe(0);
        expect(element('.no-flashcards-message').count()).toBe(1);
    });

    it('should not show a message when entering the non-empty list', function() {
        expect(element('.no-flashcards-message').count()).toBe(0);
    });

    it('should display list markdowned list of flashcards when entering the non-empty list', function() {
        // then
        expect(element('.flashcards-container > div').count()).toBe(LIST1_COUNT);

        expect(element('.flashcards-container > div:nth-child(1) > .front').text()).toMatch('front 1');
        expect(element('.flashcards-container > div:nth-child(1) > .back').text()).toMatch('back 1');

        expect(element('.flashcards-container > div:nth-child(2) > .front').text()).toMatch('front 2');
        expect(element('.flashcards-container > div:nth-child(2) > .back').text()).toMatch('back 2');
    });

});<|endoftext|>


<commit_before>var AWS = require('aws-sdk'),
  Promise = require('bluebird');

/**
 * Constructs and returns a new bloody simple SQS client.
 * @param {Object} options SQS client options.
 * @param {String} options.queueName the name of the queue to connect to.
 * @param {String} options.accessKeyId your AWS access key ID.
 * @param {String} options.secretAccessKey your AWS secret access key.
 * @param {String} [options.region=us-east-1] the region to send service requests to.
 * @constructor
 */
function BloodySimpleSQS(options) {
  var queueName, accessKeyId, secretAccessKey, region;

  // validate "options" param
  if (typeof options !== 'object') {
    throw new Error('Invalid or unspecified "options" param');
  }

  queueName = options.queueName || process.env.SQS_QUEUE_NAME;
  accessKeyId = options.accessKeyId || process.env.SQS_ACCESS_KEY_ID;
  secretAccessKey = options.secretAccessKey || process.env.SQS_SECRET_ACCESS_KEY;
  region = options.region || process.env.SQS_REGION || 'us-east-1';

  if (typeof queueName !== 'string') throw new Error('Invalid or unspecified "queueName" option');
  if (typeof accessKeyId !== 'string') throw new Error('Invalid or unspecified "accessKeyId" option');
  if (typeof secretAccessKey !== 'string') throw new Error('Invalid or unspecified "secretAccessKey" option');
  if (typeof region !== 'string') throw new Error('Invalid or unspecified "region" option');

  this.queueName = queueName;
  this.queueUrl = null;

  this.sqs = new AWS.SQS({
    queueName: queueName,
    accessKeyId: accessKeyId,
    secretAccessKey: secretAccessKey,
    region: region,
    apiVersion: '2012-11-05'
  });
}

/**
 * Retrieves the URL of the queue.
 * @return {Promise}
 * @private
 */
BloodySimpleSQS.prototype._getQueueUrl = function () {
  var params, resolver;

  // check if URL is already known
  if (this._queueUrl !== null) return Promise.resolve(this._queueUrl); // exit

  params = {
    QueueName: this.queueName
  };

  resolver = function(resolve, reject) {
    this.sqs.getQueueUrl(params, function(err, response) {
      if (err) return reject(err);

      resolve(response.QueueUrl);
    });
  }.bind(this);

  return new Promise(resolver);
};

/**
 * Appends a new message, with the designated body, at the end of the queue.
 * @param {Boolean|String|Number|Object|Null} body the body of the message.
 * @param {Function} [callback] an optional callback function, i.e. function (err, response).
 * @return {Promise}
 */
BloodySimpleSQS.prototype.add = function (body, callback) {
  var params, resolver;

  params = {
    QueueUrl: this.queueUrl,
    MessageBody: JSON.stringify(body)
  };

  resolver = function(resolve, reject) {
    this.sqs.sendMessage(params, function(err, response) {
      var message;

      if (err) return reject(err);

      message = {
        id: response.MessageId,
        body: body,
        md5: response.MD5OfMessageBody
      };

      resolve(message);
    });
  }.bind(this);

  return new Promise(resolver).nodeify(callback);
};

/**
 * Retrieves, but does not remove, the head of the queue.
 * @param {Object} [options] optional request options.
 * @param {Number} [options.timeout=0] number of seconds to wait until a message arrives in the queue.
 * @param {Function} [callback] an optional call back function, i.e. function (err, message, receiptHandle).
 * @return {Promise}
 */
BloodySimpleSQS.prototype.peek = function (options, callback) {
  var params, resolver;

  // handle optional "options" param
  if (typeof options === 'function') {
    callback = options;
    options = {};
  } else if (options === undefined) {
    options = {};
  }

  params = {
    QueueUrl: this.queueUrl,
    MaxNumberOfMessages: 1,
    WaitTimeSeconds: options.timeout || 0
  };

  resolver = function(resolve, reject) {
    this.sqs.receiveMessage(params, function(err, response) {
      var message;

      if (err) return reject(err);
      if (response.Messages.length === 0) return resolve();

      response = response.Messages[0];
      message = {
        id: response.MessageId,
        body: JSON.parse(response.Body),
        md5: response.MD5OfBody,
        receiptHandle: response.ReceiptHandle
      };

      resolve(message);
    });
  }.bind(this);

  return new Promise(resolver).nodeify(callback);
};

/**
 * Removes the designated message from queue.
 * @param {String} receiptHandle the message's receipt handle, as given on peek().
 * @param {Function} [callback] an optional callback function, i.e. function (err).
 * @return {Promise}
 */
BloodySimpleSQS.prototype.remove = function (receiptHandle, callback) {
  var params, resolver;

  params = {
    QueueUrl: this.queueUrl,
    ReceiptHandle: receiptHandle
  };

  resolver = function(resolve, reject) {
    this.sqs.deleteMessage(params, function(err) {
      if (err) return reject(err);

      resolve();
    });
  }.bind(this);

  return new Promise(resolver).nodeify(callback);
};

/**
 * Retrieves and removes the head of this queue, or returns null if this queue is empty.
 * @param {Object} [options] optional request options.
 * @param {Function} [callback] an optional call back function, i.e. function (err, message, receiptHandle).
 * @see {@link peek} for further information on the "options" param.
 * @return {Promise}
 */
BloodySimpleSQS.prototype.poll = function (options, callback) {
  return this.peek(options)
    .bind(this)
    .then(function (message) {
      return this.remove(message.receiptHandle)
        .then(function () {
          return message;
        });
    }).nodeify(callback);
};

module.exports = BloodySimpleSQS;

// var sqs = new BloodySimpleSQS();
// sqs.add(123).then(function (response) {
//   console.log(response);

//   sqs.poll().then(function (message) {
//     console.log(message);
//   });
// });
<commit_msg>BloodySimpleSQS extends EventEmitter. Emits a "ready" event after queue URL has been retrieved from AWS. #poll #remove #add #peek wait for the ready event before being executed.<commit_after>var events = require('events'),
  util = require('util'),
  AWS = require('aws-sdk'),
  Promise = require('bluebird');

/**
 * Constructs and returns a new bloody simple SQS client.
 * @param {Object} options SQS client options.
 * @param {String} options.queueName the name of the queue to connect to.
 * @param {String} options.accessKeyId your AWS access key ID.
 * @param {String} options.secretAccessKey your AWS secret access key.
 * @param {String} [options.region=us-east-1] the region to send service requests to.
 * @constructor
 */
function BloodySimpleSQS(options) {
  var queueName, accessKeyId, secretAccessKey, region;

  // validate "options" param
  if (typeof options !== 'object') {
    throw new Error('Invalid or unspecified "options" param');
  }

  queueName = options.queueName;
  accessKeyId = options.accessKeyId;
  secretAccessKey = options.secretAccessKey;
  region = options.region || 'us-east-1';

  if (typeof queueName !== 'string') throw new Error('Invalid or unspecified "queueName" option');
  if (typeof accessKeyId !== 'string') throw new Error('Invalid or unspecified "accessKeyId" option');
  if (typeof secretAccessKey !== 'string') throw new Error('Invalid or unspecified "secretAccessKey" option');
  if (typeof region !== 'string') throw new Error('Invalid or unspecified "region" option');

  this.queueName = queueName;

  this.sqs = new AWS.SQS({
    queueName: queueName,
    accessKeyId: accessKeyId,
    secretAccessKey: secretAccessKey,
    region: region,
    apiVersion: '2012-11-05'
  });

  events.EventEmitter.call(this);
  this.setMaxListeners(99);

  // load data from aws and emit ready
  this._getQueueUrl().bind(this).then(function (url) {
    this.queueUrl = url;
    this.isReady = true;
    this.emit('ready');
  });
}

// BloodySimpleSQS extends the EventEmitter class
util.inherits(BloodySimpleSQS, events.EventEmitter);

/**
 * Retrieves the URL of the queue from AWS.
 * @return {Promise}
 * @private
 */
BloodySimpleSQS.prototype._getQueueUrl = function () {
  var self = this,
    resolver;

  resolver = function(resolve, reject) {

    var params = {
      QueueName: self.queueName
    };

    self.sqs.getQueueUrl(params, function(err, response) {
      if (err) return reject(err);

      resolve(response.QueueUrl);
    });

  };

  return new Promise(resolver);
};

/**
 * Appends a new message, with the designated body, at the end of the queue.
 * @param {Boolean|String|Number|Object|Null} body the body of the message.
 * @param {Function} [callback] an optional callback function, i.e. function (err, response).
 * @return {Promise}
 */
BloodySimpleSQS.prototype.add = function (body, callback) {
  var self = this,
    resolver;

  resolver = function(resolve, reject) {

    var params = {
      QueueUrl: self.queueUrl,
      MessageBody: JSON.stringify(body)
    };

    self.sqs.sendMessage(params, function(err, response) {
      var message;

      if (err) return reject(err);

      message = {
        id: response.MessageId,
        body: body,
        md5: response.MD5OfMessageBody
      };

      resolve(message);
    });

  };

  return new Promise(function(resolve, reject) {
    if (self.isReady) {
      resolver(resolve, reject);
    } else { // delay until ready
      self.once('ready', function () {
        resolver(resolve, reject);
      });
    }
  }).nodeify(callback);
};

/**
 * Retrieves, but does not remove, the head of the queue.
 * @param {Object} [options] optional request options.
 * @param {Number} [options.timeout=0] number of seconds to wait until a message arrives in the queue.
 * @param {Function} [callback] an optional call back function, i.e. function (err, message, receiptHandle).
 * @return {Promise}
 */
BloodySimpleSQS.prototype.peek = function (options, callback) {
  var self = this,
    resolver;

  // handle optional "options" param
  if (typeof options === 'function') {
    callback = options;
    options = {};
  } else if (options === undefined) {
    options = {};
  }

  resolver = function(resolve, reject) {

    var params = {
      QueueUrl: self.queueUrl,
      MaxNumberOfMessages: 1,
      WaitTimeSeconds: options.timeout || 0
    };

    self.sqs.receiveMessage(params, function(err, response) {
      var message;

      if (err) return reject(err);
      if (response.Messages.length === 0) return resolve();

      response = response.Messages[0];
      message = {
        id: response.MessageId,
        body: JSON.parse(response.Body),
        md5: response.MD5OfBody,
        receiptHandle: response.ReceiptHandle
      };

      resolve(message);
    });

  };

  return new Promise(function(resolve, reject) {
    if (self.isReady) {
      resolver(resolve, reject);
    } else { // delay until ready
      self.once('ready', function () {
        resolver(resolve, reject);
      });
    }
  }).nodeify(callback);
};

/**
 * Removes the designated message from queue.
 * @param {String} receiptHandle the message's receipt handle, as given on peek().
 * @param {Function} [callback] an optional callback function, i.e. function (err).
 * @return {Promise}
 */
BloodySimpleSQS.prototype.remove = function (receiptHandle, callback) {
  var self = this,
    resolver;

  resolver = function(resolve, reject) {

    var params = {
      QueueUrl: self.queueUrl,
      ReceiptHandle: receiptHandle
    };

    self.sqs.deleteMessage(params, function(err) {
      if (err) return reject(err);

      resolve();
    });

  };

  return new Promise(function(resolve, reject) {
    if (self.isReady) {
      resolver(resolve, reject);
    } else { // delay until ready
      self.once('ready', function () {
        resolver(resolve, reject);
      });
    }
  }).nodeify(callback);
};

/**
 * Retrieves and removes the head of this queue, or returns null if this queue is empty.
 * @param {Object} [options] optional request options.
 * @param {Function} [callback] an optional call back function, i.e. function (err, message, receiptHandle).
 * @see {@link peek} for further information on the "options" param.
 * @return {Promise}
 */
BloodySimpleSQS.prototype.poll = function (options, callback) {
  return this.peek(options).bind(this).then(function (message) {
    return this.remove(message.receiptHandle).then(function () {
      return message;
    });
  }).nodeify(callback);
};

module.exports = BloodySimpleSQS;

// require('dotenv').load();
// var sqs = new BloodySimpleSQS({
//   queueName: process.env.SQS_QUEUE_NAME,
//   accessKeyId: process.env.SQS_ACCESS_KEY_ID,
//   secretAccessKey: process.env.SQS_SECRET_ACCESS_KEY,
//   region: process.env.SQS_REGION
// });
// sqs.add(123).then(function (response) {
//   console.log(response);

//   sqs.poll().then(function (message) {
//     console.log(message);
//   });
// });
<|endoftext|>


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

module.exports = {
  name: 'wordpress',
  guess: function(websiteUrl, next) {
    var system = this;
    async.parallel({
      readme: system.methods.readme.bind(null,websiteUrl),
      generatorHeader: system.methods.generatorHeader.bind(null,websiteUrl),
      generatorMetaOrScript: system.methods.generatorMetaOrScript.bind(null,websiteUrl),
      buttonCss: system.methods.buttonCss.bind(null,websiteUrl),
    }, function(err, results) {
        // result now equals the first file in the list that exists
        if(err){
          console.log('Error while guessing Wordpress', err);
          next(err,null);
          return;
        }

        var methods  = [];
        for(method in results){
          if(results[method]){
            methods.push(method);
          }
        }
        next(null, {guessed: methods.length > 0, method: methods});
    });
  },
  methods: {
    readme: function(websiteUrl, callback) {
      var request = require("request");

      // Check changelog
      request({
        uri: websiteUrl + '/readme.html',
      }, function(error, response, body) {
        // Something went wrong
        if(error){
          callback({method: 'readme', err: error}, null);
          return;
        }

        if(body && body.indexOf('WordPress › ReadMe') > -1) {
          callback(error, true);
        }else{
          callback(error, false);
        }
      });
    },

    generatorHeader: function(websiteUrl, callback) {
      var request = require("request");
      // Check generator headers
      request({
        method: 'HEAD',
        uri: websiteUrl,
      }, function(error, response, body) {
        // Something went wrong
        if(error){
          callback({method: 'generatorHeader', err: error}, null);
          return;
        }
        if('x-generator' in response.headers && response.headers['x-generator'].indexOf('WordPress') > -1){
          callback(error, true);
        }else{
          callback(error, false);
        }
      });
    },

    generatorMetaOrScript: function(websiteUrl, callback) {

      var request = require("request");
      var cheerio = require("cheerio");

      request({
        uri: websiteUrl,
      }, function(error, response, body) {
        // Something went wrong
        if(error){
          callback({method: 'generatorMetaOrScript', err: error}, null);
          return;
        }

        var $ = cheerio.load(body);
        // Check meta tags for generator, script & api
        if( ( $('meta[name="generator"]').attr('content')
          && $('meta[name="generator"]').attr('content').indexOf("Wordpress") > -1 )
          || $('script[src*="wp-includes"]').length > 0
          || $('script[link*="wp-json"]').length > 0){
          callback(error, true);
        }else{
          callback(error, false);
        }
      });
    },

    buttonCss: function(websiteUrl, callback) {

      var request = require("request");
      // Check CSS
      request({
        uri: websiteUrl+'/wp-includes/css/buttons.css',
      }, function(error, response, body) {
        // Something went wrong
        if(error){
          callback({method: 'buttonCss', err: error}, null);
          return;
        }
        // Check modules/node/node.css content
        if(body && body.indexOf('WordPress-style Buttons') > -1) {
          callback(error, true);
        }else{
          callback(error, false);
        }
      });
    },
  },
  version: function(websiteUrl, callback){
    var request = require("request");

    // Check readme
    request({
      uri: websiteUrl + '/feed/',
    }, function(error, response, body) {

      // Something went wrong
      if(error){
        callback(error, null);
        return;
      }

      // Check version
      var regex = /<generator>http:\/\/wordpress.org\/\?v=([0-9\.]+)<\/generator>/i;
      var match = body.match(regex);
      if(match && match.length == 2){
        callback(null, match[1]);
      }else{
        callback(new Error('Unable to get version in (/feed)'), null);
      }
    });
  }
};<commit_msg>Adapting Regex to best match Version with protocol(http/https)<commit_after>var async = require('async');

module.exports = {
  name: 'wordpress',
  guess: function(websiteUrl, next) {
    var system = this;
    async.parallel({
      readme: system.methods.readme.bind(null,websiteUrl),
      generatorHeader: system.methods.generatorHeader.bind(null,websiteUrl),
      generatorMetaOrScript: system.methods.generatorMetaOrScript.bind(null,websiteUrl),
      buttonCss: system.methods.buttonCss.bind(null,websiteUrl),
    }, function(err, results) {
        // result now equals the first file in the list that exists
        if(err){
          console.log('Error while guessing Wordpress', err);
          next(err,null);
          return;
        }

        var methods  = [];
        for(method in results){
          if(results[method]){
            methods.push(method);
          }
        }
        next(null, {guessed: methods.length > 0, method: methods});
    });
  },
  methods: {
    readme: function(websiteUrl, callback) {
      var request = require("request");

      // Check changelog
      request({
        uri: websiteUrl + '/readme.html',
      }, function(error, response, body) {
        // Something went wrong
        if(error){
          callback({method: 'readme', err: error}, null);
          return;
        }

        if(body && body.indexOf('WordPress › ReadMe') > -1) {
          callback(error, true);
        }else{
          callback(error, false);
        }
      });
    },

    generatorHeader: function(websiteUrl, callback) {
      var request = require("request");
      // Check generator headers
      request({
        method: 'HEAD',
        uri: websiteUrl,
      }, function(error, response, body) {
        // Something went wrong
        if(error){
          callback({method: 'generatorHeader', err: error}, null);
          return;
        }
        if('x-generator' in response.headers && response.headers['x-generator'].indexOf('WordPress') > -1){
          callback(error, true);
        }else{
          callback(error, false);
        }
      });
    },

    generatorMetaOrScript: function(websiteUrl, callback) {

      var request = require("request");
      var cheerio = require("cheerio");

      request({
        uri: websiteUrl,
      }, function(error, response, body) {
        // Something went wrong
        if(error){
          callback({method: 'generatorMetaOrScript', err: error}, null);
          return;
        }

        var $ = cheerio.load(body);
        // Check meta tags for generator, script & api
        if( ( $('meta[name="generator"]').attr('content')
          && $('meta[name="generator"]').attr('content').indexOf("Wordpress") > -1 )
          || $('script[src*="wp-includes"]').length > 0
          || $('script[link*="wp-json"]').length > 0){
          callback(error, true);
        }else{
          callback(error, false);
        }
      });
    },

    buttonCss: function(websiteUrl, callback) {

      var request = require("request");
      // Check CSS
      request({
        uri: websiteUrl+'/wp-includes/css/buttons.css',
      }, function(error, response, body) {
        // Something went wrong
        if(error){
          callback({method: 'buttonCss', err: error}, null);
          return;
        }
        // Check modules/node/node.css content
        if(body && body.indexOf('WordPress-style Buttons') > -1) {
          callback(error, true);
        }else{
          callback(error, false);
        }
      });
    },
  },
  version: function(websiteUrl, callback){
    var request = require("request");

    // Check readme
    request({
      uri: websiteUrl + '/feed/',
    }, function(error, response, body) {

      // Something went wrong
      if(error){
        callback(error, null);
        return;
      }

      // Check version
      var regex = /<generator>https?:\/\/wordpress.org\/\?v=([0-9\.]+)<\/generator>/i;
      var match = body.match(regex);
      if(match && match.length == 2){
        callback(null, match[1]);
      }else{
        callback(new Error('Unable to get version in (/feed)'), null);
      }
    });
  }
};<|endoftext|>


<commit_before>// ==UserScript==
// @author      PotcFdk
// @name        Steam Discovery Queue Auto-Skipper
// @namespace   https://github.com/PotcFdk/SteamDiscoveryQueueAutoSkipper
// @description Auto-clicks the "Next in Queue" button in Steam Discovery Queues.
// @include     http://store.steampowered.com/app/*
// @include     https://store.steampowered.com/app/*
// @include     http://store.steampowered.com/agecheck/app/*
// @include     https://store.steampowered.com/agecheck/app/*
// @include     http://store.steampowered.com/explore/next/*
// @include     https://store.steampowered.com/explore/next/*
// @version     0.3.0
// @grant       none
// @downloadURL https://raw.githubusercontent.com/PotcFdk/SteamDiscoveryQueueAutoSkipper/master/SteamDiscoveryQueueAutoSkipper.user.js
// @updateURL   https://raw.githubusercontent.com/PotcFdk/SteamDiscoveryQueueAutoSkipper/master/SteamDiscoveryQueueAutoSkipper.meta.js
// ==/UserScript==<commit_msg>Automatically start new queue if card drops remain<commit_after>// ==UserScript==
// @author      PotcFdk
// @name        Steam Discovery Queue Auto-Skipper
// @namespace   https://github.com/PotcFdk/SteamDiscoveryQueueAutoSkipper
// @description Auto-clicks the "Next in Queue" button in Steam Discovery Queues.
// @include     http://store.steampowered.com/app/*
// @include     https://store.steampowered.com/app/*
// @include     http://store.steampowered.com/agecheck/app/*
// @include     https://store.steampowered.com/agecheck/app/*
// @include     http://store.steampowered.com/explore*
// @include     https://store.steampowered.com/explore*
// @version     0.3.1
// @grant       none
// @downloadURL https://raw.githubusercontent.com/PotcFdk/SteamDiscoveryQueueAutoSkipper/master/SteamDiscoveryQueueAutoSkipper.user.js
// @updateURL   https://raw.githubusercontent.com/PotcFdk/SteamDiscoveryQueueAutoSkipper/master/SteamDiscoveryQueueAutoSkipper.meta.js
// ==/UserScript==
<|endoftext|>


<commit_before>//Translated from group.rb using babyruby2js
'use strict';

var Grid = require('./Grid');
var main = require('./main');

var EMPTY = main.EMPTY;

/** @class
 *  A group keeps the list of its stones, the updated number of "lives" (empty intersections around),
 *  and whatever status information we need to decide what happens to a group (e.g. when a
 *  group is killed or merged with another group, etc.).
 *  Note that most of the work here is to keep this status information up to date.
 *    public read-only attribute: goban, stones, lives, color
 *    public read-only attribute: mergedWith, mergedBy, killedBy, ndx
 *    public write attribute: mergedWith, mergedBy, extraLives  *  only used in this file
 *  Create a new group. Always with a single stone.
 *  Do not call this using Group.new but Goban#newGroup instead.
 */
function Group(goban, stone, lives, ndx) {
    this.goban = goban;
    this.stones = [stone];
    this.lives = lives;
    this.color = stone.color;
    this.mergedWith = null; // a group
    this.mergedBy = null; // a stone
    this.killedBy = null; // a stone
    this.ndx = ndx; // unique index
    this.isAlive = this.isDead = 0; // used by analysis
}
module.exports = Group;

Group.prototype.recycle = function (stone, lives, ndx) {
    this.stones.clear();
    this.stones.push(stone);
    this.lives = lives;
    this.color = stone.color;
    this.mergedWith = this.mergedBy = this.killedBy = null;
    this.ndx = ndx;
    return this;
};

Group.prototype.clear = function () {
    for (var i = this.stones.length - 1; i >= 0; i--) {
        this.stones[i].clear();
    }
    this.goban.garbageGroups.push(this);
};

Group.prototype.toString = function () {
    var s = '{group #' + this.ndx + ' of ' + this.stones.length + ' ' + Grid.colorName(this.color) + ' stones [';
    for (var stone, stone_array = this.stones, stone_ndx = 0; stone=stone_array[stone_ndx], stone_ndx < stone_array.length; stone_ndx++) {
        s += stone.asMove() + ',';
    }
    s = s.chop();
    s += '], lives:' + this.lives;
    if (this.mergedWith) {
        s += ' MERGED with #' + this.mergedWith.ndx;
    }
    if (this.killedBy) {
        s += ' KILLED by ' + this.killedBy.asMove();
    }
    s += '}';
    return s;
};

// debug dump does not have more to display now that stones are simpler
// TODO: remove it unless stones get more state data to display
Group.prototype.debugDump = function () {
    return this.toString();
};

Group.prototype.stonesDump = function () {
    return this.stones.map(function (s) {
        return s.asMove();
    }).sort().join(',');
};

// Builds a list of all lives of the group (empty stones around)
// Costly!
Group.prototype.allLives = function () {
    var lives = [];
    for (var s, s_array = this.stones, s_ndx = 0; s=s_array[s_ndx], s_ndx < s_array.length; s_ndx++) {
        for (var life, life_array = s.neighbors, life_ndx = 0; life=life_array[life_ndx], life_ndx < life_array.length; life_ndx++) {
            if (life.color !== EMPTY) continue;

            if (lives.indexOf(life) < 0) lives.push(life);
        }
    }
    return lives;
};

// Builds a list of all enemies of the group
// Costly!
Group.prototype.allEnemies = function () {
    var enemies = [];
    var enemyColor = 1 - this.color;
    for (var s, s_array = this.stones, s_ndx = 0; s=s_array[s_ndx], s_ndx < s_array.length; s_ndx++) {
        for (var en, en_array = s.neighbors, en_ndx = 0; en=en_array[en_ndx], en_ndx < en_array.length; en_ndx++) {
            if (en.color !== enemyColor) continue;

            if (enemies.indexOf(en.group) < 0) enemies.push(en.group);
        }
    }
    if (main.debugGroup) main.log.debug(this + ' has ' + enemies.length + ' enemies');
    return enemies;
};

// Counts the lives of a stone that are not already in the group
// (the stone is to be added or removed)
Group.prototype.livesAddedByStone = function (stone) {
    var lives = 0;
    for (var life, life_array = stone.neighbors, life_ndx = 0; life=life_array[life_ndx], life_ndx < life_array.length; life_ndx++) {
        if (life.color !== EMPTY) continue;

        lives++;
        for (var s, s_array = life.neighbors, s_ndx = 0; s=s_array[s_ndx], s_ndx < s_array.length; s_ndx++) {
            if (s.group === this && s !== stone) {
                lives--;
                break;
            }
        }
    }
    if (main.debugGroup) main.log.debug(lives + ' lives added by ' + stone + ' for group ' + this);
    return lives;
};

// Connect a new stone or a merged stone to this group
Group.prototype.connectStone = function (stone, onMerge) {
    if (onMerge === undefined) onMerge = false;
    if (main.debugGroup) main.log.debug('Connecting ' + stone + ' to group ' + this + ' (on_merge=' + onMerge + ')');

    this.stones.push(stone);
    this.lives += this.livesAddedByStone(stone);
    if (!onMerge) this.lives--; // minus one since the connection itself removes 1

    if (this.lives < 0) { // can be 0 if suicide-kill
        throw new Error('Unexpected error (lives<0 on connect)');
    }
    if (main.debugGroup) main.log.debug('Final group: ' + this);
};

// Disconnect a stone
// on_merge must be true for merge or unmerge-related call
Group.prototype.disconnectStone = function (stone, onMerge) {
    if (onMerge === undefined) onMerge = false;
    if (main.debugGroup) {
        main.log.debug('Disconnecting ' + stone + ' from group ' + this + ' (on_merge=' + onMerge + ')');
    }
    // groups of 1 stone become empty groups (->garbage)
    if (this.stones.length > 1) {
        this.lives -= this.livesAddedByStone(stone);
        if (!onMerge) { // see comment in connect_stone
            this.lives += 1;
        }
        if (this.lives < 0) { // can be 0 if suicide-kill
            throw new Error('Unexpected error (lives<0 on disconnect)');
        }
    } else {
        this.goban.garbageGroups.push(this);
        if (main.debugGroup) main.log.debug('Group going to recycle bin: ' + this);
    }
    // we always remove them in the reverse order they came
    if (this.stones.pop() !== stone) {
        throw new Error('Unexpected error (disconnect order)');
    }
};

// When a new stone appears next to this group
Group.prototype.attackedBy = function (stone) {
    this.lives -= 1;
    if (this.lives <= 0) { // also check <0 so we can raise in die_from method
        return this._dieFrom(stone);
    }
};

// When a group of stones reappears because we undo
// NB: it can never kill anything
Group.prototype._attackedByResuscitated = function (stone) {
    this.lives--;
    if (main.debugGroup) main.log.debug(this + ' attacked by resuscitated ' + stone);

    if (this.lives < 1) throw new Error('Unexpected error (lives<1 on attack by resucitated)');
};

// Stone parameter is just for debug for now
Group.prototype.notAttackedAnymore = function (stone) {
    this.lives++;
    if (main.debugGroup) main.log.debug(this + ' not attacked anymore by ' + stone);
};

// Merges a subgroup with this group
Group.prototype.merge = function (subgroup, byStone) {
    if (subgroup.mergedWith === this || subgroup === this || this.color !== subgroup.color) {
        throw new Error('Invalid merge');
    }
    if (main.debugGroup) main.log.debug('Merging subgroup:' + subgroup + ' to main:' + this);

    for (var s, s_array = subgroup.stones, s_ndx = 0; s=s_array[s_ndx], s_ndx < s_array.length; s_ndx++) {
        s.setGroupOnMerge(this);
        this.connectStone(s, true);
    }
    subgroup.mergedWith = this;
    subgroup.mergedBy = byStone;
    this.goban.mergedGroups.push(subgroup);
    if (main.debugGroup) main.log.debug('After merge: subgroup:' + subgroup + ' main:' + this);
};

// Reverse of merge
Group.prototype._unmerge = function (subgroup) {
    if (main.debugGroup) main.log.debug('Unmerging subgroup:' + subgroup + ' from main:' + this);

    for (var s, s_array = subgroup.stones, s_ndx = s_array.length - 1; s=s_array[s_ndx], s_ndx >= 0; s_ndx--) {
        this.disconnectStone(s, true);
        s.setGroupOnMerge(subgroup);
    }
    subgroup.mergedBy = subgroup.mergedWith = null;
    if (main.debugGroup) main.log.debug('After _unmerge: subgroup:' + subgroup + ' main:' + this);
};

// This must be called on the main group (stone.group)
Group.prototype.unmergeFrom = function (stone) {
    for (;;) {
        var subgroup = this.goban.mergedGroups[this.goban.mergedGroups.length - 1];
        if (subgroup.mergedBy !== stone || subgroup.mergedWith !== this) break;
        this._unmerge(subgroup);
        this.goban.mergedGroups.pop();
    }
};

// Called when the group has no more life left
Group.prototype._dieFrom = function (killerStone) {
    if (main.debugGroup) main.log.debug('Group dying: ' + this);
    if (this.lives < 0) throw new Error('Unexpected error (lives<0)');

    for (var stone, stone_array = this.stones, stone_ndx = 0; stone=stone_array[stone_ndx], stone_ndx < stone_array.length; stone_ndx++) {
        for (var enemy, enemy_array = stone.uniqueEnemies(this.color), enemy_ndx = 0; enemy=enemy_array[enemy_ndx], enemy_ndx < enemy_array.length; enemy_ndx++) {
            enemy.notAttackedAnymore(stone);
        }
        stone.die();
    }
    this.killedBy = killerStone;
    this.goban.killedGroups.push(this);
    if (main.debugGroup) main.log.debug('Group dead: ' + this);
};

// Called when "undo" operation removes the killer stone of this group
Group.prototype._resuscitate = function () {
    this.killedBy = null;
    this.lives = 1; // always comes back with a single life
    for (var stone, stone_array = this.stones, stone_ndx = 0; stone=stone_array[stone_ndx], stone_ndx < stone_array.length; stone_ndx++) {
        stone.resuscitateIn(this);
        for (var enemy, enemy_array = stone.uniqueEnemies(this.color), enemy_ndx = 0; enemy=enemy_array[enemy_ndx], enemy_ndx < enemy_array.length; enemy_ndx++) {
            enemy._attackedByResuscitated(stone);
        }
    }
};

Group.resuscitateFrom = function (killerStone, goban) {
    for (;;) {
        var group = goban.killedGroups[goban.killedGroups.length - 1];
        if (group.killedBy !== killerStone) break;
        goban.killedGroups.pop();
        if (main.debugGroup) main.log.debug('taking back ' + killerStone + ' so we resuscitate ' + group.debugDump());
        group._resuscitate();
    }
};

// Returns prisoners grouped by color of dead stones
Group.countPrisoners = function (goban) {
    var prisoners = [0, 0];
    for (var i = 1; i <= goban.killedGroups.length - 1; i++) {
        var g = goban.killedGroups[i];
        prisoners[g.color] += g.stones.length;
    }
    return prisoners;
};
<commit_msg>minor: 1 added check in Group#allLives<commit_after>//Translated from group.rb using babyruby2js
'use strict';

var Grid = require('./Grid');
var main = require('./main');

var EMPTY = main.EMPTY;

/** @class
 *  A group keeps the list of its stones, the updated number of "lives" (empty intersections around),
 *  and whatever status information we need to decide what happens to a group (e.g. when a
 *  group is killed or merged with another group, etc.).
 *  Note that most of the work here is to keep this status information up to date.
 *    public read-only attribute: goban, stones, lives, color
 *    public read-only attribute: mergedWith, mergedBy, killedBy, ndx
 *    public write attribute: mergedWith, mergedBy, extraLives  *  only used in this file
 *  Create a new group. Always with a single stone.
 *  Do not call this using Group.new but Goban#newGroup instead.
 */
function Group(goban, stone, lives, ndx) {
    this.goban = goban;
    this.stones = [stone];
    this.lives = lives;
    this.color = stone.color;
    this.mergedWith = null; // a group
    this.mergedBy = null; // a stone
    this.killedBy = null; // a stone
    this.ndx = ndx; // unique index
    this.isAlive = this.isDead = 0; // used by analysis
}
module.exports = Group;

Group.prototype.recycle = function (stone, lives, ndx) {
    this.stones.clear();
    this.stones.push(stone);
    this.lives = lives;
    this.color = stone.color;
    this.mergedWith = this.mergedBy = this.killedBy = null;
    this.ndx = ndx;
    return this;
};

Group.prototype.clear = function () {
    for (var i = this.stones.length - 1; i >= 0; i--) {
        this.stones[i].clear();
    }
    this.goban.garbageGroups.push(this);
};

Group.prototype.toString = function () {
    var s = '{group #' + this.ndx + ' of ' + this.stones.length + ' ' + Grid.colorName(this.color) + ' stones [';
    for (var stone, stone_array = this.stones, stone_ndx = 0; stone=stone_array[stone_ndx], stone_ndx < stone_array.length; stone_ndx++) {
        s += stone.asMove() + ',';
    }
    s = s.chop();
    s += '], lives:' + this.lives;
    if (this.mergedWith) {
        s += ' MERGED with #' + this.mergedWith.ndx;
    }
    if (this.killedBy) {
        s += ' KILLED by ' + this.killedBy.asMove();
    }
    s += '}';
    return s;
};

// debug dump does not have more to display now that stones are simpler
// TODO: remove it unless stones get more state data to display
Group.prototype.debugDump = function () {
    return this.toString();
};

Group.prototype.stonesDump = function () {
    return this.stones.map(function (s) {
        return s.asMove();
    }).sort().join(',');
};

// Builds a list of all lives of the group (empty stones around)
// Costly!
Group.prototype.allLives = function () {
    var lives = [];
    for (var s, s_array = this.stones, s_ndx = 0; s=s_array[s_ndx], s_ndx < s_array.length; s_ndx++) {
        for (var life, life_array = s.neighbors, life_ndx = 0; life=life_array[life_ndx], life_ndx < life_array.length; life_ndx++) {
            if (life.color !== EMPTY) continue;

            if (lives.indexOf(life) < 0) lives.push(life);
        }
    }
    if (lives.length !== this.lives) throw new Error('Wrong life count for group');
    return lives;
};

// Builds a list of all enemies of the group
// Costly!
Group.prototype.allEnemies = function () {
    var enemies = [];
    var enemyColor = 1 - this.color;
    for (var s, s_array = this.stones, s_ndx = 0; s=s_array[s_ndx], s_ndx < s_array.length; s_ndx++) {
        for (var en, en_array = s.neighbors, en_ndx = 0; en=en_array[en_ndx], en_ndx < en_array.length; en_ndx++) {
            if (en.color !== enemyColor) continue;

            if (enemies.indexOf(en.group) < 0) enemies.push(en.group);
        }
    }
    if (main.debugGroup) main.log.debug(this + ' has ' + enemies.length + ' enemies');
    return enemies;
};

// Counts the lives of a stone that are not already in the group
// (the stone is to be added or removed)
Group.prototype.livesAddedByStone = function (stone) {
    var lives = 0;
    for (var life, life_array = stone.neighbors, life_ndx = 0; life=life_array[life_ndx], life_ndx < life_array.length; life_ndx++) {
        if (life.color !== EMPTY) continue;

        lives++;
        for (var s, s_array = life.neighbors, s_ndx = 0; s=s_array[s_ndx], s_ndx < s_array.length; s_ndx++) {
            if (s.group === this && s !== stone) {
                lives--;
                break;
            }
        }
    }
    if (main.debugGroup) main.log.debug(lives + ' lives added by ' + stone + ' for group ' + this);
    return lives;
};

// Connect a new stone or a merged stone to this group
Group.prototype.connectStone = function (stone, onMerge) {
    if (onMerge === undefined) onMerge = false;
    if (main.debugGroup) main.log.debug('Connecting ' + stone + ' to group ' + this + ' (on_merge=' + onMerge + ')');

    this.stones.push(stone);
    this.lives += this.livesAddedByStone(stone);
    if (!onMerge) this.lives--; // minus one since the connection itself removes 1

    if (this.lives < 0) { // can be 0 if suicide-kill
        throw new Error('Unexpected error (lives<0 on connect)');
    }
    if (main.debugGroup) main.log.debug('Final group: ' + this);
};

// Disconnect a stone
// on_merge must be true for merge or unmerge-related call
Group.prototype.disconnectStone = function (stone, onMerge) {
    if (onMerge === undefined) onMerge = false;
    if (main.debugGroup) {
        main.log.debug('Disconnecting ' + stone + ' from group ' + this + ' (on_merge=' + onMerge + ')');
    }
    // groups of 1 stone become empty groups (->garbage)
    if (this.stones.length > 1) {
        this.lives -= this.livesAddedByStone(stone);
        if (!onMerge) { // see comment in connect_stone
            this.lives += 1;
        }
        if (this.lives < 0) { // can be 0 if suicide-kill
            throw new Error('Unexpected error (lives<0 on disconnect)');
        }
    } else {
        this.goban.garbageGroups.push(this);
        if (main.debugGroup) main.log.debug('Group going to recycle bin: ' + this);
    }
    // we always remove them in the reverse order they came
    if (this.stones.pop() !== stone) {
        throw new Error('Unexpected error (disconnect order)');
    }
};

// When a new stone appears next to this group
Group.prototype.attackedBy = function (stone) {
    this.lives -= 1;
    if (this.lives <= 0) { // also check <0 so we can raise in die_from method
        return this._dieFrom(stone);
    }
};

// When a group of stones reappears because we undo
// NB: it can never kill anything
Group.prototype._attackedByResuscitated = function (stone) {
    this.lives--;
    if (main.debugGroup) main.log.debug(this + ' attacked by resuscitated ' + stone);

    if (this.lives < 1) throw new Error('Unexpected error (lives<1 on attack by resucitated)');
};

// Stone parameter is just for debug for now
Group.prototype.notAttackedAnymore = function (stone) {
    this.lives++;
    if (main.debugGroup) main.log.debug(this + ' not attacked anymore by ' + stone);
};

// Merges a subgroup with this group
Group.prototype.merge = function (subgroup, byStone) {
    if (subgroup.mergedWith === this || subgroup === this || this.color !== subgroup.color) {
        throw new Error('Invalid merge');
    }
    if (main.debugGroup) main.log.debug('Merging subgroup:' + subgroup + ' to main:' + this);

    for (var s, s_array = subgroup.stones, s_ndx = 0; s=s_array[s_ndx], s_ndx < s_array.length; s_ndx++) {
        s.setGroupOnMerge(this);
        this.connectStone(s, true);
    }
    subgroup.mergedWith = this;
    subgroup.mergedBy = byStone;
    this.goban.mergedGroups.push(subgroup);
    if (main.debugGroup) main.log.debug('After merge: subgroup:' + subgroup + ' main:' + this);
};

// Reverse of merge
Group.prototype._unmerge = function (subgroup) {
    if (main.debugGroup) main.log.debug('Unmerging subgroup:' + subgroup + ' from main:' + this);

    for (var s, s_array = subgroup.stones, s_ndx = s_array.length - 1; s=s_array[s_ndx], s_ndx >= 0; s_ndx--) {
        this.disconnectStone(s, true);
        s.setGroupOnMerge(subgroup);
    }
    subgroup.mergedBy = subgroup.mergedWith = null;
    if (main.debugGroup) main.log.debug('After _unmerge: subgroup:' + subgroup + ' main:' + this);
};

// This must be called on the main group (stone.group)
Group.prototype.unmergeFrom = function (stone) {
    for (;;) {
        var subgroup = this.goban.mergedGroups[this.goban.mergedGroups.length - 1];
        if (subgroup.mergedBy !== stone || subgroup.mergedWith !== this) break;
        this._unmerge(subgroup);
        this.goban.mergedGroups.pop();
    }
};

// Called when the group has no more life left
Group.prototype._dieFrom = function (killerStone) {
    if (main.debugGroup) main.log.debug('Group dying: ' + this);
    if (this.lives < 0) throw new Error('Unexpected error (lives<0)');

    for (var stone, stone_array = this.stones, stone_ndx = 0; stone=stone_array[stone_ndx], stone_ndx < stone_array.length; stone_ndx++) {
        for (var enemy, enemy_array = stone.uniqueEnemies(this.color), enemy_ndx = 0; enemy=enemy_array[enemy_ndx], enemy_ndx < enemy_array.length; enemy_ndx++) {
            enemy.notAttackedAnymore(stone);
        }
        stone.die();
    }
    this.killedBy = killerStone;
    this.goban.killedGroups.push(this);
    if (main.debugGroup) main.log.debug('Group dead: ' + this);
};

// Called when "undo" operation removes the killer stone of this group
Group.prototype._resuscitate = function () {
    this.killedBy = null;
    this.lives = 1; // always comes back with a single life
    for (var stone, stone_array = this.stones, stone_ndx = 0; stone=stone_array[stone_ndx], stone_ndx < stone_array.length; stone_ndx++) {
        stone.resuscitateIn(this);
        for (var enemy, enemy_array = stone.uniqueEnemies(this.color), enemy_ndx = 0; enemy=enemy_array[enemy_ndx], enemy_ndx < enemy_array.length; enemy_ndx++) {
            enemy._attackedByResuscitated(stone);
        }
    }
};

Group.resuscitateFrom = function (killerStone, goban) {
    for (;;) {
        var group = goban.killedGroups[goban.killedGroups.length - 1];
        if (group.killedBy !== killerStone) break;
        goban.killedGroups.pop();
        if (main.debugGroup) main.log.debug('taking back ' + killerStone + ' so we resuscitate ' + group.debugDump());
        group._resuscitate();
    }
};

// Returns prisoners grouped by color of dead stones
Group.countPrisoners = function (goban) {
    var prisoners = [0, 0];
    for (var i = 1; i <= goban.killedGroups.length - 1; i++) {
        var g = goban.killedGroups[i];
        prisoners[g.color] += g.stones.length;
    }
    return prisoners;
};
<|endoftext|>


<commit_before>
class Controller {

    constructor(Authentication, $location, Module) {
        this.Authentication = Authentication;
        this.modules = Module;
        this.title = 'Default generic administrator';
        this.loginRequired = this.loginRequired || true;
        this.paths = {
            root: '/monad/',
            theme: 'monad/css/default.css'
        };
        this.navigation = {
            main: [
                {url: '/', title: 'Site'}
            ]
        };
        this.Authentication.read().success(result => {
            if (!this.Authentication.isAuthenticated() && this.loginRequired) {
                $location.path('/login/');
            }
        });
        this.config();
    }

    /**
     * This is for overriding in an extending root controller, so we don't
     * have to remember to re-inject all dependencies which would suck
     * pretty badly.
     */
    config() {
    }

    select(menu, item = {}) {
        this.navigation[menu].map(item => item.selected = false);
        item.selected = true;
    }

};

Controller.$inject = ['Authentication.Service', '$location', 'Module.Service'];

export {Controller};

<commit_msg>add path method and set currently selected menu item<commit_after>
"use strict";

let route;

class Controller {

    constructor(Authentication, $location, $rootScope, $route) {
        this.Authentication = Authentication;
        this.title = 'Default generic administrator';
        this.loginRequired = this.loginRequired || true;
        this.paths = {
            root: '/monad/',
            theme: 'monad/css/default.css'
        };
        this.navigation = {
            main: [
                {url: '/', title: 'Site'}
            ]
        };
        this.Authentication.read().success(result => {
            if (!this.Authentication.isAuthenticated() && this.loginRequired) {
                $location.path('/login/');
            }
        });
        route = $route;
        this.config();
        this.navigation.main.map(item => item.selected = item.url == '#' + $location.path());
    }

    /**
     * This is for overriding in an extending root controller, so we don't
     * have to remember to re-inject all dependencies which would suck
     * pretty badly.
     */
    config() {
    }

    select(menu, item = {}) {
        this.navigation[menu].map(item => item.selected = false);
        item.selected = true;
    }

    path(controller, params = {}) {
        for (let path in route.routes) {
            let pathController = route.routes[path].controller;
            if (pathController == controller) {
                let result = path;
                for (let param in params) {
                    result = result.replace(':' + param, params[param]);
                }
                return '#' + result.replace(/^#/, '');
            }
        }
        let result = controller;
        for (let param in params) {
            result = result.replace(':' + param, params[param]);
        }
        return '#' + result.replace(/^#/, '');
    }

};

Controller.$inject = ['Authentication.Service', '$location', '$rootScope', '$route'];

export {Controller};

<|endoftext|>


<commit_before>define(['md5/lib/hash'],
function(Hash) {

  describe('Hash', function() {

    describe('hex digest', function() {
      var hash = new Hash();
      hash.update('chris:elwood.innosoft.com:secret');

      it('should have correct output', function() {
        expect(hash.digest('hex')).to.equal('eb5a750053e4d2c34aa84bbc9b0b6ee7');
      });
    });

    describe('base64 digest', function() {
      var hash = new Hash();
      hash.update('chris:elwood.innosoft.com:secret');

      it('should have correct output', function() {
        expect(hash.digest('base64')).to.equal('61p1AFPk0sNKqEu8mwtu5w==');
      });
    });

  });

  return { name: "test.md5" }
});
<commit_msg>Add binary digest test cases.<commit_after>define(['md5/lib/hash'],
function(Hash) {

  describe('Hash', function() {

    describe('binary digest as default argument', function() {
      var hash = new Hash();
      hash.update('chris:elwood.innosoft.com:secret');

      it('should have correct output', function() {
        expect(hash.digest()).to.equal('ëZu\u0000SäÒÃJ¨K¼\u000bnç');
      });
    });

    describe('binary digest', function() {
      var hash = new Hash();
      hash.update('chris:elwood.innosoft.com:secret');

      it('should have correct output', function() {
        expect(hash.digest('binary')).to.equal('ëZu\u0000SäÒÃJ¨K¼\u000bnç');
      });
    });

    describe('hex digest', function() {
      var hash = new Hash();
      hash.update('chris:elwood.innosoft.com:secret');

      it('should have correct output', function() {
        expect(hash.digest('hex')).to.equal('eb5a750053e4d2c34aa84bbc9b0b6ee7');
      });
    });

    describe('base64 digest', function() {
      var hash = new Hash();
      hash.update('chris:elwood.innosoft.com:secret');

      it('should have correct output', function() {
        expect(hash.digest('base64')).to.equal('61p1AFPk0sNKqEu8mwtu5w==');
      });
    });

  });

  return { name: "test.md5" }
});
<|endoftext|>


<commit_before>let mysql = require("mysql");

class Database {

    constructor(config) {
        this.config = config || {};
        this.pool = null;
    }

    query(sql, values) {
        return new Promise((resolve, reject) => {
            this.getConnection((error, connection) => {
                if (error) {
                    return reject(error);
                }
                connection.query(sql, values, (error, rows) => {
                    this.endConnection(connection);
                    if (error) {
                        return reject(error);
                    }
                    resolve(rows);
                });
            });
        });
    }

    getConnection(callback) {
        let options = this.config.connection;
        if (this.config.pooling) {
            if (this.pool == null) {
                this.pool = mysql.createPool(options);
            }
            this.pool.getConnection(callback);
        } else {
            let connection = mysql.createConnection(options);
            connection.connect( (error) => {
                callback(error, connection);
            })
        }
    }

    endConnection(connection) {
        if (this.config.pooling) {
            if (this.pool && connection) {
                connection.release();
            }
        } else {
            if (connection) {
                connection.end();
            }
        }
    }
}

module.exports.Database = Database;<commit_msg>added transaction support<commit_after>let mysql = require("mysql");

class MySQLWrapper {

    constructor(config) {
        this.config = config || {};
        this._transactionConnection = null;
        this._pool = null;
    }

    getConnection(callback) {

        if (this._transactionConnection) {
            return callback(null, this._transactionConnection);
        }

        let options = this.config.connection;
        if (this.config.pooling) {
            if (this._pool == null) {
                this._pool = mysql.createPool(options);
            }
            this._pool.getConnection(callback);
        } else {
            let connection = mysql.createConnection(options);
            connection.connect( (error) => {
                callback(error, connection);
            })
        }
    }

    endConnection(connection) {
        if (this.config.pooling) {
            if (this._pool && connection) {
                connection.release();
                this._transactionConnection = null;
            }
        } else {
            if (connection) {
                connection.end((error) => {
                    this._transactionConnection = null;
                });
            }
        }
    }

    query(sql, values) {
        return new Promise((resolve, reject) => {
            this.getConnection((error, connection) => {
                if (error) {
                    return reject(error);
                }
                connection.query(sql, values, (error, result) => {
                    if (!this._transactionConnection) {
                        this.endConnection(connection);
                    }
                    if (error) {
                        if (this._transactionConnection) {
                            return this._transactionConnection.rollback(() => {
                                this.endConnection(this._transactionConnection);
                                reject(error);
                            });
                        } else {
                            return reject(error);
                        }
                    }
                    resolve(result);
                });
            });
        });
    }

    beginTransaction() {
        return new Promise((resolve, reject) => {
            this.getConnection((error, connection) => {
                this._transactionConnection = connection;
                if (error) {
                    reject(error);
                } else {
                    this._transactionConnection.beginTransaction((error) => {
                        if (error) {
                            reject(error);
                        } else {
                            resolve();
                        }
                    });
                }
            });
        });
    }

    endTransaction() {
        return new Promise((resolve, reject) => {
            if (this._transactionConnection) {
                this._transactionConnection.commit((error) => {
                    if (error) {
                        return this._transactionConnection.rollback(() => {
                            this.endConnection(this._transactionConnection);
                            reject(error);
                        });
                    } else {
                        this.endConnection(this._transactionConnection);
                    }
                });
            }
            resolve();
        });
    }
}

module.exports = MySQLWrapper;<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash'),
    async = require('async'),
    fs = require('fs-extra'),
    glob = require('glob'),
    path = require('path');

var mapping = require('../../fp/_mapping');

var templatePath = path.join(__dirname, 'template');

var template = _.transform(glob.sync(path.join(templatePath, '*.jst')), function(result, filePath) {
  result[path.basename(filePath, '.jst')] = _.template(fs.readFileSync(filePath));
}, {});

var aryMethods = _.union(
  mapping.aryMethod[1],
  mapping.aryMethod[2],
  mapping.aryMethod[3],
  mapping.aryMethod[4]
);

var categories = [
  'array',
  'collection',
  'date',
  'function',
  'lang',
  'math',
  'number',
  'object',
  'seq',
  'string',
  'util'
];

function isAlias(funcName) {
  return _.has(mapping.aliasToReal, funcName);
}

function isCategory(funcName) {
  return _.includes(categories, funcName);
}

function isThru(funcName) {
  return !_.includes(aryMethods, funcName);
}

function getTemplate(moduleName) {
  var data = {
    'key': mapping.key,
    'name': _.result(mapping.aliasToReal, moduleName, moduleName)
  };

  if (isAlias(moduleName)) {
    return template.alias(data);
  }
  if (isCategory(moduleName)) {
    return template.category(data);
  }
  if (isThru(moduleName)) {
    return template.thru(data);
  }
  return template.module(data);
}

/*----------------------------------------------------------------------------*/

function onComplete(error) {
  if (error) {
    throw error;
  }
}

function build(target) {
  var fpPath = path.join(target, 'fp');

  // Glob existing lodash module paths.
  var modulePaths = glob.sync(path.join(target, '*.js'), {
    'nodir': true,
    'ignore': path.join(target, '_*.js')
  });

  // Add FP alias module paths.
  _.forOwn(aliasToReal, function(realName, alias) {
    modulePaths.push(path.join(target, alias + '.js'));
  });

  modulePaths = _.uniq(modulePaths);

  var actions = modulePaths.map(function(modulePath) {
    var moduleName = path.basename(modulePath, '.js');
    return _.partial(fs.writeFile, path.join(fpPath, moduleName + '.js'), getTemplate(moduleName));
  });

  actions.unshift(_.partial(fs.copy, path.join(__dirname, '../../fp'), fpPath));
  actions.push(_.partial(fs.writeFile, path.join(target, 'fp.js'), template.fp()));
  actions.push(_.partial(fs.writeFile, path.join(fpPath, 'convert.js'), template.convert()));
  actions.push(_.partial(fs.writeFile, path.join(fpPath, '_util.js'), template._util()));

  async.series(actions, onComplete);
}

build(_.last(process.argv));
<commit_msg>Ensure remapped fp method modules are created.<commit_after>'use strict';

var _ = require('lodash'),
    async = require('async'),
    fs = require('fs-extra'),
    glob = require('glob'),
    path = require('path');

var mapping = require('../../fp/_mapping');

var templatePath = path.join(__dirname, 'template');

var template = _.transform(glob.sync(path.join(templatePath, '*.jst')), function(result, filePath) {
  result[path.basename(filePath, '.jst')] = _.template(fs.readFileSync(filePath));
}, {});

var aryMethods = _.union(
  mapping.aryMethod[1],
  mapping.aryMethod[2],
  mapping.aryMethod[3],
  mapping.aryMethod[4]
);

var categories = [
  'array',
  'collection',
  'date',
  'function',
  'lang',
  'math',
  'number',
  'object',
  'seq',
  'string',
  'util'
];

function isAlias(funcName) {
  return _.has(mapping.aliasToReal, funcName);
}

function isCategory(funcName) {
  return _.includes(categories, funcName);
}

function isThru(funcName) {
  return !_.includes(aryMethods, funcName);
}

function getTemplate(moduleName) {
  var data = {
    'key': mapping.key,
    'name': _.result(mapping.aliasToReal, moduleName, moduleName)
  };

  if (isAlias(moduleName)) {
    return template.alias(data);
  }
  if (isCategory(moduleName)) {
    return template.category(data);
  }
  if (isThru(moduleName)) {
    return template.thru(data);
  }
  return template.module(data);
}

/*----------------------------------------------------------------------------*/

function onComplete(error) {
  if (error) {
    throw error;
  }
}

function build(target) {
  var fpPath = path.join(target, 'fp');

  // Glob existing lodash module paths.
  var modulePaths = glob.sync(path.join(target, '*.js'), {
    'nodir': true,
    'ignore': path.join(target, '_*.js')
  });

  // Add FP alias and remapped module paths.
  _.each([mapping.aliasToReal, mapping.key], function(data) {
    _.forOwn(data, function(realName, alias) {
      modulePaths.push(path.join(target, alias + '.js'));
    });
  });

  modulePaths = _.uniq(modulePaths);

  var actions = modulePaths.map(function(modulePath) {
    var moduleName = path.basename(modulePath, '.js');
    return _.partial(fs.writeFile, path.join(fpPath, moduleName + '.js'), getTemplate(moduleName));
  });

  actions.unshift(_.partial(fs.copy, path.join(__dirname, '../../fp'), fpPath));
  actions.push(_.partial(fs.writeFile, path.join(target, 'fp.js'), template.fp()));
  actions.push(_.partial(fs.writeFile, path.join(fpPath, 'convert.js'), template.convert()));
  actions.push(_.partial(fs.writeFile, path.join(fpPath, '_util.js'), template._util()));

  async.series(actions, onComplete);
}

build(_.last(process.argv));
<|endoftext|>