<commit_before>'use strict';

const redis = require('redis');
const Pool = require('generic-pool').Pool;
const EventEmitter = require('events').EventEmitter;

const FLUSH_CONNECTION = true;
const DEFAULTS = {
  host: '127.0.0.1',
  port: '6379',
  max: 50,
  idleTimeoutMillis: 10000,
  reapIntervalMillis: 1000,
  noReadyCheck: false,
  returnToHead: false,
  unwatchOnRelease: true,
  name: 'default',
  log: false,
  slowPool: {
    log: false,
    elapsedThreshold: 25
  },
  emitter: {
    statusInterval: 60000
  },
  commands: []
};

/**
 * Create a new multi database Redis pool.
 * It will emit `status` event with information about each created pool.
 *
 * @param {Object} options
 * @returns {RedisPool}
 * @constructor
 */
module.exports = class RedisPool extends EventEmitter {
  constructor (options = {}) {
    super();

    this.pools = {};
    this.options = Object.assign({}, DEFAULTS, options);
    this.elapsedThreshold = this.options.slowPool.elapsedThreshold;

    if (this.options.commands.length) {
      this._addCommands(this.options.commands)
    }

    this._emitStatus(this.options.emitter.statusInterval)
  }

  /**
   * Acquire resource
   *
   * @param {String|Number} database redis database name
   * @param {Function} callback Callback to call once acquired. Takes the form `callback(err, resource)`
   */
  acquire (database, callback) {
    let pool = this.pools[database];
    if (!pool) {
      pool = this.pools[database] = makePool(this.options, database);
    }

    const startTime = Date.now();
    pool.acquire((err, client) => {
      const elapsedTime = Date.now() - startTime;
      if (elapsedTime > this.elapsedThreshold) {
        log(this.options, { db: database, action: 'acquire', elapsed: elapsedTime, waiting: pool.waitingClientsCount() });
      }
      callback(err, client);
    });
  }

  /**
   * Release resource.
   *
   * @param database {String|Number} redis database name
   * @param resource {Object} resource object to release
   */
  release (database, resource) {
    if (this.options.unwatchOnRelease) {
      resource.UNWATCH();
    }

    const pool = this.pools[database];

    if (pool) {
      pool.release(resource);
    }
  }

  _addCommands (commands = []) {
    commands.forEach(newCommand => redis.add_command(newCommand));
  }

  _emitStatus(statusInterval) {
    setInterval(() => {
      Object.keys(this.pools).forEach(poolKey => {
        const pool = this.pools[poolKey];
        this.emit('status', {
          name: this.options.name,
          db: poolKey,
          count: pool.getPoolSize(),
          unused: pool.availableObjectsCount(),
          waiting: pool.waitingClientsCount()
        });
      });
    }, statusInterval);
  }
};

/**
 * Factory to create new Redis pools for a given Redis database
 * @param options
 * @param database
 * @returns {Object}
 */
function makePool (options, database) {
  return Pool({
    name: options.name + ':' + database,

    create: function (callback) {
      let callbackCalled = false;

      const client = redis.createClient(options.port, options.host, {
        no_ready_check: options.noReadyCheck
      });

      client.on('error', function (err) {
        log(options, { db: database, action: 'error', err: err.message });
        if (!callbackCalled) {
          callbackCalled = true;
          callback(err, client);
        }
        client.end(FLUSH_CONNECTION);
      });

      client.on('ready', function () {
        client.select(database, function (err/*, res */) {
          if (!callbackCalled) {
            callbackCalled = true;
            callback(err, client);
          }
        });
      });
    },

    destroy: function (client) {
      client.quit();
      client.end(FLUSH_CONNECTION);
    },

    validate: function (client) {
      return client && client.connected;
    },

    max: options.max,
    idleTimeoutMillis: options.idleTimeoutMillis,
    reapIntervalMillis: options.reapIntervalMillis,
    returnToHead: options.returnToHead,
    log: options.log
  });
}

function log (options, what) {
  if (options.slowPool.log) {
    console.log(JSON.stringify(Object.assign({ name: options.name }, what)));
  }
}
<commit_msg>simplify loop<commit_after>'use strict';

const redis = require('redis');
const Pool = require('generic-pool').Pool;
const EventEmitter = require('events').EventEmitter;

const FLUSH_CONNECTION = true;
const DEFAULTS = {
  host: '127.0.0.1',
  port: '6379',
  max: 50,
  idleTimeoutMillis: 10000,
  reapIntervalMillis: 1000,
  noReadyCheck: false,
  returnToHead: false,
  unwatchOnRelease: true,
  name: 'default',
  log: false,
  slowPool: {
    log: false,
    elapsedThreshold: 25
  },
  emitter: {
    statusInterval: 60000
  },
  commands: []
};

/**
 * Create a new multi database Redis pool.
 * It will emit `status` event with information about each created pool.
 *
 * @param {Object} options
 * @returns {RedisPool}
 * @constructor
 */
module.exports = class RedisPool extends EventEmitter {
  constructor (options = {}) {
    super();

    this.pools = {};
    this.options = Object.assign({}, DEFAULTS, options);
    this.elapsedThreshold = this.options.slowPool.elapsedThreshold;

    if (this.options.commands.length) {
      this._addCommands(this.options.commands)
    }

    this._emitStatus(this.options.emitter.statusInterval)
  }

  /**
   * Acquire resource
   *
   * @param {String|Number} database redis database name
   * @param {Function} callback Callback to call once acquired. Takes the form `callback(err, resource)`
   */
  acquire (database, callback) {
    let pool = this.pools[database];
    if (!pool) {
      pool = this.pools[database] = makePool(this.options, database);
    }

    const startTime = Date.now();
    pool.acquire((err, client) => {
      const elapsedTime = Date.now() - startTime;
      if (elapsedTime > this.elapsedThreshold) {
        log(this.options, { db: database, action: 'acquire', elapsed: elapsedTime, waiting: pool.waitingClientsCount() });
      }
      callback(err, client);
    });
  }

  /**
   * Release resource.
   *
   * @param database {String|Number} redis database name
   * @param resource {Object} resource object to release
   */
  release (database, resource) {
    if (this.options.unwatchOnRelease) {
      resource.UNWATCH();
    }

    const pool = this.pools[database];

    if (pool) {
      pool.release(resource);
    }
  }

  _addCommands (commands = []) {
    commands.forEach(newCommand => redis.add_command(newCommand));
  }

  _emitStatus(statusInterval) {
    setInterval(() => {
      for (const [poolKey, pool] of Object.entries(this.pools)) {
        this.emit('status', {
          name: this.options.name,
          db: poolKey,
          count: pool.getPoolSize(),
          unused: pool.availableObjectsCount(),
          waiting: pool.waitingClientsCount()
        });
      }
    }, statusInterval);
  }
};

/**
 * Factory to create new Redis pools for a given Redis database
 * @param options
 * @param database
 * @returns {Object}
 */
function makePool (options, database) {
  return Pool({
    name: options.name + ':' + database,

    create: function (callback) {
      let callbackCalled = false;

      const client = redis.createClient(options.port, options.host, {
        no_ready_check: options.noReadyCheck
      });

      client.on('error', function (err) {
        log(options, { db: database, action: 'error', err: err.message });
        if (!callbackCalled) {
          callbackCalled = true;
          callback(err, client);
        }
        client.end(FLUSH_CONNECTION);
      });

      client.on('ready', function () {
        client.select(database, function (err/*, res */) {
          if (!callbackCalled) {
            callbackCalled = true;
            callback(err, client);
          }
        });
      });
    },

    destroy: function (client) {
      client.quit();
      client.end(FLUSH_CONNECTION);
    },

    validate: function (client) {
      return client && client.connected;
    },

    max: options.max,
    idleTimeoutMillis: options.idleTimeoutMillis,
    reapIntervalMillis: options.reapIntervalMillis,
    returnToHead: options.returnToHead,
    log: options.log
  });
}

function log (options, what) {
  if (options.slowPool.log) {
    console.log(JSON.stringify(Object.assign({ name: options.name }, what)));
  }
}
<|endoftext|>


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

var http_verbs = ['get', 'options', 'head', 'post', 'put', 'delete'];

module.exports = function (sails) {

  /**
   * Expose blueprint hook definition
   */
  return {
    defaults: {
      controllerDrivenRoutes: {
        prefix: '',
        routes: {},
      }
    },

    initialize: function (cb) {

      var eventsToWaitFor = [];
      eventsToWaitFor.push('router:after');
      if (sails.hooks.policies) {
        eventsToWaitFor.push('hook:policies:bound');
      }
      if (sails.hooks.controllers) {
        eventsToWaitFor.push('hook:controllers:loaded');
      }
      sails.after(eventsToWaitFor, this.bindShadowRoutes);
      return cb();
    },

    bindShadowRoutes: function () {

      _.each(sails.middleware.controllers, function eachController(controller, controllerId) {
        if (!_.isObject(controller) || _.isArray(controller)) return;

        // Get globalId for use in errors/warnings
        var globalId = sails.controllers[controllerId].globalId;

        // Determine blueprint configuration for this controller
        var config = _.merge(
          sails.config.controllerDrivenRoutes,
          controller._config || {});

        // Validate blueprint config for this controller
        if (config.prefix && !config.prefix.match(/^\//)) {
          var originalPrefix = config.prefix;
          config.prefix = '/' + config.prefix;
        }

        // Determine base route
        var baseRoute = config.prefix + '/' + controllerId;

        if (config.pluralize) {
          baseRoute = pluralize(baseRoute);
        }

        // map any specfic routes that are in the controller
        _.map(config.explicitRoutes, function (action, route) {
          sails.log.silly('Binding action (' + action.toLowerCase() + ') blueprint/shadow route for controller:', controllerId);
          var opts = {
            controller: controllerId
          }
          if (_.isString(action)) {
            opts.action = action;
          }
          else {
            opts = _.merge(opts, action);
          }
          sails.router.bind(route, action);
        });

        // map the exposed methods of the controller
        _.each(config.exposedMethods, function (method) {
          var endpoint = method != 'index' ? method : '';

          if (controller[method] !== undefined) {
            sails.log.silly('Binding ' + baseRoute + "/" + endpoint + ' to ' + controllerId + '.' + method);
            sails.router.bind(baseRoute + "/" + endpoint, {
              controller: controllerId,
              action: method
            });
          }
          ;
          //handle the verbs
          _.each(http_verbs, function (verb) {
            var candidateMethod = method + verb;
            // handle special case for index
            if (controller[candidateMethod] !== undefined) {
              sails.log.silly('Binding ' + verb.toUpperCase() + " " + baseRoute + "/" + endpoint + ' to ' + controllerId + '.' + candidateMethod);
              sails.router.bind(verb.toUpperCase() + " " + baseRoute + "/" + endpoint, {
                controller: controllerId,
                action: candidateMethod
              });
            }
            ;
          });
        });
      });
    }
  };
};

<commit_msg>swap order of route declarations so the default is added last<commit_after>var _ = require('lodash');

var http_verbs = ['get', 'options', 'head', 'post', 'put', 'delete'];

module.exports = function (sails) {

  /**
   * Expose blueprint hook definition
   */
  return {
    defaults: {
      controllerDrivenRoutes: {
        prefix: '',
        routes: {},
      }
    },

    initialize: function (cb) {

      var eventsToWaitFor = [];
      eventsToWaitFor.push('router:after');
      if (sails.hooks.policies) {
        eventsToWaitFor.push('hook:policies:bound');
      }
      if (sails.hooks.controllers) {
        eventsToWaitFor.push('hook:controllers:loaded');
      }
      sails.after(eventsToWaitFor, this.bindShadowRoutes);
      return cb();
    },

    bindShadowRoutes: function () {

      _.each(sails.middleware.controllers, function eachController(controller, controllerId) {
        if (!_.isObject(controller) || _.isArray(controller)) return;

        // Get globalId for use in errors/warnings
        var globalId = sails.controllers[controllerId].globalId;

        // Determine blueprint configuration for this controller
        var config = _.merge(
          sails.config.controllerDrivenRoutes,
          controller._config || {});

        // Validate blueprint config for this controller
        if (config.prefix && !config.prefix.match(/^\//)) {
          var originalPrefix = config.prefix;
          config.prefix = '/' + config.prefix;
        }

        // Determine base route
        var baseRoute = config.prefix + '/' + controllerId;

        if (config.pluralize) {
          baseRoute = pluralize(baseRoute);
        }

        // map any specfic routes that are in the controller
        _.map(config.explicitRoutes, function (action, route) {
          sails.log.silly('Binding action (' + action.toLowerCase() + ') blueprint/shadow route for controller:', controllerId);
          var opts = {
            controller: controllerId
          }
          if (_.isString(action)) {
            opts.action = action;
          }
          else {
            opts = _.merge(opts, action);
          }
          sails.router.bind(route, action);
        });

        // map the exposed methods of the controller
        _.each(config.exposedMethods, function (method) {
          var endpoint = method != 'index' ? method : '';
          //handle the verbs
          _.each(http_verbs, function (verb) {
            var candidateMethod = method + verb;
            // handle special case for index
            if (controller[candidateMethod] !== undefined) {
              sails.log.silly('Binding ' + verb.toUpperCase() + " " + baseRoute + "/" + endpoint + ' to ' + controllerId + '.' + candidateMethod);
              sails.router.bind(verb.toUpperCase() + " " + baseRoute + "/" + endpoint, {
                controller: controllerId,
                action: candidateMethod
              });
            }
          });
          if (controller[method] !== undefined) {
            sails.log.silly('Binding ' + baseRoute + "/" + endpoint + ' to ' + controllerId + '.' + method);
            sails.router.bind(baseRoute + "/" + endpoint, {
              controller: controllerId,
              action: method
            });
          }
        });
      });
    }
  };
};

<|endoftext|>


<commit_before>#!/usr/bin/env node --harmony

//http://blog.npmjs.org/post/118810260230/building-a-simple-command-line-tool-with-npm

const program = require('commander');
const shell = require('shelljs');

shell.exec('pwd');

program
	.version('0.1.0')
	.command('clean')
	.description('remove ./dist directory and ./dist.zip file')
	.action(function () {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('./node_modules/gulp/bin/gulp.js clean --gulpfile ./node_modules/build-scripts/gulpfile.js');
			}
		});
	});

program
	.command('zip')
	.description('zip ./dist directory into ./dist.zip file')
	.action(function () {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('./node_modules/gulp/bin/gulp.js zip --gulpfile ./node_modules/build-scripts/gulpfile.js');
			}
		});
	});

program
	.command('build-lambda')
	.description('build lambda function in /dist directory')
	.action(function () {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('./node_modules/gulp/bin/gulp.js build --gulpfile ./node_modules/build-scripts/gulpfile.js');
			}
		});
	});

program
	.command('upload-lambda')
	.description('build and deploy function to aws lambda - function must already exist')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('./node_modules/gulp/bin/gulp.js upload --gulpfile ./node_modules/build-scripts/gulpfile.js');
			}
		});
	});

/*
	  "build": "babel src --out-dir lib",
 */
program
	.command('build')
	.description('runs babel src -o lib // src/es6 to lib/es5')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run build');
			}
		});
	});

/*
	  "test": "mocha --compilers js:babel-core/register test",
 */
program
	.command('test')
	.description('runs mocha test')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('run npm test');
			}
		});
	});

/*
	  "test:watch": "mocha --compilers js:babel-core/register --watch test",
 */
program
	.command('test-watch')
	.description('runs mocha test with the watch option')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run test:watch');
			}
		});
	});

/*
	  "commit": "npm run build && npm run test && git commit",
 */
program
	.command('commit')
	.description('runs build, test and commit interactive so you enter commit message')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run commit');
			}
		});
	});

/*
	  "patch": "npm version patch",
 */
program
	.command('patch')
	.description('update package version')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run patch');
			}
		});
	});

/*
	  "push": "git push origin --follow-tags",
 */
program
	.command('push')
	.description('git push to origin')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run push');
			}
		});
	});

/*
	  "patch:push": "npm run build && npm run test && npm run patch && npm run push"
 */
program
	.command('patch-push')
	.description('update package version and git push to origin - runs build and test first')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run patch:push');
			}
		});
	});

program.parse(process.argv);
<commit_msg>fix bad cmd<commit_after>#!/usr/bin/env node --harmony

//http://blog.npmjs.org/post/118810260230/building-a-simple-command-line-tool-with-npm

const program = require('commander');
const shell = require('shelljs');

shell.exec('pwd');

program
	.version('0.1.0')
	.command('clean')
	.description('remove ./dist directory and ./dist.zip file')
	.action(function () {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('./node_modules/gulp/bin/gulp.js clean --gulpfile ./node_modules/build-scripts/gulpfile.js');
			}
		});
	});

program
	.command('zip')
	.description('zip ./dist directory into ./dist.zip file')
	.action(function () {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('./node_modules/gulp/bin/gulp.js zip --gulpfile ./node_modules/build-scripts/gulpfile.js');
			}
		});
	});

program
	.command('build-lambda')
	.description('build lambda function in /dist directory')
	.action(function () {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('./node_modules/gulp/bin/gulp.js build --gulpfile ./node_modules/build-scripts/gulpfile.js');
			}
		});
	});

program
	.command('upload-lambda')
	.description('build and deploy function to aws lambda - function must already exist')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('./node_modules/gulp/bin/gulp.js upload --gulpfile ./node_modules/build-scripts/gulpfile.js');
			}
		});
	});

/*
	  "build": "babel src --out-dir lib",
 */
program
	.command('build')
	.description('runs babel src -o lib // src/es6 to lib/es5')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run build');
			}
		});
	});

/*
	  "test": "mocha --compilers js:babel-core/register test",
 */
program
	.command('test')
	.description('runs mocha test')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run test');
			}
		});
	});

/*
	  "test:watch": "mocha --compilers js:babel-core/register --watch test",
 */
program
	.command('test-watch')
	.description('runs mocha test with the watch option')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run test:watch');
			}
		});
	});

/*
	  "commit": "npm run build && npm run test && git commit",
 */
program
	.command('commit')
	.description('runs build, test and commit interactive so you enter commit message')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run commit');
			}
		});
	});

/*
	  "patch": "npm version patch",
 */
program
	.command('patch')
	.description('update package version')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run patch');
			}
		});
	});

/*
	  "push": "git push origin --follow-tags",
 */
program
	.command('push')
	.description('git push to origin')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run push');
			}
		});
	});

/*
	  "patch:push": "npm run build && npm run test && npm run patch && npm run push"
 */
program
	.command('patch-push')
	.description('update package version and git push to origin - runs build and test first')
	.action(function (env) {
		shell.exec("npm install", function (error, stdout, stderr) {
			if (!error) {
				shell.exec('npm run patch:push');
			}
		});
	});

program.parse(process.argv);
<|endoftext|>


<commit_before>/* global describe, it */
var expect = require('unexpected')
  .clone()
  .use(require('magicpen-prism'))
  .use(require('unexpected-function-equality'));

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

expect.addAssertion('<any> to convert to [canonical] ast <object>', function (
  expect,
  subject,
  value
) {
  expect(
    esanimate.astify(subject, expect.flags.canonical),
    'to exhaustively satisfy',
    value
  );
});

expect.addAssertion('to convert to object', function (expect, subject, value) {
  expect(esanimate.objectify(subject), 'to equal', value);
});

expect.addAssertion('to be converted from ast', function (
  expect,
  subject,
  value
) {
  expect(esanimate.objectify(value), 'to equal', subject);
});

expect.addAssertion('to convert back and forth to', function (
  expect,
  subject,
  value
) {
  return expect
    .it('to convert to ast', value)
    .and(
      'to be converted from ast',
      value
    )(subject);
});

describe('esanimate', function () {
  describe('#astify', function () {
    it('should support the canonicalize option', function () {
      expect({ b: 456, a: [1, 2] }, 'to convert to canonical ast', {
        type: 'ObjectExpression',
        properties: [
          {
            type: 'Property',
            kind: 'init',
            key: { type: 'Identifier', name: 'a' },
            value: {
              type: 'ArrayExpression',
              elements: [
                { type: 'Literal', value: 1 },
                { type: 'Literal', value: 2 },
              ],
            },
          },
          {
            type: 'Property',
            kind: 'init',
            key: { type: 'Identifier', name: 'b' },
            value: { type: 'Literal', value: 456 },
          },
        ],
      });
    });
  });

  it('should convert undefined', function () {
    expect(undefined, 'to convert back and forth to', {
      type: 'Identifier',
      name: 'undefined',
    });
  });

  it('should convert null', function () {
    expect(null, 'to convert back and forth to', {
      type: 'Literal',
      value: null,
    });
  });

  it('should convert false', function () {
    expect(false, 'to convert back and forth to', {
      type: 'Literal',
      value: false,
    });
  });

  it('should convert true', function () {
    expect(true, 'to convert back and forth to', {
      type: 'Literal',
      value: true,
    });
  });

  it('should convert string literal', function () {
    expect('foo', 'to convert back and forth to', {
      type: 'Literal',
      value: 'foo',
    });
  });

  it('should convert number literal', function () {
    expect(123, 'to convert back and forth to', {
      type: 'Literal',
      value: 123,
    });
  });

  it('should convert array literal', function () {
    expect(['foo', true, [null]], 'to convert back and forth to', {
      type: 'ArrayExpression',
      elements: [
        { type: 'Literal', value: 'foo' },
        { type: 'Literal', value: true },
        {
          type: 'ArrayExpression',
          elements: [{ type: 'Literal', value: null }],
        },
      ],
    });
  });

  it('should convert object literal', function () {
    expect(
      { keyName1: 'stringValue', keyName2: [null, 10] },
      'to convert back and forth to',
      {
        type: 'ObjectExpression',
        properties: [
          {
            type: 'Property',
            kind: 'init',
            key: { type: 'Identifier', name: 'keyName1' },
            value: { type: 'Literal', value: 'stringValue' },
          },
          {
            type: 'Property',
            kind: 'init',
            key: { type: 'Identifier', name: 'keyName2' },
            value: {
              type: 'ArrayExpression',
              elements: [
                { type: 'Literal', value: null },
                { type: 'Literal', value: 10 },
              ],
            },
          },
        ],
      }
    );
  });

  it('should use a Literal for a key that needs quoting', function () {
    expect({ 'needs.quoting': 123 }, 'to convert back and forth to', {
      type: 'ObjectExpression',
      properties: [
        {
          type: 'Property',
          kind: 'init',
          key: { type: 'Literal', value: 'needs.quoting' },
          value: { type: 'Literal', value: 123 },
        },
      ],
    });
  });

  it('should convert regular expression', function () {
    expect(/foobar/gim, 'to convert back and forth to', {
      type: 'Literal',
      value: /foobar/gim,
    });
  });

  it('should convert a named function', function () {
    expect(
      function foo(bar, quux) {
        bar(123);
      },
      'to convert back and forth to',
      {
        type: 'FunctionExpression',
        id: { type: 'Identifier', name: 'foo' },
        generator: false,
        expression: false,
        async: false,
        params: [
          { type: 'Identifier', name: 'bar' },
          { type: 'Identifier', name: 'quux' },
        ],
        body: {
          type: 'BlockStatement',
          body: [
            {
              type: 'ExpressionStatement',
              expression: {
                type: 'CallExpression',
                callee: { type: 'Identifier', name: 'bar' },
                arguments: [{ type: 'Literal', value: 123, raw: '123' }],
              },
            },
          ],
        },
      }
    );
  });

  it('should convert an anonymous function', function () {
    expect(
      function (bar) {
        bar();
      },
      'to convert back and forth to',
      {
        type: 'FunctionExpression',
        id: null,
        generator: false,
        expression: false,
        async: false,
        params: [{ type: 'Identifier', name: 'bar' }],
        body: {
          type: 'BlockStatement',
          body: [
            {
              type: 'ExpressionStatement',
              expression: {
                type: 'CallExpression',
                callee: { type: 'Identifier', name: 'bar' },
                arguments: [],
              },
            },
          ],
        },
      }
    );
  });
});
<commit_msg>prettier --write '**/*.{js,json,md}'<commit_after>/* global describe, it */
var expect = require('unexpected')
  .clone()
  .use(require('magicpen-prism'))
  .use(require('unexpected-function-equality'));

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

expect.addAssertion(
  '<any> to convert to [canonical] ast <object>',
  function (expect, subject, value) {
    expect(
      esanimate.astify(subject, expect.flags.canonical),
      'to exhaustively satisfy',
      value
    );
  }
);

expect.addAssertion('to convert to object', function (expect, subject, value) {
  expect(esanimate.objectify(subject), 'to equal', value);
});

expect.addAssertion(
  'to be converted from ast',
  function (expect, subject, value) {
    expect(esanimate.objectify(value), 'to equal', subject);
  }
);

expect.addAssertion(
  'to convert back and forth to',
  function (expect, subject, value) {
    return expect
      .it('to convert to ast', value)
      .and(
        'to be converted from ast',
        value
      )(subject);
  }
);

describe('esanimate', function () {
  describe('#astify', function () {
    it('should support the canonicalize option', function () {
      expect({ b: 456, a: [1, 2] }, 'to convert to canonical ast', {
        type: 'ObjectExpression',
        properties: [
          {
            type: 'Property',
            kind: 'init',
            key: { type: 'Identifier', name: 'a' },
            value: {
              type: 'ArrayExpression',
              elements: [
                { type: 'Literal', value: 1 },
                { type: 'Literal', value: 2 },
              ],
            },
          },
          {
            type: 'Property',
            kind: 'init',
            key: { type: 'Identifier', name: 'b' },
            value: { type: 'Literal', value: 456 },
          },
        ],
      });
    });
  });

  it('should convert undefined', function () {
    expect(undefined, 'to convert back and forth to', {
      type: 'Identifier',
      name: 'undefined',
    });
  });

  it('should convert null', function () {
    expect(null, 'to convert back and forth to', {
      type: 'Literal',
      value: null,
    });
  });

  it('should convert false', function () {
    expect(false, 'to convert back and forth to', {
      type: 'Literal',
      value: false,
    });
  });

  it('should convert true', function () {
    expect(true, 'to convert back and forth to', {
      type: 'Literal',
      value: true,
    });
  });

  it('should convert string literal', function () {
    expect('foo', 'to convert back and forth to', {
      type: 'Literal',
      value: 'foo',
    });
  });

  it('should convert number literal', function () {
    expect(123, 'to convert back and forth to', {
      type: 'Literal',
      value: 123,
    });
  });

  it('should convert array literal', function () {
    expect(['foo', true, [null]], 'to convert back and forth to', {
      type: 'ArrayExpression',
      elements: [
        { type: 'Literal', value: 'foo' },
        { type: 'Literal', value: true },
        {
          type: 'ArrayExpression',
          elements: [{ type: 'Literal', value: null }],
        },
      ],
    });
  });

  it('should convert object literal', function () {
    expect(
      { keyName1: 'stringValue', keyName2: [null, 10] },
      'to convert back and forth to',
      {
        type: 'ObjectExpression',
        properties: [
          {
            type: 'Property',
            kind: 'init',
            key: { type: 'Identifier', name: 'keyName1' },
            value: { type: 'Literal', value: 'stringValue' },
          },
          {
            type: 'Property',
            kind: 'init',
            key: { type: 'Identifier', name: 'keyName2' },
            value: {
              type: 'ArrayExpression',
              elements: [
                { type: 'Literal', value: null },
                { type: 'Literal', value: 10 },
              ],
            },
          },
        ],
      }
    );
  });

  it('should use a Literal for a key that needs quoting', function () {
    expect({ 'needs.quoting': 123 }, 'to convert back and forth to', {
      type: 'ObjectExpression',
      properties: [
        {
          type: 'Property',
          kind: 'init',
          key: { type: 'Literal', value: 'needs.quoting' },
          value: { type: 'Literal', value: 123 },
        },
      ],
    });
  });

  it('should convert regular expression', function () {
    expect(/foobar/gim, 'to convert back and forth to', {
      type: 'Literal',
      value: /foobar/gim,
    });
  });

  it('should convert a named function', function () {
    expect(
      function foo(bar, quux) {
        bar(123);
      },
      'to convert back and forth to',
      {
        type: 'FunctionExpression',
        id: { type: 'Identifier', name: 'foo' },
        generator: false,
        expression: false,
        async: false,
        params: [
          { type: 'Identifier', name: 'bar' },
          { type: 'Identifier', name: 'quux' },
        ],
        body: {
          type: 'BlockStatement',
          body: [
            {
              type: 'ExpressionStatement',
              expression: {
                type: 'CallExpression',
                callee: { type: 'Identifier', name: 'bar' },
                arguments: [{ type: 'Literal', value: 123, raw: '123' }],
              },
            },
          ],
        },
      }
    );
  });

  it('should convert an anonymous function', function () {
    expect(
      function (bar) {
        bar();
      },
      'to convert back and forth to',
      {
        type: 'FunctionExpression',
        id: null,
        generator: false,
        expression: false,
        async: false,
        params: [{ type: 'Identifier', name: 'bar' }],
        body: {
          type: 'BlockStatement',
          body: [
            {
              type: 'ExpressionStatement',
              expression: {
                type: 'CallExpression',
                callee: { type: 'Identifier', name: 'bar' },
                arguments: [],
              },
            },
          ],
        },
      }
    );
  });
});
<|endoftext|>


<commit_before>var ElementType = require("./ElementType.js");

function Parser(cbs, options) {
    if (options) this._options = options;
    if (cbs) this._cbs = cbs;

    this._buffer = "";
    this._tagSep = "";
    this._stack = [];
    this._wroteSpecial = false;
    this._contentFlags = 0;
    this._done = false;
    this._running = true; //false if paused
}

//Regular expressions used for cleaning up and parsing (stateless)
var _reAttrib = /\s([^\s\/]+?)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+))|(?=\s)|\/|$)/g,
    _reTail = /\s|\/|$/;

Parser.prototype._options = {
    xmlMode: false, //Special behavior for script/style tags by default
    lowerCaseTags: false //call .toLowerCase for each tag name
};

Parser.prototype._cbs = {
    /*
		This is just a plain object
		so that the parser doesn't
		throw if no arguments were
		provided.
	*/
    /*
		oncdataend,
		oncdatastart,
		onclosetag,
		oncomment,
		oncommentend,
		onerror,
		onopentag,
		onprocessinginstruction,
		onreset,
		ontext
	*/
};

//Parses a complete HTML and pushes it to the handler
Parser.prototype.parseComplete = function(data) {
    this.reset();
    this.write(data);
    this.end();
};

//Parses a piece of an HTML document
Parser.prototype.parseChunk = Parser.prototype.write = function(data) {
    if (this._done)
        this._handleError(
            Error("Attempted to parse chunk after parsing already done")
        );
    this._buffer += data; //FIXME: this can be a bottleneck
    if (this._running) this._parseTags();
};

//Tells the parser that the HTML being parsed is complete
Parser.prototype.done = Parser.prototype.end = function(chunk) {
    if (this._done) return;

    if (chunk) this.write(chunk);
    this._done = true;

    if (this._running) this._finishParsing();
};

Parser.prototype._finishParsing = function() {
    //Parse the buffer to its end
    if (this._buffer) this._parseTags(true);

    if (this._cbs.onclosetag) {
        while (this._stack.length) this._cbs.onclosetag(this._stack.pop());
    }

    if (this._cbs.onend) this._cbs.onend();
};

Parser.prototype.pause = function() {
    if (!this._done) this._running = false;
};

Parser.prototype.resume = function() {
    if (this._running) return;
    this._running = true;
    this._parseTags();
    if (this._done) this._finishParsing();
};

//Resets the parser to a blank state, ready to parse a new HTML document
Parser.prototype.reset = function() {
    Parser.call(this);
    if (this._cbs.onreset) this._cbs.onreset();
};

//Extracts the base tag name from the data value of an element
Parser.prototype._parseTagName = function(data) {
    var match = data.substr(0, data.search(_reTail));
    if (!this._options.lowerCaseTags) return match;
    return match.toLowerCase();
};

//Special tags that are treated differently
var SpecialTags = {};
//SpecialTags[ElementType.Tag] = 0;
SpecialTags[ElementType.Style] = 1; //2^0
SpecialTags[ElementType.Script] = 2; //2^1
SpecialTags[ElementType.Comment] = 4; //2^2
SpecialTags[ElementType.CDATA] = 8; //2^3

var TagValues = {
    style: 1,
    script: 2
};

//Parses through HTML text and returns an array of found elements
Parser.prototype._parseTags = function(force) {
    var buffer = this._buffer,
        current = 0;

    var next, rawData, elementData, lastTagSep;

    var opening = buffer.indexOf("<"),
        closing = buffer.indexOf(">");

    //if force is true, parse everything
    if (force) opening = Infinity;

    //opening !== closing is just false if both are -1
    while (opening !== closing && this._running) {
        lastTagSep = this._tagSep;

        if ((opening !== -1 && opening < closing) || closing === -1) {
            next = opening;
            this._tagSep = "<";
            opening = buffer.indexOf("<", next + 1);
        } else {
            next = closing;
            this._tagSep = ">";
            closing = buffer.indexOf(">", next + 1);
        }
        rawData = buffer.substring(current, next); //The next chunk of data to parse

        //set elements for next run
        current = next + 1;

        if (this._contentFlags >= SpecialTags[ElementType.CDATA]) {
            // We're inside a CDATA section
            this._writeCDATA(rawData);
        } else if (this._contentFlags >= SpecialTags[ElementType.Comment]) {
            //We're in a comment tag
            this._writeComment(rawData);
        } else if (lastTagSep === "<") {
            elementData = rawData.trimLeft();
            if (elementData.charAt(0) === "/") {
                //elementData = elementData.substr(1).trim();
                elementData = this._parseTagName(elementData.substr(1));
                if (this._contentFlags !== 0) {
                    //if it's a closing tag, remove the flag
                    if (this._contentFlags >= TagValues[elementData]) {
                        //remove the flag
                        this._contentFlags -= TagValues[elementData];
                    } else {
                        this._writeSpecial(rawData, lastTagSep);
                        continue;
                    }
                }
                this._processCloseTag(elementData);
            } else if (elementData.charAt(0) === "!") {
                if (elementData.substr(1, 2) === "--") {
                    //This tag is a comment
                    this._contentFlags += SpecialTags[ElementType.Comment];
                    this._writeComment(rawData.substr(3));
                } else if (elementData.substr(1, 7) === "[CDATA[") {
                    this._contentFlags += SpecialTags[ElementType.CDATA];
                    if (this._cbs.oncdatastart) this._cbs.oncdatastart();
                    this._writeCDATA(elementData.substr(8));
                } else if (this._contentFlags !== 0)
                    this._writeSpecial(rawData, lastTagSep);
                //TODO: This isn't a processing instruction, needs a new name
                else if (this._cbs.onprocessinginstruction) {
                    this._cbs.onprocessinginstruction(
                        "!" + this._parseTagName(elementData.substr(1)),
                        elementData
                    );
                }
            } else if (this._contentFlags !== 0)
                this._writeSpecial(rawData, lastTagSep);
            else if (elementData.charAt(0) === "?") {
                if (this._cbs.onprocessinginstruction) {
                    this._cbs.onprocessinginstruction(
                        "?" + this._parseTagName(elementData.substr(1)),
                        elementData
                    );
                }
            } else
                this._processOpenTag(
                    this._parseTagName(elementData),
                    elementData
                );
        } else {
            if (this._contentFlags !== 0) {
                this._writeSpecial(rawData, ">");
            } else if (rawData !== "" && this._cbs.ontext) {
                if (this._tagSep === ">") rawData += ">"; //it's the second > in a row
                this._cbs.ontext(rawData);
            }
        }
    }

    this._buffer = buffer.substring(current);
};

Parser.prototype._writeCDATA = function(data) {
    if (this._tagSep === ">" && data.substr(-2) === "]]") {
        // CDATA ends
        if (data.length !== 2 && this._cbs.ontext) {
            this._cbs.ontext(data.slice(0, -2));
        }
        this._contentFlags -= SpecialTags[ElementType.CDATA];
        if (this._cbs.oncdataend) this._cbs.oncdataend();
    } else if (this._cbs.ontext) this._cbs.ontext(data + this._tagSep);
};

Parser.prototype._writeComment = function(rawData) {
    if (this._tagSep === ">" && rawData.substr(-2) === "--") {
        //comment ends
        //remove the written flag (also removes the comment flag)
        this._contentFlags -= SpecialTags[ElementType.Comment];
        this._wroteSpecial = false;
        if (this._cbs.oncomment) this._cbs.oncomment(rawData.slice(0, -2));
        if (this._cbs.oncommentend) this._cbs.oncommentend();
    } else if (this._cbs.oncomment) this._cbs.oncomment(rawData + this._tagSep);
};

Parser.prototype._writeSpecial = function(rawData, lastTagSep) {
    //if the previous element is text, append the last tag sep to element
    if (this._wroteSpecial) {
        if (this._cbs.ontext) this._cbs.ontext(lastTagSep + rawData);
    } else {
        //The previous element was not text
        this._wroteSpecial = true;
        if (rawData !== "" && this._cbs.ontext) this._cbs.ontext(rawData);
    }
};

var emptyTags = {
    __proto__: null,
    area: true,
    base: true,
    basefont: true,
    br: true,
    col: true,
    frame: true,
    hr: true,
    img: true,
    input: true,
    isindex: true,
    link: true,
    meta: true,
    param: true,
    embed: true
};

Parser.prototype._processCloseTag = function(name) {
    if (this._stack && (!(name in emptyTags) || this._options.xmlMode)) {
        var pos = this._stack.lastIndexOf(name);
        if (pos !== -1)
            if (this._cbs.onclosetag) {
                pos = this._stack.length - pos;
                while (pos--) this._cbs.onclosetag(this._stack.pop());
            } else this._stack.splice(pos);
    }
    //many browsers (eg. Safari, Chrome) convert </br> to <br>
    else if (name === "br" && !this._options.xmlMode)
        this._processOpenTag(name, "/");
};

Parser.prototype._parseAttributes = function(data) {
    for (var match; (match = _reAttrib.exec(data)); ) {
        this._cbs.onattribute(match[1], match[2] || match[3] || match[4] || "");
    }
};

//parses the attribute string
var parseAttributes = function(data) {
    var attrs = {};
    for (var match; (match = _reAttrib.exec(data)); ) {
        attrs[match[1]] = match[2] || match[3] || match[4] || "";
    }
    return attrs;
};

Parser.prototype._processOpenTag = function(name, data) {
    var type = ElementType.Tag;
    if (this._options.xmlMode) {
        /*do nothing*/
    } else if (name === "script") type = ElementType.Script;
    else if (name === "style") type = ElementType.Style;

    if (this._cbs.onopentagname) this._cbs.onopentagname(name);
    if (this._cbs.onopentag) this._cbs.onopentag(name, parseAttributes(data));
    if (this._cbs.onattribute) this._parseAttributes(data);

    //If tag self-terminates, add an explicit, separate closing tag
    if (
        data.substr(-1) === "/" ||
        (name in emptyTags && !this._options.xmlMode)
    ) {
        if (this._cbs.onclosetag) this._cbs.onclosetag(name);
    } else {
        if (type !== ElementType.Tag) {
            this._contentFlags += SpecialTags[type];
            this._wroteSpecial = false;
        }
        this._stack.push(name);
    }
};

Parser.prototype._handleError = function(error) {
    if (this._cbs.onerror) this._cbs.onerror(error);
    else throw error;
};

module.exports = Parser;
<commit_msg>Parser#_processOpenTag now takes a single argument<commit_after>var ElementType = require("./ElementType.js");

function Parser(cbs, options) {
    if (options) this._options = options;
    if (cbs) this._cbs = cbs;

    this._buffer = "";
    this._tagSep = "";
    this._stack = [];
    this._wroteSpecial = false;
    this._contentFlags = 0;
    this._done = false;
    this._running = true; //false if paused
}

//Regular expressions used for cleaning up and parsing (stateless)
var _reAttrib = /\s([^\s\/]+?)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+))|(?=\s)|\/|$)/g,
    _reTail = /\s|\/|$/;

Parser.prototype._options = {
    xmlMode: false, //Special behavior for script/style tags by default
    lowerCaseTags: false //call .toLowerCase for each tag name
};

Parser.prototype._cbs = {
    /*
		This is just a plain object
		so that the parser doesn't
		throw if no arguments were
		provided.
	*/
    /*
		oncdataend,
		oncdatastart,
		onclosetag,
		oncomment,
		oncommentend,
		onerror,
		onopentag,
		onprocessinginstruction,
		onreset,
		ontext
	*/
};

//Parses a complete HTML and pushes it to the handler
Parser.prototype.parseComplete = function(data) {
    this.reset();
    this.write(data);
    this.end();
};

//Parses a piece of an HTML document
Parser.prototype.parseChunk = Parser.prototype.write = function(data) {
    if (this._done)
        this._handleError(
            Error("Attempted to parse chunk after parsing already done")
        );
    this._buffer += data; //FIXME: this can be a bottleneck
    if (this._running) this._parseTags();
};

//Tells the parser that the HTML being parsed is complete
Parser.prototype.done = Parser.prototype.end = function(chunk) {
    if (this._done) return;

    if (chunk) this.write(chunk);
    this._done = true;

    if (this._running) this._finishParsing();
};

Parser.prototype._finishParsing = function() {
    //Parse the buffer to its end
    if (this._buffer) this._parseTags(true);

    if (this._cbs.onclosetag) {
        while (this._stack.length) this._cbs.onclosetag(this._stack.pop());
    }

    if (this._cbs.onend) this._cbs.onend();
};

Parser.prototype.pause = function() {
    if (!this._done) this._running = false;
};

Parser.prototype.resume = function() {
    if (this._running) return;
    this._running = true;
    this._parseTags();
    if (this._done) this._finishParsing();
};

//Resets the parser to a blank state, ready to parse a new HTML document
Parser.prototype.reset = function() {
    Parser.call(this);
    if (this._cbs.onreset) this._cbs.onreset();
};

//Extracts the base tag name from the data value of an element
Parser.prototype._parseTagName = function(data) {
    var match = data.substr(0, data.search(_reTail));
    if (!this._options.lowerCaseTags) return match;
    return match.toLowerCase();
};

//Special tags that are treated differently
var SpecialTags = {};
//SpecialTags[ElementType.Tag] = 0;
SpecialTags[ElementType.Style] = 1; //2^0
SpecialTags[ElementType.Script] = 2; //2^1
SpecialTags[ElementType.Comment] = 4; //2^2
SpecialTags[ElementType.CDATA] = 8; //2^3

var TagValues = {
    style: 1,
    script: 2
};

//Parses through HTML text and returns an array of found elements
Parser.prototype._parseTags = function(force) {
    var buffer = this._buffer,
        current = 0;

    var next, rawData, elementData, lastTagSep;

    var opening = buffer.indexOf("<"),
        closing = buffer.indexOf(">");

    //if force is true, parse everything
    if (force) opening = Infinity;

    //opening !== closing is just false if both are -1
    while (opening !== closing && this._running) {
        lastTagSep = this._tagSep;

        if ((opening !== -1 && opening < closing) || closing === -1) {
            next = opening;
            this._tagSep = "<";
            opening = buffer.indexOf("<", next + 1);
        } else {
            next = closing;
            this._tagSep = ">";
            closing = buffer.indexOf(">", next + 1);
        }
        rawData = buffer.substring(current, next); //The next chunk of data to parse

        //set elements for next run
        current = next + 1;

        if (this._contentFlags >= SpecialTags[ElementType.CDATA]) {
            // We're inside a CDATA section
            this._writeCDATA(rawData);
        } else if (this._contentFlags >= SpecialTags[ElementType.Comment]) {
            //We're in a comment tag
            this._writeComment(rawData);
        } else if (lastTagSep === "<") {
            elementData = rawData.trimLeft();
            if (elementData.charAt(0) === "/") {
                //elementData = elementData.substr(1).trim();
                elementData = this._parseTagName(elementData.substr(1));
                if (this._contentFlags !== 0) {
                    //if it's a closing tag, remove the flag
                    if (this._contentFlags >= TagValues[elementData]) {
                        //remove the flag
                        this._contentFlags -= TagValues[elementData];
                    } else {
                        this._writeSpecial(rawData, lastTagSep);
                        continue;
                    }
                }
                this._processCloseTag(elementData);
            } else if (elementData.charAt(0) === "!") {
                if (elementData.substr(1, 2) === "--") {
                    //This tag is a comment
                    this._contentFlags += SpecialTags[ElementType.Comment];
                    this._writeComment(rawData.substr(3));
                } else if (elementData.substr(1, 7) === "[CDATA[") {
                    this._contentFlags += SpecialTags[ElementType.CDATA];
                    if (this._cbs.oncdatastart) this._cbs.oncdatastart();
                    this._writeCDATA(elementData.substr(8));
                } else if (this._contentFlags !== 0)
                    this._writeSpecial(rawData, lastTagSep);
                //TODO: This isn't a processing instruction, needs a new name
                else if (this._cbs.onprocessinginstruction) {
                    this._cbs.onprocessinginstruction(
                        "!" + this._parseTagName(elementData.substr(1)),
                        elementData
                    );
                }
            } else if (this._contentFlags !== 0)
                this._writeSpecial(rawData, lastTagSep);
            else if (elementData.charAt(0) === "?") {
                if (this._cbs.onprocessinginstruction) {
                    this._cbs.onprocessinginstruction(
                        "?" + this._parseTagName(elementData.substr(1)),
                        elementData
                    );
                }
            } else this._processOpenTag(elementData);
        } else {
            if (this._contentFlags !== 0) {
                this._writeSpecial(rawData, ">");
            } else if (rawData !== "" && this._cbs.ontext) {
                if (this._tagSep === ">") rawData += ">"; //it's the second > in a row
                this._cbs.ontext(rawData);
            }
        }
    }

    this._buffer = buffer.substring(current);
};

Parser.prototype._writeCDATA = function(data) {
    if (this._tagSep === ">" && data.substr(-2) === "]]") {
        // CDATA ends
        if (data.length !== 2 && this._cbs.ontext) {
            this._cbs.ontext(data.slice(0, -2));
        }
        this._contentFlags -= SpecialTags[ElementType.CDATA];
        if (this._cbs.oncdataend) this._cbs.oncdataend();
    } else if (this._cbs.ontext) this._cbs.ontext(data + this._tagSep);
};

Parser.prototype._writeComment = function(rawData) {
    if (this._tagSep === ">" && rawData.substr(-2) === "--") {
        //comment ends
        //remove the written flag (also removes the comment flag)
        this._contentFlags -= SpecialTags[ElementType.Comment];
        this._wroteSpecial = false;
        if (this._cbs.oncomment) this._cbs.oncomment(rawData.slice(0, -2));
        if (this._cbs.oncommentend) this._cbs.oncommentend();
    } else if (this._cbs.oncomment) this._cbs.oncomment(rawData + this._tagSep);
};

Parser.prototype._writeSpecial = function(rawData, lastTagSep) {
    //if the previous element is text, append the last tag sep to element
    if (this._wroteSpecial) {
        if (this._cbs.ontext) this._cbs.ontext(lastTagSep + rawData);
    } else {
        //The previous element was not text
        this._wroteSpecial = true;
        if (rawData !== "" && this._cbs.ontext) this._cbs.ontext(rawData);
    }
};

var emptyTags = {
    __proto__: null,
    area: true,
    base: true,
    basefont: true,
    br: true,
    col: true,
    frame: true,
    hr: true,
    img: true,
    input: true,
    isindex: true,
    link: true,
    meta: true,
    param: true,
    embed: true
};

Parser.prototype._processCloseTag = function(name) {
    if (this._stack && (!(name in emptyTags) || this._options.xmlMode)) {
        var pos = this._stack.lastIndexOf(name);
        if (pos !== -1)
            if (this._cbs.onclosetag) {
                pos = this._stack.length - pos;
                while (pos--) this._cbs.onclosetag(this._stack.pop());
            } else this._stack.splice(pos);
    }
    //many browsers (eg. Safari, Chrome) convert </br> to <br>
    else if (name === "br" && !this._options.xmlMode)
        this._processOpenTag(name + "/");
};

Parser.prototype._parseAttributes = function(data) {
    for (var match; (match = _reAttrib.exec(data)); ) {
        this._cbs.onattribute(match[1], match[2] || match[3] || match[4] || "");
    }
};

//parses the attribute string
var parseAttributes = function(data) {
    var attrs = {};
    for (var match; (match = _reAttrib.exec(data)); ) {
        attrs[match[1]] = match[2] || match[3] || match[4] || "";
    }
    return attrs;
};

Parser.prototype._processOpenTag = function(data) {
    var name = this._parseTagName(data),
        type = ElementType.Tag;

    if (this._options.xmlMode) {
        /*do nothing*/
    } else if (name === "script") type = ElementType.Script;
    else if (name === "style") type = ElementType.Style;

    if (this._cbs.onopentagname) this._cbs.onopentagname(name);
    if (this._cbs.onopentag) this._cbs.onopentag(name, parseAttributes(data));
    if (this._cbs.onattribute) this._parseAttributes(data);

    //If tag self-terminates, add an explicit, separate closing tag
    if (
        data.substr(-1) === "/" ||
        (name in emptyTags && !this._options.xmlMode)
    ) {
        if (this._cbs.onclosetag) this._cbs.onclosetag(name);
    } else {
        if (type !== ElementType.Tag) {
            this._contentFlags += SpecialTags[type];
            this._wroteSpecial = false;
        }
        this._stack.push(name);
    }
};

Parser.prototype._handleError = function(error) {
    if (this._cbs.onerror) this._cbs.onerror(error);
    else throw error;
};

module.exports = Parser;
<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var flash = require('connect-flash');

var cors = require('cors');
var passport = require('passport');

var mongoose = require('mongoose');
var mongoUri = process.env.MONGOLAB_URI || 'mongodb://localhost/ubeat';
mongoose.connect(mongoUri);

var authentication = require('./middleware/authentication');
var login = require('./routes/login');
var signup = require('./routes/signup');
var user = require('./routes/user');
var search = require('./routes/search');
var lookup = require('./routes/lookup');
var playlist = require('./routes/playlists');
var status = require('./routes/status');

var app = express();
var corsOptions = {
    origin: '*',
    methods: ['GET', 'PUT', 'POST', 'PATCH', 'DELETEx', 'UPDATE'],
    credentials: true
};

var tokenSecret = 'UBEAT_TOKEN_SECRET' || process.env.TOKEN_SECRET;

app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.set('jwtTokenSecret', tokenSecret);

require('./middleware/passport')(passport, app);

app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({
    secret: 'ubeat_session_secret',
    resave: true,
    saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(cors(corsOptions));
app.use(express.static(__dirname + '/public'));

app.get('/status', status.getStatus);
app.get('/login', login.showLoginPage);
app.post('/login', passport.authenticate('local-login'), login.getToken);
app.get('/logout', login.logout);

app.get('/signup', signup.showSignupPage);
app.post('/signup', signup.passportSignup);
app.get('/welcome', signup.welcome);

app.get('/token', login.getToken);
app.get('/tokenInfo', authentication.isAuthenticated, login.getToken);

// Secure API
app.get('/search', authentication.isAuthenticated, search.search);
app.get('/search/albums', authentication.isAuthenticated, search.searchByAlbum);
app.get('/search/artists', authentication.isAuthenticated, search.searchByArtist);
app.get('/search/tracks', authentication.isAuthenticated, search.searchByTrack);
app.get('/search/users', authentication.isAuthenticated, user.findByName);

app.get('/users', authentication.isAuthenticated, user.allUsers);
app.get('/users/:id', authentication.isAuthenticated, user.findById);

app.post('/follow', authentication.isAuthenticated, user.follow);
app.delete('/follow/:id', authentication.isAuthenticated, user.unfollow);

app.get('/albums/:id', authentication.isAuthenticated, lookup.getAlbum);
app.get('/albums/:id/tracks', authentication.isAuthenticated, lookup.getAlbumTracks);
app.get('/artists/:id', authentication.isAuthenticated, lookup.getArtist);
app.get('/artists/:id/albums', authentication.isAuthenticated, lookup.getArtistAlbums);
app.get('/playlists', authentication.isAuthenticated, playlist.getPlaylists);
app.post('/playlists', authentication.isAuthenticated, playlist.createPlaylist);
app.delete('/playlists/:id', authentication.isAuthenticated, playlist.removePlaylist);
app.post('/playlists/:id/tracks', authentication.isAuthenticated, playlist.addTrackToPlaylist);
app.delete('/playlists/:playlistId/tracks/:trackId', authentication.isAuthenticated, playlist.removeTrackFromPlaylist);
app.get('/playlists/:id', authentication.isAuthenticated, playlist.findPlaylistById);
app.put('/playlists/:id', authentication.isAuthenticated, playlist.updatePlaylist);

// Unsecure API (Will be removed after release 2)
app.get('/unsecure/search', search.search);
app.get('/unsecure/search/albums', search.searchByAlbum);
app.get('/unsecure/search/artists', search.searchByArtist);
app.get('/unsecure/search/tracks', search.searchByTrack);
app.get('/unsecure/search/users', user.findByName);

app.get('/unsecure/users', user.allUsers);
app.get('/unsecure/users/:id', user.findById);

app.post('/unsecure/follow', user.follow);
app.delete('/unsecure/follow/:id', user.unfollow);

app.get('/unsecure/albums/:id', lookup.getAlbum);
app.get('/unsecure/albums/:id/tracks', lookup.getAlbumTracks);
app.get('/unsecure/artists/:id', lookup.getArtist);
app.get('/unsecure/artists/:id/albums', lookup.getArtistAlbums);
app.get('/unsecure/playlists', playlist.getPlaylists);
app.post('/unsecure/playlists', playlist.createPlaylist);
app.delete('/unsecure/playlists/:id', playlist.removePlaylist);
app.post('/unsecure/playlists/:id/tracks', playlist.addTrackToPlaylist);
app.delete('/unsecure/playlists/:playlistId/tracks/:trackId', playlist.removeTrackFromPlaylist);
app.get('/unsecure/playlists/:id', playlist.findPlaylistById);
app.put('/unsecure/playlists/:id, playlist.updatePlaylist);

var port = process.env.PORT || 3000;
app.listen(port);
<commit_msg>! Fix syntax error<commit_after>var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var flash = require('connect-flash');

var cors = require('cors');
var passport = require('passport');

var mongoose = require('mongoose');
var mongoUri = process.env.MONGOLAB_URI || 'mongodb://localhost/ubeat';
mongoose.connect(mongoUri);

var authentication = require('./middleware/authentication');
var login = require('./routes/login');
var signup = require('./routes/signup');
var user = require('./routes/user');
var search = require('./routes/search');
var lookup = require('./routes/lookup');
var playlist = require('./routes/playlists');
var status = require('./routes/status');

var app = express();
var corsOptions = {
    origin: '*',
    methods: ['GET', 'PUT', 'POST', 'PATCH', 'DELETEx', 'UPDATE'],
    credentials: true
};

var tokenSecret = 'UBEAT_TOKEN_SECRET' || process.env.TOKEN_SECRET;

app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.set('jwtTokenSecret', tokenSecret);

require('./middleware/passport')(passport, app);

app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({
    secret: 'ubeat_session_secret',
    resave: true,
    saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(cors(corsOptions));
app.use(express.static(__dirname + '/public'));

app.get('/status', status.getStatus);
app.get('/login', login.showLoginPage);
app.post('/login', passport.authenticate('local-login'), login.getToken);
app.get('/logout', login.logout);

app.get('/signup', signup.showSignupPage);
app.post('/signup', signup.passportSignup);
app.get('/welcome', signup.welcome);

app.get('/token', login.getToken);
app.get('/tokenInfo', authentication.isAuthenticated, login.getToken);

// Secure API
app.get('/search', authentication.isAuthenticated, search.search);
app.get('/search/albums', authentication.isAuthenticated, search.searchByAlbum);
app.get('/search/artists', authentication.isAuthenticated, search.searchByArtist);
app.get('/search/tracks', authentication.isAuthenticated, search.searchByTrack);
app.get('/search/users', authentication.isAuthenticated, user.findByName);

app.get('/users', authentication.isAuthenticated, user.allUsers);
app.get('/users/:id', authentication.isAuthenticated, user.findById);

app.post('/follow', authentication.isAuthenticated, user.follow);
app.delete('/follow/:id', authentication.isAuthenticated, user.unfollow);

app.get('/albums/:id', authentication.isAuthenticated, lookup.getAlbum);
app.get('/albums/:id/tracks', authentication.isAuthenticated, lookup.getAlbumTracks);
app.get('/artists/:id', authentication.isAuthenticated, lookup.getArtist);
app.get('/artists/:id/albums', authentication.isAuthenticated, lookup.getArtistAlbums);
app.get('/playlists', authentication.isAuthenticated, playlist.getPlaylists);
app.post('/playlists', authentication.isAuthenticated, playlist.createPlaylist);
app.delete('/playlists/:id', authentication.isAuthenticated, playlist.removePlaylist);
app.post('/playlists/:id/tracks', authentication.isAuthenticated, playlist.addTrackToPlaylist);
app.delete('/playlists/:playlistId/tracks/:trackId', authentication.isAuthenticated, playlist.removeTrackFromPlaylist);
app.get('/playlists/:id', authentication.isAuthenticated, playlist.findPlaylistById);
app.put('/playlists/:id', authentication.isAuthenticated, playlist.updatePlaylist);

// Unsecure API (Will be removed after release 2)
app.get('/unsecure/search', search.search);
app.get('/unsecure/search/albums', search.searchByAlbum);
app.get('/unsecure/search/artists', search.searchByArtist);
app.get('/unsecure/search/tracks', search.searchByTrack);
app.get('/unsecure/search/users', user.findByName);

app.get('/unsecure/users', user.allUsers);
app.get('/unsecure/users/:id', user.findById);

app.post('/unsecure/follow', user.follow);
app.delete('/unsecure/follow/:id', user.unfollow);

app.get('/unsecure/albums/:id', lookup.getAlbum);
app.get('/unsecure/albums/:id/tracks', lookup.getAlbumTracks);
app.get('/unsecure/artists/:id', lookup.getArtist);
app.get('/unsecure/artists/:id/albums', lookup.getArtistAlbums);
app.get('/unsecure/playlists', playlist.getPlaylists);
app.post('/unsecure/playlists', playlist.createPlaylist);
app.delete('/unsecure/playlists/:id', playlist.removePlaylist);
app.post('/unsecure/playlists/:id/tracks', playlist.addTrackToPlaylist);
app.delete('/unsecure/playlists/:playlistId/tracks/:trackId', playlist.removeTrackFromPlaylist);
app.get('/unsecure/playlists/:id', playlist.findPlaylistById);
app.put('/unsecure/playlists/:id', playlist.updatePlaylist);

var port = process.env.PORT || 3000;
app.listen(port);
<|endoftext|>


<commit_before>(function() {

var SERVICE = "https://games.dtco.ru/api/";

var inProgress = false;
var sid = null;
var result = null;

var showResult = function() {
  var view = Dagaz.Controller.app.view;
  var b = []; var s = []; var rb = []; var rs = [];
  for (var i = 0; i < result.length; i++) {
       var pos = Dagaz.Model.stringToPos(result[i].move);
       if (Math.abs(result[i].weight) > 500) {
           if (result[i].weight < 0) {
               rb.push(pos);
           } else {
               b.push(pos);
           }
       } else {
           if (result[i].weight < 0) {
               rs.push(pos);
           } else {
               s.push(pos);
           }
       }
  }
  view.markPositions(5, b); view.markPositions(7, rb);
  view.markPositions(6, s); view.markPositions(8, rs);
}

Dagaz.AI.clearAdvisor = function() {
  var view = Dagaz.Controller.app.view;
  view.markPositions(5, []); view.markPositions(7, []);
  view.markPositions(6, []); view.markPositions(8, []);
}

var getSid = function() {
  $.ajax({
     url: SERVICE + "ai",
     type: "GET",
     crossDomain: true,
     dataType: "json",
     success: function(data) {
         sid = data.sid;
         inProgress = false;
     },
     error: function() {
         console.log('Auth: Error!');
         window.location = '/';
     },
     statusCode: {
        500: function() {
             console.log('Auth: Internal Error!');
             window.location = '/';
        }
     }
  });
}

Dagaz.AI.putFit = function(setup, move) {
  $.ajax({
     url: SERVICE + "ai/fit",
     type: "PUT",
     crossDomain: true,
     data: {
         setup: setup,
         move: move
     },
     dataType: "json",
     success: function(data) {
         inProgress = false;
     },
     statusCode: {
        500: function() {
             console.log('Auth: Internal Error!');
             window.location = '/';
        }
     }
  });
}

Dagaz.AI.advisor = function(setup) {
  if (result !== null) {
      showResult();
      result = null;
      return true;
  }
  if (inProgress) return false;
  inProgress = true;
  if (sid === null) {
      getSid();
      return false;
  }
  console.log('sid = ' + sid + ', setup = ' + setup);
  $.ajax({
     url: SERVICE + "ai",
     type: "PUT",
     crossDomain: true,
     data: {
         sid: sid,
         setup: setup,
         variant_id: 2,
         coeff: 5
     },
     dataType: "json",
     success: function(data) {
         if (data.length > 0) {
             result = data;
         }
         inProgress = false;
     },
     statusCode: {
        404: function() {
             result = null;
             inProgress = false;
        },
        500: function() {
             console.log('Auth: Internal Error!');
             window.location = '/';
        }
     }
  });
  return false;
}

})();
<commit_msg>DagazServer (AI Fit)<commit_after>(function() {

var SERVICE = "https://games.dtco.ru/api/";

var inProgress = false;
var sid = null;
var result = null;

var showResult = function() {
  var view = Dagaz.Controller.app.view;
  var b = []; var s = []; var rb = []; var rs = [];
  for (var i = 0; i < result.length; i++) {
       var pos = Dagaz.Model.stringToPos(result[i].move);
       if (Math.abs(result[i].weight) > 500) {
           if (result[i].weight < 0) {
               rb.push(pos);
           } else {
               b.push(pos);
           }
       } else {
           if (result[i].weight < 0) {
               rs.push(pos);
           } else {
               s.push(pos);
           }
       }
  }
  view.markPositions(5, b); view.markPositions(7, rb);
  view.markPositions(6, s); view.markPositions(8, rs);
}

Dagaz.AI.clearAdvisor = function() {
  var view = Dagaz.Controller.app.view;
  view.markPositions(5, []); view.markPositions(7, []);
  view.markPositions(6, []); view.markPositions(8, []);
}

var getSid = function() {
  $.ajax({
     url: SERVICE + "ai",
     type: "GET",
     crossDomain: true,
     dataType: "json",
     success: function(data) {
         sid = data.sid;
         inProgress = false;
     },
     error: function() {
         console.log('Auth: Error!');
         window.location = '/';
     },
     statusCode: {
        500: function() {
             console.log('Auth: Internal Error!');
             window.location = '/';
        }
     }
  });
}

Dagaz.AI.putFit = function(setup, move) {
  $.ajax({
     url: SERVICE + "ai/fit",
     type: "PUT",
     crossDomain: true,
     data: {
         variant_id: 2,
         setup: setup,
         move: move
     },
     dataType: "json",
     success: function(data) {
         inProgress = false;
     },
     statusCode: {
        500: function() {
             console.log('Auth: Internal Error!');
             window.location = '/';
        }
     }
  });
}

Dagaz.AI.advisor = function(setup) {
  if (result !== null) {
      showResult();
      result = null;
      return true;
  }
  if (inProgress) return false;
  inProgress = true;
  if (sid === null) {
      getSid();
      return false;
  }
  console.log('sid = ' + sid + ', setup = ' + setup);
  $.ajax({
     url: SERVICE + "ai",
     type: "PUT",
     crossDomain: true,
     data: {
         sid: sid,
         setup: setup,
         variant_id: 2,
         coeff: 5
     },
     dataType: "json",
     success: function(data) {
         if (data.length > 0) {
             result = data;
         }
         inProgress = false;
     },
     statusCode: {
        404: function() {
             result = null;
             inProgress = false;
        },
        500: function() {
             console.log('Auth: Internal Error!');
             window.location = '/';
        }
     }
  });
  return false;
}

})();
<|endoftext|>


<commit_before>// GET /db/{db}/forms
// Forms / List all forms
//
// Alpha @ 0.1.41
//
// `200 OK`,
// [Read-only](/docs/#/concept/read-only.md),
// [Paginated](/docs/#/concept/paginated.md).
//
// Returns all the forms that can be seen by contact `{as}`, in arbitrary order.
// Supports `limit` and `offset` pagination.
//
// ### Response format
//     { "list": [ <short-form>, ... ] }
// - `list` is a list of forms on the requested page, in
//   [short format](/docs/#/format/short.js)

TEST("The response has valid return code and content type.", function(next) {

    var db = Query.mkdb();
    var response = Test.query("GET",["db/",db,"/forms"]).response();

    response.map(function(r) {
	Assert.areEqual(200, r.status).then();
	Assert.isTrue(r.responseJSON, "Response type is JSON").then();
    }).then(next);

});

// # Examples
//
// ### Example request
//     GET /db/0SNQc00211H/forms?as=0Sd7003511H&limit=3&offset=213
//
// ### Example response
//     200 OK
//     Content-Type: application/json
//
//     { "list" : [
//       { "id" : "0SNQe00311H",
//         "owner" : "contact",
//         "label" : "Why did you join our group ?",
//         "fields" : 2,
//         "access" : ["fill"] },
//       { "id" : "0SNQg00511H",
//         "label" : null,
//         "owner" : "contact",
//         "fields" : 1,
//         "pic" : ["admin","fill"] }

TEST("Returns data for all forms.", function(next) {

    var exampleA = {
	"owner": "contact",
	"audience": { "fill": "anyone" },
	"label": "Join form",
	"custom": [1,2,3],
	"fields": [ {
	    "id": "1",
	    "label": "Why did you join our group ?",
	    "kind": "text",
	    "required": true
	}, {
	    "id": "2",
	    "label": "How often do you log in ?",
	    "kind": "single",
            "choices" : [
		"Every day",
		"Once a week",
		"Once a month",
		"Less than once a month" ],
	    "required": false
	} ]
    };

    var exampleB = {
	"owner": "contact",
	"audience": { "admin": "anyone" },
	"label": "Personal information",
	"fields": [ {
	    "id": "1",
	    "label": "First pet's name",
	    "kind": "text",
	    "required": false
	} ]
    };

    var exampleC = {
	"owner": "contact",
	"audience": {},
	"label": "Private information",
	"fields": [ {
	    "id": "1",
	    "label": "Your favourite color",
	    "kind": "text",
	    "required": false
	} ]
    };

    var db = Query.mkdb();
    var auth = Query.auth(db);

    Test.query("POST",["db/",db,"/forms"],exampleA,auth).result("id")(function(idA) {
	Test.query("POST",["db/",db,"/forms"],exampleB,auth).result("id")(function(idB) {
	    Test.query("POST",["db/",db,"/forms"],exampleC,auth).result("id")(function(idC) {

		var expected = {
		    "list" : [ {
			"id": idA,
			"owner": "contact",
			"access": ["fill"],
			"fields": 2,
			"label": exampleA.label
		    }, {
			"id": idB,
			"owner": "contact",
			"access": ["admin","fill"],
			"fields": 1,
			"label": exampleB.label
		    } ]
		};

		var list = Test.query("GET",["db/",db,"/forms"]).result();

		Assert.areEqual(expected, list).then(next);

	    });
	});
    });

});

// # Errors
//
// ## Returns `404 Not Found`
// - ... if database `{db}` does not exist

TEST("Returns 404 when database does not exist.", function(next) {
    Test.query("GET",["db/00000000000/forms"]).error(404).then(next);
});

// ## Returns `401 Unauthorized`
// - ... if the provided token does not grant mathch contact `{as}`.

TEST("Returns 401 when token is not valid.", function(next) {
    var db = Query.mkdb();
    Test.query("GET",["db/",db,"/forms"],{token:"012345789a",id:"0123456789a"})
	.error(401).then(next);
});

// # Access restrictions
//
// Anyone can ask for a list of forms, and will only be shown the forms
// they can see (**fill** access is required). <commit_msg>Convert fixture to new model<commit_after>// GET /db/{db}/forms
// Forms / List all forms
//
// Alpha @ 0.1.41
//
// `200 OK`,
// [Read-only](/docs/#/concept/read-only.md),
// [Paginated](/docs/#/concept/paginated.md).
//
// Returns all the forms that can be seen by contact `{as}`, in arbitrary order.
// Supports `limit` and `offset` pagination.
//
// ### Response format
//     { "list": [ <short-form>, ... ] }
// - `list` is a list of forms on the requested page, in
//   [short format](/docs/#/format/short.js)

TEST("The response has valid return code and content type.", function(Query) {

    var db = Query.mkdb();
    return Query.get(["db/",db,"/forms"]).assertStatus(200).assertIsJson();

});

// # Examples
//
// ### Example request
//     GET /db/0SNQc00211H/forms?as=0Sd7003511H&limit=3&offset=213
//
// ### Example response
//     200 OK
//     Content-Type: application/json
//
//     { "list" : [
//       { "id" : "0SNQe00311H",
//         "owner" : "contact",
//         "label" : "Why did you join our group ?",
//         "fields" : 2,
//         "access" : ["fill"] },
//       { "id" : "0SNQg00511H",
//         "label" : null,
//         "owner" : "contact",
//         "fields" : 1,
//         "pic" : ["admin","fill"] }

TEST("Returns data for all forms.", function(Query) {

    var exampleA = {
	"owner": "contact",
	"audience": { "fill": "anyone" },
	"label": "Join form",
	"custom": [1,2,3],
	"fields": [ {
	    "id": "1",
	    "label": "Why did you join our group ?",
	    "kind": "text",
	    "required": true
	}, {
	    "id": "2",
	    "label": "How often do you log in ?",
	    "kind": "single",
            "choices" : [
		"Every day",
		"Once a week",
		"Once a month",
		"Less than once a month" ],
	    "required": false
	} ]
    };

    var exampleB = {
	"owner": "contact",
	"audience": { "admin": "anyone" },
	"label": "Personal information",
	"fields": [ {
	    "id": "1",
	    "label": "First pet's name",
	    "kind": "text",
	    "required": false
	} ]
    };

    var exampleC = {
	"owner": "contact",
	"audience": {},
	"label": "Private information",
	"fields": [ {
	    "id": "1",
	    "label": "Your favourite color",
	    "kind": "text",
	    "required": false
	} ]
    };

    var db = Query.mkdb();
    var auth = Query.auth(db);

    return Query.post(["db/",db,"/forms"],exampleA,auth).id().then(function(idA) {
	return Query.post(["db/",db,"/forms"],exampleB,auth).id().then(function(idB) {
	    return Query.post(["db/",db,"/forms"],exampleC,auth).id().then(function(idC) {

		var expected = {
		    "list" : [ {
			"id": idA,
			"owner": "contact",
			"access": ["fill"],
			"fields": 2,
			"label": exampleA.label
		    }, {
			"id": idB,
			"owner": "contact",
			"access": ["admin","fill"],
			"fields": 1,
			"label": exampleB.label
		    } ]
		};

		return Query.get(["db/",db,"/forms"]).then(function(d,s,r) {
		    return Assert.areEqual(expected, d);
		});
	    });
	});
    });

});

// # Errors
//
// ## Returns `404 Not Found`
// - ... if database `{db}` does not exist

TEST("Returns 404 when database does not exist.", function(Query) {
    return Query.get(["db/00000000000/forms"]).assertStatus(404);
});

// ## Returns `401 Unauthorized`
// - ... if the provided token does not grant mathch contact `{as}`.

TEST("Returns 401 when token is not valid.", function(Query) {
    var db = Query.mkdb();
    return Query.get(["db/",db,"/forms"],{token:"012345789a",id:"0123456789a"})
	.assertStatus(401);
});

// # Access restrictions
//
// Anyone can ask for a list of forms, and will only be shown the forms
// they can see (**fill** access is required). <|endoftext|>


<commit_before>var TelegramBot = require('node-telegram-bot-api');
var bot = new TelegramBot(process.env.CHAINTACT_BOT_TOKEN, {polling: true});
var mongoose = require('mongoose');
var dbUrl = "mongodb://chaintact_db/chaintactdb";

mongoose.connect(dbUrl);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
  console.log("I'm in!");
});

//Database
var userSchema = mongoose.Schema({
    telegramID: String,
    telegramUsername: String,
    firstName: String,
    lastName: String,
    ETHAddress: String
});

var User = mongoose.model('User', userSchema);

bot.getMe().then(function (me) {
  console.log('Hi my name is %s!', me.username);
});

//BOT commands

var helpText = "Commands for /chaintact :\n"
  + "    help - List of commands\n"
  + "    set [ETH address] - Set your ETH address to your profil\n"
  + "    get [telegram user] - Sends this user ETH address\n"
  + "    group - Sends the list of all group users ETH addresses"

//matches /start
bot.onText(/\/start/, function (msg, match) {
  var fromId = msg.from.id; // get the id, of who is sending the message
  var message = "Welcome to your ChaintactBot\n"
  message += helpText
  bot.sendMessage(fromId, message);
});

//match /chaintact [whatever]
bot.onText(/\/chaintact (.+)/, function (msg, match) {
  var fromId = msg.from.id; // get the id, of who is sending the message
  var fromUsername = "";
  var fromLastName = "";
  var fromFirstName = "";
  if(msg.from.username != null) fromUsername = msg.from.username
  if(msg.from.first_name != null) fromFirstName = msg.from.username
  if(msg.from.last_name != null) fromLastName = msg.from.username
  var command = match[1];
  var commandArr = command.split(" ");
  var message;

  if(commandArr.length < 1) {
    message = helpText;
    bot.sendMessage(fromId, message);
    return;
  }

  switch(commandArr[0]) {
    case "help":
      message = helpText;
      break;
    case "set":

      if(commandArr[1] == null) {
        message = "Please enter an ETH address!";
        break;
      }

      User.findOne({telegramID: fromId}, function(err, user) {
        if(user == null) {
          var newUser = new User({telegramID:fromId, telegramUsername:fromUsername, firstName:fromFirstName, lastName:fromLastName, ETHAddress:match[2]});
          newUser.save(function (err) {
            if (err) return handleError(err);
            console.log("User created : " + fromId);
          })
        } else {
          user.telegramUsername = fromUsername
          user.firstName = fromFirstName
          user.lastName = fromLastName
          user.ETHAddress = match[2]
          .save(function (err) {
            if (err) return handleError(err);
            console.log("User updated : " + fromId);
          })
        }
      })
      break;
    case "get":
      message = "Coming soon!";
      break;
    case "group":
      message = "Coming soon!";
      break;
    default:
      message = helpText;
  }
  bot.sendMessage(fromId, message);
});
<commit_msg>Set function<commit_after>var TelegramBot = require('node-telegram-bot-api');
var bot = new TelegramBot(process.env.CHAINTACT_BOT_TOKEN, {polling: true});
var mongoose = require('mongoose');
var dbUrl = "mongodb://chaintact_db/chaintactdb";

mongoose.connect(dbUrl);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
  console.log("I'm in!");
});

//Database
var userSchema = mongoose.Schema({
    telegramID: String,
    telegramUsername: String,
    firstName: String,
    lastName: String,
    ETHAddress: String
});

var User = mongoose.model('User', userSchema);

bot.getMe().then(function (me) {
  console.log('Hi my name is %s!', me.username);
});

//BOT commands

var helpText = "Commands for /chaintact :\n"
  + "    help - List of commands\n"
  + "    set [ETH address] - Set your ETH address to your profil\n"
  + "    get [telegram user] - Sends this user ETH address\n"
  + "    group - Sends the list of all group users ETH addresses"

//matches /start
bot.onText(/\/start/, function (msg, match) {
  var fromId = msg.from.id; // get the id, of who is sending the message
  var message = "Welcome to your ChaintactBot\n"
  message += helpText
  bot.sendMessage(fromId, message);
});

//match /chaintact [whatever]
bot.onText(/\/chaintact (.+)/, function (msg, match) {
  var fromId = msg.from.id; // get the id, of who is sending the message
  var fromUsername = "";
  var fromLastName = "";
  var fromFirstName = "";
  if(msg.from.username != null) fromUsername = msg.from.username
  if(msg.from.first_name != null) fromFirstName = msg.from.username
  if(msg.from.last_name != null) fromLastName = msg.from.username
  var command = match[1];
  var commandArr = command.split(" ");
  var message;

  if(commandArr.length < 1) {
    message = helpText;
    bot.sendMessage(fromId, message);
    return;
  }

  switch(commandArr[0]) {
    case "help":
      message = helpText;
      break;
    case "set":

      if(commandArr[1] == null) {
        message = "Please enter an ETH address!";
        break;
      }

      User.findOne({telegramID: fromId}, function(err, user) {
        if(user == null) {
          var newUser = new User({telegramID:fromId, telegramUsername:fromUsername, firstName:fromFirstName, lastName:fromLastName, ETHAddress:match[2]});
          newUser.save(function (err) {
            if (err) return handleError(err);
            console.log("User created : " + fromId);
          })
        } else {
          user.telegramUsername = fromUsername
          user.firstName = fromFirstName
          user.lastName = fromLastName
          user.ETHAddress = match[2]
          user.save(function (err) {
            if (err) return handleError(err);
            console.log("User updated : " + fromId);
          })
        }
      })
      break;
    case "get":
      message = "Coming soon!";
      break;
    case "group":
      message = "Coming soon!";
      break;
    default:
      message = helpText;
  }
  bot.sendMessage(fromId, message);
});
<|endoftext|>


<commit_before>var bag = require('bagofholding'),
  sandbox = require('sandboxed-module'),
  should = require('should'),
  checks, mocks,
  functions;

describe('functions', function () {

  function create(checks, mocks) {
    return sandbox.require('../lib/functions', {
      requires: mocks ? mocks.requires : {},
      globals: {
        Date: function () {
          return new Date(2000, 9, 10); // NOTE: 0-based month, so 10 Oct 2000
        }
      }
    });
  }

  beforeEach(function () {
    checks = {};
    mocks = {};
  });

  describe('date', function () {

    it('should return formatted date when format is specified', function () {
      functions = (create(checks, mocks))('somepage', {}, {});
      functions.date('yyyymmdd', function (data) {
        checks.data = data;
      });
      checks.data.should.equal('20001010');
    });

    it('should return date with default format when format is not specified', function () {
      functions = (create(checks, mocks))('somepage', {}, {});
      functions.date(undefined, function (data) {
        checks.data = data;
      });
      checks.data.should.equal('2000-10-10T00:00:00');
    });
  });

  describe('include', function () {

    it('should return partial template when partial exists', function () {
      functions = (create(checks, mocks))('somepage', {}, {});
      functions.include('somepartial', function (data) {
        checks.data = data;
      });
      checks.data.should.equal('[error] partial somepartial does not exist');
    });

    it('should return error message when partial does not exist', function () {
      functions = (create(checks, mocks))('somepage', {}, { partials: { somepartial: 'foobar' } });
      functions.include('somepartial', function (data) {
        checks.data = data;
      });
      checks.data.should.equal('foobar');
    });
  });

  describe('relative', function () {

    it('should return path when page is at the project root directory', function () {
      functions = (create(checks, mocks))('homepage.html', {}, {});
      functions.relative('somepage.html', function (data) {
        checks.data = data;
      });
      checks.data.should.equal('somepage.html');
    });

    it('should return a single upper directory when page is at a project subdirectory', function () {
      functions = (create(checks, mocks))('foo/homepage.html', {}, {});
      functions.relative('somepage.html', function (data) {
        checks.data = data;
      });
      checks.data.should.equal('../somepage.html');
    });

    it('should return multiple upper directories when page is at several directories deep below project directory', function () {
      functions = (create(checks, mocks))('foo/bar/homepage.html', {}, {});
      functions.relative('somepage.html', function (data) {
        checks.data = data;
      });
      checks.data.should.equal('../../somepage.html');
    });

    it('should return multiple upper directories when page and path are both at several directories deep below project directory', function () {
      functions = (create(checks, mocks))('foo/bar/homepage.html', {}, {});
      functions.relative('abc/xyz/somepage.html', function (data) {
        checks.data = data;
      });
      checks.data.should.equal('../../abc/xyz/somepage.html');
    });
  });

  describe('title', function () {

    it('should return title when file exists in sitemap and it has a title', function () {
      functions = (create(checks, mocks))('somepage.html', {}, { sitemap: { 'somepage.html': { title: 'foobar' } } });
      functions.title(function (data) {
        checks.data = data;
      });
      checks.data.should.equal('foobar');
    });

    it('should return undefined when file exists in sitemap but it does not have a title', function () {
      functions = (create(checks, mocks))('somepage.html', {}, { sitemap: { 'somepage.html': {} } });
      functions.title(function (data) {
        checks.data = data;
      });
      should.not.exist(checks.data);
    });

    it('should return error message when file does not exist in sitemap', function () {
      functions = (create(checks, mocks))('somepage.html', {}, {});
      functions.title(function (data) {
        checks.data = data;
      });
      checks.data.should.equal('[error] page somepage.html does not have any sitemap title');
    });
  });
});<commit_msg>Check callback done is called.<commit_after>var bag = require('bagofholding'),
  sandbox = require('sandboxed-module'),
  should = require('should'),
  checks, mocks,
  functions;

describe('functions', function () {

  function create(checks, mocks) {
    return sandbox.require('../lib/functions', {
      requires: mocks ? mocks.requires : {},
      globals: {
        Date: function () {
          return new Date(2000, 9, 10); // NOTE: 0-based month, so 10 Oct 2000
        }
      }
    });
  }

  beforeEach(function () {
    checks = {};
    mocks = {};
  });

  describe('date', function () {

    it('should return formatted date when format is specified', function (done) {
      functions = (create(checks, mocks))('somepage', {}, {});
      functions.date('yyyymmdd', function (data) {
        checks.data = data;
        done();
      });
      checks.data.should.equal('20001010');
    });

    it('should return date with default format when format is not specified', function (done) {
      functions = (create(checks, mocks))('somepage', {}, {});
      functions.date(undefined, function (data) {
        checks.data = data;
        done();
      });
      checks.data.should.equal('2000-10-10T00:00:00');
    });
  });

  describe('include', function () {

    it('should return partial template when partial exists', function (done) {
      functions = (create(checks, mocks))('somepage', {}, {});
      functions.include('somepartial', function (data) {
        checks.data = data;
        done();
      });
      checks.data.should.equal('[error] partial somepartial does not exist');
    });

    it('should return error message when partial does not exist', function (done) {
      functions = (create(checks, mocks))('somepage', {}, { partials: { somepartial: 'foobar' } });
      functions.include('somepartial', function (data) {
        checks.data = data;
        done();
      });
      checks.data.should.equal('foobar');
    });
  });

  describe('relative', function () {

    it('should return path when page is at the project root directory', function (done) {
      functions = (create(checks, mocks))('homepage.html', {}, {});
      functions.relative('somepage.html', function (data) {
        checks.data = data;
        done();
      });
      checks.data.should.equal('somepage.html');
    });

    it('should return a single upper directory when page is at a project subdirectory', function (done) {
      functions = (create(checks, mocks))('foo/homepage.html', {}, {});
      functions.relative('somepage.html', function (data) {
        checks.data = data;
        done();
      });
      checks.data.should.equal('../somepage.html');
    });

    it('should return multiple upper directories when page is at several directories deep below project directory', function (done) {
      functions = (create(checks, mocks))('foo/bar/homepage.html', {}, {});
      functions.relative('somepage.html', function (data) {
        checks.data = data;
        done();
      });
      checks.data.should.equal('../../somepage.html');
    });

    it('should return multiple upper directories when page and path are both at several directories deep below project directory', function (done) {
      functions = (create(checks, mocks))('foo/bar/homepage.html', {}, {});
      functions.relative('abc/xyz/somepage.html', function (data) {
        checks.data = data;
        done();
      });
      checks.data.should.equal('../../abc/xyz/somepage.html');
    });
  });

  describe('title', function () {

    it('should return title when file exists in sitemap and it has a title', function (done) {
      functions = (create(checks, mocks))('somepage.html', {}, { sitemap: { 'somepage.html': { title: 'foobar' } } });
      functions.title(function (data) {
        checks.data = data;
        done();
      });
      checks.data.should.equal('foobar');
    });

    it('should return undefined when file exists in sitemap but it does not have a title', function (done) {
      functions = (create(checks, mocks))('somepage.html', {}, { sitemap: { 'somepage.html': {} } });
      functions.title(function (data) {
        checks.data = data;
        done();
      });
      should.not.exist(checks.data);
    });

    it('should return error message when file does not exist in sitemap', function (done) {
      functions = (create(checks, mocks))('somepage.html', {}, {});
      functions.title(function (data) {
        checks.data = data;
        done();
      });
      checks.data.should.equal('[error] page somepage.html does not have any sitemap title');
    });
  });
});<|endoftext|>


<commit_before>// Person class

var databank = require("databank"),
    Identifier = require("./Identifier").Identifier,
    uuid = require("node-uuid"),
    DatabankObject = databank.DatabankObject;

var Person = DatabankObject.subClass("person");

Person.schema = {pkey: "uuid",
                 fields: [],
                 indices: []
                };

Person.beforeCreate = function(props, callback) {
    if (!props.uuid) {
        props.uuid = uuid.v4();
    }
    callback(null, props);
};

Person.fromIdentifier = function(id, callback) {
    Identifier.get(id, function(err, identifier) {
        if (err) {
            callback(err, null);
        } else {
            Person.get(identifier.person, function(err, person) {
                if (err) {
                    callback(err, null);
                } else {
                    callback(null, person);
                }
            });
        }
    });
};

Person.prototype.getIdentifiers = function(callback) {
    var person = this;

    Identifier.search({uuid: person.uuid}, function(err, identifiers) {
        if (err) {
            callback(err, null);
        } else {
            callback(null, identifiers);
        }
    });
};

exports.Person = Person;

<commit_msg>refactor callbacks<commit_after>// Person class

var databank = require("databank"),
    Identifier = require("./Identifier").Identifier,
    uuid = require("node-uuid"),
    DatabankObject = databank.DatabankObject;

var Person = DatabankObject.subClass("person");

Person.schema = {pkey: "uuid",
                 fields: [],
                 indices: []
                };

Person.beforeCreate = function(props, callback) {
    if (!props.uuid) {
        props.uuid = uuid.v4();
    }
    callback(null, props);
};

Person.fromIdentifier = function(id, callback) {
    Identifier.get(id, function(err, identifier) {
        if (err) return callback(err, null);
        Person.get(identifier.person, callback);
    });
};

Person.prototype.getIdentifiers = function(callback) {
    var person = this;

    Identifier.search({uuid: person.uuid}, callback);
};

exports.Person = Person;

<|endoftext|>


<commit_before>/*!
 * compressible
 * Copyright(c) 2013 Jonathan Ong
 * Copyright(c) 2014 Jeremiah Senkpiel
 * Copyright(c) 2015 Douglas Christopher Wilson
 * MIT Licensed
 */

'use strict'

/**
 * Module dependencies.
 * @private
 */

var db = require('mime-db')

/**
 * Module variables.
 * @private
 */

var compressibleTypeRegExp = /^text\/|\+json$|\+text$|\+xml$/i
var extractTypeRegExp = /^\s*([^;\s]*)(?:;|\s|$)/

/**
 * Module exports.
 * @public
 */

module.exports = compressible

/**
 * Checks if a type is compressible.
 *
 * @param {string} type
 * @return {Boolean} compressible
 * @public
 */

function compressible (type) {
  if (!type || typeof type !== 'string') {
    return false
  }

  // strip parameters
  var match = extractTypeRegExp.exec(type)
  var mime = match && match[1].toLowerCase()
  var data = db[mime]

  // return database information
  if (data && data.compressible !== undefined) {
    return data.compressible
  }

  // fallback to regexp or unknown
  return compressibleTypeRegExp.test(mime) || undefined
}
<commit_msg>lint: change capitalization of constants<commit_after>/*!
 * compressible
 * Copyright(c) 2013 Jonathan Ong
 * Copyright(c) 2014 Jeremiah Senkpiel
 * Copyright(c) 2015 Douglas Christopher Wilson
 * MIT Licensed
 */

'use strict'

/**
 * Module dependencies.
 * @private
 */

var db = require('mime-db')

/**
 * Module variables.
 * @private
 */

var COMPRESSIBLE_TYPE_REGEXP = /^text\/|\+json$|\+text$|\+xml$/i
var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/

/**
 * Module exports.
 * @public
 */

module.exports = compressible

/**
 * Checks if a type is compressible.
 *
 * @param {string} type
 * @return {Boolean} compressible
 * @public
 */

function compressible (type) {
  if (!type || typeof type !== 'string') {
    return false
  }

  // strip parameters
  var match = EXTRACT_TYPE_REGEXP.exec(type)
  var mime = match && match[1].toLowerCase()
  var data = db[mime]

  // return database information
  if (data && data.compressible !== undefined) {
    return data.compressible
  }

  // fallback to regexp or unknown
  return COMPRESSIBLE_TYPE_REGEXP.test(mime) || undefined
}
<|endoftext|>