<commit_before>var Phase = require('html5/parser/phase').Phase;
var inBody = require('html5/parser/in_body_phase').Phase;

var start_tag_handlers = {
	html: 'startTagHtml',
	frameset: 'startTagFrameset',
	frame: 'startTagFrame',
	noframes: 'startTagNoFrames',
	"-default": 'startTagOther'
}

var end_tag_handlers = {
	frameset: 'endTagFrameset',
	noframes: 'endTagNoframes',
	'-default': 'endTagOther',
}

exports.Phase = p = function InFramesetPhase(parser, tree) {
	Phase.call(this, parser, tree);
	this.start_tag_handlers = start_tag_handlers;
	this.end_tag_handlers = end_tag_handlers;
}

p.prototype = new Phase;

p.prototype.processCharacters = function(data) {
	this.parse_error("unexpected-char-in-frameset");
}

p.prototype.startTagFrameset = function(name, attributes) {
	this.tree.insert_element(name, attributes);
}

p.prototype.startTagFrame = function(name, attributes) {
	this.tree.insert_element(name, attributes);
	this.tree.open_elements.pop();
}

p.prototype.startTagNoframes = function(name, attributes) {
	new inBody(this.parser, this.tree).processStartTag(name, attributes);
}

p.prototype.startTagOther = function(name, attributes) {
	this.parse_error("unexpected-start-tag-in-frameset", {name: name});
}

p.prototype.endTagFrameset = function(name, attributes) {
	if(this.tree.open_elements.last().tagName == 'html') {
		// inner_html case
		this.parse_error("unexpected-frameset-in-frameset-innerhtml");
	} else {
		this.tree.open_elements.pop();
	}

	if(!this.parser.inner_html && this.tree.open_elements.last().tagName != 'frameset') {
		// If we're not in inner_html mode an the current node is not a "frameset" element (anymore) then switch
		this.parser.newPhase('afterFrameset');
	}
}

p.prototype.endTagNoframes = function(name) {
	new inBody(this.parser, this.tree).processEndTag(name);
}

p.prototype.endTagOther = function(name) {
	this.parser_error("unexpected-end-tag-in-frameset", {name: name});
}
<commit_msg>- fix noframes in frameset<commit_after>var Phase = require('html5/parser/phase').Phase;
var inBody = require('html5/parser/in_body_phase').Phase;

var start_tag_handlers = {
	html: 'startTagHtml',
	frameset: 'startTagFrameset',
	frame: 'startTagFrame',
	noframes: 'startTagNoframes',
	"-default": 'startTagOther'
}

var end_tag_handlers = {
	frameset: 'endTagFrameset',
	noframes: 'endTagNoframes',
	'-default': 'endTagOther',
}

exports.Phase = p = function InFramesetPhase(parser, tree) {
	Phase.call(this, parser, tree);
	this.start_tag_handlers = start_tag_handlers;
	this.end_tag_handlers = end_tag_handlers;
}

p.prototype = new Phase;

p.prototype.processCharacters = function(data) {
	this.parse_error("unexpected-char-in-frameset");
}

p.prototype.startTagFrameset = function(name, attributes) {
	this.tree.insert_element(name, attributes);
}

p.prototype.startTagFrame = function(name, attributes) {
	this.tree.insert_element(name, attributes);
	this.tree.open_elements.pop();
}

p.prototype.startTagNoframes = function(name, attributes) {
	new inBody(this.parser, this.tree).processStartTag(name, attributes);
}

p.prototype.startTagOther = function(name, attributes) {
	this.parse_error("unexpected-start-tag-in-frameset", {name: name});
}

p.prototype.endTagFrameset = function(name, attributes) {
	if(this.tree.open_elements.last().tagName == 'html') {
		// inner_html case
		this.parse_error("unexpected-frameset-in-frameset-innerhtml");
	} else {
		this.tree.open_elements.pop();
	}

	if(!this.parser.inner_html && this.tree.open_elements.last().tagName != 'frameset') {
		// If we're not in inner_html mode an the current node is not a "frameset" element (anymore) then switch
		this.parser.newPhase('afterFrameset');
	}
}

p.prototype.endTagNoframes = function(name) {
	new inBody(this.parser, this.tree).processEndTag(name);
}

p.prototype.endTagOther = function(name) {
	this.parser_error("unexpected-end-tag-in-frameset", {name: name});
}
<|endoftext|>


<commit_before>const d3 = require('d3');
// FIXME: do we need the extended projections here?
const defaultProjection = 'mercator';
const relative = require('require-relative');

module.exports = function getPath(options) {
  var projection = options.projection;
  if (projection === 'null' || projection === null) {
    return null;
  } else if (typeof projection === 'string') {
    try {
      return relative(projection, process.cwd());
    } catch (error) {
      console.warn('no such module:', projection, error);
      projection = defaultProjection;
    }
  }
  return (typeof projection === 'function')
    ? projection
    : d3.geo[projection || defaultProjection]();
};
<commit_msg>call the projection<commit_after>const d3 = require('d3');
// FIXME: do we need the extended projections here?
const defaultProjection = 'mercator';
const relative = require('require-relative');

module.exports = function getPath(options) {
  var projection = options.projection;
  if (projection === 'null' || projection === null) {
    return null;
  } else if (typeof projection === 'string') {
    var name = projection;
    projection = relative(projection, process.cwd());
    if (typeof projection === 'function') {
      projection = projection();
    } else {
      throw new Error('projection "' + name + '" does not export a function');
    }
  }
  return (typeof projection === 'function')
    ? projection
    : d3.geo[projection || defaultProjection]();
};
<|endoftext|>


<commit_before>(function($) {

	function defaultHandler(endpoint, data, callback) {
		$.post(endpoint, data)
			.done(function () {
		    callback();
		  })
		  .fail(function () {
		    alert("Something went wrong :/");
		    callback(true);
		  });
	}

	$.dingdong = function(options) {

		// parse options
		var opts = {};
		if (options) {
			if ($.type(options) === "object") {
				opts = options;
			} else if ($.type(options) === "string") {
				opts.endpoint = options;
			} else if ($.type(options) === "function") {
				opts.handler = options;
			} else {
				console.error("dingdong argument should be object (options), string (custom endpoint), or function (custom handler) :/");
			}
		}

		// fade options
		var fade = opts.fade !== false;
		var fadeOpen = opts.openFadeDuration || 100;
		var fadeCancel = opts.cancelFadeDuration || 100;
		var fadeSubmit = opts.submitFadeDuration || 1000;

		// custom text options
		var buttonText = opts.buttonText = "Feedback";
		var emailPlaceholder = opts.emailPlaceholder || "Your email address";
		var messagePlaceholder = opts.messagePlaceholder || "Send us your feedback or report an issue";
		var submitButtonText = opts.submitButtonText || "Send message";
		var submittedText = opts.submittedText || "Thanks!";
		var subscribeButtonText = opts.subscribeButtonText || "Subscribe";
		var fnamePlaceholder = opts.fnamePlaceholder || "First name";
		var lnamePlaceholder = opts.lnamePlaceholder || "Last name";
		var subscribeLabel = opts.subscribeLabel || "Subscribe to newsletter";

		// misc
		var messageRows = opts.messageRows || 7;
		var escapeToCancel = opts.disableEscapeToCancel !== false;
		var endpoint = opts.endpoint || "/dingdong";

		// helper function for showing
		$.dingdongShow = function (mode) {
			$("#dingdong-submit").prop("disabled", false);
			$("#dingdong-submit").text(submitButtonText);
			$("#dingdong-message").val("");
			// intentionally dont clear email, fname, lname

			if (mode === "subscribeOnly") {
				$("#dingdong-subscribe").prop("checked", true);
				$("#dingdong-name-row").show();
				$("#dingdong-message-row").hide();
				$("#dingdong-submit").text(subscribeButtonText);
				$("#dingdong-fname").prop("required", true);
				$("#dingdong-lname").prop("required", true);
				$("#dingdong-message").prop("required", false);
			} else {
				$("#dingdong-subscribe").prop("checked", false);
				$("#dingdong-name-row").hide();
				$("#dingdong-message-row").show();
				$("#dingdong-submit").text(submitButtonText);
				$("#dingdong-fname").prop("required", false);
				$("#dingdong-lname").prop("required", false);
				$("#dingdong-message").prop("required", true);
			}

			if (mode === "subscribeOnly" || mode === "messageOnly") {
				$("#dingdong-subscribe-row").hide();
			} else {
				$("#dingdong-subscribe-row").show();
			}

			if (fade) {
				$("#dingdong").fadeIn(fadeOpen);
			} else {
				$("#dingdong").show();
			}
		}

		// helper function for canceling
		$.dingdongCancel = function () {
			if (fade) {
				$("#dingdong").fadeOut(fadeCancel);
			} else {
				$("#dingdong").hide();
			}
		}

		// helper function for hiding (aka after submit)
		$.dingdongHide = function () {
			if (fade) {
				$("#dingdong").fadeOut(fadeSubmit);
			} else {
				$("#dingdong").hide();
			}
			$("#dingdong-submit").text(submittedText);
		}

		// maybe build header option
		var header;
		if (opts.header) {
			header = [
				$("<div/>", { "class": "dingdong-row" }).append(
					$("<div/>", { id: "dingdong-header", html: opts.header })
				)
			];
		}

		// maybe build subscribe section
		var subscribe = [
			$("<div/>", { id: "dingdong-subscribe-row", "class": "dingdong-row" }).append(
				$("<label/>", { for: "dingdong-subscribe", text: subscribeLabel }).append(
					$("<span/>", { "class": "dingdong-switch" }).append(
						$("<input/>", { id: "dingdong-subscribe", name: "subscribe", type: "checkbox" }),
						$("<div/>", { "class": "dingdong-switch-slider" })
					)
				)
			),
			$("<div/>", { id: "dingdong-name-row", "class": "dingdong-row" }).append(
				$("<input/>", { id: "dingdong-fname", name: "fname", type: "text", placeholder: fnamePlaceholder, width: "50%" }),
				$("<input/>", { id: "dingdong-lname", name: "lname", type: "text", placeholder: lnamePlaceholder, width: "50%" })
			)
		];

		var message = [
			$("<div/>", { id: "dingdong-message-row", "class": "dingdong-row" }).append(
				$("<textarea/>", { id: "dingdong-message", name: "message", rows: messageRows, placeholder: messagePlaceholder, required: "required" })
			)
		];

		var email = [
			$("<div/>", { "class": "dingdong-row" }).append(
				$("<input/>", { id: "dingdong-email", name: "email", type: "email", placeholder: emailPlaceholder, required: "required" })
			)
		];

		var submit = [
			$("<button/>", { id: "dingdong-submit", type: "submit", text: submitButtonText })
		];

		// remove existing if $.dingdong has already been called
		$("#dingdong-button").remove();
		$("#dingdong").remove();

		// add dingdong button
		$("body").append(
			$("<button />", { id: "dingdong-button", style: "display: none", text: buttonText })
		);

		// add dingdong modal
		$("body").append(
			$("<div/>", { id: "dingdong", style: "display: none" }).append(
				$("<div/>", { id: "dingdong-box" }).append(
					$("<div/>", { id: "dingdong-close", text: "\u00D7" }),
					$("<form/>", { id: "dingdong-form" }).append(
						header,
						email,
						message,
						subscribe,
						submit
					)
				)
			)
		);

		// maybe listen for esc to cancel
		if (escapeToCancel) {
			$(document).keydown(function(e) {
		    if (e.keyCode == 27) {
		        $.dingdongCancel();
		    }
			});
		}

		// toggle name fields when subscribe checkbox changes
		$("#dingdong-subscribe").change(function () {
			var checked = $(this).is(":checked");
			if (checked) {
				$("#dingdong-name-row").slideDown();
			} else {
				$("#dingdong-name-row").slideUp();
			}
			$("#dingdong-fname").prop("required", checked);
			$("#dingdong-lname").prop("required", checked);
		});

		// show dingdong when button is clicked
		$("#dingdong-button").click(function () {
			$.dingdongShow();
		});

		// cancel dingdong when backdrop or close is clicked
		$("#dingdong, #dingdong-close").click(function () {
			$.dingdongCancel();
		});

		// prevent clicks inside the box from propagating
		// (otherwise any click inside will trigger above cancel)
		$("#dingdong-box").click(function (e) {
			e.stopPropagation();
		});

		// handle form submission (prevent default behavior since ajax)
		$("#dingdong-form").submit(function (e) {
			e.preventDefault();
			var data = {
				message: $("#dingdong-message").val(),
				email: $("#dingdong-email").val(),
				subscribe: $("#dingdong-subscribe").is(":checked"),
				fname: $("#dingdong-fname").val(),
				lname: $("#dingdong-lname").val()
			};
			function callback(err) {
				if (err) {
					$("#dingdong-submit").prop("disabled", false);
				} else {
					$.dingdongHide();
				}
			}
			$("#dingdong-submit").prop("disabled", true);
			if (opts.handler) {
				opts.handler(data, callback);
			} else {
				defaultHandler(opts.endpoint, data, callback);
			}
			return false;
		});

	}

}(jQuery));
<commit_msg>Fixed typo in options<commit_after>(function($) {

	function defaultHandler(endpoint, data, callback) {
		$.post(endpoint, data)
			.done(function () {
		    callback();
		  })
		  .fail(function () {
		    alert("Something went wrong :/");
		    callback(true);
		  });
	}

	$.dingdong = function(options) {

		// parse options
		var opts = {};
		if (options) {
			if ($.type(options) === "object") {
				opts = options;
			} else if ($.type(options) === "string") {
				opts.endpoint = options;
			} else if ($.type(options) === "function") {
				opts.handler = options;
			} else {
				console.error("dingdong argument should be object (options), string (custom endpoint), or function (custom handler) :/");
			}
		}

		// fade options
		var fade = opts.fade !== false;
		var fadeOpen = opts.openFadeDuration || 100;
		var fadeCancel = opts.cancelFadeDuration || 100;
		var fadeSubmit = opts.submitFadeDuration || 1000;

		// custom text options
		var buttonText = opts.buttonText = "Feedback";
		var emailPlaceholder = opts.emailPlaceholder || "Your email address";
		var messagePlaceholder = opts.messagePlaceholder || "Send us your feedback or report an issue";
		var submitButtonText = opts.submitButtonText || "Send message";
		var submittedText = opts.submittedText || "Thanks!";
		var subscribeButtonText = opts.subscribeButtonText || "Subscribe";
		var fnamePlaceholder = opts.fnamePlaceholder || "First name";
		var lnamePlaceholder = opts.lnamePlaceholder || "Last name";
		var subscribeLabel = opts.subscribeLabel || "Subscribe to newsletter";

		// misc
		var messageRows = opts.messageRows || 7;
		var escapeToCancel = opts.escapeToCancel !== false;
		var endpoint = opts.endpoint || "/dingdong";

		// helper function for showing
		$.dingdongShow = function (mode) {
			$("#dingdong-submit").prop("disabled", false);
			$("#dingdong-submit").text(submitButtonText);
			$("#dingdong-message").val("");
			// intentionally dont clear email, fname, lname

			if (mode === "subscribeOnly") {
				$("#dingdong-subscribe").prop("checked", true);
				$("#dingdong-name-row").show();
				$("#dingdong-message-row").hide();
				$("#dingdong-submit").text(subscribeButtonText);
				$("#dingdong-fname").prop("required", true);
				$("#dingdong-lname").prop("required", true);
				$("#dingdong-message").prop("required", false);
			} else {
				$("#dingdong-subscribe").prop("checked", false);
				$("#dingdong-name-row").hide();
				$("#dingdong-message-row").show();
				$("#dingdong-submit").text(submitButtonText);
				$("#dingdong-fname").prop("required", false);
				$("#dingdong-lname").prop("required", false);
				$("#dingdong-message").prop("required", true);
			}

			if (mode === "subscribeOnly" || mode === "messageOnly") {
				$("#dingdong-subscribe-row").hide();
			} else {
				$("#dingdong-subscribe-row").show();
			}

			if (fade) {
				$("#dingdong").fadeIn(fadeOpen);
			} else {
				$("#dingdong").show();
			}
		}

		// helper function for canceling
		$.dingdongCancel = function () {
			if (fade) {
				$("#dingdong").fadeOut(fadeCancel);
			} else {
				$("#dingdong").hide();
			}
		}

		// helper function for hiding (aka after submit)
		$.dingdongHide = function () {
			if (fade) {
				$("#dingdong").fadeOut(fadeSubmit);
			} else {
				$("#dingdong").hide();
			}
			$("#dingdong-submit").text(submittedText);
		}

		// maybe build header option
		var header;
		if (opts.header) {
			header = [
				$("<div/>", { "class": "dingdong-row" }).append(
					$("<div/>", { id: "dingdong-header", html: opts.header })
				)
			];
		}

		// maybe build subscribe section
		var subscribe = [
			$("<div/>", { id: "dingdong-subscribe-row", "class": "dingdong-row" }).append(
				$("<label/>", { for: "dingdong-subscribe", text: subscribeLabel }).append(
					$("<span/>", { "class": "dingdong-switch" }).append(
						$("<input/>", { id: "dingdong-subscribe", name: "subscribe", type: "checkbox" }),
						$("<div/>", { "class": "dingdong-switch-slider" })
					)
				)
			),
			$("<div/>", { id: "dingdong-name-row", "class": "dingdong-row" }).append(
				$("<input/>", { id: "dingdong-fname", name: "fname", type: "text", placeholder: fnamePlaceholder, width: "50%" }),
				$("<input/>", { id: "dingdong-lname", name: "lname", type: "text", placeholder: lnamePlaceholder, width: "50%" })
			)
		];

		var message = [
			$("<div/>", { id: "dingdong-message-row", "class": "dingdong-row" }).append(
				$("<textarea/>", { id: "dingdong-message", name: "message", rows: messageRows, placeholder: messagePlaceholder, required: "required" })
			)
		];

		var email = [
			$("<div/>", { "class": "dingdong-row" }).append(
				$("<input/>", { id: "dingdong-email", name: "email", type: "email", placeholder: emailPlaceholder, required: "required" })
			)
		];

		var submit = [
			$("<button/>", { id: "dingdong-submit", type: "submit", text: submitButtonText })
		];

		// remove existing if $.dingdong has already been called
		$("#dingdong-button").remove();
		$("#dingdong").remove();

		// add dingdong button
		$("body").append(
			$("<button />", { id: "dingdong-button", style: "display: none", text: buttonText })
		);

		// add dingdong modal
		$("body").append(
			$("<div/>", { id: "dingdong", style: "display: none" }).append(
				$("<div/>", { id: "dingdong-box" }).append(
					$("<div/>", { id: "dingdong-close", text: "\u00D7" }),
					$("<form/>", { id: "dingdong-form" }).append(
						header,
						email,
						message,
						subscribe,
						submit
					)
				)
			)
		);

		// maybe listen for esc to cancel
		if (escapeToCancel) {
			$(document).keydown(function(e) {
		    if (e.keyCode == 27) {
		        $.dingdongCancel();
		    }
			});
		}

		// toggle name fields when subscribe checkbox changes
		$("#dingdong-subscribe").change(function () {
			var checked = $(this).is(":checked");
			if (checked) {
				$("#dingdong-name-row").slideDown();
			} else {
				$("#dingdong-name-row").slideUp();
			}
			$("#dingdong-fname").prop("required", checked);
			$("#dingdong-lname").prop("required", checked);
		});

		// show dingdong when button is clicked
		$("#dingdong-button").click(function () {
			$.dingdongShow();
		});

		// cancel dingdong when backdrop or close is clicked
		$("#dingdong, #dingdong-close").click(function () {
			$.dingdongCancel();
		});

		// prevent clicks inside the box from propagating
		// (otherwise any click inside will trigger above cancel)
		$("#dingdong-box").click(function (e) {
			e.stopPropagation();
		});

		// handle form submission (prevent default behavior since ajax)
		$("#dingdong-form").submit(function (e) {
			e.preventDefault();
			var data = {
				message: $("#dingdong-message").val(),
				email: $("#dingdong-email").val(),
				subscribe: $("#dingdong-subscribe").is(":checked"),
				fname: $("#dingdong-fname").val(),
				lname: $("#dingdong-lname").val()
			};
			function callback(err) {
				if (err) {
					$("#dingdong-submit").prop("disabled", false);
				} else {
					$.dingdongHide();
				}
			}
			$("#dingdong-submit").prop("disabled", true);
			if (opts.handler) {
				opts.handler(data, callback);
			} else {
				defaultHandler(opts.endpoint, data, callback);
			}
			return false;
		});

	}

}(jQuery));
<|endoftext|>


<commit_before>/*
 * Middleware that rewrites `req.url` to `/<fileName>.<localeId>.html`
 * (as output by `buildProduction`) based on the value of a cookie
 * (optional, set by `options.cookieName`), the `Accept-Language`
 * request header, and the directory contents.
 *
 * rewriteToLocalizedHtml is intended to run right before `static`
 * pointed at the same directory as `options.root`.
 *
 * If `options.cookieName` is specified, the `cookieParser` middleware
 * must also be in the middleware chain.
 */

var fs = require('fs'),
    Path = require('path'),
    passError = require('../passError'),
    memoizeAsync = require('../memoizeAsync'),
    memoizer = require('memoizer');

/*
 * Helper for getting a prioritized list of relevant locale ids from a
 * specific locale id. For instance, `en_US` produces `["en_US", "en"]`.
 */
function expandLocaleIdToPrioritizedList(localeId) {
    var localeIds = [localeId];
    while (/_[^_]+$/.test(localeId)) {
        localeId = localeId.replace(/_[^_]+$/, '');
        localeIds.push(localeId);
    }
    return localeIds;
}

module.exports = function (options) {
    options = options || {};
    if (!('root' in options)) {
        throw new Error('rewriteToLocalizedHtml: options.root is required');
    }

    var memoizerByDir = {};
    function getExistsByFileName(dir, cb) {
        if (!(dir in memoizerByDir)) {
            memoizerByDir[dir] = memoizeAsync(function (cb_) {
                fs.readdir(dir, function (err, fileNames) {
                    if (err) {
                        if (err.code === 'ENOENT') {
                            // Pretend that non-existent directories are empty
                            return cb(null, {});
                        } else {
                            return cb(err);
                        }
                    }
                    var existsByFileName = {};
                    if (!err) {
                        fileNames.forEach(function (fileName) {
                            existsByFileName[fileName] = true;
                        });
                    }
                    cb_(null, existsByFileName);
                });
            });
        }
        memoizerByDir[dir](cb);
    }

    var fileNameByDirAndLocaleCookieValue = {};
    function getTargetUrl(dir, fileName, prioritizedLocaleIds, cb) {
        if (fileNameByDirAndLocaleCookieValue[dir] && fileNameByDirAndLocaleCookieValue[dir][localeCookieValue]) {
            return cb(null, fileNameByDirAndLocaleCookieValue[dir][localeCookieValue]);
        } else {
            getExistsByFileName(Path.resolve(options.root, dir.substr(1)), passError(cb, function (existsByFileName) {
                for (var i = 0 ; i < prioritizedLocaleIds.length ; i += 1) {
                    var localizedFileName = (fileName || 'index') + '.' + prioritizedLocaleIds[i] + '.html';
                    if (existsByFileName[localizedFileName]) {
                        return cb(null, dir + localizedFileName);
                    }
                }
                if (fileName === '' && existsByFileName['index.html']) {
                    cb(null, dir + "index.html"); // Useful in development mode
                } else if (existsByFileName[fileName + '.html']) {
                    cb(null, dir + fileName + ".html"); // Also useful in development mode
                } else {
                    // No suitable localized version found, don't rewrite the request:
                    cb();
                }
            }));
        }
    }

    var getPrioritizedLocaleIds = memoizer(function (localeCookieValue, acceptLanguageHeaderValue) {
        var prioritizedLocaleIds = [];
        if (localeCookieValue) {
            localeCookieValue.split(',').forEach(function (localeId) {
                Array.prototype.push.apply(prioritizedLocaleIds, expandLocaleIdToPrioritizedList(localeId));
            });
        }
        if (acceptLanguageHeaderValue) {
            acceptLanguageHeaderValue.replace(/;[^,]*/g, "").split(",").forEach(function (localeId) {
                localeId = localeId.replace(/-/g, '_');
                Array.prototype.push.apply(prioritizedLocaleIds, expandLocaleIdToPrioritizedList(localeId));
            });
        }
        prioritizedLocaleIds.push('en_US', 'en');
        return prioritizedLocaleIds;
    });

    var cookieNameLowerCased = options.cookieName && options.cookieName.toLowerCase();

    return function rewriteToLocalizedIndexHtml(req, res, next) {
        // Express has a bug that doesn't consider wildcards in the 'Accept' header correctly:
        if (req.accepts('html') || /(?:^|,| )(?:text|\*)\/(?:\*|html)(?:,| |$)/.test(req.headers.accept)) {
            var matchDirAndFileName = req.url.match(/^(\/(?:[\w%+@*\-\.]+\/)*)(\w*)((?:\?.*)?$)/);
            if (matchDirAndFileName) {
                var dir = matchDirAndFileName[1],
                    fileName = matchDirAndFileName[2],
                    queryString = matchDirAndFileName[3],
                    cookieValue = cookieNameLowerCased && req.cookies && req.cookies[cookieNameLowerCased],
                    prioritizedLocaleIds = getPrioritizedLocaleIds(cookieValue, req.headers['accept-language']);

                return getTargetUrl(dir, fileName, prioritizedLocaleIds, passError(next, function (targetUrl) {
                    if (typeof targetUrl === 'string') {
                        req.url = targetUrl + queryString;

                        // Only allow ETag revalidation with conditional GET for these requests, otherwise the static middleware
                        // might reply with a 304 after a locale switch.
                        delete req.headers['if-modified-since'];
                    }
                    next();
                }));
            }
        }
        next();
    };
};
<commit_msg>Get passError from the 'passerror' module and don't expose it as serverHelper.passError anymore.<commit_after>/*
 * Middleware that rewrites `req.url` to `/<fileName>.<localeId>.html`
 * (as output by `buildProduction`) based on the value of a cookie
 * (optional, set by `options.cookieName`), the `Accept-Language`
 * request header, and the directory contents.
 *
 * rewriteToLocalizedHtml is intended to run right before `static`
 * pointed at the same directory as `options.root`.
 *
 * If `options.cookieName` is specified, the `cookieParser` middleware
 * must also be in the middleware chain.
 */

var fs = require('fs'),
    Path = require('path'),
    passError = require('passerror'),
    memoizeAsync = require('../memoizeAsync'),
    memoizer = require('memoizer');

/*
 * Helper for getting a prioritized list of relevant locale ids from a
 * specific locale id. For instance, `en_US` produces `["en_US", "en"]`.
 */
function expandLocaleIdToPrioritizedList(localeId) {
    var localeIds = [localeId];
    while (/_[^_]+$/.test(localeId)) {
        localeId = localeId.replace(/_[^_]+$/, '');
        localeIds.push(localeId);
    }
    return localeIds;
}

module.exports = function (options) {
    options = options || {};
    if (!('root' in options)) {
        throw new Error('rewriteToLocalizedHtml: options.root is required');
    }

    var memoizerByDir = {};
    function getExistsByFileName(dir, cb) {
        if (!(dir in memoizerByDir)) {
            memoizerByDir[dir] = memoizeAsync(function (cb_) {
                fs.readdir(dir, function (err, fileNames) {
                    if (err) {
                        if (err.code === 'ENOENT') {
                            // Pretend that non-existent directories are empty
                            return cb(null, {});
                        } else {
                            return cb(err);
                        }
                    }
                    var existsByFileName = {};
                    if (!err) {
                        fileNames.forEach(function (fileName) {
                            existsByFileName[fileName] = true;
                        });
                    }
                    cb_(null, existsByFileName);
                });
            });
        }
        memoizerByDir[dir](cb);
    }

    var fileNameByDirAndLocaleCookieValue = {};
    function getTargetUrl(dir, fileName, prioritizedLocaleIds, cb) {
        if (fileNameByDirAndLocaleCookieValue[dir] && fileNameByDirAndLocaleCookieValue[dir][localeCookieValue]) {
            return cb(null, fileNameByDirAndLocaleCookieValue[dir][localeCookieValue]);
        } else {
            getExistsByFileName(Path.resolve(options.root, dir.substr(1)), passError(cb, function (existsByFileName) {
                for (var i = 0 ; i < prioritizedLocaleIds.length ; i += 1) {
                    var localizedFileName = (fileName || 'index') + '.' + prioritizedLocaleIds[i] + '.html';
                    if (existsByFileName[localizedFileName]) {
                        return cb(null, dir + localizedFileName);
                    }
                }
                if (fileName === '' && existsByFileName['index.html']) {
                    cb(null, dir + "index.html"); // Useful in development mode
                } else if (existsByFileName[fileName + '.html']) {
                    cb(null, dir + fileName + ".html"); // Also useful in development mode
                } else {
                    // No suitable localized version found, don't rewrite the request:
                    cb();
                }
            }));
        }
    }

    var getPrioritizedLocaleIds = memoizer(function (localeCookieValue, acceptLanguageHeaderValue) {
        var prioritizedLocaleIds = [];
        if (localeCookieValue) {
            localeCookieValue.split(',').forEach(function (localeId) {
                Array.prototype.push.apply(prioritizedLocaleIds, expandLocaleIdToPrioritizedList(localeId));
            });
        }
        if (acceptLanguageHeaderValue) {
            acceptLanguageHeaderValue.replace(/;[^,]*/g, "").split(",").forEach(function (localeId) {
                localeId = localeId.replace(/-/g, '_');
                Array.prototype.push.apply(prioritizedLocaleIds, expandLocaleIdToPrioritizedList(localeId));
            });
        }
        prioritizedLocaleIds.push('en_US', 'en');
        return prioritizedLocaleIds;
    });

    var cookieNameLowerCased = options.cookieName && options.cookieName.toLowerCase();

    return function rewriteToLocalizedIndexHtml(req, res, next) {
        // Express has a bug that doesn't consider wildcards in the 'Accept' header correctly:
        if (req.accepts('html') || /(?:^|,| )(?:text|\*)\/(?:\*|html)(?:,| |$)/.test(req.headers.accept)) {
            var matchDirAndFileName = req.url.match(/^(\/(?:[\w%+@*\-\.]+\/)*)(\w*)((?:\?.*)?$)/);
            if (matchDirAndFileName) {
                var dir = matchDirAndFileName[1],
                    fileName = matchDirAndFileName[2],
                    queryString = matchDirAndFileName[3],
                    cookieValue = cookieNameLowerCased && req.cookies && req.cookies[cookieNameLowerCased],
                    prioritizedLocaleIds = getPrioritizedLocaleIds(cookieValue, req.headers['accept-language']);

                return getTargetUrl(dir, fileName, prioritizedLocaleIds, passError(next, function (targetUrl) {
                    if (typeof targetUrl === 'string') {
                        req.url = targetUrl + queryString;

                        // Only allow ETag revalidation with conditional GET for these requests, otherwise the static middleware
                        // might reply with a 304 after a locale switch.
                        delete req.headers['if-modified-since'];
                    }
                    next();
                }));
            }
        }
        next();
    };
};
<|endoftext|>


<commit_before>/** @babel */

import {CompositeDisposable, Disposable, File} from 'atom'
import Repository from './models/repository'
import FileSystemChangeObserver from './models/file-system-change-observer'
import WorkspaceChangeObserver from './models/workspace-change-observer'
import GitPanelController from './controllers/git-panel-controller'
import FilePatchController from './controllers/file-patch-controller'
import ChangedFilesCountController from './controllers/changed-files-count-controller'

import path from 'path'

export default class GithubPackage {
  constructor (workspace, project, commandRegistry, notificationManager) {
    this.workspace = workspace
    this.project = project
    this.commandRegistry = commandRegistry
    this.notificationManager = notificationManager
    this.changeObserver = process.platform === 'linux' ?
      new WorkspaceChangeObserver(window, atom.workspace) :
      new FileSystemChangeObserver()
    this.activeRepository = null
    this.repositoriesByProjectDirectory = new Map()
    this.subscriptions = new CompositeDisposable()
    this.gitPanelController = new GitPanelController({
      repository: null,
      workspace,
      commandRegistry,
      notificationManager,
      didSelectFilePatch: this.didSelectFilePatch.bind(this),
      didSelectMergeConflictFile: this.didSelectMergeConflictFile.bind(this)
    })
    this.changedFilesCountController = new ChangedFilesCountController({
      repository: null, didClick: this.toggleGitPanel.bind(this)
    })
    this.filePatchController = null
  }

  async activate () {
    await this.updateActiveRepository()
    await this.changeObserver.start()
    this.subscriptions.add(
      this.project.onDidChangePaths(this.didChangeProjectPaths.bind(this)),
      this.workspace.onDidChangeActivePaneItem(this.didChangeActivePaneItem.bind(this)),
      this.changeObserver.onDidChange(this.refreshActiveRepository.bind(this)),
      this.commandRegistry.add('atom-workspace', {'git:toggle-git-panel': this.toggleGitPanel.bind(this)})
    )
  }

  async deactivate () {
    await this.changeObserver.stop()
  }

  consumeStatusBar (statusBar) {
    const tile = statusBar.addRightTile({item: this.changedFilesCountController, priority: -100})
    this.subscriptions.add(new Disposable(() => tile.destroy()))
  }

  async didChangeProjectPaths () {
    await this.destroyRepositoriesForRemovedProjectFolders()
    await this.updateActiveRepository()
  }

  async didChangeActivePaneItem () {
    await this.updateActiveRepository()
  }

  async refreshActiveRepository () {
    if (this.activeRepository) {
      await this.activeRepository.refresh()
    }
  }

  didSelectFilePatch (filePatch, stagingStatus) {
    if (!filePatch) return

    const repository = this.getActiveRepository()
    if (this.filePatchController) {
      this.filePatchController.update({filePatch, repository, stagingStatus})
      const containingPane = this.workspace.paneForItem(this.filePatchController)
      containingPane.activate()
      containingPane.activateItem(this.filePatchController)
    } else {
      this.filePatchController = new FilePatchController({filePatch, repository, stagingStatus})
      this.filePatchController.onDidDestroy(() => { this.filePatchController = null })
      this.workspace.getActivePane().activateItem(this.filePatchController)
    }
  }

  async didSelectMergeConflictFile (relativeFilePath) {
    const absolutePath = path.join(this.getActiveRepository().getWorkingDirectoryPath(), relativeFilePath)
    if (await new File(absolutePath).exists()) {
      return this.workspace.open(absolutePath, {activatePane: false})
    } else {
      this.notificationManager.addInfo('File has been deleted.')
    }
  }

  toggleGitPanel () {
    if (this.workspaceGitPanel) {
      this.workspaceGitPanel.destroy()
      this.workspaceGitPanel = null
    } else {
      this.workspaceGitPanel = this.workspace.addRightPanel({item: this.gitPanelController})
      this.gitPanelController.focus()
    }
  }

  getActiveRepository () {
    return this.activeRepository
  }

  async updateActiveRepository () {
    let activeRepository

    if (this.activeRepository && this.project.getDirectories().indexOf(this.activeRepository.getWorkingDirectory()) === -1) {
      this.activeRepository = null
      await this.changeObserver.setActiveRepository(null)
    }

    let activeItem = this.workspace.getActivePaneItem()
    if (activeItem && typeof activeItem.getPath === 'function') {
      let projectDirectory = this.projectDirectoryForPath(activeItem.getPath())
      if (projectDirectory) {
        activeRepository = await this.repositoryForProjectDirectory(projectDirectory)
      }
    }

    if (!(activeRepository || this.activeRepository)) {
      for (let directory of this.project.getDirectories()) {
        activeRepository = await this.repositoryForProjectDirectory(directory) // eslint-disable-line babel/no-await-in-loop
        if (activeRepository) break
      }
    }

    if (activeRepository && activeRepository !== this.activeRepository) {
      this.activeRepository = activeRepository
      await this.changedFilesCountController.update({repository: this.getActiveRepository()})
      await this.gitPanelController.update({repository: this.getActiveRepository()})
      await this.changeObserver.setActiveRepository(this.getActiveRepository())
    }
  }

  projectDirectoryForPath (path) {
    return this.project.getDirectories().find(d => d.getPath() === path || d.contains(path))
  }

  async repositoryForProjectDirectory (projectDirectory) {
    let repository = this.repositoriesByProjectDirectory.get(projectDirectory)
    if (!repository) {
      try {
        repository = await Repository.open(projectDirectory)
        this.repositoriesByProjectDirectory.set(projectDirectory, repository)
      } catch (e) {
        repository = null
      }
    }
    return repository
  }

  async repositoryForWorkdirPath (workdirPath) {
    return this.repositoryForProjectDirectory(this.projectDirectoryForPath(workdirPath))
  }

  destroyRepositoriesForRemovedProjectFolders () {
    const projectDirectories = this.project.getDirectories()
    for (let [projectDirectory, repository] of this.repositoriesByProjectDirectory) {
      if (projectDirectories.indexOf(projectDirectory) === -1) {
        repository.destroy()
        this.repositoriesByProjectDirectory.delete(projectDirectory)
      }
    }
  }

  destroy () {
    this.subscriptions.dispose()
    this.gitPanelController.destroy()
  }
}
<commit_msg>Retain focus on StagingView when FilePatch instance is selected<commit_after>/** @babel */

import {CompositeDisposable, Disposable, File} from 'atom'
import Repository from './models/repository'
import FileSystemChangeObserver from './models/file-system-change-observer'
import WorkspaceChangeObserver from './models/workspace-change-observer'
import GitPanelController from './controllers/git-panel-controller'
import FilePatchController from './controllers/file-patch-controller'
import ChangedFilesCountController from './controllers/changed-files-count-controller'

import path from 'path'

export default class GithubPackage {
  constructor (workspace, project, commandRegistry, notificationManager) {
    this.workspace = workspace
    this.project = project
    this.commandRegistry = commandRegistry
    this.notificationManager = notificationManager
    this.changeObserver = process.platform === 'linux' ?
      new WorkspaceChangeObserver(window, atom.workspace) :
      new FileSystemChangeObserver()
    this.activeRepository = null
    this.repositoriesByProjectDirectory = new Map()
    this.subscriptions = new CompositeDisposable()
    this.gitPanelController = new GitPanelController({
      repository: null,
      workspace,
      commandRegistry,
      notificationManager,
      didSelectFilePatch: this.didSelectFilePatch.bind(this),
      didSelectMergeConflictFile: this.didSelectMergeConflictFile.bind(this)
    })
    this.changedFilesCountController = new ChangedFilesCountController({
      repository: null, didClick: this.toggleGitPanel.bind(this)
    })
    this.filePatchController = null
  }

  async activate () {
    await this.updateActiveRepository()
    await this.changeObserver.start()
    this.subscriptions.add(
      this.project.onDidChangePaths(this.didChangeProjectPaths.bind(this)),
      this.workspace.onDidChangeActivePaneItem(this.didChangeActivePaneItem.bind(this)),
      this.changeObserver.onDidChange(this.refreshActiveRepository.bind(this)),
      this.commandRegistry.add('atom-workspace', {'git:toggle-git-panel': this.toggleGitPanel.bind(this)})
    )
  }

  async deactivate () {
    await this.changeObserver.stop()
  }

  consumeStatusBar (statusBar) {
    const tile = statusBar.addRightTile({item: this.changedFilesCountController, priority: -100})
    this.subscriptions.add(new Disposable(() => tile.destroy()))
  }

  async didChangeProjectPaths () {
    await this.destroyRepositoriesForRemovedProjectFolders()
    await this.updateActiveRepository()
  }

  async didChangeActivePaneItem () {
    await this.updateActiveRepository()
  }

  async refreshActiveRepository () {
    if (this.activeRepository) {
      await this.activeRepository.refresh()
    }
  }

  didSelectFilePatch (filePatch, stagingStatus) {
    if (!filePatch) return

    const repository = this.getActiveRepository()
    if (this.filePatchController) {
      this.filePatchController.update({filePatch, repository, stagingStatus})
      const containingPane = this.workspace.paneForItem(this.filePatchController)
      containingPane.activate()
      containingPane.activateItem(this.filePatchController)
      this.gitPanelController.focus()
    } else {
      this.filePatchController = new FilePatchController({filePatch, repository, stagingStatus})
      this.filePatchController.onDidDestroy(() => { this.filePatchController = null })
      this.workspace.getActivePane().activateItem(this.filePatchController)
    }
  }

  async didSelectMergeConflictFile (relativeFilePath) {
    const absolutePath = path.join(this.getActiveRepository().getWorkingDirectoryPath(), relativeFilePath)
    if (await new File(absolutePath).exists()) {
      return this.workspace.open(absolutePath, {activatePane: false})
    } else {
      this.notificationManager.addInfo('File has been deleted.')
    }
  }

  toggleGitPanel () {
    if (this.workspaceGitPanel) {
      this.workspaceGitPanel.destroy()
      this.workspaceGitPanel = null
    } else {
      this.workspaceGitPanel = this.workspace.addRightPanel({item: this.gitPanelController})
      this.gitPanelController.focus()
    }
  }

  getActiveRepository () {
    return this.activeRepository
  }

  async updateActiveRepository () {
    let activeRepository

    if (this.activeRepository && this.project.getDirectories().indexOf(this.activeRepository.getWorkingDirectory()) === -1) {
      this.activeRepository = null
      await this.changeObserver.setActiveRepository(null)
    }

    let activeItem = this.workspace.getActivePaneItem()
    if (activeItem && typeof activeItem.getPath === 'function') {
      let projectDirectory = this.projectDirectoryForPath(activeItem.getPath())
      if (projectDirectory) {
        activeRepository = await this.repositoryForProjectDirectory(projectDirectory)
      }
    }

    if (!(activeRepository || this.activeRepository)) {
      for (let directory of this.project.getDirectories()) {
        activeRepository = await this.repositoryForProjectDirectory(directory) // eslint-disable-line babel/no-await-in-loop
        if (activeRepository) break
      }
    }

    if (activeRepository && activeRepository !== this.activeRepository) {
      this.activeRepository = activeRepository
      await this.changedFilesCountController.update({repository: this.getActiveRepository()})
      await this.gitPanelController.update({repository: this.getActiveRepository()})
      await this.changeObserver.setActiveRepository(this.getActiveRepository())
    }
  }

  projectDirectoryForPath (path) {
    return this.project.getDirectories().find(d => d.getPath() === path || d.contains(path))
  }

  async repositoryForProjectDirectory (projectDirectory) {
    let repository = this.repositoriesByProjectDirectory.get(projectDirectory)
    if (!repository) {
      try {
        repository = await Repository.open(projectDirectory)
        this.repositoriesByProjectDirectory.set(projectDirectory, repository)
      } catch (e) {
        repository = null
      }
    }
    return repository
  }

  async repositoryForWorkdirPath (workdirPath) {
    return this.repositoryForProjectDirectory(this.projectDirectoryForPath(workdirPath))
  }

  destroyRepositoriesForRemovedProjectFolders () {
    const projectDirectories = this.project.getDirectories()
    for (let [projectDirectory, repository] of this.repositoriesByProjectDirectory) {
      if (projectDirectories.indexOf(projectDirectory) === -1) {
        repository.destroy()
        this.repositoriesByProjectDirectory.delete(projectDirectory)
      }
    }
  }

  destroy () {
    this.subscriptions.dispose()
    this.gitPanelController.destroy()
  }
}
<|endoftext|>


<commit_before>/**
 * Normalize Japanese inputs and expose function to perform several conversions.
 *
 * Note: The space character is treated like a roman character as it usually
 *   has the same width as them in Japanese texts.
 *
 * \@todo Lazy initializations of conversionTables and converters.
 * \@todo Would fixHalfwidthKana be useful?
 *
 * Descriptions of functions exposed:
 * normalizeJapanese 「全角」英字・数字を「半角」、「半角」記・カタカナを「全角」に変換
 * converters.fullwidthToHalfwidth.alphabet    「全角」英字を「半角」に変換
 * converters.halfwidthToFullwidth.alphabet    「半角」英字を「全角」に変換
 * converters.fullwidthToHalfwidth.numbers     「全角」数字を「半角」に変換
 * converters.halfwidthToFullwidth.numbers     「半角」数字を「全角」に変換 「全角」スペースを「半角」
 * converters.fullwidthToHalfwidth.punctuation 「全角」記号を「半角」に変換 「半角」スペースを「全角」
 * converters.halfwidthToFullwidth.punctuation 「半角」記号を「全角」に変換
 * converters.fullwidthToHalfwidth.katakana    「全角カタカナ」を「半角カタカナ」に変換
 * converters.halfwidthToFullwidth.katakana    「半角カタカナ」を「全角カタカナ」に変換
 */

var flip = require('../util/utils.js').flip;
var merge = require('../util/utils.js').merge;
var Replacer = require('../util/utils').Replacer;

// From http://fernweh.jp/b/mb_convert_kana_js/
var conversionTables = {
  fullwidthToHalfwidth: {
    alphabet: {
      'ａ': 'a',
      'ｂ': 'b',
      'ｃ': 'c',
      'ｄ': 'd',
      'ｅ': 'e',
      'ｆ': 'f',
      'ｇ': 'g',
      'ｈ': 'h',
      'ｉ': 'i',
      'ｊ': 'j',
      'ｋ': 'k',
      'ｌ': 'l',
      'ｍ': 'm',
      'ｎ': 'n',
      'ｏ': 'o',
      'ｐ': 'p',
      'ｑ': 'q',
      'ｒ': 'r',
      'ｓ': 's',
      'ｔ': 't',
      'ｕ': 'u',
      'ｖ': 'v',
      'ｗ': 'w',
      'ｘ': 'x',
      'ｙ': 'y',
      'ｚ': 'z',
      'Ａ': 'A',
      'Ｂ': 'B',
      'Ｃ': 'C',
      'Ｄ': 'D',
      'Ｅ': 'E',
      'Ｆ': 'F',
      'Ｇ': 'G',
      'Ｈ': 'H',
      'Ｉ': 'I',
      'Ｊ': 'J',
      'Ｋ': 'K',
      'Ｌ': 'L',
      'Ｍ': 'M',
      'Ｎ': 'N',
      'Ｏ': 'O',
      'Ｐ': 'P',
      'Ｑ': 'Q',
      'Ｒ': 'R',
      'Ｓ': 'S',
      'Ｔ': 'T',
      'Ｕ': 'U',
      'Ｖ': 'V',
      'Ｗ': 'W',
      'Ｘ': 'X',
      'Ｙ': 'Y',
      'Ｚ': 'Z',
      '　': ' ' // Fullwidth space
    },

    numbers: {
      '０': '0',
      '１': '1',
      '２': '2',
      '３': '3',
      '４': '4',
      '５': '5',
      '６': '6',
      '７': '7',
      '８': '8',
      '９': '9'
    },

    punctuation: {
      '＿': '_',
      '－': '-',
      '・': '･',
      '，': ',',
      '、': '､',
      '；': ';',
      '：': ':',
      '！': '!',
      '？': '?',
      '．': '.',
      '。': '｡',
      '（': '(',
      '）': ')',
      '［': '[',
      '］': ']',
      '｛': '{',
      '｝': '}',
      '｢': '「',
      '｣': '」',
      '＠': '@',
      '＊': '*',
      '＼': '\\',
      '／': '/',
      '＆': '&',
      '＃': '#',
      '％': '%',
      '｀': '`',
      '＾': '^',
      '＋': '+',
      '＜': '<',
      '＝': '=',
      '＞': '>',
      '｜': '|',
      '～': '~',
      '≪': '«',
      '≫': '»',
      '─': '-',
      '＄': '$',
      '＂': '"'
    },

    katakana: {
      '゛': 'ﾞ',
      '゜': 'ﾟ',
      'ー': 'ｰ',

      'ヴ': 'ｳﾞ',
      'ガ': 'ｶﾞ',
      'ギ': 'ｷﾞ',
      'グ': 'ｸﾞ',
      'ゲ': 'ｹﾞ',
      'ゴ': 'ｺﾞ',
      'ザ': 'ｻﾞ',
      'ジ': 'ｼﾞ',
      'ズ': 'ｽﾞ',
      'ゼ': 'ｾﾞ',
      'ゾ': 'ｿﾞ',
      'ダ': 'ﾀﾞ',
      'ヂ': 'ﾁﾞ',
      'ヅ': 'ﾂﾞ',
      'デ': 'ﾃﾞ',
      'ド': 'ﾄﾞ',
      'バ': 'ﾊﾞ',
      'パ': 'ﾊﾟ',
      'ビ': 'ﾋﾞ',
      'ピ': 'ﾋﾟ',
      'ブ': 'ﾌﾞ',
      'プ': 'ﾌﾟ',
      'ベ': 'ﾍﾞ',
      'ペ': 'ﾍﾟ',
      'ボ': 'ﾎﾞ',
      'ポ': 'ﾎﾟ',

      'ァ': 'ｧ',
      'ア': 'ｱ',
      'ィ': 'ｨ',
      'イ': 'ｲ',
      'ゥ': 'ｩ',
      'ウ': 'ｳ',
      'ェ': 'ｪ',
      'エ': 'ｴ',
      'ォ': 'ｫ',
      'オ': 'ｵ',
      'カ': 'ｶ',
      'キ': 'ｷ',
      'ク': 'ｸ',
      'ケ': 'ｹ',
      'コ': 'ｺ',
      'サ': 'ｻ',
      'シ': 'ｼ',
      'ス': 'ｽ',
      'セ': 'ｾ',
      'ソ': 'ｿ',
      'タ': 'ﾀ',
      'チ': 'ﾁ',
      'ッ': 'ｯ',
      'ツ': 'ﾂ',
      'テ': 'ﾃ',
      'ト': 'ﾄ',
      'ナ': 'ﾅ',
      'ニ': 'ﾆ',
      'ヌ': 'ﾇ',
      'ネ': 'ﾈ',
      'ノ': 'ﾉ',
      'ハ': 'ﾊ',
      'ヒ': 'ﾋ',
      'フ': 'ﾌ',
      'ヘ': 'ﾍ',
      'ホ': 'ﾎ',
      'マ': 'ﾏ',
      'ミ': 'ﾐ',
      'ム': 'ﾑ',
      'メ': 'ﾒ',
      'モ': 'ﾓ',
      'ャ': 'ｬ',
      'ヤ': 'ﾔ',
      'ュ': 'ｭ',
      'ユ': 'ﾕ',
      'ョ': 'ｮ',
      'ヨ': 'ﾖ',
      'ラ': 'ﾗ',
      'リ': 'ﾘ',
      'ル': 'ﾙ',
      'レ': 'ﾚ',
      'ロ': 'ﾛ',
      'ワ': 'ﾜ',
      'ヲ': 'ｦ',
      'ン': 'ﾝ'
    }
  },

  halfwidthToFullwidth: {}
};

var fixFullwidthKana = {
  'ゝ゛': 'ゞ',
  'ヽ゛': 'ヾ',

  'う゛': 'ゔ',
  'か゛': 'が',
  'き゛': 'ぎ',
  'く゛': 'ぐ',
  'け゛': 'げ',
  'こ゛': 'ご',
  'さ゛': 'ざ',
  'し゛': 'じ',
  'す゛': 'ず',
  'せ゛': 'ぜ',
  'そ゛': 'ぞ',
  'た゛': 'だ',
  'ち゛': 'ぢ',
  'つ゛': 'づ',
  'て゛': 'で',
  'と゛': 'ど',
  'は゛': 'ば',
  'は゜': 'ぱ',
  'ひ゛': 'び',
  'ひ゜': 'ぴ',
  'ふ゛': 'ぶ',
  'ふ゜': 'ぷ',
  'へ゛': 'べ',
  'へ゜': 'ぺ',
  'ほ゛': 'ぼ',
  'ほ゜': 'ぽ',
  'っな': 'んな',
  'っに': 'んに',
  'っぬ': 'んぬ',
  'っね': 'んね',
  'っの': 'んの',

  'ウ゛': 'ヴ',
  'カ゛': 'ガ',
  'キ゛': 'ギ',
  'ク゛': 'グ',
  'ケ゛': 'ゲ',
  'コ゛': 'ゴ',
  'サ゛': 'ザ',
  'シ゛': 'ジ',
  'ス゛': 'ズ',
  'セ゛': 'ゼ',
  'ソ゛': 'ゾ',
  'タ゛': 'ダ',
  'チ゛': 'ヂ',
  'ツ゛': 'ヅ',
  'テ゛': 'デ',
  'ト゛': 'ド',
  'ハ゛': 'バ',
  'ハ゜': 'パ',
  'ヒ゛': 'ビ',
  'ヒ゜': 'ピ',
  'フ゛': 'ブ',
  'フ゜': 'プ',
  'ヘ゛': 'ベ',
  'ヘ゜': 'ペ',
  'ホ゛': 'ボ',
  'ホ゜': 'ポ',
  'ッナ': 'ンナ',
  'ッニ': 'ンニ',
  'ッヌ': 'ンヌ',
  'ッネ': 'ンネ',
  'ッノ': 'ンノ'
};

// Fill in the conversion tables with the flipped tables.
conversionTables.halfwidthToFullwidth.alphabet = flip(conversionTables.fullwidthToHalfwidth.alphabet);
conversionTables.halfwidthToFullwidth.numbers = flip(conversionTables.fullwidthToHalfwidth.numbers);
conversionTables.halfwidthToFullwidth.punctuation = flip(conversionTables.fullwidthToHalfwidth.punctuation);
conversionTables.halfwidthToFullwidth.katakana = flip(conversionTables.fullwidthToHalfwidth.katakana);

// Build the normalization table.
conversionTables.normalize = merge(
    conversionTables.fullwidthToHalfwidth.alphabet,
    conversionTables.fullwidthToHalfwidth.numbers,
    conversionTables.halfwidthToFullwidth.punctuation,
    conversionTables.halfwidthToFullwidth.katakana
    );

var converters = {
  fullwidthToHalfwidth: {
    alphabet: new Replacer(conversionTables.fullwidthToHalfwidth.alphabet),
    numbers: new Replacer(conversionTables.fullwidthToHalfwidth.numbers),
    punctuation: new Replacer(conversionTables.fullwidthToHalfwidth.punctuation),
    katakana: new Replacer(conversionTables.fullwidthToHalfwidth.katakana)
  },

  halfwidthToFullwidth: {
    alphabet: new Replacer(conversionTables.halfwidthToFullwidth.alphabet),
    numbers: new Replacer(conversionTables.halfwidthToFullwidth.numbers),
    punctuation: new Replacer(conversionTables.halfwidthToFullwidth.punctuation),
    katakana: new Replacer(conversionTables.halfwidthToFullwidth.katakana)
  },

  fixFullwidthKana: new Replacer(fixFullwidthKana),
  normalize: new Replacer(conversionTables.normalize)
};

/**
 * Fix kana and apply the following processes;
 * * Alphabet to halfwidth
 * * Numbers to halfwidth
 * * Punctuation to fullwidth
 * * Katakana to fullwidth
 *
 * @param str
 * @return {String}
 */
var normalize_ja = function(str) {
  str = converters.normalize(str);
  str = converters.fixFullwidthKana(str);

  return str;
};

exports.normalize_ja = normalize_ja;
exports.converters = converters;
<commit_msg>Add a todo<commit_after>/**
 * Normalize Japanese inputs and expose function to perform several conversions.
 *
 * Note: The space character is treated like a roman character as it usually
 *   has the same width as them in Japanese texts.
 *
 * \@todo Add functions to convert between hiragana and katakana.
 * \@todo Lazy initializations of conversionTables and converters.
 * \@todo Would fixHalfwidthKana be useful?
 *
 * Descriptions of functions exposed:
 * normalizeJapanese 「全角」英字・数字を「半角」、「半角」記・カタカナを「全角」に変換
 * converters.fullwidthToHalfwidth.alphabet    「全角」英字を「半角」に変換
 * converters.halfwidthToFullwidth.alphabet    「半角」英字を「全角」に変換
 * converters.fullwidthToHalfwidth.numbers     「全角」数字を「半角」に変換
 * converters.halfwidthToFullwidth.numbers     「半角」数字を「全角」に変換 「全角」スペースを「半角」
 * converters.fullwidthToHalfwidth.punctuation 「全角」記号を「半角」に変換 「半角」スペースを「全角」
 * converters.halfwidthToFullwidth.punctuation 「半角」記号を「全角」に変換
 * converters.fullwidthToHalfwidth.katakana    「全角カタカナ」を「半角カタカナ」に変換
 * converters.halfwidthToFullwidth.katakana    「半角カタカナ」を「全角カタカナ」に変換
 */

var flip = require('../util/utils.js').flip;
var merge = require('../util/utils.js').merge;
var Replacer = require('../util/utils').Replacer;

// From http://fernweh.jp/b/mb_convert_kana_js/
var conversionTables = {
  fullwidthToHalfwidth: {
    alphabet: {
      'ａ': 'a',
      'ｂ': 'b',
      'ｃ': 'c',
      'ｄ': 'd',
      'ｅ': 'e',
      'ｆ': 'f',
      'ｇ': 'g',
      'ｈ': 'h',
      'ｉ': 'i',
      'ｊ': 'j',
      'ｋ': 'k',
      'ｌ': 'l',
      'ｍ': 'm',
      'ｎ': 'n',
      'ｏ': 'o',
      'ｐ': 'p',
      'ｑ': 'q',
      'ｒ': 'r',
      'ｓ': 's',
      'ｔ': 't',
      'ｕ': 'u',
      'ｖ': 'v',
      'ｗ': 'w',
      'ｘ': 'x',
      'ｙ': 'y',
      'ｚ': 'z',
      'Ａ': 'A',
      'Ｂ': 'B',
      'Ｃ': 'C',
      'Ｄ': 'D',
      'Ｅ': 'E',
      'Ｆ': 'F',
      'Ｇ': 'G',
      'Ｈ': 'H',
      'Ｉ': 'I',
      'Ｊ': 'J',
      'Ｋ': 'K',
      'Ｌ': 'L',
      'Ｍ': 'M',
      'Ｎ': 'N',
      'Ｏ': 'O',
      'Ｐ': 'P',
      'Ｑ': 'Q',
      'Ｒ': 'R',
      'Ｓ': 'S',
      'Ｔ': 'T',
      'Ｕ': 'U',
      'Ｖ': 'V',
      'Ｗ': 'W',
      'Ｘ': 'X',
      'Ｙ': 'Y',
      'Ｚ': 'Z',
      '　': ' ' // Fullwidth space
    },

    numbers: {
      '０': '0',
      '１': '1',
      '２': '2',
      '３': '3',
      '４': '4',
      '５': '5',
      '６': '6',
      '７': '7',
      '８': '8',
      '９': '9'
    },

    punctuation: {
      '＿': '_',
      '－': '-',
      '・': '･',
      '，': ',',
      '、': '､',
      '；': ';',
      '：': ':',
      '！': '!',
      '？': '?',
      '．': '.',
      '。': '｡',
      '（': '(',
      '）': ')',
      '［': '[',
      '］': ']',
      '｛': '{',
      '｝': '}',
      '｢': '「',
      '｣': '」',
      '＠': '@',
      '＊': '*',
      '＼': '\\',
      '／': '/',
      '＆': '&',
      '＃': '#',
      '％': '%',
      '｀': '`',
      '＾': '^',
      '＋': '+',
      '＜': '<',
      '＝': '=',
      '＞': '>',
      '｜': '|',
      '～': '~',
      '≪': '«',
      '≫': '»',
      '─': '-',
      '＄': '$',
      '＂': '"'
    },

    katakana: {
      '゛': 'ﾞ',
      '゜': 'ﾟ',
      'ー': 'ｰ',

      'ヴ': 'ｳﾞ',
      'ガ': 'ｶﾞ',
      'ギ': 'ｷﾞ',
      'グ': 'ｸﾞ',
      'ゲ': 'ｹﾞ',
      'ゴ': 'ｺﾞ',
      'ザ': 'ｻﾞ',
      'ジ': 'ｼﾞ',
      'ズ': 'ｽﾞ',
      'ゼ': 'ｾﾞ',
      'ゾ': 'ｿﾞ',
      'ダ': 'ﾀﾞ',
      'ヂ': 'ﾁﾞ',
      'ヅ': 'ﾂﾞ',
      'デ': 'ﾃﾞ',
      'ド': 'ﾄﾞ',
      'バ': 'ﾊﾞ',
      'パ': 'ﾊﾟ',
      'ビ': 'ﾋﾞ',
      'ピ': 'ﾋﾟ',
      'ブ': 'ﾌﾞ',
      'プ': 'ﾌﾟ',
      'ベ': 'ﾍﾞ',
      'ペ': 'ﾍﾟ',
      'ボ': 'ﾎﾞ',
      'ポ': 'ﾎﾟ',

      'ァ': 'ｧ',
      'ア': 'ｱ',
      'ィ': 'ｨ',
      'イ': 'ｲ',
      'ゥ': 'ｩ',
      'ウ': 'ｳ',
      'ェ': 'ｪ',
      'エ': 'ｴ',
      'ォ': 'ｫ',
      'オ': 'ｵ',
      'カ': 'ｶ',
      'キ': 'ｷ',
      'ク': 'ｸ',
      'ケ': 'ｹ',
      'コ': 'ｺ',
      'サ': 'ｻ',
      'シ': 'ｼ',
      'ス': 'ｽ',
      'セ': 'ｾ',
      'ソ': 'ｿ',
      'タ': 'ﾀ',
      'チ': 'ﾁ',
      'ッ': 'ｯ',
      'ツ': 'ﾂ',
      'テ': 'ﾃ',
      'ト': 'ﾄ',
      'ナ': 'ﾅ',
      'ニ': 'ﾆ',
      'ヌ': 'ﾇ',
      'ネ': 'ﾈ',
      'ノ': 'ﾉ',
      'ハ': 'ﾊ',
      'ヒ': 'ﾋ',
      'フ': 'ﾌ',
      'ヘ': 'ﾍ',
      'ホ': 'ﾎ',
      'マ': 'ﾏ',
      'ミ': 'ﾐ',
      'ム': 'ﾑ',
      'メ': 'ﾒ',
      'モ': 'ﾓ',
      'ャ': 'ｬ',
      'ヤ': 'ﾔ',
      'ュ': 'ｭ',
      'ユ': 'ﾕ',
      'ョ': 'ｮ',
      'ヨ': 'ﾖ',
      'ラ': 'ﾗ',
      'リ': 'ﾘ',
      'ル': 'ﾙ',
      'レ': 'ﾚ',
      'ロ': 'ﾛ',
      'ワ': 'ﾜ',
      'ヲ': 'ｦ',
      'ン': 'ﾝ'
    }
  },

  halfwidthToFullwidth: {}
};

var fixFullwidthKana = {
  'ゝ゛': 'ゞ',
  'ヽ゛': 'ヾ',

  'う゛': 'ゔ',
  'か゛': 'が',
  'き゛': 'ぎ',
  'く゛': 'ぐ',
  'け゛': 'げ',
  'こ゛': 'ご',
  'さ゛': 'ざ',
  'し゛': 'じ',
  'す゛': 'ず',
  'せ゛': 'ぜ',
  'そ゛': 'ぞ',
  'た゛': 'だ',
  'ち゛': 'ぢ',
  'つ゛': 'づ',
  'て゛': 'で',
  'と゛': 'ど',
  'は゛': 'ば',
  'は゜': 'ぱ',
  'ひ゛': 'び',
  'ひ゜': 'ぴ',
  'ふ゛': 'ぶ',
  'ふ゜': 'ぷ',
  'へ゛': 'べ',
  'へ゜': 'ぺ',
  'ほ゛': 'ぼ',
  'ほ゜': 'ぽ',
  'っな': 'んな',
  'っに': 'んに',
  'っぬ': 'んぬ',
  'っね': 'んね',
  'っの': 'んの',

  'ウ゛': 'ヴ',
  'カ゛': 'ガ',
  'キ゛': 'ギ',
  'ク゛': 'グ',
  'ケ゛': 'ゲ',
  'コ゛': 'ゴ',
  'サ゛': 'ザ',
  'シ゛': 'ジ',
  'ス゛': 'ズ',
  'セ゛': 'ゼ',
  'ソ゛': 'ゾ',
  'タ゛': 'ダ',
  'チ゛': 'ヂ',
  'ツ゛': 'ヅ',
  'テ゛': 'デ',
  'ト゛': 'ド',
  'ハ゛': 'バ',
  'ハ゜': 'パ',
  'ヒ゛': 'ビ',
  'ヒ゜': 'ピ',
  'フ゛': 'ブ',
  'フ゜': 'プ',
  'ヘ゛': 'ベ',
  'ヘ゜': 'ペ',
  'ホ゛': 'ボ',
  'ホ゜': 'ポ',
  'ッナ': 'ンナ',
  'ッニ': 'ンニ',
  'ッヌ': 'ンヌ',
  'ッネ': 'ンネ',
  'ッノ': 'ンノ'
};

// Fill in the conversion tables with the flipped tables.
conversionTables.halfwidthToFullwidth.alphabet = flip(conversionTables.fullwidthToHalfwidth.alphabet);
conversionTables.halfwidthToFullwidth.numbers = flip(conversionTables.fullwidthToHalfwidth.numbers);
conversionTables.halfwidthToFullwidth.punctuation = flip(conversionTables.fullwidthToHalfwidth.punctuation);
conversionTables.halfwidthToFullwidth.katakana = flip(conversionTables.fullwidthToHalfwidth.katakana);

// Build the normalization table.
conversionTables.normalize = merge(
    conversionTables.fullwidthToHalfwidth.alphabet,
    conversionTables.fullwidthToHalfwidth.numbers,
    conversionTables.halfwidthToFullwidth.punctuation,
    conversionTables.halfwidthToFullwidth.katakana
    );

var converters = {
  fullwidthToHalfwidth: {
    alphabet: new Replacer(conversionTables.fullwidthToHalfwidth.alphabet),
    numbers: new Replacer(conversionTables.fullwidthToHalfwidth.numbers),
    punctuation: new Replacer(conversionTables.fullwidthToHalfwidth.punctuation),
    katakana: new Replacer(conversionTables.fullwidthToHalfwidth.katakana)
  },

  halfwidthToFullwidth: {
    alphabet: new Replacer(conversionTables.halfwidthToFullwidth.alphabet),
    numbers: new Replacer(conversionTables.halfwidthToFullwidth.numbers),
    punctuation: new Replacer(conversionTables.halfwidthToFullwidth.punctuation),
    katakana: new Replacer(conversionTables.halfwidthToFullwidth.katakana)
  },

  fixFullwidthKana: new Replacer(fixFullwidthKana),
  normalize: new Replacer(conversionTables.normalize)
};

/**
 * Fix kana and apply the following processes;
 * * Alphabet to halfwidth
 * * Numbers to halfwidth
 * * Punctuation to fullwidth
 * * Katakana to fullwidth
 *
 * @param str
 * @return {String}
 */
var normalize_ja = function(str) {
  str = converters.normalize(str);
  str = converters.fixFullwidthKana(str);

  return str;
};

exports.normalize_ja = normalize_ja;
exports.converters = converters;
<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
"use strict";
class ChunkModuleIdRangePlugin {
	constructor(options) {
		this.options = options;
	}
	apply(compiler) {
		const options = this.options;
		compiler.plugin("compilation", (compilation) => {
			compilation.plugin("module-ids", (modules) => {
				const chunk = this.chunks.filter((chunk) => {
					return chunk.name === options.name;
				})[0];
				if(!chunk) throw new Error("ChunkModuleIdRangePlugin: Chunk with name '" + options.name + "' was not found");
				let currentId = options.start;
				let chunkModules;
				if(options.order) {
					chunkModules = chunk.modules.slice();
					switch(options.order) {
						case "index":
							chunkModules.sort((a, b) => {
								return a.index - b.index;
							});
							break;
						case "index2":
							chunkModules.sort((a, b) => {
								return a.index2 - b.index2;
							});
							break;
						default:
							throw new Error("ChunkModuleIdRangePlugin: unexpected value of order");
					}

				} else {
					chunkModules = modules.filter((m) => {
						return m.chunks.indexOf(chunk) >= 0;
					});
				}
				console.log(chunkModules);
				for(let i = 0; i < chunkModules.length; i++) {
					const m = chunkModules[i];
					if(m.id === null) {
						m.id = currentId++;
					}
					if(options.end && currentId > options.end)
						break;
				}
			});
		});
	}
}
module.exports = ChunkModuleIdRangePlugin;
<commit_msg>remove leftover console.log in ChunkModuleIdRangePlugin<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
"use strict";
class ChunkModuleIdRangePlugin {
	constructor(options) {
		this.options = options;
	}
	apply(compiler) {
		const options = this.options;
		compiler.plugin("compilation", (compilation) => {
			compilation.plugin("module-ids", (modules) => {
				const chunk = this.chunks.filter((chunk) => {
					return chunk.name === options.name;
				})[0];
				if(!chunk) throw new Error("ChunkModuleIdRangePlugin: Chunk with name '" + options.name + "' was not found");
				let currentId = options.start;
				let chunkModules;
				if(options.order) {
					chunkModules = chunk.modules.slice();
					switch(options.order) {
						case "index":
							chunkModules.sort((a, b) => {
								return a.index - b.index;
							});
							break;
						case "index2":
							chunkModules.sort((a, b) => {
								return a.index2 - b.index2;
							});
							break;
						default:
							throw new Error("ChunkModuleIdRangePlugin: unexpected value of order");
					}

				} else {
					chunkModules = modules.filter((m) => {
						return m.chunks.indexOf(chunk) >= 0;
					});
				}

				for(let i = 0; i < chunkModules.length; i++) {
					const m = chunkModules[i];
					if(m.id === null) {
						m.id = currentId++;
					}
					if(options.end && currentId > options.end)
						break;
				}
			});
		});
	}
}
module.exports = ChunkModuleIdRangePlugin;
<|endoftext|>


<commit_before>var RC4WD = RC4WD || {};
RC4WD.ws = RC4WD.ws || new WebSocket('ws://'+location.host+'/ws');
RC4WD.top = function () {
    console.log('top');
    if(typeof BLE != 'undefined') {
        BLE.run('top');
    }
    console.log(RC4WD.ws);
    if(RC4WD.ws.readyState) {
        console.log('top');
        RC4WD.ws.send('top')
    }
}
RC4WD.buttom = function () {
    console.log('buttom');
    if(typeof BLE != 'undefined') {
        BLE.run('buttom');
    }
    console.log(RC4WD.ws);
}
RC4WD.left = function () {
    console.log('left');
    if(typeof BLE != 'undefined') {
        BLE.run('left');
    }
    console.log(RC4WD.ws);
}
RC4WD.right = function () {
    console.log('right');
    if(typeof BLE != 'undefined') {
        BLE.run('right');
    }
    console.log(RC4WD.ws);
}
RC4WD.stop = function () {
    console.log('stop');
    if(typeof BLE != 'undefined') {
        BLE.run('stop');
    }
    console.log(RC4WD.ws);
}
<commit_msg>Update 4wd.js<commit_after>var RC4WD = RC4WD || {};
RC4WD.ws = RC4WD.ws || new WebSocket('ws://'+location.host+'/ws','4wd-protocol');
RC4WD.top = function () {
    console.log('top');
    if(typeof BLE != 'undefined') {
        BLE.run('top');
    }
    console.log(RC4WD.ws);
    if(RC4WD.ws.readyState) {
        console.log('top');
        RC4WD.ws.send('top')
    }
}
RC4WD.buttom = function () {
    console.log('buttom');
    if(typeof BLE != 'undefined') {
        BLE.run('buttom');
    }
    console.log(RC4WD.ws);
}
RC4WD.left = function () {
    console.log('left');
    if(typeof BLE != 'undefined') {
        BLE.run('left');
    }
    console.log(RC4WD.ws);
}
RC4WD.right = function () {
    console.log('right');
    if(typeof BLE != 'undefined') {
        BLE.run('right');
    }
    console.log(RC4WD.ws);
}
RC4WD.stop = function () {
    console.log('stop');
    if(typeof BLE != 'undefined') {
        BLE.run('stop');
    }
    console.log(RC4WD.ws);
}
<|endoftext|>


<commit_before>var modelUtils = require('./lib/modelUtils.js');
var _ = require('lodash');
var choicesList = require('../lib/options');

module.exports = function(sequelize, DataTypes) {
  var attributes = {};
  var classMethods = {};
  var instanceMethods = {};
  attributes = {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      unique: true,
      autoIncrement: true
    },
    title:  {
      type: DataTypes.STRING,
      allowNull: false,
      label:'Program Title',
      validate: {
      }
    },
    purpose: {
      type: DataTypes.TEXT,
      allowNull: false,
      widget: 'textArea',
      validate: {
      },
      label: 'Purpose'
    },
    canBeReappliedFor: {
      type: DataTypes.BOOLEAN,
      defaultValue: false,
      widget: 'select',
      allowNull: false,
      label: 'Can Be Reapplied For',
      choices: { 0: 'No', 1:'Yes' }
    },
    eligibleBusinessLocation: {
      type: DataTypes.ARRAY(DataTypes.STRING),
      allowNull: false,
      multiple: true,
      widget: 'checkbox',
      choices: choicesList.eligibleBusinessLocation,
      label: 'Eligible Business Location'
    },
    disqualifyingFactors: {
      type: DataTypes.ARRAY(DataTypes.TEXT),
      allowNull: false,
      multiple: true,
      widget: 'textArea',
      label: 'Disqualifying Factors'
    },
    paperworkRequired: {
      type: DataTypes.ARRAY(DataTypes.TEXT),
      widget: 'textArea',
      label: 'Paperwork Required',
      multiple: true,
      allowNull: false,
    },
    applicationCost: {
      type: DataTypes.INTEGER,
      allowNull: false,
      label: 'Application Cost',
      widget: 'text',
    },
    applicationDeadline: {
      type: DataTypes.DATE,
      allowNull: false,
      widget: 'date',
      label: 'Application Deadline'
    },
    avgApplicationTime: {
      type: DataTypes.STRING,
      allowNull: false,
      widget: 'text',
      label: 'Average Application Time'
    },
    // TODO -- abstract choices to freaking callbacks.
    benefitType: {
      type: DataTypes.STRING,
      allowNull: false,
      widget: 'select',
      choices: choicesList.benefitType,
      label: 'Benefit Type'
    },
    benefitDescription: {
      type: DataTypes.TEXT,
      allowNull: false,
      widget: 'textArea',
      label: 'Benefit Description',
    },
    agencyName: {
      type: DataTypes.STRING,
      label: 'Agency Name',
      allowNull: false,
      widget: 'text',
    },
    agencyContactName: {
      type: DataTypes.STRING,
      label: 'Agency Contact Name',
      allowNull: false,
      widget: 'text',
    },
    agencyContactEmail: {
      type: DataTypes.STRING,
      label: 'Agency Contact Email',
      allowNull: false,
      widget: 'text',
    },
    agencyContactPhone: {
      type: DataTypes.STRING,
      label: 'Agency Contact Phone',
      allowNull: false,
      widget: 'text',
    },
    minimumYearsInBusiness: {
      type: DataTypes.INTEGER,
      allowNull: false,
      label: 'Minimum Years In Business',
      widget: 'text',
    },
    eligibleEntityTypes: {
      type: DataTypes.ARRAY(DataTypes.STRING),
      widget: 'checkbox',
      allowNull: false,
      multiple: true,
      choices: choicesList.eligibleEntityTypes,
      label: 'Eligible Entity Types'
    },
    currentEmployeesRequired: {
      type: DataTypes.ARRAY(DataTypes.STRING),
      widget: 'multiSelect',
      multiple: true,
      allowNull: false,
      choices: choicesList.currentEmployeesRequired,
      label: 'Current Employees Required',
    },
    annualRevenue: {
      type: DataTypes.STRING,
      widget: 'multiSelect',
      choices: choicesList.annualRevenue,
      multiple: true,
      allowNull: false,
      label: 'Annual Revenue',
    },
    eligibleIndustries: {
      type: DataTypes.ARRAY(DataTypes.STRING),
      multiple: true,
      allowNull: false,
      widget: 'multiSelect',
      choices: choicesList.eligibleIndustries,
      label: 'Eligible Industries',
    },
    gender: {
      type: DataTypes.STRING,
      allowNull: false,
      label: 'Gender',
      widget: 'radio',
      choices: { male: 'Male', female: 'Female'}
    },
    age: {
      type: DataTypes.INTEGER,
      allowNull: false,
      label: 'Age'
    },
    additionalDemographics:{
      type: DataTypes.ARRAY(DataTypes.STRING),
      allowNull: false,
      widget: 'checkbox',
      label: 'Additional Demographics',
      choices: { student: 'student', veteran: 'veteran', minority: 'minority' }
    }
 }

  classMethods = _.extend(modelUtils.classMethods, {});
  instanceMethods = _.extend(modelUtils.instanceMethods, {});

  return sequelize.define('Opportunity', attributes, {
    classMethods: classMethods,
    instanceMethods: instanceMethods
  });
}
<commit_msg>Add comment for fixing Opportunity Schema<commit_after>var modelUtils = require('./lib/modelUtils.js');
var _ = require('lodash');
var choicesList = require('../lib/options');

module.exports = function(sequelize, DataTypes) {
  var attributes = {};
  var classMethods = {};
  var instanceMethods = {};
  attributes = {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      unique: true,
      autoIncrement: true
    },
    title:  {
      type: DataTypes.STRING,
      allowNull: false,
      label:'Program Title',
      validate: {
      }
    },
    // TODO: Change to choices selection. Add 'other' field
    purpose: {
      type: DataTypes.TEXT,
      allowNull: false,
      widget: 'textArea',
      validate: {
      },
      label: 'Purpose'
    },
    // TODO: Remove later - Not used
    // canBeReappliedFor: {
    //   type: DataTypes.BOOLEAN,
    //   defaultValue: false,
    //   widget: 'select',
    //   allowNull: false,
    //   label: 'Can Be Reapplied For',
    //   choices: { 0: 'No', 1:'Yes' }
    // },
    // TODO: Add 'other' field and need options for distinct municipalities
    // TODO: Are we using zipcode's for this? Consider possibility
    eligibleBusinessLocation: {
      type: DataTypes.ARRAY(DataTypes.STRING),
      allowNull: false,
      multiple: true,
      widget: 'checkbox',
      choices: choicesList.eligibleBusinessLocation,
      label: 'Eligible Business Location'
    },
    // TODO: Remove later - Not used
    // disqualifyingFactors: {
    //   type: DataTypes.ARRAY(DataTypes.TEXT),
    //   allowNull: false,
    //   multiple: true,
    //   widget: 'textArea',
    //   label: 'Disqualifying Factors'
    // },
    // Note: These need to be separate inputs on the UI that get joined
    // in the backend.
    paperworkRequired: {
      type: DataTypes.ARRAY(DataTypes.TEXT),
      widget: 'textArea',
      label: 'Paperwork Required',
      multiple: true,
      allowNull: false,
    },
    applicationCost: {
      type: DataTypes.INTEGER,
      allowNull: false,
      label: 'Application Cost',
      widget: 'text',
    },
    applicationDeadline: {
      type: DataTypes.DATE,
      allowNull: false,
      widget: 'date',
      label: 'Application Deadline'
    },
    avgApplicationTime: {
      type: DataTypes.STRING,
      allowNull: false,
      widget: 'text',
      label: 'Average Application Time'
    },
    // TODO -- abstract choices to freaking callbacks.
    // TODO: Add 'other' field
    benefitType: {
      type: DataTypes.STRING,
      allowNull: false,
      widget: 'select',
      choices: choicesList.benefitType,
      label: 'Benefit Type'
    },
    benefitDescription: {
      type: DataTypes.TEXT,
      allowNull: false,
      widget: 'textArea',
      label: 'Benefit Description',
    },
    agencyName: {
      type: DataTypes.STRING,
      label: 'Agency Name',
      allowNull: false,
      widget: 'text',
    },
    agencyContactName: {
      type: DataTypes.STRING,
      label: 'Agency Contact Name',
      allowNull: false,
      widget: 'text',
    },
    agencyContactEmail: {
      type: DataTypes.STRING,
      label: 'Agency Contact Email',
      allowNull: false,
      widget: 'text',
    },
    agencyContactPhone: {
      type: DataTypes.STRING,
      label: 'Agency Contact Phone',
      allowNull: false,
      widget: 'text',
    },
    // TODO: Change it to options widget. Options are in options.js
    minimumYearsInBusiness: {
      type: DataTypes.INTEGER,
      allowNull: false,
      label: 'Minimum Years In Business',
      widget: 'text',
    },
    eligibleEntityTypes: {
      type: DataTypes.ARRAY(DataTypes.STRING),
      widget: 'checkbox',
      allowNull: false,
      multiple: true,
      choices: choicesList.eligibleEntityTypes,
      label: 'Eligible Entity Types'
    },
    currentEmployeesRequired: {
      type: DataTypes.ARRAY(DataTypes.STRING),
      widget: 'multiSelect',
      multiple: true,
      allowNull: false,
      choices: choicesList.currentEmployeesRequired,
      label: 'Current Employees Required',
    },
    annualRevenue: {
      type: DataTypes.STRING,
      widget: 'multiSelect',
      choices: choicesList.annualRevenue,
      multiple: true,
      allowNull: false,
      label: 'Annual Revenue',
    },
    // TODO: Need to add eligibleIndustries - other
    eligibleIndustries: {
      type: DataTypes.ARRAY(DataTypes.STRING),
      multiple: true,
      allowNull: false,
      widget: 'multiSelect',
      choices: choicesList.eligibleIndustries,
      label: 'Eligible Industries',
    },
    gender: {
      type: DataTypes.STRING,
      allowNull: false,
      label: 'Gender',
      widget: 'radio',
      choices: { any: 'Any', male: 'Male', female: 'Female', other: 'Other'}
    },
    // TODO: Make options field. Options in options.js
    age: {
      type: DataTypes.INTEGER,
      allowNull: false,
      label: 'Age'
    },
    additionalDemographics:{
      type: DataTypes.ARRAY(DataTypes.STRING),
      allowNull: false,
      widget: 'checkbox',
      label: 'Additional Demographics',
      choices: { any: 'any', student: 'student', veteran: 'veteran', minority: 'minority' }
    }
    // TODO: Add additionalGeneralInformation textArea
    // TODO: Add investingOwnMoney boolean field
    // TODO: Add moneyInvested text field for whene investingOwnMoney field is true
 }

  classMethods = _.extend(modelUtils.classMethods, {});
  instanceMethods = _.extend(modelUtils.instanceMethods, {});

  return sequelize.define('Opportunity', attributes, {
    classMethods: classMethods,
    instanceMethods: instanceMethods
  });
}
<|endoftext|>


<commit_before>var keystone = require('keystone'),
  async = require('async'),
  _ = require('underscore'),
  util = require('util'),
  Types = keystone.Field.Types;

/**
 * Translation Model
 * =============
 */

var Translation = new keystone.List('Translation', {
  track: true,
  drilldown: "authors"
});

Translation.add({
  when: { type: Types.Date, default: Date.now, initial: true },
  author: { type: Types.Relationship, ref: 'Student', hidden: true  },
  authors: { type: Types.Relationship, ref: 'Student', initial: true, index: true, many: true },
}, 'Meta', {
  partial: { type: Types.Boolean, default: false, hidden: true },
  multipleAuthors: { type: Types.Boolean, noedit: true },
});

/**
 * Hooks
 * =====
 */

Translation.schema.post('init', function() {
    this._original = this.toObject();
} );

Translation.schema.post('save', function() {
  var prevAuthors = [];

  if (this._original != undefined) {
    //console.log("Comparing translation to previous version.")
    var arr1 = _.pluck(this._original.authors, "id");
    var arr2 = _.pluck(this.authors, "id");
    var diff = _.difference(arr1, arr2);

    prevAuthors = _.filter(this._original.authors, function(obj) { return diff.indexOf(obj.id) >= 0; });

    //console.log("Translation had " + prevAuthors.length + " author(s) previously.")
  }

  //debugger;

	keystone.list('Student').model.find().where('_id').in(this.authors).exec(
    function(err, students) {

      async.each(students,
        function(student, _next) {
          //console.log("Post save -> student: " + student);

          student.refreshTranslations();
          _next();
		    }, function(err) {
          if (err) {
            console.error('===== Error updating translation author  =====');
          }
		    }
      );
    }
  );

  if (prevAuthors.length > 0) {
    keystone.list('Student').model.find().where('_id').in(prevAuthors).exec(
      function(err, students) {

        async.each(students,
          function(student, _next) {
            //console.log("Post save -> student: " + student);

            student.refreshTranslations();
            _next();
          }, function(err) {
            if (err) {
              console.error('===== Error updating previous translation author  =====');
            }
          }
        );
      }
    );
  }

});

Translation.schema.pre('save', function(next) {
  var translation = this;

  async.parallel([

    function(done) {
      //console.log("Translation has " + translation.authors.length + " author(s).")
      if (translation.authors.length > 1) {
        translation.multipleAuthors = true
      } else {
        translation.multipleAuthors = false
      }

      return done();
    }

  ], next);
});

Translation.schema.post('remove', function() {
	keystone.list('Student').model.findById(this.authors, function(err, student) {
		if (student) student.refreshTranslations();
	});
})

/**
 * Registration
 * ============
 */

Translation.defaultSort = '-when';
Translation.defaultColumns = 'when, authors';
Translation.register();
<commit_msg>editor for translations<commit_after>var keystone = require('keystone'),
  async = require('async'),
  _ = require('underscore'),
  util = require('util'),
  Types = keystone.Field.Types;

/**
 * Translation Model
 * =============
 */

var Translation = new keystone.List('Translation', {
  track: true,
  drilldown: "authors"
});

Translation.add({
  when: { type: Types.Date, default: Date.now, initial: true },
  author: { type: Types.Relationship, ref: 'Student', hidden: true  },
  authors: { type: Types.Relationship, ref: 'Student', initial: true, index: true, many: true },
  editor: { type: Types.Relationship, ref: 'Student', filters: { canEditArticles: true }}
}, 'Meta', {
  partial: { type: Types.Boolean, default: false, hidden: true },
  multipleAuthors: { type: Types.Boolean, noedit: true },
});

/**
 * Hooks
 * =====
 */

Translation.schema.post('init', function() {
    this._original = this.toObject();
} );

Translation.schema.post('save', function() {
  var prevAuthors = [];

  if (this._original != undefined) {
    //console.log("Comparing translation to previous version.")
    var arr1 = _.pluck(this._original.authors, "id");
    var arr2 = _.pluck(this.authors, "id");
    var diff = _.difference(arr1, arr2);

    prevAuthors = _.filter(this._original.authors, function(obj) { return diff.indexOf(obj.id) >= 0; });

    //console.log("Translation had " + prevAuthors.length + " author(s) previously.")
  }

  //debugger;

	keystone.list('Student').model.find().where('_id').in(this.authors).exec(
    function(err, students) {

      async.each(students,
        function(student, _next) {
          //console.log("Post save -> student: " + student);

          student.refreshTranslations();
          _next();
		    }, function(err) {
          if (err) {
            console.error('===== Error updating translation author  =====');
          }
		    }
      );
    }
  );

  if (prevAuthors.length > 0) {
    keystone.list('Student').model.find().where('_id').in(prevAuthors).exec(
      function(err, students) {

        async.each(students,
          function(student, _next) {
            //console.log("Post save -> student: " + student);

            student.refreshTranslations();
            _next();
          }, function(err) {
            if (err) {
              console.error('===== Error updating previous translation author  =====');
            }
          }
        );
      }
    );
  }

});

Translation.schema.pre('save', function(next) {
  var translation = this;

  async.parallel([

    function(done) {
      //console.log("Translation has " + translation.authors.length + " author(s).")
      if (translation.authors.length > 1) {
        translation.multipleAuthors = true
      } else {
        translation.multipleAuthors = false
      }

      return done();
    }

  ], next);
});

Translation.schema.post('remove', function() {
	keystone.list('Student').model.findById(this.authors, function(err, student) {
		if (student) student.refreshTranslations();
	});
})

/**
 * Registration
 * ============
 */

Translation.defaultSort = '-when';
Translation.defaultColumns = 'when, authors';
Translation.register();
<|endoftext|>