<commit_before>var io = require('socket.io');
var DEFAULT_PORT = 8999;
var fs = require('fs');
var q = require('q');

var nodePath = require('path');

exports = module.exports = function(hotReload, config) {
    var port = config.port || DEFAULT_PORT;

    var io = require('socket.io').listen(port, { log: false });

    var readyEvent = config['ready-event'] || 'ready';

    io.sockets.on('connection', function (socket) {

        function emitModified(eventArgs) {
            socket.emit('modified', {path: eventArgs.path});
        }

        hotReload.afterReload(emitModified)
            .afterSpecialReload(emitModified);

        socket.on('disconnect', function () {
            hotReload.removeListener('afterReload', emitModified);
            hotReload.removeListener('afterSpecialReload', emitModified);
        });
    });

    hotReload.childProcessEnv.HOT_RELOAD_BROWSER_REFRESH_PORT = port;

    hotReload.on('reload', function() {
        if (!hotReload.childProcess) {
            return;
        }

        var deferred = q.defer();
        hotReload.childProcess.once('message', function(message) {
            hotReload.log('Server is ready. Triggering page refresh...');
            if (message === readyEvent) {
                deferred.resolve();
            }
        });
        hotReload.waitFor(deferred.promise);
    });
};<commit_msg>Better handling of when a server does not emit a ready event<commit_after>var io = require('socket.io');
var DEFAULT_PORT = 8999;
var fs = require('fs');
var q = require('q');

var nodePath = require('path');
var DEFAULT_DELAY = 500;

exports = module.exports = function(hotReload, config) {
    var port = config.port || DEFAULT_PORT;

    var io = require('socket.io').listen(port, { log: false });

    var readyEvent = config['ready-event'] || config.readyEvent || 'ready';

    io.sockets.on('connection', function (socket) {

        function emitModified(eventArgs) {
            socket.emit('modified', {path: eventArgs.path});
        }

        hotReload.afterReload(emitModified)
            .afterSpecialReload(emitModified);

        socket.on('disconnect', function () {
            hotReload.removeListener('afterReload', emitModified);
            hotReload.removeListener('afterSpecialReload', emitModified);
        });
    });

    hotReload.childProcessEnv.HOT_RELOAD_BROWSER_REFRESH_PORT = port;

    hotReload.on('reload', function() {
        if (!hotReload.childProcess) {
            return;
        }

        var deferred = q.defer();
        var ready = false;
        var delay = config.delay || DEFAULT_DELAY;

        var timeoutId = setTimeout(function() {
            if (ready) {
                return;
            }
            hotReload.log('Waited ' + delay + 'ms without receiving "' + readyEvent + '" from child process. Triggering page refresh...');
            ready = true;
            deferred.resolve();
        }, delay);

        hotReload.childProcess.once('message', function(message) {
            if (ready) {
                return;
            }

            if (message === readyEvent) {
                clearTimeout(timeoutId);
                hotReload.log('Server is ready. Triggering page refresh...');
                ready = true;
                deferred.resolve();
            }
        });

        hotReload.waitFor(deferred.promise);
    });
};<|endoftext|>


<commit_before>var fs = require('fs');
var http = require('http');
var jsonlint = require('jsonlint');
var selectObjectFromJson = require('./selectObjectFromJson');

var validate = {};

var Ajv = require('ajv');

function loadSchema(json, file) {
	var versions = { "3.0":true,"3.1":true,"3.2":true,"3.3":true,"3.4":true, "4.0":true }
	var version = json.X3D["@version"];
	if (!versions[version]) {
		console.error("Can only validate version 3.0-4.0 presently. Switching version to 3.3.");
		version = "3.3";
	}
        if (typeof validate[version] === 'undefined') {
		var schema = fs.readFileSync(__dirname+"/x3d-"+version+"-JSONSchema.json").toString();
		var ajv = new Ajv({ allErrors:true});
		ajv.addFormat("uri", /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9a-f]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9a-f]{2})*)?$/i);

		http.get('http://json-schema.org/draft-04/schema', (res) => {
		  const { statusCode } = res;
		  const contentType = res.headers['content-type'];

		  var error;
		  if (statusCode !== 200) {
		    error = new Error(`Request Failed.\n` +
				      `Status Code: ${statusCode}`);
		  } else if (!/^application\/octet-stream/.test(contentType)) {
		    error = new Error(`Invalid content-type.\n` +
				      `Expected application/json but received ${contentType}`);
		  }
		  if (error) {
		    console.error(error.message);
		    // consume response data to free up memory
		    res.resume();
		    return;
		  }

		  res.setEncoding('utf8');
		  var rawData = '';
		  res.on('data', (chunk) => { rawData += chunk; });
		  res.on('end', () => {
		    try {
		      console.log("MetaSchema received");
		      var metaschemajson = jsonlint.parse(rawData);
		      ajv.addMetaSchema(metaschemajson);
		      console.log("MetaSchema added");
		      var schemajson = jsonlint.parse(schema);
		      console.log("Schema", version, "parsed");
		      ajv.addSchema(schemajson);
		      console.log("Schema", version, "added");
		      validate[version] = ajv.compile(schemajson);
		      if (typeof validate[version] !== 'undefined') {
			      console.log("Schema compiled");
		      } else {
			      console.log("Schema not compiled");
		      }
		      doValidate(json, file);
		    } catch (e) {
		      console.error(e.message);
		    }
		  });
		}).on('error', (e) => {
		  console.error(`Got error: ${e.message}`);
		});
	}
}

function doValidate(json, file) {
	var version = json.X3D["@version"];
	if (typeof validate[version] !== 'undefined') {
		var valid = validate[version](json);
		if (!valid) {
			var errs = validate[version].errors;
			var error = ""
			// error += " errs: " + JSON.stringify(errs, null, 2) + "\r\n";
			for (var e in errs) {
				error += "\r\n keyword: " + errs[e].keyword + "\r\n";
				dataPath = errs[e].dataPath.replace(/^\./, "").replace(/[\.\[\]']+/g, " > ");

				error += " dataPath: " + dataPath+ "\r\n";
				error += " parentObject: " + JSON.stringify(selectObjectFromJson(json, dataPath)) + "\r\n";
				error += " message: " + errs[e].message + "\r\n";
				error += " params: " + JSON.stringify(errs[e].params) + "\r\n";
				error += " file: " + file + "\r\n";
			}
			if (error !== "") {
				console.error(error);
			}
		}
	}
}

function validateJSON(files) {

	for (var f in files) {
		var file = files[f];
		try {
			var str = fs.readFileSync(file).toString();
			if (typeof str === 'undefined') {
				throw("Read nothing, or possbile error");
			}
			var json = jsonlint.parse(str);
			var version = json.X3D["@version"];
			if (!validate[version]) {
				loadSchema(json, file);  // loads schema.
			} else {
				doValidate(json, file);
			}

		} catch (e) {
			console.error("Error reading", file, e);
		}
	}
}

module.exports = validateJSON
<commit_msg>removed space<commit_after>var fs = require('fs');
var http = require('http');
var jsonlint = require('jsonlint');
var selectObjectFromJson = require('./selectObjectFromJson');

var validate = {};

var Ajv = require('ajv');

function loadSchema(json, file) {
	var versions = { "3.0":true,"3.1":true,"3.2":true,"3.3":true,"3.4":true, "4.0":true }
	var version = json.X3D["@version"];
	if (!versions[version]) {
		console.error("Can only validate version 3.0-4.0 presently. Switching version to 3.3.");
		version = "3.3";
	}
        if (typeof validate[version] === 'undefined') {
		var schema = fs.readFileSync(__dirname+"/x3d-"+version+"-JSONSchema.json").toString();
		var ajv = new Ajv({ allErrors:true});
		ajv.addFormat("uri", /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9a-f]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9a-f]{2})*)?$/i);

		http.get('http://json-schema.org/draft-04/schema', (res) => {
		  const { statusCode } = res;
		  const contentType = res.headers['content-type'];

		  var error;
		  if (statusCode !== 200) {
		    error = new Error(`Request Failed.\n` +
				      `Status Code: ${statusCode}`);
		  } else if (!/^application\/octet-stream/.test(contentType)) {
		    error = new Error(`Invalid content-type.\n` +
				      `Expected application/json but received ${contentType}`);
		  }
		  if (error) {
		    console.error(error.message);
		    // consume response data to free up memory
		    res.resume();
		    return;
		  }

		  res.setEncoding('utf8');
		  var rawData = '';
		  res.on('data', (chunk) => { rawData += chunk; });
		  res.on('end', () => {
		    try {
		      console.log("MetaSchema received");
		      var metaschemajson = jsonlint.parse(rawData);
		      ajv.addMetaSchema(metaschemajson);
		      console.log("MetaSchema added");
		      var schemajson = jsonlint.parse(schema);
		      console.log("Schema", version, "parsed");
		      ajv.addSchema(schemajson);
		      console.log("Schema", version, "added");
		      validate[version] = ajv.compile(schemajson);
		      if (typeof validate[version] !== 'undefined') {
			      console.log("Schema compiled");
		      } else {
			      console.log("Schema not compiled");
		      }
		      doValidate(json, file);
		    } catch (e) {
		      console.error(e.message);
		    }
		  });
		}).on('error', (e) => {
		  console.error(`Got error: ${e.message}`);
		});
	}
}

function doValidate(json, file) {
	var version = json.X3D["@version"];
	if (typeof validate[version] !== 'undefined') {
		var valid = validate[version](json);
		if (!valid) {
			var errs = validate[version].errors;
			var error = ""
			// error += " errs: " + JSON.stringify(errs, null, 2) + "\r\n";
			for (var e in errs) {
				error += "\r\n keyword: " + errs[e].keyword + "\r\n";
				dataPath = errs[e].dataPath.replace(/^\./, "").replace(/[\.\[\]']+/g, " > ");
				error += " dataPath: " + dataPath+ "\r\n";
				error += " parentObject: " + JSON.stringify(selectObjectFromJson(json, dataPath)) + "\r\n";
				error += " message: " + errs[e].message + "\r\n";
				error += " params: " + JSON.stringify(errs[e].params) + "\r\n";
				error += " file: " + file + "\r\n";
			}
			if (error !== "") {
				console.error(error);
			}
		}
	}
}

function validateJSON(files) {

	for (var f in files) {
		var file = files[f];
		try {
			var str = fs.readFileSync(file).toString();
			if (typeof str === 'undefined') {
				throw("Read nothing, or possbile error");
			}
			var json = jsonlint.parse(str);
			var version = json.X3D["@version"];
			if (!validate[version]) {
				loadSchema(json, file);  // loads schema.
			} else {
				doValidate(json, file);
			}

		} catch (e) {
			console.error("Error reading", file, e);
		}
	}
}

module.exports = validateJSON
<|endoftext|>


<commit_before>'use strict';

var util = require('util')
, koa = require('koa')
, common = require('koa-common')
, router = require('koa-router')
, views = require('co-views')
, parse = require('co-body')
, Q = require('q')
, request = Q.denodeify(require('request'))
, port = process.env.PORT || 3000
, app = koa()
, csrf = require('koa-csrf')
, key = process.env.APP_KEY || 'im a secret'
, Client = require('github-api-client')
, client
, lgtmMarkdown = function(hash) {
  return '![LGTM](http://www.lgtm.in/p/' + hash + ')';
}
;

app.use(common.logger());
app.keys = [key];
app.use(common.session());
csrf(app);
app.use(function *(next) {
  var _render = views('views', { default: 'jade' });
  this.render = function (view, locals) {
    var body, html
    ;

    if (!locals) locals = {};

    return function *() {
      this.type = 'text/html';
      body = yield _render(view, locals);
      html = yield _render('layout', { body: body });
      this.body = html;
    }
  }

  yield next;
});
app.use(router(app));

client = new Client(app);

app.get('/', function *(next) {
  this.body = 'hello';
});

app.get('/lgtm', function *(next) {
  var NUM_LGTMS = 3
  , REQUIRED_QUERY = ['user', 'repo', 'number']
  , ret
  , lgtmReqs = []
  , lgtms = []
  , i
  ;

  function assertQuery(ctx, query) {
    var key, val
    ;
    try {
      if(REQUIRED_QUERY.sort().toString()
         !== Object.keys(query).sort().toString()) {
        ctx.throw(400, 'Bad Request');
      }
    } catch (e) {
      ctx.throw(400, 'Bad Request');
    }
    for(key in query) {
      val = query[key];
      if(val == null || val == '') {
        ctx.throw(400, 'Bad Request');
      }
    }
  }

  assertQuery(this, this.request.query);

  for(i = 0; i < NUM_LGTMS; i++) {
    lgtmReqs.push(request({
      json: true
      , url: 'http://www.lgtm.in/g'
    }));
  }

  ret = yield lgtmReqs;

  ret.forEach(function(_ret) { lgtms.push(_ret[1]); });

  yield this.render('index', {
    lgtms: lgtms
    , query: this.request.query
    , csrfToken: this.csrf
  });
});

app.post('/lgtm/create', client.requireAuth(function *(next) {
  var ret
  , lgtm = yield parse(this)
  ;

  this.assertCsrf(lgtm);

  ret = yield Q.denodeify(this.github.issues.createComment)({
    user: lgtm.user
    , repo: lgtm.repo
    , number: lgtm.number
    , body: lgtmMarkdown(lgtm.hash)
  }).then(function(comments) {
    return comments;
  });

  this.body = util.inspect(ret);
}));

app.listen(port);
<commit_msg>assert params<commit_after>'use strict';

var util = require('util')
, koa = require('koa')
, common = require('koa-common')
, router = require('koa-router')
, views = require('co-views')
, parse = require('co-body')
, Q = require('q')
, request = Q.denodeify(require('request'))
, port = process.env.PORT || 3000
, app = koa()
, csrf = require('koa-csrf')
, key = process.env.APP_KEY || 'im a secret'
, Client = require('github-api-client')
, client
, lgtmMarkdown = function(hash) {
  return '![LGTM](http://www.lgtm.in/p/' + hash + ')';
}
;

app.use(common.logger());
app.keys = [key];
app.use(common.session());
csrf(app);
app.use(function *(next) {
  var _render = views('views', { default: 'jade' });
  this.render = function (view, locals) {
    var body, html
    ;

    if (!locals) locals = {};

    return function *() {
      this.type = 'text/html';
      body = yield _render(view, locals);
      html = yield _render('layout', { body: body });
      this.body = html;
    }
  }

  yield next;
});
app.use(router(app));

client = new Client(app);

app.get('/', function *(next) {
  this.body = 'hello';
});

function assertParams(ctx, params, required) {
  var key, val
  ;
  try {
    if(required.sort().toString()
       !== Object.keys(params).sort().toString()) {
      ctx.throw(400, 'Bad Request');
    }
  } catch (e) {
    ctx.throw(400, 'Bad Request');
  }
  for(key in params) {
    val = params[key];
    if(val == null || val == '') {
      ctx.throw(400, 'Bad Request');
    }
  }
}

app.get('/lgtm', function *(next) {
  var NUM_LGTMS = 3
  , ret
  , lgtmReqs = []
  , lgtms = []
  , i
  ;

  assertParams(this, this.request.query, ['user', 'repo', 'number']);

  for(i = 0; i < NUM_LGTMS; i++) {
    lgtmReqs.push(request({
      json: true
      , url: 'http://www.lgtm.in/g'
    }));
  }

  ret = yield lgtmReqs;

  ret.forEach(function(_ret) { lgtms.push(_ret[1]); });

  yield this.render('index', {
    lgtms: lgtms
    , query: this.request.query
    , csrfToken: this.csrf
  });
});

app.post('/lgtm/create', client.requireAuth(function *(next) {
  var ret
  , lgtm = yield parse(this)
  ;

  this.assertCsrf(lgtm);
  delete lgtm._csrf;
  assertParams(this, lgtm, ['user', 'repo', 'number', 'hash']);

  ret = yield Q.denodeify(this.github.issues.createComment)({
    user: lgtm.user
    , repo: lgtm.repo
    , number: lgtm.number
    , body: lgtmMarkdown(lgtm.hash)
  }).then(function(comments) {
    return comments;
  });

  this.body = util.inspect(ret);
}));

app.listen(port);
<|endoftext|>


<commit_before>'use strict';

function Literal(str) { this.str = str; }
Literal.prototype.render = function* (data) { yield this.str; }

function Interpolation(path, verbatim) {
	this.path = path;
	this.verbatim = verbatim;
}

function resolve(data, path) {
	if (!data) return;
	if (path.length === 0) return data;
	else return resolve(data[path[0]], path.slice(1));
}

function stringify(value) {
	return "" + (value || "");
}

Interpolation.prototype.render = function* (data) {
	const resolved = stringify(resolve(data, this.path));
	if (this.verbatim) yield resolved;
	else yield* escape(resolved);
}

function* escape(str) {
	var i = 0;
	while (i < str.length) {
		var j = str.slice(i).search(/[&<>"']/) + i;
		if (j === -1) {
			yield str.slice(i);
			return;
		}
		if (j !== i) yield str.slice(i, j);
		switch (str[j]) {
			case '&': yield '&'; break;
			case '<': yield '<'; break;
			case '>': yield '>'; break;
			case '"': yield '"'; break;
			case "'": yield '''; break;
		}
		i = j+1;
	}
}

function* parse(str) {
	var openDelimiter = '{{';
	var closeDelimiter = '}}';

	var i = 0;
	while (i < str.length) {
		const openPos = str.indexOf(openDelimiter, i);

		if (openPos === -1) {
			yield new Literal(str.slice(i));
			break;
		}

		if (openPos > i) {
			yield new Literal(str.slice(i, openPos));
		}

		i = openPos + openDelimiter.length;

		if (i >= str.length) throw new Error("Mustache tag opened without being closed");

		var expectedCloseDelimiter = closeDelimiter;

		var fn = str[i];

		switch (str[i]) {
		case '{': expectedCloseDelimiter = '}' + closeDelimiter; break;
		case '=': expectedCloseDelimiter = '=' + closeDelimiter; break;
		}

		if (fn.match(/[{&=<#/]/)) i++;
		else fn = '';

		const closePos = str.indexOf(expectedCloseDelimiter, i);
		if (closePos === -1) throw new Error("Mustache tag opened without being closed");

		const tagContents = str.slice(i, closePos).trim();

		switch (fn) {
		case '': yield new Interpolation(tagContents.split('.')); break;
		case '{':
		case '&':
			yield new Interpolation(tagContents.split('.'), true); break;
		case '=':
			const delimiters = tagContents.split(/\s+/);
			if (delimiters.length !== 2) throw new Error(`Invalid delimiter specification: ${JSON.stringify(tagContents)}`);
			openDelimiter = delimiters[0];
			closeDelimiter = delimiters[1];
			break;
		}

		i = closePos + expectedCloseDelimiter.length;
	}
}

function* generate(template, data) {
	for (var x = template.next(); !x.done; x = template.next()) {
		yield* x.value.render(data);
	}
}

function render(template, data) {
	var g = generate(parse(template), data);

	var bufs = [];
	for (var x = g.next(); !x.done; x = g.next()) {
		bufs.push(x.value);
	}

	return bufs.join('');
}

module.exports = {
	parse,
	render
};
<commit_msg>Refactor to return AST from parse function to allow control structures (mustache sections)<commit_after>'use strict';

function resolve(data, path) {
	if (!data) return;
	if (path.length === 0) return data;
	else return resolve(data[path[0]], path.slice(1));
}

function stringify(value) {
	return "" + (value || "");
}

function Literal(str) { this.str = str; }
Literal.prototype.render = function* (data) { yield this.str; }

function Interpolation(path, verbatim) {
	this.path = path;
	this.verbatim = verbatim;
}

Interpolation.prototype.render = function* (data) {
	const resolved = stringify(resolve(data, this.path));
	if (this.verbatim) yield resolved;
	else yield* escape(resolved);
}

function Sequence(seq) { this.seq = seq; }

Sequence.prototype.render = function* (data) {
	for (var i = 0; i < this.seq.length; ++i) {
		yield* this.seq[i].render(data);
	}
};

function* escape(str) {
	var i = 0;
	while (i < str.length) {
		var j = str.slice(i).search(/[&<>"']/);
		if (j === -1) {
			yield str.slice(i);
			return;
		}
		j += i;
		if (j !== i) yield str.slice(i, j);
		switch (str[j]) {
			case '&': yield '&'; break;
			case '<': yield '<'; break;
			case '>': yield '>'; break;
			case '"': yield '"'; break;
			case "'": yield '''; break;
		}
		i = j+1;
	}
}

function getSequence(ctx, str) {
	var i = 0;
	var seq = [];

	while (i < str.length) {
		const openPos = str.indexOf(ctx.openDelimiter, i);

		if (openPos === -1) {
			seq.push(new Literal(str.slice(i)));
			break;
		}

		if (openPos > i) {
			seq.push(new Literal(str.slice(i, openPos)));
		}

		i = openPos + ctx.openDelimiter.length;

		if (i >= str.length) throw new Error("Mustache tag opened without being closed");

		var expectedCloseDelimiter = ctx.closeDelimiter;

		var fn = str[i];

		switch (str[i]) {
		case '{': expectedCloseDelimiter = '}' + ctx.closeDelimiter; break;
		case '=': expectedCloseDelimiter = '=' + ctx.closeDelimiter; break;
		}

		if (fn.match(/[{&=<#/]/)) i++;
		else fn = '';

		const closePos = str.indexOf(expectedCloseDelimiter, i);
		if (closePos === -1) throw new Error("Mustache tag opened without being closed");

		const tagContents = str.slice(i, closePos).trim();

		switch (fn) {
		case '': seq.push(new Interpolation(tagContents.split('.'))); break;
		case '{':
		case '&':
			seq.push(new Interpolation(tagContents.split('.'), true)); break;
		case '=':
			const delimiters = tagContents.split(/\s+/);
			if (delimiters.length !== 2) throw new Error(`Invalid delimiter specification: ${JSON.stringify(tagContents)}`);
			ctx.openDelimiter = delimiters[0];
			ctx.closeDelimiter = delimiters[1];
			break;
		}

		i = closePos + expectedCloseDelimiter.length;
	}

	return new Sequence(seq);
}

function parse(str) {
	const ctx = {
		openDelimiter: '{{',
		closeDelimiter: '}}'
	};

	return getSequence(ctx, str);
}

function render(template, data) {
	var g = parse(template).render(data);

	var bufs = [];
	for (var x = g.next(); !x.done; x = g.next()) {
		bufs.push(x.value);
	}

	return bufs.join('');
}

module.exports = {
	render
};
<|endoftext|>


<commit_before>'use strict';

import React, { Component, PropTypes } from 'react';
import { Image, Platform, Dimensions } from 'react-native';

const IMG_CENTER_MODE = Platform.OS === 'ios' ? 'center' : 'contain';

class Ikon extends Component {

  constructor(props) {
    super(props);

    const {disabled, name, style} = props;

    this.iconSet = __iconSet;

    const resizeMode = props.resizeMode ? props.resizeMode : this.traverseIconSet(name, 'resizeMode');
    const autoScale = props.autoScale ? props.autoScale : this.traverseIconSet(name, 'autoScale');

    const doScale = (value) => {
      return autoScale ? Ikon.__normalize(value) : value;
    }

    const width = doScale( props.width ? props.width : this.traverseIconSet(name, 'width') );
    const height = doScale( props.height ? props.height : this.traverseIconSet(name, 'height') );
    const source = props.source ? props.source : this.traverseIconSet(name, 'source');

    let _style = style ? style : {};
    _style = [..._style, {width, height}];

    if(!!disabled) {
      let disabledStyle = this.traverseIconSet(name, '$disabled')
      if(!disabledStyle) {
        disabledStyle = {opacity: 0.5};
      }
      _style = [..._style, disabledStyle];
    }

    this.state = {
        style: _style,
        resizeMode: resizeMode ? resizeMode : IMG_CENTER_MODE,
        width,
        height,
        source
    }
  }

  // register an IconSet
  static registerIconSet(iconSet) {
      __iconSet = iconSet;
  }

  render() {
    return (
      <Image resizeMode={this.state.resizeMode} width={this.state.width} height={this.state.height}
            source={this.state.source} style={this.state.style}>
      </Image>
    )
  }

  // try to find a value while traversing up the iconSet structure
  traverseIconSet(name, property) {
    let obj = Ikon.__resolvePropertyByKey(this.iconSet, name);
    while(obj) {
      if(obj[property]) {
        return obj[property];
      }

      const p = name.lastIndexOf('.');
      if(!p) return null;
      name = name.substr(0, p);
      obj = Ikon.__resolvePropertyByKey(this.iconSet, name);
    }
    return null;
  }

  // traverse down a nested object to resolve the 'path'
  static __resolvePropertyByKey(obj, path) {
      return path.split('.').reduce(function(prev, curr) {
          return prev ? prev[curr] : undefined
      }, obj)
  }

  static __normalize(value : number) {
    return Math.round(__scale * value);
  }

}

const __scale = Dimensions ? Dimensions.get('window').width / 375 : 1;

// global iconSet
// assign your personal IconSet with Ikon.registerIconSet()
let __iconSet = null;

Ikon.propTypes = {
  name: PropTypes.string.isRequired,
  style: PropTypes.object,
  resizeMode: PropTypes.string,
  autoScale: PropTypes.boolean,
}

Ikon.defaultProps = {
}

module.exports = Ikon;
<commit_msg>Fixed wrong PropType for autoScale<commit_after>'use strict';

import React, { Component, PropTypes } from 'react';
import { Image, Platform, Dimensions } from 'react-native';

const IMG_CENTER_MODE = Platform.OS === 'ios' ? 'center' : 'contain';

class Ikon extends Component {

  constructor(props) {
    super(props);

    const {disabled, name, style} = props;

    this.iconSet = __iconSet;

    const resizeMode = props.resizeMode ? props.resizeMode : this.traverseIconSet(name, 'resizeMode');
    const autoScale = props.autoScale ? props.autoScale : this.traverseIconSet(name, 'autoScale');

    const doScale = (value) => {
      return autoScale ? Ikon.__normalize(value) : value;
    }

    const width = doScale( props.width ? props.width : this.traverseIconSet(name, 'width') );
    const height = doScale( props.height ? props.height : this.traverseIconSet(name, 'height') );
    const source = props.source ? props.source : this.traverseIconSet(name, 'source');

    let _style = style ? style : {};
    _style = [..._style, {width, height}];

    if(!!disabled) {
      let disabledStyle = this.traverseIconSet(name, '$disabled')
      if(!disabledStyle) {
        disabledStyle = {opacity: 0.5};
      }
      _style = [..._style, disabledStyle];
    }

    this.state = {
        style: _style,
        resizeMode: resizeMode ? resizeMode : IMG_CENTER_MODE,
        width,
        height,
        source
    }
  }

  // register an IconSet
  static registerIconSet(iconSet) {
      __iconSet = iconSet;
  }

  render() {
    return (
      <Image resizeMode={this.state.resizeMode} width={this.state.width} height={this.state.height}
            source={this.state.source} style={this.state.style}>
      </Image>
    )
  }

  // try to find a value while traversing up the iconSet structure
  traverseIconSet(name, property) {
    let obj = Ikon.__resolvePropertyByKey(this.iconSet, name);
    while(obj) {
      if(obj[property]) {
        return obj[property];
      }

      const p = name.lastIndexOf('.');
      if(!p) return null;
      name = name.substr(0, p);
      obj = Ikon.__resolvePropertyByKey(this.iconSet, name);
    }
    return null;
  }

  // traverse down a nested object to resolve the 'path'
  static __resolvePropertyByKey(obj, path) {
      return path.split('.').reduce(function(prev, curr) {
          return prev ? prev[curr] : undefined
      }, obj)
  }

  static __normalize(value : number) {
    return Math.round(__scale * value);
  }

}

const __scale = Dimensions ? Dimensions.get('window').width / 375 : 1;

// global iconSet
// assign your personal IconSet with Ikon.registerIconSet()
let __iconSet = null;

Ikon.propTypes = {
  name: PropTypes.string.isRequired,
  style: PropTypes.object,
  resizeMode: PropTypes.string,
  autoScale: PropTypes.bool,
}

Ikon.defaultProps = {
}

module.exports = Ikon;
<|endoftext|>


<commit_before>pageflow.ConfigurationEditorView.register('audio_loop', {
  configure: function() {
    this.tab('general', function() {
      this.group('general');

      this.input('additional_title', pageflow.TextInputView);
      this.input('additional_description', pageflow.TextAreaInputView, {size: 'short'});
    });

    this.tab('files', function() {
      this.input('audio_file_id', pageflow.FileInputView, {collection: pageflow.audioFiles});
      this.input('background_image_id', pageflow.FileInputView, {collection: pageflow.imageFiles});
      this.input('thumbnail_image_id', pageflow.FileInputView, {
        collection: pageflow.imageFiles,
        positioning: false
      });
    });

    this.tab('options', function() {
      this.group('options');
    });
  }
});<commit_msg>Remove Additional Info Box Fields for Audio Loop Page<commit_after>pageflow.ConfigurationEditorView.register('audio_loop', {
  configure: function() {
    this.tab('general', function() {
      this.group('general');
    });

    this.tab('files', function() {
      this.input('audio_file_id', pageflow.FileInputView, {collection: pageflow.audioFiles});
      this.input('background_image_id', pageflow.FileInputView, {collection: pageflow.imageFiles});
      this.input('thumbnail_image_id', pageflow.FileInputView, {
        collection: pageflow.imageFiles,
        positioning: false
      });
    });

    this.tab('options', function() {
      this.group('options');
    });
  }
});<|endoftext|>


<commit_before>var Bloom = require('bloom-lite');
var showmemory = require('showmemory');
var jschardet = require('jschardet');
var iconv = require('iconv-lite');
var htmlparser = require('htmlparser2');
var http = require('http');
var url = require('url');
showmemory();

var PORTAL = "http://www.jd.com";
var bloom = new Bloom();
var urls = [];
var options = {};
var count = 0;
var INTERVAL = 100;
var buffers = [], buf, encoding;

var parser = new htmlparser.Parser({
	onopentag: function (name, attribs) {
		if(name === "a") {
			if(!bloom.exist(attribs.href)) {
				count++;
				if ( (count & 511) == 0) {
					console.log("total pages: %s, url: %s", count, attribs.href);
				}
				urls.push(attribs.href);
			}
		}
	}
});

var crawl = function (crawlURL) {
	if (!crawlURL) return process.exit(0);
	var parsedUrl = url.parse(crawlURL);
	if ("https:" === parsedUrl.protocol || !parsedUrl.protocol)
		return crawl(urls.pop());
	//extract url
	options.hostname = parsedUrl.hostname;
	options.path = parsedUrl.path;

	http.request(options, function (res) {
		res.on('data', function (chunk) {
			buffers.push(chunk);
		});

		res.on('end', function () {
			buf = buf = Buffer.concat(buffers);
			// console.log(jschardet.detect(buf));
			encoding = jschardet.detect(buf).encoding;
			body = iconv.decode(buf, encoding);
			parser.write(body);
			parser.end();
			console.log("url list length:", urls.length);
			setTimeout(function(){
				crawl(urls.pop());
			}, INTERVAL);
		});
	}).end();
};

crawl(PORTAL);

<commit_msg>fix process out of memory.<commit_after>'use strict';

var Bloom = require('bloom-lite');
var showmemory = require('showmemory');
var jschardet = require('jschardet');
var iconv = require('iconv-lite');
var htmlparser = require('htmlparser2');
var http = require('http');
var url = require('url');
showmemory();

var PORTAL = "http://www.jd.com";
var bloom = new Bloom();
var urls = [];
var options = {};
var count = 0;
// var INTERVAL = 100;
var buffers = [], buf, encoding, body;

var parser = new htmlparser.Parser({
	onopentag: function (name, attribs) {
		if(name === "a") {
			if(!bloom.exist(attribs.href)
				&& (url.parse(attribs.href).protocol != null)) {
				count++;
				if ( (count & 2047) == 0) {
					console.log("total pages: %s, url: %s", count, attribs.href);
				}
				urls.push(attribs.href);
			}
		}
	}
});

var crawl = function (crawlURL) {
	if (!crawlURL) return process.exit(0);
	var parsedUrl = url.parse(crawlURL);
	if ("https:" === parsedUrl.protocol || !parsedUrl.protocol)
		return crawl(urls.pop());
	//extract url
	options.hostname = parsedUrl.hostname;
	options.path = parsedUrl.path;

	http.request(options, function (res) {
		res.on('data', function (chunk) {
			buffers.push(chunk);
		});

		res.on('end', function () {
			buf = Buffer.concat(buffers);
			// console.log(jschardet.detect(buf));
			encoding = jschardet.detect(buf).encoding;
			body = iconv.decode(buf, encoding);
			parser.write(body);
			parser.end();
			console.log("url list length:", urls.length);
			buf = null;
			process.nextTick(function () {
				crawl(urls.pop());
			});
		});
	}).end();
};

crawl(PORTAL);

<|endoftext|>


<commit_before>/*jslint white:false plusplus:false browser:true nomen:false */
/*globals window, console, alert */
/* FuncyTag version 0.0.4 - see more at https://github.com/BrentNoorda/FuncyTag */

(function(window) {
    var gCamelToDashRegexp, gNextUniqueId, gUniqueLen, gNextIdChar, gInitQueue, gElems,
        gGCTimeout, gRenderTimeout, DEBUG = true;

    /*************** build tag ***************/

    gCamelToDashRegexp = new RegExp('([A-Z])','g');

    function camel_to_dash(camel)
    // turn upper characters to -c, for example, "cssBackgroundColor" becomes "css-background-color"
    {
        return camel.replace(gCamelToDashRegexp,function(match,c,offset,string){
                //alert("arguments.length = " + arguments.length + ' match='+match + ' c='+c+' offset='+offset+' string='+string);
                return '-' + c.toLowerCase();
            });
    }

    /*************** utility functions ***************/

    function is_array(o) {  // from http://web.archive.org/web/20100424091244/http://www.ajaxdr.com/code/javascript-version-of-phps-is_array-function/
        if((o !== null) && (typeof o === 'object')) {
            return (typeof o.push === 'undefined') ? false : true;
        }else {
            return false;
        }
    }

    function isPlainObj(o) { // from http://stackoverflow.com/questions/5876332/how-can-i-differentiate-between-an-object-literal-other-javascript-objects
        return (typeof o === 'object') && (o.constructor === Object)  && !('_ft_render_' in o);
    }

    /*************** tool to create a unique ID, forever, if one is not suppliedglobal event trackers ***************/

    gNextUniqueId = "";  // each time an id isn't supplied, and we need one, supply it here
    gUniqueLen = 0;
    gNextIdChar = 'a'; // will roll among all the characters of the alphabet

    function get_next_unique_id() {
        var ret = gNextUniqueId + gNextIdChar + '-ft-unq';

        function increment_root_string(len)
        {
            var ret = true, endChar;
            if ( len === 0 )
            {
                ret = false;
            }
            else
            {
                endChar = gNextUniqueId.charAt(len-1);
                if ( endChar === 'z' )
                {
                    endChar = 'a';
                    ret = increment_root_string(len-1);
                }
                else
                {
                    endChar = String.fromCharCode(endChar.charCodeAt(0)+1);
                }
                gNextUniqueId = gNextUniqueId.substring(0,len-1) + endChar;
            }
            return ret;
        }

        if ( gNextIdChar === 'z' )
        {
            // increment the root string
            if ( !increment_root_string(gUniqueLen) )
            {
                gUniqueLen++;
                gNextUniqueId += 'a';
            }
            gNextIdChar = 'a';
        }
        else
        {
            gNextIdChar = String.fromCharCode(gNextIdChar.charCodeAt(0)+1);
        }
        return ret;
    }

    /*************** global event/data trackers ***************/
    gInitQueue = { }; // elements waiting to initialize (via oninit), indexed by element id
    gElems = { }; // all elements we keep data about (indexed by id)
    gRenderTimeout = null;
    gGCTimeout = null; // timeout for when we're removing unused elements

    function next_oninit()
    {
        var id, elem, data, funcname, func, evHandler;
        gRenderTimeout = null;

        function event_handler_fn(func)
        {
            return function() {
                func();
            };
        }

        /*jslint forin:true */
        for ( id in gInitQueue )
        {
            elem = document.getElementById(id);
            if ( elem !== null )
            {
                data = gElems[id] = gInitQueue[id];
                delete gInitQueue[id];

                // add event listeners for all the funcs (except oninit and onterm)
                for ( funcname in data._funcs )
                {
                    if ( (funcname !== 'oninit') && (funcname !== 'onterm') )
                    {
                        func = data._funcs[funcname];

                        if (elem.addEventListener)
                        {
                            elem.addEventListener(funcname.substring(2), event_handler_fn(func), false);
                        }
                        else
                        {
                            elem.attachEvent(funcname, event_handler_fn(func));
                        }
                    }
                }

                if ( 'oninit' in data._funcs )
                {
                    data._funcs.oninit(id,data,elem);
                }
            }
        }
        /*jslint forin:false */

        // if there is still stuff to render, then call again real soon
        if ( gRenderTimeout === null )
        {
            /*jslint forin:true */
            for ( id in gInitQueue )
            {
                if ( DEBUG )
                {
                    console.log("RERENDER because something not ready yet");
                }
                gRenderTimeout = setTimeout(next_oninit,0);
            }
            /*jslint forin:false */
        }
    }

    function remove_elem(id,bodyunload)
    {
        var data = gElems[id];
        delete gElems[id];
        if ( 'onterm' in data._funcs )
        {
            data._funcs.onterm(id,data,bodyunload);
        }
    }

    function elem_GC()
    {
        var id, elem;

        gGCTimeout = null;

        /*jslint forin:true */
        for ( id in gElems )
        {
            elem = document.getElementById(id);
            if ( elem === null )
            {
                remove_elem(id,false);
            }
        }
        /*jslint forin:false */

        gGCTimeout = setTimeout(elem_GC,1000);
    }
    setTimeout(elem_GC,1000);

    function _attach_window_unload()
    {
        function unload()
        {
            var id;
            if ( gGCTimeout !== null )
            {
                clearTimeout(gGCTimeout);
                gGCTimeout = null;
            }

            /*jslint forin:true */
            for ( id in gElems )
            {
                remove_elem(id,true);
            }
            /*jslint forin:false */
        }

        if (window.addEventListener) { window.addEventListener('unload', unload, false); }
	    else { window.attachEvent("onunload", unload); }
    }
    _attach_window_unload();

    /*************** build tag ***************/

    function funcyTag(name_or_funcytag,default_attributes)
    {
        var name, tag, prop;

        try
        {
            if ( '_ft_name' in name_or_funcytag )
            {
                // if name_or_functytag is itself another funcytag, then inherit default attributes from that one
                name = name_or_funcytag._ft_name;
                if ( name_or_funcytag.default_attributes !== undefined )
                {
                    default_attributes = default_attributes || { };
                    /*jslint forin:true */
                    for ( prop in name_or_funcytag.default_attributes )
                    {
                        if ( !(prop in default_attributes) )
                        {
                            default_attributes[prop] = name_or_funcytag.default_attributes[prop];
                        }
                    }
                    /*jslint forin:false */
                }
            }
        } catch(e) {
            name = name_or_funcytag;
        }

        /*************** tag instance ***************/

        tag = function(attributes/*,inside1,inside2...*/) {
            var tagobj, argidx, inside, xprop, has_attr;
            has_attr = isPlainObj(attributes);
            tagobj = { _ft_name:name, _insides:[], _attributes: has_attr ? attributes :  {} };

            if ( default_attributes !== undefined )
            {
                // inherit default attributes, but let attributes override them
                tagobj._attributes = { };
                /*jslint forin:true */
                for ( xprop in default_attributes )
                {
                    tagobj._attributes[xprop] = default_attributes[xprop];
                }
                if ( has_attr )
                {
                    for ( xprop in attributes )
                    {
                        tagobj._attributes[xprop] = attributes[xprop];
                    }
                }
                /*jslint forin:false */
            }
            for ( argidx = has_attr ? 1 : 0; argidx < arguments.length; argidx++ )
            {
                inside = arguments[argidx];
                tagobj._insides.push(inside);
            }

            tagobj._ft_render_ = function(stringPadding) {
                var html, idx, jdx, content, inside, value, attr, units, style, innerHTML, first_, innerPadding, skipNextPadding,
                    data = null, funcs = { }, hasFuncs = false, id = null;

                // start tag and add all attributes, including decoding of styles
                style = '';
                html = '<' + this._ft_name;
                /*jslint forin:true */
                for ( attr in this._attributes )
                {
                    first_ = attr.indexOf('_'); // skip attributes that start with underscore
                    if ( first_ !== 0 )
                    {
                        value = this._attributes[attr];
                        if ( value !== undefined )  // if decodes as undefined then don't add this attribute
                        {
                            // sometimes there is a unit as part of the attr name
                            if ( -1 === first_ )
                            {
                                units = '';
                            }
                            else
                            {
                                jdx = attr.lastIndexOf('_');
                                units = attr.substring(jdx+1);
                                attr = attr.substring(0,jdx);
                                if ( units === 'pct') // because cannot have % be part of a name
                                {
                                    units = '%';
                                }
                            }

                            if ( attr === 'data' )
                            {
                                // adding the data object
                                data = value;
                            }
                            else if ( attr.substring(0,2) === 'on' )
                            {
                                // adding an on--- function
                                funcs[attr] = value;
                                hasFuncs = true;
                            }
                            else
                            {
                                if ( is_array(value) )
                                {
                                    // do not count any undefined values, so remove those from the array
                                    for ( jdx = 0; jdx < value.length; jdx++ )
                                    {
                                        if ( value[jdx] === undefined )
                                        {
                                            value.splice(jdx,1);
                                            jdx--;
                                        }
                                    }
                                    if ( value.length === 0 )
                                    {
                                        // no values in the array, so don't output this attribute
                                        continue;
                                    }
                                    // if value is an array, turn it into a space-delimited string
                                    value = value.join(units + ' ');
                                }
                                value += units;

                                if ( attr.substring(0,3) === 'css' )
                                {
                                    style += camel_to_dash(attr).substring(4) + ':' + value + ';';
                                }
                                else
                                {
                                    html += ' ' + attr + '="' + value + '"';
                                    if ( attr === 'id' )
                                    {
                                        id = value;
                                    }
                                }
                            }
                        }
                    }
                }
                /*jslint forin:false */

                if ( !this._attributes._nobrout )
                {
                    html = stringPadding + html;
                }

                if ( (stringPadding.length === 0) && !this._attributes._nobrin )
                {
                    stringPadding = '\r\n';
                }

                if ( style.length !== 0 )
                {
                    html += ' style="' + style + '"';
                }

                // for later callbacks, we may now need onfunctions, and data, and a unique id
                if ( hasFuncs )
                {
                    if ( data === null )
                    {
                        data = { };
                    }
                }
                if ( data !== null )
                {
                    data._funcs = funcs;
                    // need to have a unique id for this element, so create one if not there already
                    if ( id === null )
                    {
                        id = get_next_unique_id();
                        html += ' id="' + id + '"';
                    }
                    if ( DEBUG )
                    {
                        if ( id in gInitQueue )
                        {
                            alert('FuncyTags adding id "' + id + '" when previous "' + id + '" has not initialized yet.');
                        }
                    }
                    if ( id in gElems )
                    {
                        // id being reused, so remove existing instance of it
                        remove_elem(id,false);
                    }
                    gInitQueue[id] = data;
                    if ( gRenderTimeout === null )
                    {
                        gRenderTimeout = setTimeout(next_oninit,0);
                    }
                }

                innerHTML = '';
                innerPadding = this._attributes._nobrin ? '' : (stringPadding + '  ');
                skipNextPadding = false;
                for ( idx = 0; idx < this._insides.length; idx++ )
                {
                    inside = this._insides[idx];
                    if ( !is_array(inside) ) { inside = [inside]; }
                    for ( jdx = 0; jdx < inside.length; jdx++ )
                    {
                        content = inside[jdx];
                        if ( content !== undefined )
                        {
                            try {
                                innerHTML += content._ft_render_(skipNextPadding?'':innerPadding);
                                skipNextPadding = content._attributes._nobrout;
                            } catch(e) {
                                if ( !skipNextPadding )
                                {
                                    innerHTML += innerPadding;
                                }
                                else
                                {
                                    skipNextPadding = false;
                                }
                                innerHTML += String(content);
                            }
                        }
                    }
                }

                if ( (innerHTML.length === 0) && !(this._attributes._noslfcls) )
                {
                    html += '/>';
                }
                else
                {
                    html += '>' + innerHTML + ((this._attributes._nobrin) ? '' : stringPadding) + '</' + this._ft_name + '>';
                }

                return html;
            };

            tagobj.toString = function() { return this._ft_render_(''); };

            return tagobj;
        };
        tag._ft_name = name;
        tag.default_attributes = default_attributes;
        return tag;
    }

    /*************** initialize ***************/

    window.funcyTag = funcyTag;

    /*************** the "esc" feature ***************/

    window.funcyTag.esc = function( str )
    {
        return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
    };

    window.funcyTag.debugTrackers = function()
    {
        var id, count, ret = "FuncyTag debug trackers";

        ret += "\r\n\r\ngInitQueue items:\r\n";
        count = 0;
        /*jslint forin:true */
        for ( id in gInitQueue )
        {
            count++;
            ret += " " + id + "\r\n";
        }
        ret += "Total gInitQueue items: " + count + '\r\n';

        ret += "\r\n\r\ngElems items:\r\n";
        count = 0;
        for ( id in gElems )
        {
            count++;
            ret += " " + id + "\r\n";
        }
        ret += "Total gElems items: " + count + '\r\n';
        /*jslint forin:false */

        return ret;
    };

}(window));
<commit_msg>pass more to the onxxxx callbacks<commit_after>/*jslint white:false plusplus:false browser:true nomen:false */
/*globals window, console, alert */
/* FuncyTag version 0.0.4 - see more at https://github.com/BrentNoorda/FuncyTag */

(function(window) {
    var gCamelToDashRegexp, gNextUniqueId, gUniqueLen, gNextIdChar, gInitQueue, gElems,
        gGCTimeout, gRenderTimeout, DEBUG = true;

    /*************** build tag ***************/

    gCamelToDashRegexp = new RegExp('([A-Z])','g');

    function camel_to_dash(camel)
    // turn upper characters to -c, for example, "cssBackgroundColor" becomes "css-background-color"
    {
        return camel.replace(gCamelToDashRegexp,function(match,c,offset,string){
                //alert("arguments.length = " + arguments.length + ' match='+match + ' c='+c+' offset='+offset+' string='+string);
                return '-' + c.toLowerCase();
            });
    }

    /*************** utility functions ***************/

    function is_array(o) {  // from http://web.archive.org/web/20100424091244/http://www.ajaxdr.com/code/javascript-version-of-phps-is_array-function/
        if((o !== null) && (typeof o === 'object')) {
            return (typeof o.push === 'undefined') ? false : true;
        }else {
            return false;
        }
    }

    function isPlainObj(o) { // from http://stackoverflow.com/questions/5876332/how-can-i-differentiate-between-an-object-literal-other-javascript-objects
        return (typeof o === 'object') && (o.constructor === Object)  && !('_ft_render_' in o);
    }

    /*************** tool to create a unique ID, forever, if one is not suppliedglobal event trackers ***************/

    gNextUniqueId = "";  // each time an id isn't supplied, and we need one, supply it here
    gUniqueLen = 0;
    gNextIdChar = 'a'; // will roll among all the characters of the alphabet

    function get_next_unique_id() {
        var ret = gNextUniqueId + gNextIdChar + '-ft-unq';

        function increment_root_string(len)
        {
            var ret = true, endChar;
            if ( len === 0 )
            {
                ret = false;
            }
            else
            {
                endChar = gNextUniqueId.charAt(len-1);
                if ( endChar === 'z' )
                {
                    endChar = 'a';
                    ret = increment_root_string(len-1);
                }
                else
                {
                    endChar = String.fromCharCode(endChar.charCodeAt(0)+1);
                }
                gNextUniqueId = gNextUniqueId.substring(0,len-1) + endChar;
            }
            return ret;
        }

        if ( gNextIdChar === 'z' )
        {
            // increment the root string
            if ( !increment_root_string(gUniqueLen) )
            {
                gUniqueLen++;
                gNextUniqueId += 'a';
            }
            gNextIdChar = 'a';
        }
        else
        {
            gNextIdChar = String.fromCharCode(gNextIdChar.charCodeAt(0)+1);
        }
        return ret;
    }

    /*************** global event/data trackers ***************/
    gInitQueue = { }; // elements waiting to initialize (via oninit), indexed by element id
    gElems = { }; // all elements we keep data about (indexed by id)
    gRenderTimeout = null;
    gGCTimeout = null; // timeout for when we're removing unused elements

    function next_oninit()
    {
        var id, elem, data, funcname, func, evHandler;
        gRenderTimeout = null;

        function event_handler_fn(id,data,func)
        {
            return function(e) {
                func(id,data,document.getElementById(id),e || window.event);
            };
        }

        /*jslint forin:true */
        for ( id in gInitQueue )
        {
            elem = document.getElementById(id);
            if ( elem !== null )
            {
                data = gElems[id] = gInitQueue[id];
                delete gInitQueue[id];

                // add event listeners for all the funcs (except oninit and onterm)
                for ( funcname in data._funcs )
                {
                    if ( (funcname !== 'oninit') && (funcname !== 'onterm') )
                    {
                        func = data._funcs[funcname];

                        if (elem.addEventListener)
                        {
                            elem.addEventListener(funcname.substring(2), event_handler_fn(id,data,func), false);
                        }
                        else
                        {
                            elem.attachEvent(funcname, event_handler_fn(id,data,func));
                        }
                    }
                }

                if ( 'oninit' in data._funcs )
                {
                    data._funcs.oninit(id,data,elem);
                }
            }
        }
        /*jslint forin:false */

        // if there is still stuff to render, then call again real soon
        if ( gRenderTimeout === null )
        {
            /*jslint forin:true */
            for ( id in gInitQueue )
            {
                if ( DEBUG )
                {
                    console.log("RERENDER because something not ready yet");
                }
                gRenderTimeout = setTimeout(next_oninit,0);
            }
            /*jslint forin:false */
        }
    }

    function remove_elem(id,bodyunload)
    {
        var data = gElems[id];
        delete gElems[id];
        if ( 'onterm' in data._funcs )
        {
            data._funcs.onterm(id,data,bodyunload);
        }
    }

    function elem_GC()
    {
        var id, elem;

        gGCTimeout = null;

        /*jslint forin:true */
        for ( id in gElems )
        {
            elem = document.getElementById(id);
            if ( elem === null )
            {
                remove_elem(id,false);
            }
        }
        /*jslint forin:false */

        gGCTimeout = setTimeout(elem_GC,1000);
    }
    setTimeout(elem_GC,1000);

    function _attach_window_unload()
    {
        function unload()
        {
            var id;
            if ( gGCTimeout !== null )
            {
                clearTimeout(gGCTimeout);
                gGCTimeout = null;
            }

            /*jslint forin:true */
            for ( id in gElems )
            {
                remove_elem(id,true);
            }
            /*jslint forin:false */
        }

        if (window.addEventListener) { window.addEventListener('unload', unload, false); }
	    else { window.attachEvent("onunload", unload); }
    }
    _attach_window_unload();

    /*************** build tag ***************/

    function funcyTag(name_or_funcytag,default_attributes)
    {
        var name, tag, prop;

        try
        {
            if ( '_ft_name' in name_or_funcytag )
            {
                // if name_or_functytag is itself another funcytag, then inherit default attributes from that one
                name = name_or_funcytag._ft_name;
                if ( name_or_funcytag.default_attributes !== undefined )
                {
                    default_attributes = default_attributes || { };
                    /*jslint forin:true */
                    for ( prop in name_or_funcytag.default_attributes )
                    {
                        if ( !(prop in default_attributes) )
                        {
                            default_attributes[prop] = name_or_funcytag.default_attributes[prop];
                        }
                    }
                    /*jslint forin:false */
                }
            }
        } catch(e) {
            name = name_or_funcytag;
        }

        /*************** tag instance ***************/

        tag = function(attributes/*,inside1,inside2...*/) {
            var tagobj, argidx, inside, xprop, has_attr;
            has_attr = isPlainObj(attributes);
            tagobj = { _ft_name:name, _insides:[], _attributes: has_attr ? attributes :  {} };

            if ( default_attributes !== undefined )
            {
                // inherit default attributes, but let attributes override them
                tagobj._attributes = { };
                /*jslint forin:true */
                for ( xprop in default_attributes )
                {
                    tagobj._attributes[xprop] = default_attributes[xprop];
                }
                if ( has_attr )
                {
                    for ( xprop in attributes )
                    {
                        tagobj._attributes[xprop] = attributes[xprop];
                    }
                }
                /*jslint forin:false */
            }
            for ( argidx = has_attr ? 1 : 0; argidx < arguments.length; argidx++ )
            {
                inside = arguments[argidx];
                tagobj._insides.push(inside);
            }

            tagobj._ft_render_ = function(stringPadding) {
                var html, idx, jdx, content, inside, value, attr, units, style, innerHTML, first_, innerPadding, skipNextPadding,
                    data = null, funcs = { }, hasFuncs = false, id = null;

                // start tag and add all attributes, including decoding of styles
                style = '';
                html = '<' + this._ft_name;
                /*jslint forin:true */
                for ( attr in this._attributes )
                {
                    first_ = attr.indexOf('_'); // skip attributes that start with underscore
                    if ( first_ !== 0 )
                    {
                        value = this._attributes[attr];
                        if ( value !== undefined )  // if decodes as undefined then don't add this attribute
                        {
                            // sometimes there is a unit as part of the attr name
                            if ( -1 === first_ )
                            {
                                units = '';
                            }
                            else
                            {
                                jdx = attr.lastIndexOf('_');
                                units = attr.substring(jdx+1);
                                attr = attr.substring(0,jdx);
                                if ( units === 'pct') // because cannot have % be part of a name
                                {
                                    units = '%';
                                }
                            }

                            if ( attr === 'data' )
                            {
                                // adding the data object
                                data = value;
                            }
                            else if ( attr.substring(0,2) === 'on' )
                            {
                                // adding an on--- function
                                funcs[attr] = value;
                                hasFuncs = true;
                            }
                            else
                            {
                                if ( is_array(value) )
                                {
                                    // do not count any undefined values, so remove those from the array
                                    for ( jdx = 0; jdx < value.length; jdx++ )
                                    {
                                        if ( value[jdx] === undefined )
                                        {
                                            value.splice(jdx,1);
                                            jdx--;
                                        }
                                    }
                                    if ( value.length === 0 )
                                    {
                                        // no values in the array, so don't output this attribute
                                        continue;
                                    }
                                    // if value is an array, turn it into a space-delimited string
                                    value = value.join(units + ' ');
                                }
                                value += units;

                                if ( attr.substring(0,3) === 'css' )
                                {
                                    style += camel_to_dash(attr).substring(4) + ':' + value + ';';
                                }
                                else
                                {
                                    html += ' ' + attr + '="' + value + '"';
                                    if ( attr === 'id' )
                                    {
                                        id = value;
                                    }
                                }
                            }
                        }
                    }
                }
                /*jslint forin:false */

                if ( !this._attributes._nobrout )
                {
                    html = stringPadding + html;
                }

                if ( (stringPadding.length === 0) && !this._attributes._nobrin )
                {
                    stringPadding = '\r\n';
                }

                if ( style.length !== 0 )
                {
                    html += ' style="' + style + '"';
                }

                // for later callbacks, we may now need onfunctions, and data, and a unique id
                if ( hasFuncs )
                {
                    if ( data === null )
                    {
                        data = { };
                    }
                }
                if ( data !== null )
                {
                    data._funcs = funcs;
                    // need to have a unique id for this element, so create one if not there already
                    if ( id === null )
                    {
                        id = get_next_unique_id();
                        html += ' id="' + id + '"';
                    }
                    if ( DEBUG )
                    {
                        if ( id in gInitQueue )
                        {
                            alert('FuncyTags adding id "' + id + '" when previous "' + id + '" has not initialized yet.');
                        }
                    }
                    if ( id in gElems )
                    {
                        // id being reused, so remove existing instance of it
                        remove_elem(id,false);
                    }
                    gInitQueue[id] = data;
                    if ( gRenderTimeout === null )
                    {
                        gRenderTimeout = setTimeout(next_oninit,0);
                    }
                }

                innerHTML = '';
                innerPadding = this._attributes._nobrin ? '' : (stringPadding + '  ');
                skipNextPadding = false;
                for ( idx = 0; idx < this._insides.length; idx++ )
                {
                    inside = this._insides[idx];
                    if ( !is_array(inside) ) { inside = [inside]; }
                    for ( jdx = 0; jdx < inside.length; jdx++ )
                    {
                        content = inside[jdx];
                        if ( content !== undefined )
                        {
                            try {
                                innerHTML += content._ft_render_(skipNextPadding?'':innerPadding);
                                skipNextPadding = content._attributes._nobrout;
                            } catch(e) {
                                if ( !skipNextPadding )
                                {
                                    innerHTML += innerPadding;
                                }
                                else
                                {
                                    skipNextPadding = false;
                                }
                                innerHTML += String(content);
                            }
                        }
                    }
                }

                if ( (innerHTML.length === 0) && !(this._attributes._noslfcls) )
                {
                    html += '/>';
                }
                else
                {
                    html += '>' + innerHTML + ((this._attributes._nobrin) ? '' : stringPadding) + '</' + this._ft_name + '>';
                }

                return html;
            };

            tagobj.toString = function() { return this._ft_render_(''); };

            return tagobj;
        };
        tag._ft_name = name;
        tag.default_attributes = default_attributes;
        return tag;
    }

    /*************** initialize ***************/

    window.funcyTag = funcyTag;

    /*************** the "esc" feature ***************/

    window.funcyTag.esc = function( str )
    {
        return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
    };

    window.funcyTag.debugTrackers = function()
    {
        var id, count, ret = "FuncyTag debug trackers";

        ret += "\r\n\r\ngInitQueue items:\r\n";
        count = 0;
        /*jslint forin:true */
        for ( id in gInitQueue )
        {
            count++;
            ret += " " + id + "\r\n";
        }
        ret += "Total gInitQueue items: " + count + '\r\n';

        ret += "\r\n\r\ngElems items:\r\n";
        count = 0;
        for ( id in gElems )
        {
            count++;
            ret += " " + id + "\r\n";
        }
        ret += "Total gElems items: " + count + '\r\n';
        /*jslint forin:false */

        return ret;
    };

}(window));
<|endoftext|>


<commit_before>'use strict';

if (typeof window !== 'undefined' && typeof exports === 'undefined') {
    if (typeof window.utils !== 'object') {
        window.utils = {};
    }
}

if (typeof exports !== 'undefined') {
    var _ = require('underscore');
}

(function(exports) {
    //
    // Message Text Formatting
    //

    function trim(text) {
        return text.trim();
    }

    function mentions(text) {
        var mentionPattern = /\B@(\w+)(?!@)\b/g;
        return text.replace(mentionPattern, '@$1');
    }

    function roomLinks(text, extras, rooms) {
        var slugPattern = /\B(\#[a-z0-9_]+)\b/g;

        return text.replace(slugPattern, function(slug) {
            var s = slug.substring(1);
            var room = rooms.find(function(room) {
                return room.attributes.slug === s;
            });

            if (!room) {
                return slug;
            }

            return '' + slug + '';
        });
    }

    function links(text) {
        var imagePattern = /^\s*((https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;'"!()]*[-A-Z0-9+&@#\/%=~_|][.](jpe?g|png|gif))\s*$/i,
        linkPattern = /((https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;'"!()]*[-A-Z0-9+&@#\/%=~_|])/ig;

        if (imagePattern.test(text)) {
            return text.replace(imagePattern, function(url) {
                url = _.escape(url);
                return '';
            });
        } else {
            return text.replace(linkPattern, function(url) {
                url = _.escape(url);
                return '' + url + '';
            });
        }
    }

    function emotes(text, extras) {
        var regex = new RegExp('\\B(:[a-z0-9_\\+\\-]+:?)[\\b]?', 'ig');

        return text.replace(regex, function(group) {
            var key = group.split(':')[1];
            var emote = _.find(extras.emotes, function(emote) {
                return emote.emote === key;
            });

            if (!emote) {
                return group;
            }

            var image = _.escape(emote.image),
                emo = _.escape(':' + emote.emote + ':'),
                size = _.escape(emote.size || 20);

            return '';
        });
    }

    function replacements(text, extras) {
        _.each(extras.replacements, function(replacement) {
            text = text.replace(new RegExp(replacement.regex, 'ig'), replacement.template);
        });
        return text;
    }

    exports.format = function(text, extras, rooms) {
        var pipeline = [
            trim,
            mentions,
            roomLinks,
            links,
            emotes,
            replacements
        ];

        _.each(pipeline, function(func) {
            text = func(text, extras, rooms);
        });

        return text;
    };

})(typeof exports === 'undefined' ? window.utils.message = {} : exports);
<commit_msg>Skip formatting room links if no room collection is supplied.<commit_after>'use strict';

if (typeof window !== 'undefined' && typeof exports === 'undefined') {
    if (typeof window.utils !== 'object') {
        window.utils = {};
    }
}

if (typeof exports !== 'undefined') {
    var _ = require('underscore');
}

(function(exports) {
    //
    // Message Text Formatting
    //

    function trim(text) {
        return text.trim();
    }

    function mentions(text) {
        var mentionPattern = /\B@(\w+)(?!@)\b/g;
        return text.replace(mentionPattern, '@$1');
    }

    function roomLinks(text, extras, rooms) {
        if (!rooms) {
            return text;
        }

        var slugPattern = /\B(\#[a-z0-9_]+)\b/g;

        return text.replace(slugPattern, function(slug) {
            var s = slug.substring(1);
            var room = rooms.find(function(room) {
                return room.attributes.slug === s;
            });

            if (!room) {
                return slug;
            }

            return '' + slug + '';
        });
    }

    function links(text) {
        var imagePattern = /^\s*((https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;'"!()]*[-A-Z0-9+&@#\/%=~_|][.](jpe?g|png|gif))\s*$/i,
        linkPattern = /((https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;'"!()]*[-A-Z0-9+&@#\/%=~_|])/ig;

        if (imagePattern.test(text)) {
            return text.replace(imagePattern, function(url) {
                url = _.escape(url);
                return '';
            });
        } else {
            return text.replace(linkPattern, function(url) {
                url = _.escape(url);
                return '' + url + '';
            });
        }
    }

    function emotes(text, extras) {
        var regex = new RegExp('\\B(:[a-z0-9_\\+\\-]+:?)[\\b]?', 'ig');

        return text.replace(regex, function(group) {
            var key = group.split(':')[1];
            var emote = _.find(extras.emotes, function(emote) {
                return emote.emote === key;
            });

            if (!emote) {
                return group;
            }

            var image = _.escape(emote.image),
                emo = _.escape(':' + emote.emote + ':'),
                size = _.escape(emote.size || 20);

            return '';
        });
    }

    function replacements(text, extras) {
        _.each(extras.replacements, function(replacement) {
            text = text.replace(new RegExp(replacement.regex, 'ig'), replacement.template);
        });
        return text;
    }

    exports.format = function(text, extras, rooms) {
        var pipeline = [
            trim,
            mentions,
            roomLinks,
            links,
            emotes,
            replacements
        ];

        _.each(pipeline, function(func) {
            text = func(text, extras, rooms);
        });

        return text;
    };

})(typeof exports === 'undefined' ? window.utils.message = {} : exports);
<|endoftext|>


<commit_before>/*
  node-http-proxy.js: Lookup table for proxy targets in node.js

  Copyright (c) 2010 Charlie Robbins

  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

var util = require('util'),
    events = require('events'),
    fs = require('fs'),
    url = require('url');

//
// ### function ProxyTable (router, silent)
// #### @router {Object} Object containing the host based routes
// #### @silent {Boolean} Value indicating whether we should suppress logs
// #### @hostnameOnly {Boolean} Value indicating if we should route based on __hostname string only__
// #### @pathnameOnly {Boolean} Value indicating if we should route based on only the pathname.  __This causes hostnames to be ignored.__.  Using this along with hostnameOnly wont work at all.
// Constructor function for the ProxyTable responsible for getting
// locations of proxy targets based on ServerRequest headers; specifically
// the HTTP host header.
//
var ProxyTable = exports.ProxyTable = function (options) {
  events.EventEmitter.call(this);

  this.silent       = options.silent || options.silent !== true;
  this.target       = options.target || {};
  this.pathnameOnly = options.pathnameOnly === true;
  this.hostnameOnly = options.hostnameOnly === true;

  if (typeof options.router === 'object') {
    //
    // If we are passed an object literal setup
    // the routes with RegExps from the router
    //
    this.setRoutes(options.router);
  }
  else if (typeof options.router === 'string') {
    //
    // If we are passed a string then assume it is a
    // file path, parse that file and watch it for changes
    //
    var self = this;
    this.routeFile = options.router;
    this.setRoutes(JSON.parse(fs.readFileSync(options.router)).router);

    fs.watchFile(this.routeFile, function () {
      fs.readFile(self.routeFile, function (err, data) {
        if (err) {
          self.emit('error', err);
        }

        self.setRoutes(JSON.parse(data).router);
        self.emit('routes', self.hostnameOnly === false ? self.routes : self.router);
      });
    });
  }
  else {
    throw new Error('Cannot parse router with unknown type: ' + typeof router);
  }
};

//
// Inherit from `events.EventEmitter`
//
util.inherits(ProxyTable, events.EventEmitter);

//
// ### function setRoutes (router)
// #### @router {Object} Object containing the host based routes
// Sets the host-based routes to be used by this instance.
//
ProxyTable.prototype.setRoutes = function (router) {
  if (!router) {
    throw new Error('Cannot update ProxyTable routes without router.');
  }

  var self = this;
  this.router = router;

  if (this.hostnameOnly === false) {
    this.routes = [];

    Object.keys(router).forEach(function (path) {
      if (!/http[s]?/.test(router[path])) {
        router[path] = (self.target.https ? 'https://' : 'http://')
          + router[path];
      }

      var target = url.parse(router[path]),
          defaultPort = self.target.https ? 443 : 80;

      //
      // Setup a robust lookup table for the route:
      //
      //    {
      //      source: {
      //        regexp: /^foo.com/i,
      //        sref: 'foo.com',
      //        url: {
      //          protocol: 'http:',
      //          slashes: true,
      //          host: 'foo.com',
      //          hostname: 'foo.com',
      //          href: 'http://foo.com/',
      //          pathname: '/',
      //          path: '/'
      //        }
      //    },
      //    {
      //      target: {
      //        sref: '127.0.0.1:8000/',
      //        url: {
      //          protocol: 'http:',
      //          slashes: true,
      //          host: '127.0.0.1:8000',
      //          hostname: '127.0.0.1',
      //          href: 'http://127.0.0.1:8000/',
      //          pathname: '/',
      //          path: '/'
      //        }
      //    },
      //
      self.routes.push({
        source: {
          regexp: new RegExp('^' + path, 'i'),
          sref: path,
          url: url.parse('http://' + path)
        },
        target: {
          sref: target.hostname + ':' + (target.port || defaultPort) + target.path,
          url: target
        }
      });
    });
  }
};

//
// ### function getProxyLocation (req)
// #### @req {ServerRequest} The incoming server request to get proxy information about.
// Returns the proxy location based on the HTTP Headers in the  ServerRequest `req`
// available to this instance.
//
ProxyTable.prototype.getProxyLocation = function (req) {
  if (!req || !req.headers || !req.headers.host) {
    return null;
  }

  var targetHost = req.headers.host.split(':')[0];
  if (this.hostnameOnly === true) {
    var target = targetHost;
    if (this.router.hasOwnProperty(target)) {
      var location = this.router[target].split(':'),
          host = location[0],
          port = location.length === 1 ? 80 : location[1];

      return {
        port: port,
        host: host
      };
    }
  }
  else if (this.pathnameOnly === true) {
    var target = req.url;
    for (var i in this.routes) {
        var route = this.routes[i];
        if (target.match(route.source.regexp)) {
            req.url = url.format(target.replace(route.source.regexp, ''));
            return {
              protocol: route.target.url.protocol.replace(':', ''),
              host: route.target.url.hostname,
              port: route.target.url.port
                || (this.target.https ? 443 : 80)
            };
        }
    }

  }
  else {
    var target = targetHost + req.url;
    for (var i in this.routes) {
      var route = this.routes[i];
      if (target.match(route.source.regexp)) {
        //
        // Attempt to perform any path replacement for differences
        // between the source path and the target path. This replaces the
        // path's part of the URL to the target's part of the URL.
        //
        // 1. Parse the request URL
        // 2. Replace any portions of the source path with the target path
        // 3. Set the request URL to the formatted URL with replacements.
        //
        var parsed = url.parse(req.url);

        parsed.pathname = parsed.pathname.replace(
          route.source.url.pathname,
          route.target.url.pathname
        );

        req.url = url.format(parsed);

        return {
          protocol: route.target.url.protocol.replace(':', ''),
          host: route.target.url.hostname,
          port: route.target.url.port
            || (this.target.https ? 443 : 80)
        };
      }
    }
  }

  return null;
};

//
// ### close function ()
// Cleans up the event listeneners maintained
// by this instance.
//
ProxyTable.prototype.close = function () {
  if (typeof this.routeFile === 'string') {
    fs.unwatchFile(this.routeFile);
  }
};
<commit_msg>[doc] added comments to pathnameOnly block.<commit_after>/*
  node-http-proxy.js: Lookup table for proxy targets in node.js

  Copyright (c) 2010 Charlie Robbins

  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

var util = require('util'),
    events = require('events'),
    fs = require('fs'),
    url = require('url');

//
// ### function ProxyTable (router, silent)
// #### @router {Object} Object containing the host based routes
// #### @silent {Boolean} Value indicating whether we should suppress logs
// #### @hostnameOnly {Boolean} Value indicating if we should route based on __hostname string only__
// #### @pathnameOnly {Boolean} Value indicating if we should route based on only the pathname.  __This causes hostnames to be ignored.__.  Using this along with hostnameOnly wont work at all.
// Constructor function for the ProxyTable responsible for getting
// locations of proxy targets based on ServerRequest headers; specifically
// the HTTP host header.
//
var ProxyTable = exports.ProxyTable = function (options) {
  events.EventEmitter.call(this);

  this.silent       = options.silent || options.silent !== true;
  this.target       = options.target || {};
  this.pathnameOnly = options.pathnameOnly === true;
  this.hostnameOnly = options.hostnameOnly === true;

  if (typeof options.router === 'object') {
    //
    // If we are passed an object literal setup
    // the routes with RegExps from the router
    //
    this.setRoutes(options.router);
  }
  else if (typeof options.router === 'string') {
    //
    // If we are passed a string then assume it is a
    // file path, parse that file and watch it for changes
    //
    var self = this;
    this.routeFile = options.router;
    this.setRoutes(JSON.parse(fs.readFileSync(options.router)).router);

    fs.watchFile(this.routeFile, function () {
      fs.readFile(self.routeFile, function (err, data) {
        if (err) {
          self.emit('error', err);
        }

        self.setRoutes(JSON.parse(data).router);
        self.emit('routes', self.hostnameOnly === false ? self.routes : self.router);
      });
    });
  }
  else {
    throw new Error('Cannot parse router with unknown type: ' + typeof router);
  }
};

//
// Inherit from `events.EventEmitter`
//
util.inherits(ProxyTable, events.EventEmitter);

//
// ### function setRoutes (router)
// #### @router {Object} Object containing the host based routes
// Sets the host-based routes to be used by this instance.
//
ProxyTable.prototype.setRoutes = function (router) {
  if (!router) {
    throw new Error('Cannot update ProxyTable routes without router.');
  }

  var self = this;
  this.router = router;

  if (this.hostnameOnly === false) {
    this.routes = [];

    Object.keys(router).forEach(function (path) {
      if (!/http[s]?/.test(router[path])) {
        router[path] = (self.target.https ? 'https://' : 'http://')
          + router[path];
      }

      var target = url.parse(router[path]),
          defaultPort = self.target.https ? 443 : 80;

      //
      // Setup a robust lookup table for the route:
      //
      //    {
      //      source: {
      //        regexp: /^foo.com/i,
      //        sref: 'foo.com',
      //        url: {
      //          protocol: 'http:',
      //          slashes: true,
      //          host: 'foo.com',
      //          hostname: 'foo.com',
      //          href: 'http://foo.com/',
      //          pathname: '/',
      //          path: '/'
      //        }
      //    },
      //    {
      //      target: {
      //        sref: '127.0.0.1:8000/',
      //        url: {
      //          protocol: 'http:',
      //          slashes: true,
      //          host: '127.0.0.1:8000',
      //          hostname: '127.0.0.1',
      //          href: 'http://127.0.0.1:8000/',
      //          pathname: '/',
      //          path: '/'
      //        }
      //    },
      //
      self.routes.push({
        source: {
          regexp: new RegExp('^' + path, 'i'),
          sref: path,
          url: url.parse('http://' + path)
        },
        target: {
          sref: target.hostname + ':' + (target.port || defaultPort) + target.path,
          url: target
        }
      });
    });
  }
};

//
// ### function getProxyLocation (req)
// #### @req {ServerRequest} The incoming server request to get proxy information about.
// Returns the proxy location based on the HTTP Headers in the  ServerRequest `req`
// available to this instance.
//
ProxyTable.prototype.getProxyLocation = function (req) {
  if (!req || !req.headers || !req.headers.host) {
    return null;
  }

  var targetHost = req.headers.host.split(':')[0];
  if (this.hostnameOnly === true) {
    var target = targetHost;
    if (this.router.hasOwnProperty(target)) {
      var location = this.router[target].split(':'),
          host = location[0],
          port = location.length === 1 ? 80 : location[1];

      return {
        port: port,
        host: host
      };
    }
  }
  else if (this.pathnameOnly === true) {
    var target = req.url;
    for (var i in this.routes) {
      var route = this.routes[i];
      //
      // If we are matching pathname only, we remove the matched pattern.
      //
      // IE /wiki/heartbeat
      // is redirected to
      // /heartbeat
      //
      // for the route "/wiki" : "127.0.0.1:8020"
      //
      if (target.match(route.source.regexp)) {
        req.url = url.format(target.replace(route.source.regexp, ''));
        return {
          protocol: route.target.url.protocol.replace(':', ''),
          host: route.target.url.hostname,
          port: route.target.url.port
            || (this.target.https ? 443 : 80)
        };
      }
    }

  }
  else {
    var target = targetHost + req.url;
    for (var i in this.routes) {
      var route = this.routes[i];
      if (target.match(route.source.regexp)) {
        //
        // Attempt to perform any path replacement for differences
        // between the source path and the target path. This replaces the
        // path's part of the URL to the target's part of the URL.
        //
        // 1. Parse the request URL
        // 2. Replace any portions of the source path with the target path
        // 3. Set the request URL to the formatted URL with replacements.
        //
        var parsed = url.parse(req.url);

        parsed.pathname = parsed.pathname.replace(
          route.source.url.pathname,
          route.target.url.pathname
        );

        req.url = url.format(parsed);

        return {
          protocol: route.target.url.protocol.replace(':', ''),
          host: route.target.url.hostname,
          port: route.target.url.port
            || (this.target.https ? 443 : 80)
        };
      }
    }
  }

  return null;
};

//
// ### close function ()
// Cleans up the event listeneners maintained
// by this instance.
//
ProxyTable.prototype.close = function () {
  if (typeof this.routeFile === 'string') {
    fs.unwatchFile(this.routeFile);
  }
};
<|endoftext|>


<commit_before>'use strict';

let angular = require('angular');

module.exports = angular.module('spinnaker.core.pipeline.trigger.docker', [
    require('../../../../../core/config/settings.js'),
  ])
  .config(function (pipelineConfigProvider) {
    pipelineConfigProvider.registerTrigger({
      label: 'Docker',
      description: 'Executes the pipeline on an image update',
      key: 'docker',
      controller: 'DockerTriggerCtrl as ctrl',
      controllerAs: 'vm',
      templateUrl: require('./dockerTrigger.html'),
      popoverLabelUrl: require('./dockerPopoverLabel.html'),
    });
  })
  .controller('DockerTriggerCtrl', function (trigger, $scope, Restangular) {
    $scope.viewState = {
      imagesLoaded: false,
      imagesRefreshing: false,
    };

    function loadImages() {
      return Restangular.all('images/find').getList({ provider: 'dockerRegistry' }, {}).then(function(results) {
          return results;
        },
        function() {
          return [];
        });
    }

    function updateOrganizationsList() {
      if (!$scope.accountMap) {
        return;
      }
      trigger.registry = $scope.registryMap[trigger.account];
      $scope.organizations = $scope.accountMap[trigger.account] || [];
      if ($scope.organizations.indexOf(trigger.organization) < 0) {
        trigger.organization = null;
      }
      updateRepositoryList();
    }

    function updateRepositoryList() {
      if (!$scope.organizationMap) {
        return;
      }
      let key = `${trigger.account}/${trigger.organization || '' }`;
      $scope.repositories = $scope.organizationMap[key] || [];
      if ($scope.repositories.indexOf(trigger.repository) < 0) {
        trigger.repository = null;
      }
      updateTag();
    }

    function updateTag() {
      if (trigger.tag !== null && trigger.tag.trim() === '') {
        trigger.tag = null;
      }
    }

    function initializeImages() {
      loadImages().then(function (images) {
        $scope.images = images;
        $scope.registryMap = images.reduce((map, image) => {
          map[image.account] = image.registry;
          return map;
        }, {});
        $scope.accountMap = images.reduce((map, image) => {
          let key = image.account;
          if (!key) {
            return map;
          }
          let all = map[key] || [];
          let parts = image.repository.split('/');
          parts.pop();
          let org = parts.join('/');
          if (all.indexOf(org) < 0) {
            map[key] = all.concat(org);
          }
          return map;
        }, {});
        $scope.accounts = Object.keys($scope.accountMap);
        $scope.organizationMap = images.reduce((map, image) => {
          let parts = image.repository.split('/');
          parts.pop();
          let key = `${image.account}/${parts.join('/')}`;
          let all = map[key] || [];
          if (all.indexOf(image.repository) < 0) {
            map[key] = all.concat(image.repository);
          }
          return map;
        }, {});
        $scope.organizations = Object.keys($scope.organizationMap);
        updateOrganizationsList();

        $scope.viewState.imagesLoaded = true;
        $scope.viewState.imagesRefreshing = false;
      });
    }

    this.refreshImages = function() {
      $scope.viewState.imagesRefreshing = true;
      initializeImages();
    };

    initializeImages();

    $scope.$watch('trigger.account', updateOrganizationsList);
    $scope.$watch('trigger.organization', updateRepositoryList);
    $scope.$watch('trigger.tag', updateTag);

  });
<commit_msg>Revert "provider/kubernetes: Fix docker trigger" (#2360)<commit_after>'use strict';

let angular = require('angular');

module.exports = angular.module('spinnaker.core.pipeline.trigger.docker', [
    require('../../../../../core/config/settings.js'),
  ])
  .config(function (pipelineConfigProvider) {
    pipelineConfigProvider.registerTrigger({
      label: 'Docker',
      description: 'Executes the pipeline on an image update',
      key: 'docker',
      controller: 'DockerTriggerCtrl as ctrl',
      controllerAs: 'vm',
      templateUrl: require('./dockerTrigger.html'),
      popoverLabelUrl: require('./dockerPopoverLabel.html'),
    });
  })
  .controller('DockerTriggerCtrl', function (trigger, $scope, Restangular) {
    $scope.viewState = {
      imagesLoaded: false,
      imagesRefreshing: false,
    };

    function loadImages() {
      return Restangular.all('images/find').getList({ provider: 'dockerRegistry' }, {}).then(function(results) {
          return results;
        },
        function() {
          return [];
        });
    }

    function updateOrganizationsList() {
      if (!$scope.accountMap) {
        return;
      }
      $scope.organizations = $scope.accountMap[trigger.account] || [];
      if ($scope.organizations.indexOf(trigger.organization) < 0) {
        trigger.organization = null;
      }
      updateRepositoryList();
    }

    function updateRepositoryList() {
      if (!$scope.organizationMap) {
        return;
      }
      let key = `${trigger.account}/${trigger.organization || '' }`;
      $scope.repositories = $scope.organizationMap[key] || [];
      if ($scope.repositories.indexOf(trigger.repository) < 0) {
        trigger.repository = null;
      }
      updateTag();
    }

    function updateTag() {
      if (trigger.tag !== null && trigger.tag.trim() === '') {
        trigger.tag = null;
      }
    }

    function initializeImages() {
      loadImages().then(function (images) {
        $scope.images = images;
        $scope.accountMap = images.reduce((map, image) => {
          let key = image.account;
          if (!key) {
            return map;
          }
          let all = map[key] || [];
          let parts = image.repository.split('/');
          parts.pop();
          let org = parts.join('/');
          if (all.indexOf(org) < 0) {
            map[key] = all.concat(org);
          }
          return map;
        }, {});
        $scope.accounts = Object.keys($scope.accountMap);
        $scope.organizationMap = images.reduce((map, image) => {
          let parts = image.repository.split('/');
          parts.pop();
          let key = `${image.account}/${parts.join('/')}`;
          let all = map[key] || [];
          if (all.indexOf(image.repository) < 0) {
            map[key] = all.concat(image.repository);
          }
          return map;
        }, {});
        $scope.organizations = Object.keys($scope.organizationMap);
        updateOrganizationsList();

        $scope.viewState.imagesLoaded = true;
        $scope.viewState.imagesRefreshing = false;
      });
    }

    this.refreshImages = function() {
      $scope.viewState.imagesRefreshing = true;
      initializeImages();
    };

    initializeImages();

    $scope.$watch('trigger.account', updateOrganizationsList);
    $scope.$watch('trigger.organization', updateRepositoryList);
    $scope.$watch('trigger.tag', updateTag);

  });
<|endoftext|>