<commit_before>var fs = require('fs');
var path = require('path');
var through = require('through2');
var gutil = require('gulp-util');
var swaggerParser = require('swagger-parser');
var swaggerTools = require('swagger-tools').specs.v2; // Validate using the latest Swagger 2.x specification
var CodeGen = require('swagger-js-codegen').CodeGen;
var CircularJSON = require('circular-json');
var PLUGIN_NAME = 'gulp-swagger';

module.exports = function gulpSwagger (filename, options) {
	// Allow for passing the `filename` as part of the options.
	if (typeof filename === 'object') {
		options = filename;
		filename = options.filename;
	}

	// File name is mandatory (otherwise gulp won't be able to write the file properly)
	if (!filename) {
		throw new gutil.PluginError(PLUGIN_NAME, 'A file name is required');
	}

	options = options || {};

	// expose options from swagger-parser
	// https://github.com/BigstickCarpet/swagger-parser/blob/master/docs/options.md
	var parserSettings = options.parser || {};

	// Flag if user actually wants to use codeGen or just parse the schema and get json back.
	var useCodeGen = typeof options.codegen === 'object';
	var codeGenSettings = options.codegen || {};

	// If user wants to use the codeGen
	if (useCodeGen) {
		// Allow for shortcuts by providing sensitive defaults.
		codeGenSettings.type = codeGenSettings.type || 'custom'; // type of codeGen, either: 'angular', 'node' or 'custom'.
		codeGenSettings.moduleName = codeGenSettings.moduleName || 'API';
		codeGenSettings.className = codeGenSettings.className || 'API';

		// If codeGen is of type custom, user must provide templates.
		if (codeGenSettings.type === 'custom' && !codeGenSettings.template) {
			throw new gutil.PluginError(PLUGIN_NAME, 'Templates are mandatory for a custom codegen');
		}

		// Shortcut: Allow `template` to be a string passing a single template file.
		else if (typeof codeGenSettings.template === 'string') {
			var template = fs.readFileSync(codeGenSettings.template, 'utf-8');

			if ( typeof template !== 'string' || !template.length ) {
				throw new gutil.PluginError(PLUGIN_NAME, 'Could not load template file');
			}

			codeGenSettings.template = {
				class: template,
				method: '',
				request: ''
			};
		}

		// Regular codeGen template object, but allowing for missing templates.
		// (e.g. use case: if `request` is too simple, there's no need for a dedicated template file)
		else if (typeof codeGenSettings.template === 'object') {
			['class', 'method', 'request']
				.forEach(function loadTemplateFile (tmpl) {
					var template = codeGenSettings.template[tmpl];

					if (typeof template !== 'string' || !template.length) {
						return (codeGenSettings.template[tmpl] = '');
					}

					template = fs.readFileSync(template, 'utf-8');

					if (typeof template !== 'string' || !template.length) {
						throw new gutil.PluginError(PLUGIN_NAME, 'Could not load ' + tmpl + ' template file. Please make sure path to file is correct.');
					}

					codeGenSettings.template[tmpl] = template;
				});
		}
	}

	return through.obj(function throughObj (file, encoding, callback) {
		var _this = this;

		if ( file.isStream() ) {
			throw new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported');
		}

		// Load swagger main file resolving *only* external $refs and validate schema (1st pass).
		// We keep internal $refs intact for more accurate results in 2nd validation pass bellow.
		swaggerParser.dereference(file.history[0], {
			$refs: { internal: false }
		}, function parseSchema (error, swaggerObject) {
			if ( error ) {
				callback(new gutil.PluginError(PLUGIN_NAME, error));
				return;
			}

			// Re-Validate resulting schema using different project (2nd pass), the
			// reason being that this validator gives different (and more accurate) resutls.
			swaggerTools.validate(swaggerObject, function validateSchema (err, result) {
				if (err) {
					callback(new gutil.PluginError(PLUGIN_NAME, err));
					return;
				}

				if ( typeof result !== 'undefined' ) {
					if ( result.errors.length > 0 ) {
						gutil.log(
							gutil.colors.red([
								'',
								'',
								'Swagger Schema Errors (' + result.errors.length + ')',
								'--------------------------',
								result.errors.map(function (err) {
									return '#/' + err.path.join('/') + ': ' + err.message +
										'\n' +
										JSON.stringify(err) +
										'\n';
								}).join('\n'),
								''
							].join('\n')),
							''
						);
					}

					if ( result.warnings.length > 0 ) {
						gutil.log(
							gutil.colors.yellow([
								'',
								'',
								'Swagger Schema Warnings (' + result.warnings.length + ')',
								'------------------------',
								result.warnings.map(function (warn) {
									return '#/' + warn.path.join('/') + ': ' + warn.message +
										'\n' +
										JSON.stringify(warn) +
										'\n';
								}).join('\n'),
								''
							].join('\n')),
							''
						);
					}

					if ( result.errors.length > 0 ) {
						callback(new gutil.PluginError(PLUGIN_NAME, 'The Swagger schema is invalid'));
						return;
					}
				}

				// Now that we know for sure the schema is 100% valid,
				// dereference internal $refs as well.
				swaggerParser.dereference(swaggerObject, parserSettings, function parseSchema (error, swaggerObject) {
					if (error) {
						callback(new gutil.PluginError(PLUGIN_NAME, error));
						return;
					}

					var fileBuffer;

					if ( useCodeGen ) {
						var codeGenFunction = 'get' +
							codeGenSettings.type[0].toUpperCase() +
							codeGenSettings.type.slice(1, codeGenSettings.type.length) +
							'Code';

						codeGenSettings.esnext = true;
						codeGenSettings.swagger = swaggerObject;
						delete codeGenSettings.type;

						codeGenSettings.mustache = codeGenSettings.mustache || {};
						// Allow swagger schema to be easily accessed inside templates.
						codeGenSettings.mustache.swaggerObject = swaggerObject;
						codeGenSettings.mustache.swaggerJSON = JSON.stringify(swaggerObject);
						// Allow each individual JSON schema to be easily accessed inside templates (for validation purposes).
						codeGenSettings.mustache.JSONSchemas = JSON.stringify(
							Object.keys(swaggerObject.paths)
								.reduce(function reducePaths (newPathCollection, currentPath) {
									var pathMethods = swaggerObject.paths[currentPath] || {};
									var pathSchemas = Object.keys(pathMethods)
										.reduce(function reduceMethods (newMethodCollection, currentMethod) {
											var methodParameters = (pathMethods[currentMethod].parameters || [])
												.filter(function filterBodyParameter (parameter) {
													return parameter.in === 'body';
												})[0] || {};
											var methodResponses = pathMethods[currentMethod].responses || {};
											var methodSchemas = {
												request: methodParameters.schema,
												responses: Object.keys(methodResponses)
													.reduce(function reduceMethods (newResponsesCollection, currentResponse) {
														var responseSchema = methodResponses[currentResponse].schema || {};

														newResponsesCollection[currentResponse] = responseSchema;
														return newResponsesCollection;
													}, {})
											};

											newMethodCollection[currentMethod] = methodSchemas;
											return newMethodCollection;
										}, {});

									newPathCollection[currentPath] = pathSchemas;
									return newPathCollection;
								}, {})
						);

						fileBuffer = CodeGen[codeGenFunction](codeGenSettings);
					}
					else {
						try{
								fileBuffer = JSON.stringify(swaggerObject);
						} catch (e) {
							fileBuffer = CircularJSON.stringify(swaggerObject);
						}

					}

					// Return processed file to gulp
					_this.push(new gutil.File({
						cwd: file.cwd,
						base: file.base,
						path: path.join(file.base, filename),
						contents: new Buffer(fileBuffer)
					}));

					callback();
				}); // swaggerParser.dereference (internal $refs)
			}); // swaggerTools.validate
		}); // swaggerParser.dereference (external $refs)
	}); // return through.obj
};
<commit_msg>Allow validation-only if not props are passed.<commit_after>var fs = require('fs');
var path = require('path');
var through = require('through2');
var gutil = require('gulp-util');
var swaggerParser = require('swagger-parser');
var swaggerTools = require('swagger-tools').specs.v2; // Validate using the latest Swagger 2.x specification
var CodeGen = require('swagger-js-codegen').CodeGen;
var CircularJSON = require('circular-json');
var PLUGIN_NAME = 'gulp-swagger';

module.exports = function gulpSwagger (filename, options) {
	// Allow for passing the `filename` as part of the options.
	if (typeof filename === 'object') {
		options = filename;
		filename = options.filename;
	}

	options = options || {};

	// expose options from swagger-parser
	// https://github.com/BigstickCarpet/swagger-parser/blob/master/docs/options.md
	var parserSettings = options.parser || {};

	// Flag if user actually wants to use codeGen or just parse the schema and get json back.
	var useCodeGen = typeof options.codegen === 'object';
	var codeGenSettings = options.codegen || {};

	// If user wants to use the codeGen
	if (useCodeGen) {
		// Allow for shortcuts by providing sensitive defaults.
		codeGenSettings.type = codeGenSettings.type || 'custom'; // type of codeGen, either: 'angular', 'node' or 'custom'.
		codeGenSettings.moduleName = codeGenSettings.moduleName || 'API';
		codeGenSettings.className = codeGenSettings.className || 'API';

		// If codeGen is of type custom, user must provide templates.
		if (codeGenSettings.type === 'custom' && !codeGenSettings.template) {
			throw new gutil.PluginError(PLUGIN_NAME, 'Templates are mandatory for a custom codegen');
		}

		// Shortcut: Allow `template` to be a string passing a single template file.
		else if (typeof codeGenSettings.template === 'string') {
			var template = fs.readFileSync(codeGenSettings.template, 'utf-8');

			if ( typeof template !== 'string' || !template.length ) {
				throw new gutil.PluginError(PLUGIN_NAME, 'Could not load template file');
			}

			codeGenSettings.template = {
				class: template,
				method: '',
				request: ''
			};
		}

		// Regular codeGen template object, but allowing for missing templates.
		// (e.g. use case: if `request` is too simple, there's no need for a dedicated template file)
		else if (typeof codeGenSettings.template === 'object') {
			['class', 'method', 'request']
				.forEach(function loadTemplateFile (tmpl) {
					var template = codeGenSettings.template[tmpl];

					if (typeof template !== 'string' || !template.length) {
						return (codeGenSettings.template[tmpl] = '');
					}

					template = fs.readFileSync(template, 'utf-8');

					if (typeof template !== 'string' || !template.length) {
						throw new gutil.PluginError(PLUGIN_NAME, 'Could not load ' + tmpl + ' template file. Please make sure path to file is correct.');
					}

					codeGenSettings.template[tmpl] = template;
				});
		}
	}

	return through.obj(function throughObj (file, encoding, callback) {
		var _this = this;

		if ( file.isStream() ) {
			throw new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported');
		}

		// Load swagger main file resolving *only* external $refs and validate schema (1st pass).
		// We keep internal $refs intact for more accurate results in 2nd validation pass bellow.
		swaggerParser.dereference(file.history[0], {
			$refs: { internal: false }
		}, function parseSchema (error, swaggerObject) {
			if ( error ) {
				callback(new gutil.PluginError(PLUGIN_NAME, error));
				return;
			}

			// Re-Validate resulting schema using different project (2nd pass), the
			// reason being that this validator gives different (and more accurate) resutls.
			swaggerTools.validate(swaggerObject, function validateSchema (err, result) {
				if (err) {
					callback(new gutil.PluginError(PLUGIN_NAME, err));
					return;
				}

				if ( typeof result !== 'undefined' ) {
					if ( result.errors.length > 0 ) {
						gutil.log(
							gutil.colors.red([
								'',
								'',
								'Swagger Schema Errors (' + result.errors.length + ')',
								'--------------------------',
								result.errors.map(function (err) {
									return '#/' + err.path.join('/') + ': ' + err.message +
										'\n' +
										JSON.stringify(err) +
										'\n';
								}).join('\n'),
								''
							].join('\n')),
							''
						);
					}

					if ( result.warnings.length > 0 ) {
						gutil.log(
							gutil.colors.yellow([
								'',
								'',
								'Swagger Schema Warnings (' + result.warnings.length + ')',
								'------------------------',
								result.warnings.map(function (warn) {
									return '#/' + warn.path.join('/') + ': ' + warn.message +
										'\n' +
										JSON.stringify(warn) +
										'\n';
								}).join('\n'),
								''
							].join('\n')),
							''
						);
					}

					if ( result.errors.length > 0 ) {
						callback(new gutil.PluginError(PLUGIN_NAME, 'The Swagger schema is invalid'));
						return;
					}
				}

				// Now that we know for sure the schema is 100% valid,
				// if there is not file name...
				if (!filename) {
					// ...return validated file to gulp without making changes to it
					return _this.push(file);
				}

				// ...or continue by dereferencing internal $refs as well.
				swaggerParser.dereference(swaggerObject, parserSettings, function parseSchema (error, swaggerObject) {
					if (error) {
						callback(new gutil.PluginError(PLUGIN_NAME, error));
						return;
					}

					var fileBuffer;

					if ( useCodeGen ) {
						var codeGenFunction = 'get' +
							codeGenSettings.type[0].toUpperCase() +
							codeGenSettings.type.slice(1, codeGenSettings.type.length) +
							'Code';

						codeGenSettings.esnext = true;
						codeGenSettings.swagger = swaggerObject;
						delete codeGenSettings.type;

						codeGenSettings.mustache = codeGenSettings.mustache || {};
						// Allow swagger schema to be easily accessed inside templates.
						codeGenSettings.mustache.swaggerObject = swaggerObject;
						codeGenSettings.mustache.swaggerJSON = JSON.stringify(swaggerObject);
						// Allow each individual JSON schema to be easily accessed inside templates (for validation purposes).
						codeGenSettings.mustache.JSONSchemas = JSON.stringify(
							Object.keys(swaggerObject.paths)
								.reduce(function reducePaths (newPathCollection, currentPath) {
									var pathMethods = swaggerObject.paths[currentPath] || {};
									var pathSchemas = Object.keys(pathMethods)
										.reduce(function reduceMethods (newMethodCollection, currentMethod) {
											var methodParameters = (pathMethods[currentMethod].parameters || [])
												.filter(function filterBodyParameter (parameter) {
													return parameter.in === 'body';
												})[0] || {};
											var methodResponses = pathMethods[currentMethod].responses || {};
											var methodSchemas = {
												request: methodParameters.schema,
												responses: Object.keys(methodResponses)
													.reduce(function reduceMethods (newResponsesCollection, currentResponse) {
														var responseSchema = methodResponses[currentResponse].schema || {};

														newResponsesCollection[currentResponse] = responseSchema;
														return newResponsesCollection;
													}, {})
											};

											newMethodCollection[currentMethod] = methodSchemas;
											return newMethodCollection;
										}, {});

									newPathCollection[currentPath] = pathSchemas;
									return newPathCollection;
								}, {})
						);

						fileBuffer = CodeGen[codeGenFunction](codeGenSettings);
					}
					else {
						try {
							fileBuffer = JSON.stringify(swaggerObject);
						}
						catch (error) {
							fileBuffer = CircularJSON.stringify(swaggerObject);
						}
					}

					// Return processed file to gulp
					_this.push(new gutil.File({
						cwd: file.cwd,
						base: file.base,
						path: path.join(file.base, filename),
						contents: new Buffer(fileBuffer)
					}));

					callback();
				}); // swaggerParser.dereference (internal $refs)
			}); // swaggerTools.validate
		}); // swaggerParser.dereference (external $refs)
	}); // return through.obj
};
<|endoftext|>


<commit_before>const fs = require('fs');
const minimist = require('minimist');

const KeyQueue = require('./KeyQueue.js');

const transcoder = require('./transcoder');

const ookToBf = require('./ookToBf');

function validateBrackets(instructions) {
  return instructions.reduce((a, e) => {
    if(e === '[') return ++a;
    else if(e === ']') return --a;
    else return a;
  }, 0) === 0;
}

function condense(instructions) {
  const newSet = [];
  let isCellChange = false;
  let isCellMove = false;
  let elementCounter = 0;
  instructions.forEach((e, i, a) => {
    if(isCellChange) {
      if(e === '+' || e === '-') {
        elementCounter += (e === '+' ? 1 : -1);
      } else {
        if(elementCounter !== 0) {
          newSet.push('+', elementCounter);
          elementCounter = 0;
        }
        isCellChange = false;
      }
    } else if(isCellMove) {
      if(e === '>' || e === '<') {
        elementCounter += (e === '>' ? 1 : -1);
      } else {
        if(elementCounter !== 0) {
          newSet.push('>', elementCounter);
          elementCounter = 0;
        }
        isCellMove = false;
      }
    }

    if(e === '+' || e === '-') {
      if(isCellChange) return;
      isCellChange = true;
      elementCounter = (e === '+' ? 1 : -1);
    } else if(e === '>' || e === '<') {
      if(isCellMove) return;
      isCellMove = true;
      elementCounter = (e === '>' ? 1 : -1);
    } else {
      newSet.push(e);
    }
  });
  return newSet;
}

async function init() {
  const argv = minimist(process.argv.slice(2), {alias: {'input': 'i', 'length': 'l', 'debug': 'd', 'speed': 's', 'ook': 'o', 'tick': 't'}, default: {'input': 'main.b', 'length': 30000, 'speed': 0}});
  argv.l = (typeof argv.l === 'number' && argv.l > 0) ? argv.l : 30000;
  argv.s = (typeof argv.s === 'number' && argv.s >= 0) ? argv.s : 0;

	const keyQueue = new KeyQueue(argv.t)

	let rawArray;
	if(argv.o) rawArray = ookToBf(fs.readFileSync(argv.i, 'utf8'));
	else rawArray = fs.readFileSync(argv.i, 'utf8').split('');

  const contents = condense(rawArray.filter(e => ['+', '-', '.', ',', '[', ']', '>', '<'].includes(e)));

  if(!validateBrackets(contents)) throw new Error('Non matching brackets');

  const tape = Buffer.alloc(argv.l, 0);

  const loopStack = [];

  let progCount = 0;
  let tapeCount = 0;

  if(argv.d) console.log('tapeCount |', 'tape |', 'instruction |', 'next instruction |', 'instruction length |', 'program counter');

  while(progCount < contents.length) {
    const instruction = contents[progCount];
    const next = contents[progCount + 1];
    if(argv.d) console.log(tapeCount, tape[tapeCount], instruction, next, contents.length, progCount);
    if(instruction === '+') {
      tape[tapeCount] += next;
      progCount++;
    } else if(instruction === '>') {
      tapeCount = (tapeCount + (tape.length * Math.abs(next)) + next) % tape.length;
      progCount++;
    } else if(instruction === '[') {
      if(tape[tapeCount] === 0) {
        progCount = contents.indexOf(']', progCount);
      } else {
        loopStack.push(progCount);
      }
    } else if(instruction === ']') {
      if(tape[tapeCount] !== 0) {
        progCount = loopStack[loopStack.length - 1];
      } else {
        loopStack.pop();
      }
    } else if(instruction === '.') {
      // console.log(transcoder.asciiToUnicode(tape[tapeCount]));
      process.stdout.write(String.fromCharCode(transcoder.asciiToUnicode(tape[tapeCount])));
    } else if(instruction === ',') {
      tape[tapeCount] = transcoder.unicodeToAscii(await keyQueue.getInput());
    }
    progCount++;
    if(argv.s > 0) {
      await new Promise((resolve, reject) => {
        setTimeout(resolve, argv.s);
      });
    }
  }
  keyQueue.stop();
}
init().catch(error => {
  return console.error(error);
});
<commit_msg>Fix looping<commit_after>const fs = require('fs');
const minimist = require('minimist');

const KeyQueue = require('./KeyQueue.js');

const transcoder = require('./transcoder');

const ookToBf = require('./ookToBf');

function validateBrackets(instructions) {
  return instructions.reduce((a, e) => {
    if(e === '[') return ++a;
    else if(e === ']') return --a;
    else return a;
  }, 0) === 0;
}

function condense(instructions) {
  const newSet = [];
  let isCellChange = false;
  let isCellMove = false;
  let elementCounter = 0;
  instructions.forEach((e, i, a) => {
    if(isCellChange) {
      if(e === '+' || e === '-') {
        elementCounter += (e === '+' ? 1 : -1);
      } else {
        if(elementCounter !== 0) {
          newSet.push('+', elementCounter);
          elementCounter = 0;
        }
        isCellChange = false;
      }
    } else if(isCellMove) {
      if(e === '>' || e === '<') {
        elementCounter += (e === '>' ? 1 : -1);
      } else {
        if(elementCounter !== 0) {
          newSet.push('>', elementCounter);
          elementCounter = 0;
        }
        isCellMove = false;
      }
    }

    if(e === '+' || e === '-') {
      if(isCellChange) return;
      isCellChange = true;
      elementCounter = (e === '+' ? 1 : -1);
    } else if(e === '>' || e === '<') {
      if(isCellMove) return;
      isCellMove = true;
      elementCounter = (e === '>' ? 1 : -1);
    } else {
      newSet.push(e);
    }
  });
  return newSet;
}

async function init() {
  const argv = minimist(process.argv.slice(2), {alias: {'input': 'i', 'length': 'l', 'debug': 'd', 'speed': 's', 'ook': 'o', 'tick': 't'}, default: {'input': 'main.b', 'length': 30000, 'speed': 0}});
  argv.l = (typeof argv.l === 'number' && argv.l > 0) ? argv.l : 30000;
  argv.s = (typeof argv.s === 'number' && argv.s >= 0) ? argv.s : 0;

	const keyQueue = new KeyQueue(argv.t)

	let rawArray;
	if(argv.o) rawArray = ookToBf(fs.readFileSync(argv.i, 'utf8'));
	else rawArray = fs.readFileSync(argv.i, 'utf8').split('');

  const contents = condense(rawArray.filter(e => ['+', '-', '.', ',', '[', ']', '>', '<'].includes(e)));

  if(!validateBrackets(contents)) throw new Error('Non matching brackets');

  const tape = Buffer.alloc(argv.l, 0);

  const loopStack = [];

  let progCount = 0;
  let tapeCount = 0;

  if(argv.d) console.log('tapeCount |', 'tape |', 'instruction |', 'next instruction |', 'instruction length |', 'program counter');

  while(progCount < contents.length) {
    const instruction = contents[progCount];
    const next = contents[progCount + 1];
    if(argv.d) console.log(tapeCount, tape[tapeCount], instruction, next, contents.length, progCount);
    if(instruction === '+') {
      tape[tapeCount] += next;
      progCount++;
    } else if(instruction === '>') {
      tapeCount = (tapeCount + (tape.length * Math.abs(next)) + next) % tape.length;
      progCount++;
    } else if(instruction === '[') {
      if(tape[tapeCount] === 0) {
				let bCount = 0;
				for(let i = progCount; i < contents.length; i++) {
					if(contents[i] === '[') bCount++;
					else if(contents[i] === ']') bCount--;

					if(bCount === 0) break;
					progCount++;
				}
      } else {
        loopStack.push(progCount);
      }
    } else if(instruction === ']') {
      if(tape[tapeCount] !== 0) {
        progCount = loopStack[loopStack.length - 1];
      } else {
        loopStack.pop();
      }
    } else if(instruction === '.') {
      // console.log(transcoder.asciiToUnicode(tape[tapeCount]));
      process.stdout.write(String.fromCharCode(transcoder.asciiToUnicode(tape[tapeCount])));
    } else if(instruction === ',') {
      tape[tapeCount] = transcoder.unicodeToAscii(await keyQueue.getInput());
    }
    progCount++;
    if(argv.s > 0) {
      await new Promise((resolve, reject) => {
        setTimeout(resolve, argv.s);
      });
    }
  }
  keyQueue.stop();
}
init().catch(error => {
  return console.error(error);
});
<|endoftext|>


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

exports = module.exports = Invent;

function Invent(options) {
    options || (options = {});
    this.name = options.name || 'invent';
    this.destination = options.name || '.';
    this.color = options.color || true;
    this.force = options.force || false;
    this.templatePath = path.join(__dirname, 'templates');
};

Invent.prototype.create = function () {
    var self = this;
    process.on('exit', function (code) {
        if (code === 0) {
            console.log();
            console.log(' getting started :');
            console.log(' $ cd ' + self.destination + ' && vagrant up');
            console.log(' $ vagrant ssh');
            console.log();
            if (self.color) {
                console.log(' \x1b[36mstart inventing ;)\x1b[0m');
            } else {
                console.log(' start inventing ;)');
            }
            console.log();
        }
    });
    this.mkdir(this.destination, function () {
        self.writeTemplate('Vagrantfile');
        self.writeTemplate('package.json');
        self.writeTemplate('Berksfile');
    });
};

Invent.prototype.mkdir = function (destination, cb) {
    mkdirp(destination, 0755, function (err) {
    if (err) {
        throw err;
    }
    if (this.color) {
        console.log(' \033[36mcreated\033[0m : ' + destination);
    } else {
        console.log(' created : ' + destination);
    }
    cb && cb();
    });
};

Invent.prototype.writeTemplate = function (template) {
    var contents = fs.readFileSync(
            path.join(this.templatePath, template), 'utf-8'
        ).replace('{appName}', this.name);
    this.write(path.join(this.destination, template), contents);
};

Invent.prototype.write = function (destination, content, mode) {
    fs.writeFile(destination, content, { mode: mode || 0666 });
    if (this.color) {
        console.log(' \x1b[36mcreated\x1b[0m : ' + destination);
    } else {
        console.log(' created : ' + destination);
    }
};
<commit_msg>cleaned up structure<commit_after>var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');

exports = module.exports = new Invent();

function Invent() {
    this.templatePath = path.join(__dirname, 'templates');
};

Invent.prototype.create = function (options) {
    options || (options = {});
    this.name = options.name || 'invent';
    this.destination = options.name || '.';
    this.color = options.color || true;
    this.force = options.force || false;
    var self = this;
    process.on('exit', function (code) {
        if (code === 0) {
            console.log();
            console.log(' getting started :');
            console.log(' $ cd ' + self.destination + ' && vagrant up');
            console.log(' $ vagrant ssh');
            console.log();
            if (self.color) {
                console.log(' \x1b[36mstart inventing ;)\x1b[0m');
            } else {
                console.log(' start inventing ;)');
            }
            console.log();
        }
    });
    this.mkdir(this.destination, function () {
        self.writeTemplate('Vagrantfile');
        self.writeTemplate('package.json');
        self.writeTemplate('Berksfile');
    });
};

Invent.prototype.mkdir = function (destination, cb) {
    mkdirp(destination, 0755, function (err) {
    if (err) {
        throw err;
    }
    if (this.color) {
        console.log(' \033[36mcreated\033[0m : ' + destination);
    } else {
        console.log(' created : ' + destination);
    }
    cb && cb();
    });
};

Invent.prototype.writeTemplate = function (template) {
    var contents = fs.readFileSync(
            path.join(this.templatePath, template), 'utf-8'
        ).replace('{appName}', this.name);
    this.write(path.join(this.destination, template), contents);
};

Invent.prototype.write = function (destination, content, mode) {
    fs.writeFile(destination, content, { mode: mode || 0666 });
    if (this.color) {
        console.log(' \x1b[36mcreated\x1b[0m : ' + destination);
    } else {
        console.log(' created : ' + destination);
    }
};
<|endoftext|>


<commit_before>const path = require('path')
const minimist = require('minimist')
const shell = require('shelljs')

const argv = minimist(process.argv.slice(2), {
  boolean: ['interactive', 'yarn'],
  alias: {
    'projectName': ['project-name', 'name', 'n'],
    'outputPath': ['output-path', 'output', 'o'],
    'yarn': ['yarn-pkg', 'y'],
    'interactive': ['i'],
  },
  '--': true,
})

console.log(JSON.stringify(argv))

const [oldVersion, newVersion] = argv._
const cliArgs = argv['--']
const {
  projectName = 'project-name',
  outputPath = path.join(__dirname, `./reports/changes-of-${oldVersion}-to-${newVersion}.patch`),
  yarn = false,
  interactive = false,
} = argv

const cliArgsStr = cliArgs.join(' ')
const basePath = `/tmp/workspaces`
const cliProjectPath = `${basePath}/cli-change-observer`
const projectPath = `${basePath}/${projectName}`
const projectOldPath = `${basePath}/${projectName}-old`
const binPath = `${cliProjectPath}/node_modules/.bin`

const installCmd = yarn ? `yarn add` : `npm install`

shell.echo(`Checking difference from ${oldVersion} to ${newVersion}`)
shell.echo(`For command: ng new ${cliArgsStr} ${projectName}`)

shell.rm('-rf', cliProjectPath)
shell.rm('-rf', projectPath)
shell.rm('-rf', projectOldPath)

shell.mkdir('-p', cliProjectPath)
shell.mkdir('-p', projectPath)

shell.cd(cliProjectPath)
shell.echo(`Installing Angular CLI version ${oldVersion}`)
shell.exec(`${installCmd} @angular/cli@${oldVersion}`)

shell.cd(basePath)
shell.echo(`Creating project in version ${oldVersion}`)
shell.exec(`${binPath}/ng new -si ${cliArgsStr} ${projectName}`)

shell.mv(projectPath, projectOldPath)

shell.cd(cliProjectPath)
shell.echo(`Installing Angular CLI version ${newVersion}`)
shell.exec(`${installCmd} @angular/cli@${newVersion}`)

shell.cd(basePath)
shell.echo(`Creating project in version ${newVersion}`)
shell.exec(`${binPath}/ng new -si ${cliArgsStr} ${projectName}`)

shell.rm('-rf', `${projectPath}/.git`)
shell.cp('-r', `${projectOldPath}/.git`, `${projectPath}/.git`)

shell.cd(projectPath)
if (interactive) {
  shell.exec('git diff')
} else {
  shell.exec(`git diff > ${outputPath}`)
}
<commit_msg>remove log for debugging<commit_after>const path = require('path')
const minimist = require('minimist')
const shell = require('shelljs')

const argv = minimist(process.argv.slice(2), {
  boolean: ['interactive', 'yarn'],
  alias: {
    'projectName': ['project-name', 'name', 'n'],
    'outputPath': ['output-path', 'output', 'o'],
    'yarn': ['yarn-pkg', 'y'],
    'interactive': ['i'],
  },
  '--': true,
})

const [oldVersion, newVersion] = argv._
const cliArgs = argv['--']
const {
  projectName = 'project-name',
  outputPath = path.join(__dirname, `./reports/changes-of-${oldVersion}-to-${newVersion}.patch`),
  yarn = false,
  interactive = false,
} = argv

const cliArgsStr = cliArgs.join(' ')
const basePath = `/tmp/workspaces`
const cliProjectPath = `${basePath}/cli-change-observer`
const projectPath = `${basePath}/${projectName}`
const projectOldPath = `${basePath}/${projectName}-old`
const binPath = `${cliProjectPath}/node_modules/.bin`

const installCmd = yarn ? `yarn add` : `npm install`

shell.echo(`Checking difference from ${oldVersion} to ${newVersion}`)
shell.echo(`For command: ng new ${cliArgsStr} ${projectName}`)

shell.rm('-rf', cliProjectPath)
shell.rm('-rf', projectPath)
shell.rm('-rf', projectOldPath)

shell.mkdir('-p', cliProjectPath)
shell.mkdir('-p', projectPath)

shell.cd(cliProjectPath)
shell.echo(`Installing Angular CLI version ${oldVersion}`)
shell.exec(`${installCmd} @angular/cli@${oldVersion}`)

shell.cd(basePath)
shell.echo(`Creating project in version ${oldVersion}`)
shell.exec(`${binPath}/ng new -si ${cliArgsStr} ${projectName}`)

shell.mv(projectPath, projectOldPath)

shell.cd(cliProjectPath)
shell.echo(`Installing Angular CLI version ${newVersion}`)
shell.exec(`${installCmd} @angular/cli@${newVersion}`)

shell.cd(basePath)
shell.echo(`Creating project in version ${newVersion}`)
shell.exec(`${binPath}/ng new -si ${cliArgsStr} ${projectName}`)

shell.rm('-rf', `${projectPath}/.git`)
shell.cp('-r', `${projectOldPath}/.git`, `${projectPath}/.git`)

shell.cd(projectPath)
if (interactive) {
  shell.exec('git diff')
} else {
  shell.exec(`git diff > ${outputPath}`)
}
<|endoftext|>


<commit_before>var save_image_url = 'https://c1.staticflickr.com/3/2900/33745640515_a90c44b434_t.jpg';
var remove_image_url = 'https://c1.staticflickr.com/4/3684/33135618604_414134ce5c_t.jpg';
var contentCollection = getValues();

  window.onload = function(){
    buildExtensionField();
    buildContentActions();
    populateDropDownMenu();
    attachInputListener();
    checkForResolved();
  }

  function checkForResolved() {
    var pageContent = document.getElementById('fc--message-list');
    var checkQuestions = setInterval(function() {
      if ($('.fc--question-node').length) {
        if ($('.active').length) {
          if (document.getElementById('fc--message-list').textContent.includes('Resolved')) {
            location.reload();
          }
        }
      }
      console.log('running');
    }, 10000)
    // keep an eye on timer and adjust as needed
  }

  function buildExtensionField() {
    var expertSection = document.getElementsByClassName('module__foot')[0];
    var newSection = document.createElement('div');
    newSection.setAttribute('class', 'content-filler');
    expertSection.children[1].before(newSection);
  }

  function getExtensionField() {
    return document.getElementsByClassName('module__foot')[0].children[1];
  }

  function buildContentActions() {
    var elements = [];
    elements.push(createButton('save'));
    elements.push(buildMenuField());
    elements.push(createButton('remove'));
    appendElementsToExtension(elements);
  }

  function createButton(type) {
    var newButton = document.createElement('button');
    var image = buttonImage(type);
    newButton.appendChild(image);
    newButton.id = `${type}_button`;
    newButton.style = "cursor: pointer";
    var titleName = type.charAt(0).toUpperCase() + type.slice(1);
    newButton.setAttribute('title', `${titleName} content`);
    newButton.onclick = function(event){
      var type = event.target.id.split("_")[0];
      eval(type + 'Action()');
    }
    return newButton;
 }

 function buttonImage(type){
    var image = document.createElement('img');
    var image_url = `${type}_image_url`;
    image.id = `${type}_image`;
    image.src = eval(image_url);
    return image;
 }

 function appendElementsToExtension(buttons) {
   var section = getExtensionField();
   for (i in buttons) {
     section.appendChild(buttons[i]);
   }
 }

 function buildMenuField() {
   var menuElement = document.createElement('select');
   menuElement.setAttribute('id', 'menu_element');
   return menuElement;
 }

 function getMenuElement() {
   return document.getElementById('menu_element');
 }

 function populateDropDownMenu(content = contentCollection) {
   content.unshift(" ");
   var uniqueContents = [...new Set(content.sort())];
   for (var i = 0; i < uniqueContents.length; i++) {
     var item = uniqueContents[i];
     var element = document.createElement('option');
     element.text = item;
     element.value = item;
     getMenuElement().appendChild(element);
   }
   getMenuElement().addEventListener('change', function() {
     setInput();
   })
 }

 function resetMenu() {
   getMenuElement().innerHTML = " ";
 }
 //
 // function reloadMenu() {
 //   resetMenu();
 //   populateDropDownMenu();
 // }

 function getValues(callback) {
   contentCollection = [];
   chrome.storage.sync.get(null, function(items) {
     var content = Object.keys(items);
     for (var i = 0; i < content.length; i++) {
       contentCollection.push(content[i]);
     }
   });
   callback;
   return contentCollection;
 }

 function saveAction() {
   var content = document.getElementsByTagName('textarea')[1].value;
   if (content.length <= 1) {
     console.log('Error: No content selected');
     return;
   }
   var obj = {};
   obj[content] = content;
   chrome.storage.sync.set(obj, function() {
     console.log('content saved');
   });
   //  reloadMenu();
 }

 function removeAction() {
   var menu = getMenuElement();
   var value = menu.options[menu.selectedIndex].value;
   menu.remove(menu.selectedIndex);
   if (value != " ") {
     if (confirm('Are you sure you want to delete this item?')) {
       chrome.storage.sync.remove(value, function() {
         alert('content deleted');
       })
     }
   }
  // reloadMenu();
 }

 function setInput() {
   var menu = getMenuElement();
   var value = menu.options[menu.selectedIndex].value;
   document.getElementsByTagName('textarea')[1].value = value;
   document.getElementsByTagName('textarea')[1].focus();
 }

 function reloadDiv() {
   console.log('reloading');
   $('.content-filler').remove();
   buildExtensionField();
   buildContentActions();
   getValues(populateDropDownMenu());
 }

 function attachInputListener() {
   var input = document.getElementsByTagName('textarea')[1];
   input.addEventListener('change', function(event) {
     filterMenu();
   });
 }

 function filterMenu() {
  //  need to account for upper/lower case

   filteredList = [];
   var menu = getMenuElement();
   var input = document.getElementsByTagName('textarea')[1];
   input.oninput = function(event) {
     var filteredList = isIncluded(event);
     resetMenu();
     populateDropDownMenu(filteredList);
   }
  //  bring in filter function
 }

 function isIncluded(event) {
   var newList = [];
   for (var i = 0; i < contentCollection.length; i++) {
     if (contentCollection[i].search(event.target.value) >= 0)
      newList.push(contentCollection[i])
   }
   return newList;
 }
<commit_msg>confirming save<commit_after>// filter capitalization
// keyboard shortcuts for save and delete

var save_image_url = 'https://c1.staticflickr.com/3/2900/33745640515_a90c44b434_t.jpg';
var remove_image_url = 'https://c1.staticflickr.com/4/3684/33135618604_414134ce5c_t.jpg';
var contentCollection = getValues();

  window.onload = function(){
    buildExtensionField();
    buildContentActions();
    populateDropDownMenu();
    attachInputListener();
    checkForResolved();
  }

  function checkForResolved() {
    var pageContent = document.getElementById('fc--message-list');
    var checkQuestions = setInterval(function() {
      if ($('.fc--question-node').length) {
        if ($('.active').length) {
          if (document.getElementById('fc--message-list').textContent.includes('Resolved')) {
            location.reload();
          }
        }
      }
      console.log('running');
    }, 10000)
    // keep an eye on timer and adjust as needed
  }

  function buildExtensionField() {
    var expertSection = document.getElementsByClassName('module__foot')[0];
    var newSection = document.createElement('div');
    newSection.setAttribute('class', 'content-filler');
    expertSection.children[1].before(newSection);
  }

  function getExtensionField() {
    return document.getElementsByClassName('module__foot')[0].children[1];
  }

  function buildContentActions() {
    var elements = [];
    elements.push(createButton('save'));
    elements.push(buildMenuField());
    elements.push(createButton('remove'));
    appendElementsToExtension(elements);
  }

  function createButton(type) {
    var newButton = document.createElement('button');
    var image = buttonImage(type);
    newButton.appendChild(image);
    newButton.id = `${type}_button`;
    newButton.style = "cursor: pointer";
    var titleName = type.charAt(0).toUpperCase() + type.slice(1);
    newButton.setAttribute('title', `${titleName} content`);
    newButton.onclick = function(event){
      var type = event.target.id.split("_")[0];
      eval(type + 'Action()');
    }
    return newButton;
 }

 function buttonImage(type){
    var image = document.createElement('img');
    var image_url = `${type}_image_url`;
    image.id = `${type}_image`;
    image.src = eval(image_url);
    return image;
 }

 function appendElementsToExtension(buttons) {
   var section = getExtensionField();
   for (i in buttons) {
     section.appendChild(buttons[i]);
   }
 }

 function buildMenuField() {
   var menuElement = document.createElement('select');
   menuElement.setAttribute('id', 'menu_element');
   return menuElement;
 }

 function getMenuElement() {
   return document.getElementById('menu_element');
 }

 function populateDropDownMenu(content = contentCollection) {
   content.unshift(" ");
   var uniqueContents = [...new Set(content.sort())];
   for (var i = 0; i < uniqueContents.length; i++) {
     var item = uniqueContents[i];
     var element = document.createElement('option');
     element.text = item;
     element.value = item;
     getMenuElement().appendChild(element);
   }
   getMenuElement().addEventListener('change', function() {
     setInput();
   })
 }

 function resetMenu() {
   getMenuElement().innerHTML = " ";
 }
 //
 // function reloadMenu() {
 //   resetMenu();
 //   populateDropDownMenu();
 // }

 function getValues(callback) {
   contentCollection = [];
   chrome.storage.sync.get(null, function(items) {
     var content = Object.keys(items);
     for (var i = 0; i < content.length; i++) {
       contentCollection.push(content[i]);
     }
   });
   callback;
   return contentCollection;
 }

 function saveAction() {
   var content = document.getElementsByTagName('textarea')[1].value;
   if (content.length <= 1) {
     console.log('Error: No content selected');
     return;
   }
   var obj = {};
   obj[content] = content;
   chrome.storage.sync.set(obj, function() {
     alert('content saved');
     console.log('content saved');
   });
   //  reloadMenu();
 }

 function removeAction() {
   var menu = getMenuElement();
   var value = menu.options[menu.selectedIndex].value;
   menu.remove(menu.selectedIndex);
   if (value != " ") {
     if (confirm('Are you sure you want to delete this item?')) {
       chrome.storage.sync.remove(value, function() {
         alert('content deleted');
       })
     }
   }
  // reloadMenu();
 }

 function setInput() {
   var menu = getMenuElement();
   var value = menu.options[menu.selectedIndex].value;
   document.getElementsByTagName('textarea')[1].value = value;
   document.getElementsByTagName('textarea')[1].focus();
 }

 function reloadDiv() {
   console.log('reloading');
   $('.content-filler').remove();
   buildExtensionField();
   buildContentActions();
   getValues(populateDropDownMenu());
 }

 function attachInputListener() {
   var input = document.getElementsByTagName('textarea')[1];
   input.addEventListener('change', function(event) {
     filterMenu();
   });
  //  listen for enter and clear
  input.addEventListener('keydown', function(e) {
    detectEnter(clearInput);
  })
 }

 function filterMenu() {
  //  need to account for upper/lower case

   filteredList = [];
   var menu = getMenuElement();
   var input = document.getElementsByTagName('textarea')[1];
   input.oninput = function(event) {
     var filteredList = isIncluded(event);
     resetMenu();
     populateDropDownMenu(filteredList);
   }
 }

 function isIncluded(event) {
   var newList = [];
   for (var i = 0; i < contentCollection.length; i++) {
     if (contentCollection[i].search(event.target.value) >= 0)
      newList.push(contentCollection[i])
   }
   return newList;
 }

 function clearInput() {
   debugger;
   var input = document.getElementsByTagName('textarea')[1].value == " ";
 }

 function detectEnter(callback){
   var key = e.which || e.keyCode;
   if (key == 13) {
     callback();
   }
 }
<|endoftext|>


<commit_before>'use strict';

/*
Runner properties:
  config
  swagger
  api  // (sway)
  connectMiddleware()
  resolveAppPath()
  securityHandlers
  bagpipes

Runner events:
 responseValidationError

config properties:
  appRoot
  mockMode
  configDir
  controllersDirs
  mockControllersDirs
  securityHandlers
 */

module.exports = {
  create: create
};

var _ = require('lodash');
var yaml = require('js-yaml');
var path = require('path');
var sway = require('sway');
var debug = require('debug')('swagger');
var bagpipes = require('bagpipes');
var EventEmitter = require('events').EventEmitter;
var util = require('util');

var SWAGGER_SELECTED_PIPE = 'x-swagger-pipe';
var SWAGGER_ROUTER_CONTROLLER = 'x-swagger-router-controller';
var DEFAULT_FITTINGS_DIRS = [ 'api/fittings' ];
var DEFAULT_VIEWS_DIRS = [ 'api/views' ];
var DEFAULT_SWAGGER_FILE = 'api/swagger/swagger.yaml'; // relative to appRoot

/*
SwaggerNode config priority:
  1. swagger_* environment vars
  2. config passed to create()
  3. read from swagger node in default.yaml in config directory
  4. defaults in this file
 */

function create(config, cb) {

  if (!_.isFunction(cb)) { throw new Error('callback is required'); }
  if (!config || !config.appRoot) { return cb(new Error('config.appRoot is required')); }

  new Runner(config, cb);
}

util.inherits(Runner, EventEmitter);

function Runner(appJsConfig, cb) {

  EventEmitter.call(this);

  this.resolveAppPath = function resolveAppPath(to) {
    return path.resolve(appJsConfig.appRoot, to);
  };

  this.connectMiddleware = function connectMiddleware() {
    return require('./lib/connect_middleware')(this);
  };

  this.expressMiddleware = this.connectMiddleware;

  this.restifyMiddleware = function restifyMiddleware() {
    return require('./lib/restify_middleware')(this);
  };

  this.sailsMiddleware = function sailsMiddleware() {
    return require('./lib/sails_middleware')(this);
  };

  this.hapiMiddleware = function hapiMiddleware() {
    return require('./lib/hapi_middleware')(this);
  };

  this.defaultErrorHandler = function() {

    return this.bagpipes.createPipeFromFitting(defaultErrorFitting, { name: 'defaultErrorHandler' });

    function defaultErrorFitting(context, next) {

      debug('default error handler: %s', context.error.message);
      next();
    }
  };

  this.getOperation = function getOperation(req) {
    return this.api.getOperation(req);
  };

  this.getPath = function getPath(req) {
    return this.api.getPath(req);
  };

  // adds req.swagger to the request
  this.applyMetadata = function applyMetadata(req, operation, cb) {

    var swagger = req.swagger = {};
    swagger.operation = operation;
    cb();
  };

    // must assign req.swagger (see #applyMetadata) before calling
  this.getPipe = function getPipe(req) {

    var operation = req.swagger.operation;

    var path = operation ? operation.pathObject : this.getPath(req);
    var config = this.config.swagger;

    // prefer explicit pipe
    var pipeName;
    if (operation) {
      pipeName = operation[SWAGGER_SELECTED_PIPE];
    }
    if (!pipeName) {
      pipeName = path[SWAGGER_SELECTED_PIPE];
    }

    // no explicit pipe, but there's a controller
    if (!pipeName) {
      if ((operation && operation[SWAGGER_ROUTER_CONTROLLER]) || path[SWAGGER_ROUTER_CONTROLLER])
      {
        pipeName = config.swaggerControllerPipe;
      }
    }
    debug('pipe requested:', pipeName);

    // default pipe
    if (!pipeName) { pipeName = config.defaultPipe; }

    if (!pipeName) {
      debug('no default pipe');
      return null;
    }

    var pipe = this.bagpipes.pipes[pipeName];

    if (!pipe) {
      debug('no defined pipe: ', pipeName);
      return null;
    }

    debug('executing pipe %s', pipeName);

    return pipe;
  };

  // don't override if env var already set
  if (!process.env.NODE_CONFIG_DIR) {
    if (!appJsConfig.configDir) { appJsConfig.configDir = 'config'; }
    process.env.NODE_CONFIG_DIR = path.resolve(appJsConfig.appRoot, appJsConfig.configDir);
  }
  var Config = require('config');

  var swaggerConfigDefaults = {
    enforceUniqueOperationId: false,
    startWithErrors: false,
    startWithWarnings: true
  };

  this.config = Config.util.cloneDeep(Config);
  this.config.swagger =
    Config.util.extendDeep(
      swaggerConfigDefaults,
      this.config.swagger,
      appJsConfig,
      readEnvConfig());

  debug('resolved config: %j', this.config);

  var self = this;
  var swayOpts = {
    definition: appJsConfig.swagger || appJsConfig.swaggerFile || this.resolveAppPath(DEFAULT_SWAGGER_FILE)
  };

  // sway uses Promises
  sway.create(swayOpts)
    .then(function(api) {

      var validateResult = api.validate();

      var errors = validateResult.errors;
      if (errors && errors.length > 0) {
        if (!self.config.swagger.enforceUniqueOperationId) {
          errors = errors.filter(function(err) {
            return (err.code !== 'DUPLICATE_OPERATIONID');
          });
        }
        if (errors.length > 0) {
          if (self.config.swagger.startWithErrors) {
            var errorText = JSON.stringify(errors);
            console.error(errorText, 2);
          } else {
            var err = new Error('Swagger validation errors:');
            err.validationErrors = errors;
            throw err;
          }
        }
      }

      var warnings = validateResult.warnings;
      if (warnings && warnings.length > 0) {
        var warningText = JSON.stringify(warnings);
        if (self.config.swagger.startWithWarnings) {
          console.error(warningText, 2);
        } else {
          var err = new Error('Swagger validation warnings:');
          err.validationWarnings = warnings;
          throw err;
        }
      }

      self.api = api;
      self.swagger = api.definition;
      self.securityHandlers = appJsConfig.securityHandlers || appJsConfig.swaggerSecurityHandlers; // legacy name
      self.bagpipes = createPipes(self);

      cb(null, self);
    })
    .catch(function(err) {
      cb(err);
    })
    .catch(function(err) {
      console.error('Error in callback! Tossing to global error handler.', err.stack);
      process.nextTick(function() { throw err; });
    })
}

function createPipes(self) {
  var config = self.config.swagger;

  var fittingsDirs = (config.fittingsDirs || DEFAULT_FITTINGS_DIRS).map(function(dir) {
    return path.resolve(config.appRoot, dir);
  });
  var swaggerNodeFittingsDir = path.resolve(__dirname, './fittings');
  fittingsDirs.push(swaggerNodeFittingsDir);

  var viewsDirs = (config.viewsDirs || DEFAULT_VIEWS_DIRS).map(function(dir) {
    return path.resolve(config.appRoot, dir);
  });

  // legacy support: set up a default piping for traditional swagger-node if nothing is specified
  if (!config.bagpipes || config.bagpipes ==='DEFAULTS_TEST') {

    debug('**** No bagpipes defined in config. Using default setup. ****');

    config.swaggerControllerPipe = 'swagger_controllers';

    config.bagpipes = {
      _router: {
        name: 'swagger_router',
        mockMode: false,
        mockControllersDirs: [ 'api/mocks' ],
        controllersDirs: [ 'api/controllers' ]
      },
      _swagger_validate: {
        name: 'swagger_validator',
        validateReponse: true
      },
      swagger_controllers: [
        'cors',
        'swagger_params_parser',
        'swagger_security',
        '_swagger_validate',
        'express_compatibility',
        '_router'
      ]
    };

    if (config.mapErrorsToJson) {
      config.bagpipes.swagger_controllers.unshift({ onError: 'json_error_handler' });
    }
  }

  var pipesDefs = config.bagpipes;

  var pipesConfig = {
    userFittingsDirs: fittingsDirs,
    userViewsDirs: viewsDirs,
    swaggerNodeRunner: self
  };
  return bagpipes.create(pipesDefs, pipesConfig);
}

function readEnvConfig() {

  var config = {};
  _.each(process.env, function(value, key) {
    var split = key.split('_');
    if (split[0] === 'swagger') {
      var configItem = config;
      for (var i = 1; i < split.length; i++) {
        var subKey = split[i];
        if (i < split.length - 1) {
          if (!configItem[subKey]) { configItem[subKey] = {}; }
          configItem = configItem[subKey];
        } else {
          try {
            configItem[subKey] = JSON.parse(value);
          } catch (err) {
            configItem[subKey] = value;
          }
        }
      }
    }
  });
  debug('loaded env vars: %j', config);
  return config;
}<commit_msg>add additional debugging<commit_after>'use strict';

/*
Runner properties:
  config
  swagger
  api  // (sway)
  connectMiddleware()
  resolveAppPath()
  securityHandlers
  bagpipes

Runner events:
 responseValidationError

config properties:
  appRoot
  mockMode
  configDir
  controllersDirs
  mockControllersDirs
  securityHandlers
 */

module.exports = {
  create: create
};

var _ = require('lodash');
var yaml = require('js-yaml');
var path = require('path');
var sway = require('sway');
var debug = require('debug')('swagger');
var bagpipes = require('bagpipes');
var EventEmitter = require('events').EventEmitter;
var util = require('util');

var SWAGGER_SELECTED_PIPE = 'x-swagger-pipe';
var SWAGGER_ROUTER_CONTROLLER = 'x-swagger-router-controller';
var DEFAULT_FITTINGS_DIRS = [ 'api/fittings' ];
var DEFAULT_VIEWS_DIRS = [ 'api/views' ];
var DEFAULT_SWAGGER_FILE = 'api/swagger/swagger.yaml'; // relative to appRoot

/*
SwaggerNode config priority:
  1. swagger_* environment vars
  2. config passed to create()
  3. read from swagger node in default.yaml in config directory
  4. defaults in this file
 */

function create(config, cb) {

  if (!_.isFunction(cb)) { throw new Error('callback is required'); }
  if (!config || !config.appRoot) { return cb(new Error('config.appRoot is required')); }

  new Runner(config, cb);
}

util.inherits(Runner, EventEmitter);

function Runner(appJsConfig, cb) {

  EventEmitter.call(this);

  this.resolveAppPath = function resolveAppPath(to) {
    return path.resolve(appJsConfig.appRoot, to);
  };

  this.connectMiddleware = function connectMiddleware() {
    return require('./lib/connect_middleware')(this);
  };

  this.expressMiddleware = this.connectMiddleware;

  this.restifyMiddleware = function restifyMiddleware() {
    return require('./lib/restify_middleware')(this);
  };

  this.sailsMiddleware = function sailsMiddleware() {
    return require('./lib/sails_middleware')(this);
  };

  this.hapiMiddleware = function hapiMiddleware() {
    return require('./lib/hapi_middleware')(this);
  };

  this.defaultErrorHandler = function() {

    return this.bagpipes.createPipeFromFitting(defaultErrorFitting, { name: 'defaultErrorHandler' });

    function defaultErrorFitting(context, next) {

      debug('default error handler: %s', context.error.message);
      next();
    }
  };

  this.getOperation = function getOperation(req) {
    return this.api.getOperation(req);
  };

  this.getPath = function getPath(req) {
    return this.api.getPath(req);
  };

  // adds req.swagger to the request
  this.applyMetadata = function applyMetadata(req, operation, cb) {

    var swagger = req.swagger = {};
    swagger.operation = operation;
    cb();
  };

    // must assign req.swagger (see #applyMetadata) before calling
  this.getPipe = function getPipe(req) {

    var operation = req.swagger.operation;

    var path = operation ? operation.pathObject : this.getPath(req);
    var config = this.config.swagger;

    // prefer explicit pipe
    var pipeName;
    if (operation) {
      pipeName = operation[SWAGGER_SELECTED_PIPE];
    }
    if (!pipeName) {
      pipeName = path[SWAGGER_SELECTED_PIPE];
    }

    // no explicit pipe, but there's a controller
    if (!pipeName) {
      if ((operation && operation[SWAGGER_ROUTER_CONTROLLER]) || path[SWAGGER_ROUTER_CONTROLLER])
      {
        pipeName = config.swaggerControllerPipe;
      }
    }
    debug('pipe requested:', pipeName);

    // default pipe
    if (!pipeName) { pipeName = config.defaultPipe; }

    if (!pipeName) {
      debug('no default pipe');
      return null;
    }

    var pipe = this.bagpipes.pipes[pipeName];

    if (!pipe) {
      debug('no defined pipe: ', pipeName);
      return null;
    }

    debug('executing pipe %s', pipeName);

    return pipe;
  };

  // don't override if env var already set
  if (!process.env.NODE_CONFIG_DIR) {
    if (!appJsConfig.configDir) { appJsConfig.configDir = 'config'; }
    process.env.NODE_CONFIG_DIR = path.resolve(appJsConfig.appRoot, appJsConfig.configDir);
  }
  var Config = require('config');

  var swaggerConfigDefaults = {
    enforceUniqueOperationId: false,
    startWithErrors: false,
    startWithWarnings: true
  };

  this.config = Config.util.cloneDeep(Config);
  this.config.swagger =
    Config.util.extendDeep(
      swaggerConfigDefaults,
      this.config.swagger,
      appJsConfig,
      readEnvConfig());

  debug('resolved config: %j', this.config);

  var self = this;
  var swayOpts = {
    definition: appJsConfig.swagger || appJsConfig.swaggerFile || this.resolveAppPath(DEFAULT_SWAGGER_FILE)
  };

  debug('initializing Sway');
  // sway uses Promises
  sway.create(swayOpts)
    .then(function(api) {

      debug('validating api');
      var validateResult = api.validate();
      debug('done validating api. errors: %d, warnings: %d', validateResult.errors.length, validateResult.warnings.length);

      var errors = validateResult.errors;
      if (errors && errors.length > 0) {
        if (!self.config.swagger.enforceUniqueOperationId) {
          errors = errors.filter(function(err) {
            return (err.code !== 'DUPLICATE_OPERATIONID');
          });
        }
        if (errors.length > 0) {
          if (self.config.swagger.startWithErrors) {
            var errorText = JSON.stringify(errors);
            console.error(errorText, 2);
          } else {
            var err = new Error('Swagger validation errors:');
            err.validationErrors = errors;
            throw err;
          }
        }
      }

      var warnings = validateResult.warnings;
      if (warnings && warnings.length > 0) {
        var warningText = JSON.stringify(warnings);
        if (self.config.swagger.startWithWarnings) {
          console.error(warningText, 2);
        } else {
          var err = new Error('Swagger validation warnings:');
          err.validationWarnings = warnings;
          throw err;
        }
      }

      self.api = api;
      self.swagger = api.definition;
      self.securityHandlers = appJsConfig.securityHandlers || appJsConfig.swaggerSecurityHandlers; // legacy name
      self.bagpipes = createPipes(self);

      cb(null, self);
    })
    .catch(function(err) {
      cb(err);
    })
    .catch(function(err) {
      console.error('Error in callback! Tossing to global error handler.', err.stack);
      process.nextTick(function() { throw err; });
    })
}

function createPipes(self) {
  var config = self.config.swagger;

  var fittingsDirs = (config.fittingsDirs || DEFAULT_FITTINGS_DIRS).map(function(dir) {
    return path.resolve(config.appRoot, dir);
  });
  var swaggerNodeFittingsDir = path.resolve(__dirname, './fittings');
  fittingsDirs.push(swaggerNodeFittingsDir);

  var viewsDirs = (config.viewsDirs || DEFAULT_VIEWS_DIRS).map(function(dir) {
    return path.resolve(config.appRoot, dir);
  });

  // legacy support: set up a default piping for traditional swagger-node if nothing is specified
  if (!config.bagpipes || config.bagpipes ==='DEFAULTS_TEST') {

    debug('**** No bagpipes defined in config. Using default setup. ****');

    config.swaggerControllerPipe = 'swagger_controllers';

    config.bagpipes = {
      _router: {
        name: 'swagger_router',
        mockMode: false,
        mockControllersDirs: [ 'api/mocks' ],
        controllersDirs: [ 'api/controllers' ]
      },
      _swagger_validate: {
        name: 'swagger_validator',
        validateReponse: true
      },
      swagger_controllers: [
        'cors',
        'swagger_params_parser',
        'swagger_security',
        '_swagger_validate',
        'express_compatibility',
        '_router'
      ]
    };

    if (config.mapErrorsToJson) {
      config.bagpipes.swagger_controllers.unshift({ onError: 'json_error_handler' });
    }
  }

  var pipesDefs = config.bagpipes;

  var pipesConfig = {
    userFittingsDirs: fittingsDirs,
    userViewsDirs: viewsDirs,
    swaggerNodeRunner: self
  };
  return bagpipes.create(pipesDefs, pipesConfig);
}

function readEnvConfig() {

  var config = {};
  _.each(process.env, function(value, key) {
    var split = key.split('_');
    if (split[0] === 'swagger') {
      var configItem = config;
      for (var i = 1; i < split.length; i++) {
        var subKey = split[i];
        if (i < split.length - 1) {
          if (!configItem[subKey]) { configItem[subKey] = {}; }
          configItem = configItem[subKey];
        } else {
          try {
            configItem[subKey] = JSON.parse(value);
          } catch (err) {
            configItem[subKey] = value;
          }
        }
      }
    }
  });
  debug('loaded env vars: %j', config);
  return config;
}<|endoftext|>


<commit_before>/*!
 * template-helper-apidocs <https://github.com/jonschlinkert/template-helper-apidocs>
 *
 * Copyright (c) 2014-2015, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

/**
 * Module dependencies
 */

var path = require('path');
var glob = require('globby');
var async = require('async');
var isGlob = require('is-glob');
var relative = require('relative');
var comments = require('js-comments');
var extend = require('extend-shallow');
var extract = require('extract-gfm');

/**
 * Expose `apidocs` helper
 */

module.exports = apidocs;

/**
 * Generate API docs from code comments in the JavaScript
 * files that match the given `patterns`. Only code comments
 * with `@api public` are rendered.
 *
 * @param  {String} `patterns`
 * @param  {Object} `options`
 * @return {String}
 * @api public
 */

function apidocs(app) {
  app.create('apidoc', {isRenderable: true, isPartial: true });
  app.option('renameKey', false);

  var appDelims = app.delims['.*'].original;

  return function (patterns, options, cb) {
    if (typeof patterns === 'object' && !Array.isArray(patterns)) {
      cb = options; options = patterns; patterns = null;
    }

    if (typeof options === 'function') {
      cb = options; options = {};
    }

    var opts = extend({sep: '\n', dest: 'README.md'}, options);
    opts.cwd = path.resolve(opts.cwd || app.option('cwd') || process.cwd());
    var delims = opts.escapeDelims || appDelims || ['<%=', '%>'];
    var dest = opts.dest;

    if (dest && dest.indexOf('://') === -1) {
      dest = relative(dest);
    }

    if (!patterns) {
      patterns = path.join(opts.cwd, '*.js');
    }

    if (!isGlob(patterns)) {
      var fp = path.join(opts.cwd, patterns);
      return renderFile(app, delims, fp, dest, opts, cb);
    }

    glob(patterns, opts, function(err, files) {
      async.mapSeries(files, function(fp, next) {
        renderFile(app, delims, fp, dest, opts, next);
      }, function (err, arr) {
        if (err) return cb(err);
        cb(null, arr.join('\n'));
      });
    });
  };
}

function renderFile(app, delims, fp, dest, opts, next) {
  var res = headings(comments(fp, dest, opts));
  var delim = delims[0];

  // protect escaped template variables
  res = res.split(delim + '%').join('__DELIM__');

  app.apidoc({ path: fp, content: res, ext: '.md', engine: '.md' });
  var file = app.views.apidocs[fp];

  app.render(file, opts, function (err, content) {
    if (err) return next(err);

    // replace escaped template variables
    next(null, content.split('__DELIM__').join(delim));
  });
}

function headings(str, lvl) {
  var o = extract.parseBlocks(str);
  lvl = lvl ? '######'.substr(lvl + 2) : '##';
  o.text = o.text.replace(/^#/gm, lvl);
  return extract.injectBlocks(o.text, o.blocks);
}
<commit_msg>refactor<commit_after>/*!
 * template-helper-apidocs <https://github.com/jonschlinkert/template-helper-apidocs>
 *
 * Copyright (c) 2014-2015, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

/**
 * Module dependencies
 */

var fs = require('fs');
var glob = require('globby');
var comments = require('js-comments');
var isGlob = require('is-glob');

/**
 * Generate API docs from code comments for any JavaScript
 * files that match the given `patterns`.
 *
 * **Only code comments with `@api public` will be rendered.**
 *
 * @param  {String} `patterns`
 * @param  {Object} `options`
 * @return {String}
 * @api public
 */

module.exports = function apidocs(patterns, opts) {
  opts = opts || {};
  opts.file = opts.file || {};

  var delims = opts.escapeDelims || ['<%%', '<%'];
  var files = isGlob ? glob.sync(patterns, opts) : [patterns];
  var dest = opts && opts.dest || 'README.md';
  var len = files.length, i = 0;
  var res = '';

  while (len--) {
    var fp = files[i++];
    var str = fs.readFileSync(fp, 'utf8');
    var arr = comments.parse(str);
    opts.file.path = fp;
    res += comments.render(arr, opts);
  }

  res = comments.format(res);
  if (this && this.app) {
    res = res.split(delims[0]).join('__DELIM__');
    res = this.app.render(res, opts);
    res = res.split('__DELIM__').join(delims[1]);
  }
  return res;
};
<|endoftext|>


<commit_before>
module.exports = exports = function (_ua, obj) {
  try {
    _ua = _ua.toLowerCase()
  } catch (e) {
    _ua = ''
  }
  if (obj === true) {
    obj = exports
  } else if (!obj) {
    obj = {}
  }
  // _ua = 'webos; linux - large screen'
  var _ff = 'firefox'
  var _android = 'android'
  var _mobile = '.+mobile'
  var _webkit = 'webkit'
  var _ps = 'playstation'
  var _xbox = 'xbox'
  var _linux = 'linux'
  var _castDetect = 'crkey'
  var _chromecast = 'chromecast'
  var _tablet = 'tablet'
  var _windows = 'windows'
  var _phone = 'phone'
  var _firetv = 'firetv'
  var _sticktv = 'sticktv'
  var _rikstv = 'rikstv'
  var _facebook = 'facebook'

  /**
   * browser detection
   */
  test.call(obj, _ua,
    function (query, arr) {
      obj.browser = arr[ 2 ] || query
      var _v = _ua.match(
        new RegExp('((([\\/ ]version|' + arr[ 0 ] + '(?!.+version))[\/ ])| rv:)([0-9]{1,4}\\.[0-9]{0,2})')
      )
      obj.version = _v ? Number(_v[ 4 ]) : 0
      obj.prefix = arr[ 1 ]
      // TODO: add prefix for opera v>12.15;
      // TODO: windows check for ie 11 may be too general;
    },
    [ true, _webkit ],
    [ '\\(windows', 'ms', 'ie' ],
    [ 'safari', _webkit ],
    [ _ff, 'Moz' ],
    [ 'opera', 'O' ],
    [ 'msie', 'ms', 'ie' ],
    [ _facebook, _facebook ],
    [ 'chrome|crios\/', _webkit, 'chrome' ]
  )

  /**
   * platform detection
   */
  test.call(obj, _ua, 'platform',
    [ true, _windows ],
    [ _linux, _linux ],
    [ 'lg.{0,3}netcast', 'lg' ], // TODO:propably need to add more!
    [ _ff + _mobile, _ff ],
    [ 'mac os x', 'mac' ], [ 'iphone|ipod|ipad', 'ios' ],
    [ _xbox, _xbox ],
    [ _ps, _ps ],
    [ _android, _android ],
    [ _windows, _windows ],
    [ _castDetect, _chromecast ],
    [ 'smart-tv;|;samsung;smarttv', 'samsung' ], // SmartTV2013
    [ _rikstv, _rikstv ]
  )

  /**
   * device detection
   */
  test.call(obj, _ua, 'device',
    [ true, 'desktop' ],
    [ _windows + '.+touch|ipad|' + _android, _tablet ],
    [
      'phone|iphone|(' +
      _android + _mobile + ')|(' + _ff + _mobile +
      ')|' + _windows + ' phone|iemobile', _phone
    ],
    [ _xbox + '|' + _ps, 'console' ],
    [ 'tv|smarttv|googletv|appletv|hbbtv|pov_tv|netcast.tv|webos.+large', 'tv' ],
    [ _castDetect, _chromecast ],
    [ 'tablet|amazon-fireos|nexus (?=[^1-6])\\d{1,2}', _tablet ],
    [ 'aftb|afts', _firetv ],
    [ 'aftm', _sticktv ],
    [ 'RiksTV', _rikstv ]
  )

  test.call(obj, _ua, 'webview',
    [ true, false ],
    [ 'vigour-wrapper', true ]
  )

  return obj

  /**
   * test
   * search for regexps in the userAgent
   * fn is a on succes callback
   * check tests in https://github.com/faisalman/ua-parser-js to test for userAgents
   * @method
   */
  function test (_ua, fn) {
    for (var tests = arguments, i = tests.length - 1, query = tests[i][0]; query !== true && !new RegExp(query).test(_ua) && i > 0; query = tests[--i][0]); //eslint-disable-line
    // this for has no body

    if (fn.slice || fn.call(this, query, tests[i])) {
      this[fn] = tests[i][1]
    }
  }
}
<commit_msg>Use `typeof` instead of `try catch`<commit_after>
module.exports = exports = function (_ua, obj) {
  if (typeof _ua === 'string') {
    _ua = _ua.toLowerCase()
  } else {
    _ua = ''
  }
  if (obj === true) {
    obj = exports
  } else if (!obj) {
    obj = {}
  }
  // _ua = 'webos; linux - large screen'
  var _ff = 'firefox'
  var _android = 'android'
  var _mobile = '.+mobile'
  var _webkit = 'webkit'
  var _ps = 'playstation'
  var _xbox = 'xbox'
  var _linux = 'linux'
  var _castDetect = 'crkey'
  var _chromecast = 'chromecast'
  var _tablet = 'tablet'
  var _windows = 'windows'
  var _phone = 'phone'
  var _firetv = 'firetv'
  var _sticktv = 'sticktv'
  var _rikstv = 'rikstv'
  var _facebook = 'facebook'

  /**
   * browser detection
   */
  test.call(obj, _ua,
    function (query, arr) {
      obj.browser = arr[ 2 ] || query
      var _v = _ua.match(
        new RegExp('((([\\/ ]version|' + arr[ 0 ] + '(?!.+version))[\/ ])| rv:)([0-9]{1,4}\\.[0-9]{0,2})')
      )
      obj.version = _v ? Number(_v[ 4 ]) : 0
      obj.prefix = arr[ 1 ]
      // TODO: add prefix for opera v>12.15;
      // TODO: windows check for ie 11 may be too general;
    },
    [ true, _webkit ],
    [ '\\(windows', 'ms', 'ie' ],
    [ 'safari', _webkit ],
    [ _ff, 'Moz' ],
    [ 'opera', 'O' ],
    [ 'msie', 'ms', 'ie' ],
    [ _facebook, _facebook ],
    [ 'chrome|crios\/', _webkit, 'chrome' ]
  )

  /**
   * platform detection
   */
  test.call(obj, _ua, 'platform',
    [ true, _windows ],
    [ _linux, _linux ],
    [ 'lg.{0,3}netcast', 'lg' ], // TODO:propably need to add more!
    [ _ff + _mobile, _ff ],
    [ 'mac os x', 'mac' ], [ 'iphone|ipod|ipad', 'ios' ],
    [ _xbox, _xbox ],
    [ _ps, _ps ],
    [ _android, _android ],
    [ _windows, _windows ],
    [ _castDetect, _chromecast ],
    [ 'smart-tv;|;samsung;smarttv', 'samsung' ], // SmartTV2013
    [ _rikstv, _rikstv ]
  )

  /**
   * device detection
   */
  test.call(obj, _ua, 'device',
    [ true, 'desktop' ],
    [ _windows + '.+touch|ipad|' + _android, _tablet ],
    [
      'phone|iphone|(' +
      _android + _mobile + ')|(' + _ff + _mobile +
      ')|' + _windows + ' phone|iemobile', _phone
    ],
    [ _xbox + '|' + _ps, 'console' ],
    [ 'tv|smarttv|googletv|appletv|hbbtv|pov_tv|netcast.tv|webos.+large', 'tv' ],
    [ _castDetect, _chromecast ],
    [ 'tablet|amazon-fireos|nexus (?=[^1-6])\\d{1,2}', _tablet ],
    [ 'aftb|afts', _firetv ],
    [ 'aftm', _sticktv ],
    [ 'RiksTV', _rikstv ]
  )

  test.call(obj, _ua, 'webview',
    [ true, false ],
    [ 'vigour-wrapper', true ]
  )

  return obj

  /**
   * test
   * search for regexps in the userAgent
   * fn is a on succes callback
   * check tests in https://github.com/faisalman/ua-parser-js to test for userAgents
   * @method
   */
  function test (_ua, fn) {
    for (var tests = arguments, i = tests.length - 1, query = tests[i][0]; query !== true && !new RegExp(query).test(_ua) && i > 0; query = tests[--i][0]); //eslint-disable-line
    // this for has no body

    if (fn.slice || fn.call(this, query, tests[i])) {
      this[fn] = tests[i][1]
    }
  }
}
<|endoftext|>


<commit_before>/**
 * @module parenthesis
 */

function parse (str, opts) {
	//pretend non-string parsed per-se
	if (typeof str !== 'string') return [str];

	var res = [str];

	opts = opts || {};

	var brackets = opts.brackets ? (Array.isArray(opts.brackets) ? opts.brackets : [opts.brackets]) : ['{}', '[]', '()'];

	var escape = opts.escape || '\\';

	var flat = !!opts.flat;

	brackets.forEach(function (bracket) {
		//create parenthesis regex
		var pRE = new RegExp(['\\', bracket[0], '[^\\', bracket[0], '\\', bracket[1], ']*\\', bracket[1]].join(''));

		var ids = [];

		function replaceToken(token, idx, str){
			//save token to res
			var refId = res.push(token.slice(bracket[0].length, -bracket[1].length)) - 1;

			ids.push(refId);

			return escape + refId;
		}

		res.forEach(function (str, i) {
			var prevStr;

			//replace paren tokens till there’s none
			var a = 0;
			while (str != prevStr) {
				prevStr = str;
				str = str.replace(pRE, replaceToken);
				if (a++ > 10e3) throw Error('References have circular dependency. Please, check them.')
			}

			res[i] = str;
		});

		//wrap found refs to brackets
		res = res.map(function (str) {
			ids.forEach(function (id) {
				str = str.replace(new RegExp('(\\' + escape + id + ')', 'g'), bracket[0] + '$1' + bracket[1])
			});
			return str;
		});
	});

	var re = new RegExp('\\' + escape + '([0-9]+)');

	//transform references to tree
	function nest (str, refs, escape) {
		var res = [], match;
		while (match = re.exec(str)) {
			res.push(str.slice(0, match.index));

			res.push(nest(refs[match[1]], refs));

			str = str.slice(match.index + match[0].length);
		}

		res.push(str);

		return res;
	}

	return flat ? res : nest(res[0], res);
};

function stringify (arg) {
	return arg.reduce(function f (prev, curr) {
		if (Array.isArray(curr)) {
			curr = curr.reduce(f, '');
		}
		return prev + curr;
	}, '');
}

function parenthesis (arg, opts) {
	if (Array.isArray(arg)) {
		return stringify(arg);
	}
	else {
		return parse(arg, opts);
	}
}

parenthesis.parse = parse;
parenthesis.stringify = stringify;

module.exports = parenthesis;<commit_msg>Fix default escape seq<commit_after>/**
 * @module parenthesis
 */

function parse (str, opts) {
	//pretend non-string parsed per-se
	if (typeof str !== 'string') return [str];

	var res = [str];

	opts = opts || {};

	var brackets = opts.brackets ? (Array.isArray(opts.brackets) ? opts.brackets : [opts.brackets]) : ['{}', '[]', '()'];

	var escape = opts.escape || '___';

	var flat = !!opts.flat;

	brackets.forEach(function (bracket) {
		//create parenthesis regex
		var pRE = new RegExp(['\\', bracket[0], '[^\\', bracket[0], '\\', bracket[1], ']*\\', bracket[1]].join(''));

		var ids = [];

		function replaceToken(token, idx, str){
			//save token to res
			var refId = res.push(token.slice(bracket[0].length, -bracket[1].length)) - 1;

			ids.push(refId);

			return escape + refId;
		}

		res.forEach(function (str, i) {
			var prevStr;

			//replace paren tokens till there’s none
			var a = 0;
			while (str != prevStr) {
				prevStr = str;
				str = str.replace(pRE, replaceToken);
				if (a++ > 10e3) throw Error('References have circular dependency. Please, check them.')
			}

			res[i] = str;
		});

		//wrap found refs to brackets
		res = res.map(function (str) {
			ids.forEach(function (id) {
				str = str.replace(new RegExp('(\\' + escape + id + ')', 'g'), bracket[0] + '$1' + bracket[1])
			});
			return str;
		});
	});

	var re = new RegExp('\\' + escape + '([0-9]+)');

	//transform references to tree
	function nest (str, refs, escape) {
		var res = [], match;
		while (match = re.exec(str)) {
			res.push(str.slice(0, match.index));

			res.push(nest(refs[match[1]], refs));

			str = str.slice(match.index + match[0].length);
		}

		res.push(str);

		return res;
	}

	return flat ? res : nest(res[0], res);
};

function stringify (arg) {
	return arg.reduce(function f (prev, curr) {
		if (Array.isArray(curr)) {
			curr = curr.reduce(f, '');
		}
		return prev + curr;
	}, '');
}

function parenthesis (arg, opts) {
	if (Array.isArray(arg)) {
		return stringify(arg);
	}
	else {
		return parse(arg, opts);
	}
}

parenthesis.parse = parse;
parenthesis.stringify = stringify;

module.exports = parenthesis;<|endoftext|>


<commit_before>var bitcore = module.exports;

//main bitcoin library
bitcore.Address = require('./lib/address');
bitcore.Base58 = require('./lib/base58');
bitcore.Base58Check = require('./lib/base58check');
bitcore.BIP32 = require('./lib/bip32');
bitcore.Block = require('./lib/block');
bitcore.Blockheader = require('./lib/blockheader');
bitcore.BN = require('./lib/bn');
bitcore.BufferReader = require('./lib/bufferreader');
bitcore.BufferWriter = require('./lib/bufferwriter');
bitcore.Constants = require('./lib/constants');
bitcore.ECDSA = require('./lib/ecdsa');
bitcore.Hash = require('./lib/hash');
bitcore.KDF = require('./lib/kdf');
bitcore.Keypair = require('./lib/keypair');
bitcore.Message = require('./lib/message');
bitcore.Opcode = require('./lib/opcode');
bitcore.Point = require('./lib/point');
bitcore.Privkey = require('./lib/privkey');
bitcore.Pubkey = require('./lib/pubkey');
bitcore.Random = require('./lib/random');
bitcore.Script = require('./lib/script');
bitcore.Signature = require('./lib/signature');
bitcore.Transaction = require('./lib/transaction');
bitcore.Txin = require('./lib/txin');
bitcore.Txout = require('./lib/txout');
bitcore.Varint = require('./lib/varint');

//experimental, nonstandard, or unstable features
bitcore.expmt = {};
bitcore.expmt.AES = require('./lib/expmt/aes');
bitcore.expmt.AESCBC = require('./lib/expmt/aescbc');
bitcore.expmt.CBC = require('./lib/expmt/cbc');
bitcore.expmt.ECIES = require('./lib/expmt/ecies');
bitcore.expmt.StealthAddress = require('./lib/expmt/stealthaddress');
bitcore.expmt.Stealthkey = require('./lib/expmt/stealthkey');
bitcore.expmt.StealthMessage = require('./lib/expmt/stealthmessage');
bitcore.expmt.StealthTx = require('./lib/expmt/stealthtx');

//dependencies, subject to change
bitcore.deps = {};
bitcore.deps.aes = require('aes');
bitcore.deps.bnjs = require('bn.js');
bitcore.deps.bs58 = require('bs58');
bitcore.deps.Buffer = Buffer;
bitcore.deps.elliptic = require('elliptic');
bitcore.deps.hashjs = require('hash.js');
bitcore.deps.sha512 = require('sha512');

//bitcore.scriptexec = require('lib/scriptexec');
//bitcore.tx = require('lib/tx');
//bitcore.txpartial = require('lib/txpartial');

//bitcore.bip70 = require('lib/bip70');
<commit_msg>Add exportable class for BitAuth.<commit_after>var bitcore = module.exports;

//main bitcoin library
bitcore.Address = require('./lib/address');
bitcore.Base58 = require('./lib/base58');
bitcore.Base58Check = require('./lib/base58check');
bitcore.BIP32 = require('./lib/bip32');
bitcore.Block = require('./lib/block');
bitcore.Blockheader = require('./lib/blockheader');
bitcore.BN = require('./lib/bn');
bitcore.BufferReader = require('./lib/bufferreader');
bitcore.BufferWriter = require('./lib/bufferwriter');
bitcore.Constants = require('./lib/constants');
bitcore.ECDSA = require('./lib/ecdsa');
bitcore.Hash = require('./lib/hash');
bitcore.Identity = require('./lib/identity');
bitcore.KDF = require('./lib/kdf');
bitcore.Keypair = require('./lib/keypair');
bitcore.Message = require('./lib/message');
bitcore.Opcode = require('./lib/opcode');
bitcore.Point = require('./lib/point');
bitcore.Privkey = require('./lib/privkey');
bitcore.Pubkey = require('./lib/pubkey');
bitcore.Random = require('./lib/random');
bitcore.Script = require('./lib/script');
bitcore.Signature = require('./lib/signature');
bitcore.Transaction = require('./lib/transaction');
bitcore.Txin = require('./lib/txin');
bitcore.Txout = require('./lib/txout');
bitcore.Varint = require('./lib/varint');

//experimental, nonstandard, or unstable features
bitcore.expmt = {};
bitcore.expmt.AES = require('./lib/expmt/aes');
bitcore.expmt.AESCBC = require('./lib/expmt/aescbc');
bitcore.expmt.CBC = require('./lib/expmt/cbc');
bitcore.expmt.ECIES = require('./lib/expmt/ecies');
bitcore.expmt.StealthAddress = require('./lib/expmt/stealthaddress');
bitcore.expmt.Stealthkey = require('./lib/expmt/stealthkey');
bitcore.expmt.StealthMessage = require('./lib/expmt/stealthmessage');
bitcore.expmt.StealthTx = require('./lib/expmt/stealthtx');

//dependencies, subject to change
bitcore.deps = {};
bitcore.deps.aes = require('aes');
bitcore.deps.bnjs = require('bn.js');
bitcore.deps.bs58 = require('bs58');
bitcore.deps.Buffer = Buffer;
bitcore.deps.elliptic = require('elliptic');
bitcore.deps.hashjs = require('hash.js');
bitcore.deps.sha512 = require('sha512');

//bitcore.scriptexec = require('lib/scriptexec');
//bitcore.tx = require('lib/tx');
//bitcore.txpartial = require('lib/txpartial');

//bitcore.bip70 = require('lib/bip70');
<|endoftext|>


<commit_before>var _ = require('underscore');
var async = require('async');
var request = require('request');
var linters = require('./linters');

var repoURL = 'https://api.github.com/repos/nicolasmccurdy/repos';
var options = {
  headers: {
    Accept: 'application/vnd.github.v3',
    'User-Agent': 'ghlint'
  },
  qs: {
    client_id: process.env.GHLINT_ID,
    client_secret: process.env.GHLINT_SECRET
  },
  url: repoURL
};
var commitOptions = _.extend(options, { url: repoURL + '/commits' });

module.exports = {
  linters: linters,
  lintAll: function (callback) {
    request(options, function (err, repo) {
      request(commitOptions, function (err, commits) {
        callback(err, linters.map(function (linter) {
          return {
            message: linter.message,
            result: linter.lint(repo, commits)
          };
        }));
      });
    });
  }
};
<commit_msg>Use request.defaults() to simplify GitHub API calls<commit_after>var _ = require('underscore');
var async = require('async');
var request = require('request');
var linters = require('./linters');

var repoURL = 'https://api.github.com/repos/nicolasmccurdy/repos';
var githubRequest = request.defaults({
  headers: {
    Accept: 'application/vnd.github.v3',
    'User-Agent': 'ghlint'
  },
  qs: {
    client_id: process.env.GHLINT_ID,
    client_secret: process.env.GHLINT_SECRET
  }
});

module.exports = {
  linters: linters,
  lintAll: function (callback) {
    githubRequest(repoURL, function (err, repo) {
      githubRequest(repoURL + '/commits', function (err, commits) {
        callback(err, linters.map(function (linter) {
          return {
            message: linter.message,
            result: linter.lint(repo, commits)
          };
        }));
      });
    });
  }
};
<|endoftext|>


<commit_before>module.exports = {
  rules: {
    'strict': [2, 'function'],          // http://eslint.org/docs/rules/strict
    'linebreak-style': [2, 'windows'],  // http://eslint.org/docs/rules/linebreak-style
    'operator-linebreak': [2, 'after'], // http://eslint.org/docs/rules/operator-linebreak
    'padded-blocks': 0,                 // http://eslint.org/docs/rules/padded-blocks
    'spaced-comment': 0,                // http://eslint.org/docs/rules/spaced-comment
    'require-jsdoc': 2,                 // http://eslint.org/docs/rules/require-jsdoc
    'valid-jsdoc': [2, {                // http://eslint.org/docs/rules/valid-jsdoc
      'requireParamDescription': false,
      'requireReturnDescription': false
    }]
  }
};
<commit_msg>remove linebreak-style rule<commit_after>module.exports = {
  rules: {
    'strict': [2, 'function'],          // http://eslint.org/docs/rules/strict
    'operator-linebreak': [2, 'after'], // http://eslint.org/docs/rules/operator-linebreak
    'padded-blocks': 0,                 // http://eslint.org/docs/rules/padded-blocks
    'spaced-comment': 0,                // http://eslint.org/docs/rules/spaced-comment
    'require-jsdoc': 2,                 // http://eslint.org/docs/rules/require-jsdoc
    'valid-jsdoc': [2, {                // http://eslint.org/docs/rules/valid-jsdoc
      'requireParamDescription': false,
      'requireReturnDescription': false
    }]
  }
};
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var EventEmitter = require('events').EventEmitter;
var Reporter = require('./lib/reporter');
var MonitoredConnection = require('./lib/connection').MonitoredConnection;
var error = require('./lib/error');
var util = require('./lib/util');
var provider = require('./lib/provider');
var wildcard = require('wildcard');

var OPTIONAL_MONITOR_EVENTS = [
    'negotiate:request', 'negotiate:renegotiate', 'negotiate:abort',
    'negotiate:createOffer', 'negotiate:createOffer:created',
    'negotiate:createAnswer', 'negotiate:createAnswer:created',
    'negotiate:setlocaldescription',
    'icecandidate:local', 'icecandidate:remote', 'icecandidate:gathered', 'icecandidate:added',
    'sdp:received'
];

/**
  # rtc-health

  The `rtc-health` module helps make it easier to expose health information
  about your RTC connections. It hooks into the WebRTC Stats API, as well as the
  underlying signaller and PeerConnection events to provide insight as to events,
  and metrics about any peer connections initiated by the provided quickconnect instance.

  ## Example Usage

  <<< examples/basic.js

  This shows some simple logging of the sdp filter, and events

  <<< examples/capture.js

  This captures data for video streaming

**/
module.exports = function(qc, opts) {

  if (!provider) {
    console.log('WARNING! No WebRTC provider detected - rtc-health is disabled');
    return;
  }

  opts = opts || {};

  var emitter = new EventEmitter();
  var connections = {};
  var timers = {};
  var logs = {};

  function log(peerId, pc, data) {
    provider.getStats(pc, null, function(err, reports) {
      var tc = connections[data.id];

      // Only reschedule while we are monitoring
      if (tc) {
        timers[data.id] = setTimeout(log.bind(this, peerId, pc, data), opts.pollInterval || 1000);
      }

      var reporter = new Reporter({
            source: qc.id,
            about: data,
            pc: pc,
            reports: reports
          });

      emitter.emit('health:report', reporter, pc);
    });
  }

  /**
    Emit a generic notification event that allows for tapping into the activity that is happening
    within quickconnect
   **/
  function notify(eventName, opts) {
    var args = Array.prototype.slice.call(arguments, 2);
    emitter.emit('health:notify', eventName, opts, args);
    emitter.emit.apply(emitter, (['health:' + eventName, opts].concat(args)));
  }

  function trackConnection(peerId, pc, data) {
    var tc = new MonitoredConnection(qc.id, pc, data);
    connections[data.id] = tc;
    notify('started', { source: qc.id, about: data.id, tracker: tc });
    log(peerId, pc, data);
    return tc;
  }

  /**
    Handle the peer connection being created
   **/
  qc.on('peer:connect', trackConnection);

  qc.on('peer:couple', function(peerId, pc, data, monitor) {

    // Store that we are currently tracking the target peer
    var tc = connections[data.id];
    var status = util.toStatus(pc.iceConnectionState);
    if (!tc) tc = trackConnection(peerId, pc, data);

    monitor.on('statechange', function(pc, state) {
      var iceConnectionState = pc.iceConnectionState;
      var newStatus = util.toStatus(iceConnectionState);
      notify('icestatus', {
        source: qc.id, about: data.id, tracker: tc
      }, iceConnectionState);
      emitter.emit('health:changed', tc, iceConnectionState);

      if (status != newStatus) {
        emitter.emit('health:connection:status', tc, newStatus, status);
        status = newStatus;
      }
    });

    monitor.on('closed', function() {

      tc.closed();

      // Stop the reporting for this peer connection
      if (timers[data.id]) clearTimeout(timers[data.id]);
      delete connections[data.id];

      // Emit a closure status update
      emitter.emit('health:report', new Reporter({
        source: qc.id,
        about: data,
        status: 'closed',
        force: true
      }));

      notify('closed', { source: qc.id, about: data.id, tracker: tc });
    });

  });

  // Setup to listen to the entire feed
  qc.feed(function(evt) {
    var name = evt.name;

    if (util.SIGNALLER_EVENTS.indexOf(name) >= 0) {
      return notify.apply(
        notify,
        [name, { source: qc.id, about: 'signaller' }].concat(evt.args)
      );
    }

    // Listen for the optional verbose events
    var matching = opts.verbose && wildcard('pc.*', name);
    if (matching) {
      var peerId = matching[1];
      var shortName = matching.slice(2).join('.');
      var tc = connections[peerId];
      return notify.apply(
        notify,
        [shortName, { source: qc.id, about: peerId, tracker: tc }].concat(evt.args)
      );
    }
  });

  // Helper method to safely close all connections
  emitter.closeConnections = function() {
    for (var connId in connections) {
      connections[connId].close();
    }
  };

  // Helper method to expose the current tracked connections
  emitter.getConnections = function() {
    var results = [];
    for (var target in connections) {
      results.push(connections[target]);
    }
    return results;
  }

  return emitter;
};
<commit_msg>Expose pollInterval on the monitor emitter<commit_after>/* jshint node: true */
'use strict';

var EventEmitter = require('events').EventEmitter;
var Reporter = require('./lib/reporter');
var MonitoredConnection = require('./lib/connection').MonitoredConnection;
var error = require('./lib/error');
var util = require('./lib/util');
var provider = require('./lib/provider');
var wildcard = require('wildcard');

var OPTIONAL_MONITOR_EVENTS = [
    'negotiate:request', 'negotiate:renegotiate', 'negotiate:abort',
    'negotiate:createOffer', 'negotiate:createOffer:created',
    'negotiate:createAnswer', 'negotiate:createAnswer:created',
    'negotiate:setlocaldescription',
    'icecandidate:local', 'icecandidate:remote', 'icecandidate:gathered', 'icecandidate:added',
    'sdp:received'
];

/**
  # rtc-health

  The `rtc-health` module helps make it easier to expose health information
  about your RTC connections. It hooks into the WebRTC Stats API, as well as the
  underlying signaller and PeerConnection events to provide insight as to events,
  and metrics about any peer connections initiated by the provided quickconnect instance.

  ## Example Usage

  <<< examples/basic.js

  This shows some simple logging of the sdp filter, and events

  <<< examples/capture.js

  This captures data for video streaming

**/
module.exports = function(qc, opts) {

  if (!provider) {
    console.log('WARNING! No WebRTC provider detected - rtc-health is disabled');
    return;
  }

  opts = opts || {};

  var emitter = new EventEmitter();
  emitter.pollInterval = opts.pollInterval || 1000;
  var connections = {};
  var timers = {};
  var logs = {};

  function log(peerId, pc, data) {
    provider.getStats(pc, null, function(err, reports) {
      var tc = connections[data.id];

      // Only reschedule while we are monitoring
      if (tc) {
        timers[data.id] = setTimeout(log.bind(this, peerId, pc, data), emitter.pollInterval);
      }

      var reporter = new Reporter({
            source: qc.id,
            about: data,
            pc: pc,
            reports: reports
          });

      emitter.emit('health:report', reporter, pc);
    });
  }

  /**
    Emit a generic notification event that allows for tapping into the activity that is happening
    within quickconnect
   **/
  function notify(eventName, opts) {
    var args = Array.prototype.slice.call(arguments, 2);
    emitter.emit('health:notify', eventName, opts, args);
    emitter.emit.apply(emitter, (['health:' + eventName, opts].concat(args)));
  }

  function trackConnection(peerId, pc, data) {
    var tc = new MonitoredConnection(qc.id, pc, data);
    connections[data.id] = tc;
    notify('started', { source: qc.id, about: data.id, tracker: tc });
    log(peerId, pc, data);
    return tc;
  }

  /**
    Handle the peer connection being created
   **/
  qc.on('peer:connect', trackConnection);

  qc.on('peer:couple', function(peerId, pc, data, monitor) {

    // Store that we are currently tracking the target peer
    var tc = connections[data.id];
    var status = util.toStatus(pc.iceConnectionState);
    if (!tc) tc = trackConnection(peerId, pc, data);

    monitor.on('statechange', function(pc, state) {
      var iceConnectionState = pc.iceConnectionState;
      var newStatus = util.toStatus(iceConnectionState);
      notify('icestatus', {
        source: qc.id, about: data.id, tracker: tc
      }, iceConnectionState);
      emitter.emit('health:changed', tc, iceConnectionState);

      if (status != newStatus) {
        emitter.emit('health:connection:status', tc, newStatus, status);
        status = newStatus;
      }
    });

    monitor.on('closed', function() {

      tc.closed();

      // Stop the reporting for this peer connection
      if (timers[data.id]) clearTimeout(timers[data.id]);
      delete connections[data.id];

      // Emit a closure status update
      emitter.emit('health:report', new Reporter({
        source: qc.id,
        about: data,
        status: 'closed',
        force: true
      }));

      notify('closed', { source: qc.id, about: data.id, tracker: tc });
    });

  });

  // Setup to listen to the entire feed
  qc.feed(function(evt) {
    var name = evt.name;

    if (util.SIGNALLER_EVENTS.indexOf(name) >= 0) {
      return notify.apply(
        notify,
        [name, { source: qc.id, about: 'signaller' }].concat(evt.args)
      );
    }

    // Listen for the optional verbose events
    var matching = opts.verbose && wildcard('pc.*', name);
    if (matching) {
      var peerId = matching[1];
      var shortName = matching.slice(2).join('.');
      var tc = connections[peerId];
      return notify.apply(
        notify,
        [shortName, { source: qc.id, about: peerId, tracker: tc }].concat(evt.args)
      );
    }
  });

  // Helper method to safely close all connections
  emitter.closeConnections = function() {
    for (var connId in connections) {
      connections[connId].close();
    }
  };

  // Helper method to expose the current tracked connections
  emitter.getConnections = function() {
    var results = [];
    for (var target in connections) {
      results.push(connections[target]);
    }
    return results;
  }

  return emitter;
};
<|endoftext|>


<commit_before>
module.exports = process.env.COV
  ? require('./lib-cov/engine-io')
  : require('./lib/engine-io');
<commit_msg>Corrected path.<commit_after>
module.exports = process.env.COV
  ? require('./lib-cov/engine.io')
  : require('./lib/engine.io');
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */

var parser = require('slick').parse;

/**
* Parses a selector and returns the tokens.
*
* @param {String} selector
* @api private.
*/

function parse(text) {
    try {
        return parser(text)[0];
    } catch (e) {
        return [];
    }
}

/**
 * CSS selector constructor.
 *
 * @param {String} selector text
 * @param {Array} optionally, precalculated specificity
 * @api public
 */

function Selector(text, spec) {
    this.text = text;
    this.spec = spec;
}

/**
 * Get parsed selector.
 *
 * @api public
 */

Selector.prototype.parsed = function () {
    if (!this.tokens) {
        this.tokens = parse(this.text);
    }
    return this.tokens;
};

/**
 * Lazy specificity getter
 *
 * @api public
 */

Selector.prototype.specificity = function () {

    function specificity(text, parsed) {
        var expressions = parsed || parse(text),
            spec = [ 0, 0, 0, 0 ],
            nots = [],
            i,
            expression,
            pseudos,
            p,
            ii,
            not,
            jj;

        for (i = 0; i < expressions.length; i++) {
            expression = expressions[i];
            pseudos = expression.pseudos;

            // id awards a point in the second column
            if (expression.id) {
                spec[1]++;
            }

            // classes and attributes award a point each in the third column
            if (expression.attributes) {
                spec[2] += expression.attributes.length;
            }
            if (expression.classList) {
                spec[2] += expression.classList.length;
            }

            // tag awards a point in the fourth column
            if (expression.tag && expression.tag !== '*') {
                spec[3]++;
            }

            // pseudos award a point each in the fourth column
            if (pseudos) {
                spec[3] += pseudos.length;

                for (p = 0; p < pseudos.length; p++) {
                    if (pseudos[p].key === 'not') {
                        nots.push(pseudos[p].value);
                        spec[3]--;
                    }
                }
            }
        }

        for (ii = nots.length; ii--;) {
            not = specificity(nots[ii]);
            for (jj = 4; jj--;) {
                spec[jj] += not[jj];
            }
        }

        return spec;
    }

    if (!this.spec) {
        this.spec = specificity(this.text, this.parsed());
    }
    return this.spec;
};

/**
* Module exports.
*/

module.exports = exports = Selector;
<commit_msg>Eliminate use of new.<commit_after>'use strict';

/**
 * Module dependencies.
 */

var parser = require('slick').parse;

/**
* Parses a selector and returns the tokens.
*
* @param {String} selector
* @api private.
*/

function parse(text) {
    try {
        return parser(text)[0];
    } catch (e) {
        return [];
    }
}

/**
* Returns specificity based on selector text and tokens.
*
* @param {String} selector
* @param {Array} tokens
* @api private.
*/

function getSpecificity(text, parsed) {
    var expressions = parsed || parse(text),
        spec = [ 0, 0, 0, 0 ],
        nots = [],
        i,
        expression,
        pseudos,
        p,
        ii,
        not,
        jj;

    for (i = 0; i < expressions.length; i++) {
        expression = expressions[i];
        pseudos = expression.pseudos;

        // id awards a point in the second column
        if (expression.id) {
            spec[1]++;
        }

        // classes and attributes award a point each in the third column
        if (expression.attributes) {
            spec[2] += expression.attributes.length;
        }
        if (expression.classList) {
            spec[2] += expression.classList.length;
        }

        // tag awards a point in the fourth column
        if (expression.tag && expression.tag !== '*') {
            spec[3]++;
        }

        // pseudos award a point each in the fourth column
        if (pseudos) {
            spec[3] += pseudos.length;

            for (p = 0; p < pseudos.length; p++) {
                if (pseudos[p].key === 'not') {
                    nots.push(pseudos[p].value);
                    spec[3]--;
                }
            }
        }
    }

    for (ii = nots.length; ii--;) {
        not = getSpecificity(nots[ii]);
        for (jj = 4; jj--;) {
            spec[jj] += not[jj];
        }
    }

    return spec;
}

/**
 * CSS selector constructor.
 *
 * @param {String} selector text
 * @param {Array} optionally, precalculated specificity
 * @api public
 */

module.exports = function (text, spec) {
    var tokens,
        _spec,

        /**
         * Get parsed selector.
         *
         * @api public
         */

        parsed = function () {
            if (!tokens) {
                tokens = parse(text);
            }
            return tokens;
        },

        /**
         * Lazy specificity getter
         *
         * @api public
         */

        specificity = function () {
            if (!spec) {
                _spec = getSpecificity(text, parsed());
            }
            return _spec;
        };

    return {
        text: text,

        spec: spec,

        parsed: parsed,

        specificity: specificity
    };
};
<|endoftext|>