<commit_before>(function($){

var win = $(window),
	body = $('body'),
	headerContainer = $('header'),
	header = $('#header'),
	tab = $('.tab');

var siteURLs = [
	'lisaot.to',
	'localhost',
	'grad.lisaot.to',
	'staging.lisaot.to'
];

// scroll to the content...
// different for mobile
function scrollToContent(e, amount, time) {
	if (e) e.preventDefault();

	var top = amount || $('#content').offset().top,
		el = navigator.userAgent.match(/(iPod|iPhone|iPad|Android)/) ? body : $('html, body');
	el.animate({
		scrollTop: top
	}, time || 500);
}

function headerThings() {
	headerContainer.height( win.height() );
}
headerThings();
win.resize( headerThings );

function toggle() {
	$( this.getAttribute('data-toggle') ).toggleClass( this.getAttribute('data-toggle-class') );
	promptScrollOff();
}
body.on('click', '[data-toggle]', toggle);

function toggleGridOverlay() {
	var overlay = $('.gridoverlay');
	overlay.animate({
		opacity: overlay.css('opacity') === '0' ? 1 : 0
	});

	var $this = $(this);
	$this.text( $this.text() === 'VIEW GRID' ? 'HIDE GRID' : 'VIEW GRID' );
}
body.on('click', '.gridbutton', toggleGridOverlay);

// scroll "back up"
body.on('click', '.backup .title', scrollToContent);

// Scroll down for more button
function promptScrollOn() {
	$('.scroll').addClass('prompting');
}

function promptScrollOff() {
	$('.scroll').removeClass('prompting');
}

function decideWhenToPrompt() {
	var url = location.href;
	url = url.split('/');
	for ( var i = 0; i < url.length; i++ ) {
		if ( url[i] === 'project' ) {
			setTimeout(promptScrollOn, 2500);
			return;
		}
	}
}

body.on('click', '.scroll', function(e) {
	promptScrollOff();
	scrollToContent( e, win.height() * 0.75 );
});

decideWhenToPrompt();
win.scroll(promptScrollOff);

// Return booleans for home page, about page, and just having been on a project page
function isHome() {
	return location.href === 'http://localhost/portfolio/' || location.pathname === '/';
}
function isAbout() {
	return location.href === 'http://localhost/portfolio/about/' || location.href === 'http://localhost/portfolio/about' || location.pathname === '/about/' || location.pathname === '/about';
}
function is404() {
	return $('.error').length > 0;
}
function comingFromInternal() {
	var referrer = document.referrer || loadedFromPage,
	 	internal;
	siteURLs.forEach(function(url) {
		if ( referrer.indexOf(url) >= 0 ) return internal = true;
	});
	return internal ? true : false;
}

// click on the work link: if on the work page, should scroll to where the content starts
function scrollToWork(e) {
	e.preventDefault();
	if ( isHome() ) {
		scrollToContent();
	}
}

$('#work-link').click(scrollToWork);

// Smooth AJAX loading!
function loadElements(data) {

	if ( loadedFromElement.closest('#content').length > 0 ) {
		loadedFromElement.fadeOut();
	}

	promptScrollOff();

	// time delay
	var delay = 500;

	// Fade out and remove current project elements
	var curContent = $('#content');

	curContent.height( curContent.height() );
	curContent.find('*').fadeOut(delay);

	// Animate back to the top of the content and remove old elements
	setTimeout(function(){
		if (win.width() > 960) {
			scrollToContent(null, null, 1);
		} else {
			if ( comingFromInternal() && (isHome() || isAbout()) ) {
				scrollToContent(null, null);
			}
		}
		curContent.find('*').remove();
	}, delay + 5);

	var $data = $(data),
		url,
		title,
		newContent;

	var newBody = data.slice(data.indexOf('') + 1);
	var newBodyClass = newBody.slice(newBody.indexOf('class="') + 7);
	newBodyClass = newBodyClass.slice(0, newBodyClass.indexOf('"'));
	var newBodyScroll = newBody.slice(newBody.indexOf('data-scroll="') + 13);
	newBodyScroll = newBodyScroll.slice(0, newBodyScroll.indexOf('"'));

	body.attr('class', newBodyClass);
	body.attr('data-scroll', newBodyScroll);

	for ( var i = 0; i < $data.length; i++ ) {
		var el = $data[i];

		if (el.tagName === 'HEADER') url = $(el).find('#page-url').html();
		if (el.tagName === 'TITLE') title = el.innerHTML;
		if (el.id === 'content') newContent = $(el);
	}

	if ( !!history ) {
		window.history.pushState({}, title, url);
		document.title = title;
	}

	decideWhenToPrompt();

	var newElements = newContent.children(),
		projectSamples = newContent.find('.project-sample'),
		newReadyElements = newContent.find('.navigation, .intro'),
		banner = newContent.find('.banner'),
		newScrollingElements = newElements.not('.banner, .navigation, .intro').find('img, p').not('.icon-arrow-box');

	banner.children().addClass('fader faded');
	projectSamples.addClass('fader faded');
	newReadyElements.addClass('fader faded');
	newScrollingElements.addClass('fader faded');

	setTimeout(function(){

		newElements.appendTo(curContent);

		setTimeout(function(){
			banner.find('.hgroup').removeClass('faded');
			newReadyElements.removeClass('faded');
		}, 100);

		banner.imagesLoaded()
			.done(function(){
				banner.children().removeClass('faded');
			});

		projectSamples.each(function(){
			var $this = $(this);
			setTimeout(function(){
				$this.removeClass('faded');
			}, $this.index() * delay / 2);
		});

		if ( isAbout() ) newElements.find('.faded').removeClass('faded');

		centerPageContent();
		curContent.height('auto');

	}, delay + 10);

	win.scroll(function() {
		newScrollingElements.each(function(){
			var $this = $(this);
			if ( win.scrollTop() + win.height() > $this.offset().top + 50 ) {
				// Three columns in a row (or two columns)
				if ( $this.hasClass('onecolumn') && $this.prev('.onecolumn').length > 0 && $this.next('.onecolumn.last').length > 0 || $this.hasClass('halfcolumn') && $this.hasClass('last')) {
					setTimeout(function(){
						$this.removeClass('faded');
					}, 150);
				} else if ( $this.hasClass('last') && $this.prev('.onecolumn').length > 0) {
					setTimeout(function(){
						$this.removeClass('faded');
					}, 300);

				} else {
					$this.removeClass('faded');
				}
			}
		});
	});

	// send a pageview
	ga('send', 'pageview');
}

var loadedFromPage,
	loadedFromElement;
function loadPage(e) {
	if (e) e.preventDefault();

	loadedFromElement = $(this);
	loadedFromPage = location.href;

	var url = this.href;

	// update nav highlighting
	var aboutLink = $('#about-link'),
		workLink = $('#work-link');

	if ( loadedFromElement.closest('#about-link').length === 1 ) {
		workLink.find('p').removeClass('blue');
		workLink.find('span').remove();
		aboutLink.find('p').addClass('blue');
	} else {
		workLink.find('p').addClass('blue');
		if ( workLink.find('span').length === 0 ) {
			workLink.append('');
		}
		aboutLink.find('p').removeClass('blue');
	}

	if ( url !== location.href && url + '/' !== location.href) {
		$.ajax({
			url: url,
			success: loadElements
		});
	}
}
if ( !$('html').hasClass('oldie')) {
	body.on('click', '.navigation .next, .project-sample, .back, nav a', loadPage);
}

function shouldWeCenter() {
	return body.attr('data-scroll') === 'false';
}

function centerPageContent() {
	if ( shouldWeCenter() ) {
		var content = $('#content'),
			vcenter = $('.vcenter');
        content.height('auto');
        if ( win.height() > content.height() ) {
            content.height(win.height());
			setTimeout(function(){
				content.height(win.height());
			}, 1);
        }
        if (content.height() > vcenter.height() + 2 * Math.round(parseInt( vcenter.parent().css('margin-top'), 10))) {
            vcenter.css({
                top: (content.height() - vcenter.height() - 2 * parseInt( vcenter.parent().css('margin-top'), 10)) / 2
            });
        } else {
            vcenter.css({ top: 0 });
        }
    }
}
centerPageContent();
win.on('load resize', centerPageContent);

}(jQuery));
<commit_msg>don't show scroll prompt when past 100 px<commit_after>(function($){

var win = $(window),
	body = $('body'),
	headerContainer = $('header'),
	header = $('#header'),
	tab = $('.tab');

var siteURLs = [
	'lisaot.to',
	'localhost',
	'grad.lisaot.to',
	'staging.lisaot.to'
];

// scroll to the content...
// different for mobile
function scrollToContent(e, amount, time) {
	if (e) e.preventDefault();

	var top = amount || $('#content').offset().top,
		el = navigator.userAgent.match(/(iPod|iPhone|iPad|Android)/) ? body : $('html, body');
	el.animate({
		scrollTop: top
	}, time || 500);
}

function headerThings() {
	headerContainer.height( win.height() );
}
headerThings();
win.resize( headerThings );

function toggle() {
	$( this.getAttribute('data-toggle') ).toggleClass( this.getAttribute('data-toggle-class') );
	promptScrollOff();
}
body.on('click', '[data-toggle]', toggle);

function toggleGridOverlay() {
	var overlay = $('.gridoverlay');
	overlay.animate({
		opacity: overlay.css('opacity') === '0' ? 1 : 0
	});

	var $this = $(this);
	$this.text( $this.text() === 'VIEW GRID' ? 'HIDE GRID' : 'VIEW GRID' );
}
body.on('click', '.gridbutton', toggleGridOverlay);

// scroll "back up"
body.on('click', '.backup .title', scrollToContent);

// Scroll down for more button
function promptScrollOn() {
	if ( win.scrollTop < 100 ) $('.scroll').addClass('prompting');
}

function promptScrollOff() {
	$('.scroll').removeClass('prompting');
}

function decideWhenToPrompt() {
	var url = location.href;
	url = url.split('/');
	// only prompt if we're on a project page
	for ( var i = 0; i < url.length; i++ ) {
		if ( url[i] === 'project' ) {
			setTimeout(promptScrollOn, 2500);
			return;
		}
	}
}

body.on('click', '.scroll', function(e) {
	promptScrollOff();
	scrollToContent( e, win.height() * 0.75 );
});

decideWhenToPrompt();
win.scroll(promptScrollOff);

// Return booleans for home page, about page, and just having been on a project page
function isHome() {
	return location.href === 'http://localhost/portfolio/' || location.pathname === '/';
}
function isAbout() {
	return location.href === 'http://localhost/portfolio/about/' || location.href === 'http://localhost/portfolio/about' || location.pathname === '/about/' || location.pathname === '/about';
}
function is404() {
	return $('.error').length > 0;
}
function comingFromInternal() {
	var referrer = document.referrer || loadedFromPage,
	 	internal;
	siteURLs.forEach(function(url) {
		if ( referrer.indexOf(url) >= 0 ) return internal = true;
	});
	return internal ? true : false;
}

// click on the work link: if on the work page, should scroll to where the content starts
function scrollToWork(e) {
	e.preventDefault();
	if ( isHome() ) {
		scrollToContent();
	}
}

$('#work-link').click(scrollToWork);

// Smooth AJAX loading!
function loadElements(data) {

	if ( loadedFromElement.closest('#content').length > 0 ) {
		loadedFromElement.fadeOut();
	}

	promptScrollOff();

	// time delay
	var delay = 500;

	// Fade out and remove current project elements
	var curContent = $('#content');

	curContent.height( curContent.height() );
	curContent.find('*').fadeOut(delay);

	// Animate back to the top of the content and remove old elements
	setTimeout(function(){
		if (win.width() > 960) {
			scrollToContent(null, null, 1);
		} else {
			if ( comingFromInternal() && (isHome() || isAbout()) ) {
				scrollToContent(null, null);
			}
		}
		curContent.find('*').remove();
	}, delay + 5);

	var $data = $(data),
		url,
		title,
		newContent;

	var newBody = data.slice(data.indexOf('') + 1);
	var newBodyClass = newBody.slice(newBody.indexOf('class="') + 7);
	newBodyClass = newBodyClass.slice(0, newBodyClass.indexOf('"'));
	var newBodyScroll = newBody.slice(newBody.indexOf('data-scroll="') + 13);
	newBodyScroll = newBodyScroll.slice(0, newBodyScroll.indexOf('"'));

	body.attr('class', newBodyClass);
	body.attr('data-scroll', newBodyScroll);

	for ( var i = 0; i < $data.length; i++ ) {
		var el = $data[i];

		if (el.tagName === 'HEADER') url = $(el).find('#page-url').html();
		if (el.tagName === 'TITLE') title = el.innerHTML;
		if (el.id === 'content') newContent = $(el);
	}

	if ( !!history ) {
		window.history.pushState({}, title, url);
		document.title = title;
	}

	decideWhenToPrompt();

	var newElements = newContent.children(),
		projectSamples = newContent.find('.project-sample'),
		newReadyElements = newContent.find('.navigation, .intro'),
		banner = newContent.find('.banner'),
		newScrollingElements = newElements.not('.banner, .navigation, .intro').find('img, p').not('.icon-arrow-box');

	banner.children().addClass('fader faded');
	projectSamples.addClass('fader faded');
	newReadyElements.addClass('fader faded');
	newScrollingElements.addClass('fader faded');

	setTimeout(function(){

		newElements.appendTo(curContent);

		setTimeout(function(){
			banner.find('.hgroup').removeClass('faded');
			newReadyElements.removeClass('faded');
		}, 100);

		banner.imagesLoaded()
			.done(function(){
				banner.children().removeClass('faded');
			});

		projectSamples.each(function(){
			var $this = $(this);
			setTimeout(function(){
				$this.removeClass('faded');
			}, $this.index() * delay / 2);
		});

		if ( isAbout() ) newElements.find('.faded').removeClass('faded');

		centerPageContent();
		curContent.height('auto');

	}, delay + 10);

	win.scroll(function() {
		newScrollingElements.each(function(){
			var $this = $(this);
			if ( win.scrollTop() + win.height() > $this.offset().top + 50 ) {
				// Three columns in a row (or two columns)
				if ( $this.hasClass('onecolumn') && $this.prev('.onecolumn').length > 0 && $this.next('.onecolumn.last').length > 0 || $this.hasClass('halfcolumn') && $this.hasClass('last')) {
					setTimeout(function(){
						$this.removeClass('faded');
					}, 150);
				} else if ( $this.hasClass('last') && $this.prev('.onecolumn').length > 0) {
					setTimeout(function(){
						$this.removeClass('faded');
					}, 300);

				} else {
					$this.removeClass('faded');
				}
			}
		});
	});

	// send a pageview
	ga('send', 'pageview');
}

var loadedFromPage,
	loadedFromElement;
function loadPage(e) {
	if (e) e.preventDefault();

	loadedFromElement = $(this);
	loadedFromPage = location.href;

	var url = this.href;

	// update nav highlighting
	var aboutLink = $('#about-link'),
		workLink = $('#work-link');

	if ( loadedFromElement.closest('#about-link').length === 1 ) {
		workLink.find('p').removeClass('blue');
		workLink.find('span').remove();
		aboutLink.find('p').addClass('blue');
	} else {
		workLink.find('p').addClass('blue');
		if ( workLink.find('span').length === 0 ) {
			workLink.append('');
		}
		aboutLink.find('p').removeClass('blue');
	}

	if ( url !== location.href && url + '/' !== location.href) {
		$.ajax({
			url: url,
			success: loadElements
		});
	}
}
if ( !$('html').hasClass('oldie')) {
	body.on('click', '.navigation .next, .project-sample, .back, nav a', loadPage);
}

function shouldWeCenter() {
	return body.attr('data-scroll') === 'false';
}

function centerPageContent() {
	if ( shouldWeCenter() ) {
		var content = $('#content'),
			vcenter = $('.vcenter');
        content.height('auto');
        if ( win.height() > content.height() ) {
            content.height(win.height());
			setTimeout(function(){
				content.height(win.height());
			}, 1);
        }
        if (content.height() > vcenter.height() + 2 * Math.round(parseInt( vcenter.parent().css('margin-top'), 10))) {
            vcenter.css({
                top: (content.height() - vcenter.height() - 2 * parseInt( vcenter.parent().css('margin-top'), 10)) / 2
            });
        } else {
            vcenter.css({ top: 0 });
        }
    }
}
centerPageContent();
win.on('load resize', centerPageContent);

}(jQuery));
<|endoftext|>


<commit_before>require('dotenv-safe').config();
require('./app');<commit_msg>lint fix<commit_after>require('dotenv-safe').config();
require('./app');
<|endoftext|>


<commit_before>(function(window, document) {
  var diff = require('virtual-dom/diff');
  var patch = require('virtual-dom/patch');
  var createElement = require('virtual-dom/create-element');
  var _ = require('underscore');
  var render = require('./view.js');

  document.addEventListener("DOMContentLoaded", function() {
    var eventQueue = [];

    document.body.addEventListener("click", function(e) { eventQueue.push(e); });
    document.body.addEventListener("dblclick", function(e) { eventQueue.push(e); });
    document.body.addEventListener("keydown", function(e) { eventQueue.push(e); });
    window.addEventListener("hashchange", function(e) { eventQueue.push(e); });

    var view = window.location.hash.split("#")[1] || "/";

    var stored = JSON.parse(localStorage.getItem('state'));
    var state;
    if (stored) {
      state = stored;
      state.view = view;
    } else {
      state = { todos: [], input: "", currentId: 1, view: view };
    }

    //populate DOM
    var tree = render(state);
    var rootNode = createElement(tree);
    document.body.appendChild(rootNode);

    function update() {
      function findTodo(target) {
        var id = parseInt(ev.target.dataset.id);
        return _.find(state.todos, function(t) { return t.id === id });
      }

      function endEdit(todo) {
        if (todo !== null && todo !== undefined) {
          var text = todo.text.trim();
          if (text === "") {
            state.todos = _.reject(state.todos, function(t) { return t.id === todo.id });
          } else {
            todo.editing = false;
          }
        }
      }

      while (eventQueue.length > 0) {
        var ev = eventQueue.pop();
        switch (ev.type) {

          case "keydown":
            if (ev.target.id === "todo-input") {
              if (ev.key === "Enter") {
                var text = ev.target.value.trim();
                if (text.length > 0) {
                  state.todos.push({
                    text: text,
                    completed: false,
                    editing: false,
                    id: state.currentId
                  });
                  state.currentId++;
                  state.input = "";
                }
              } else {
                state.input = ev.target.value;
              }
            } else if (ev.target.className === "edit") {
              if (ev.key === "Enter") {
                var edit = _.find(state.todos, function(t) { return t.editing });
                endEdit(edit);
              } else {
                var todo = findTodo(ev.target);
                todo.text = ev.target.value;
              }
            }
            break;

          case "click":
            var id = parseInt(parseInt(ev.target.dataset.id));
            var edit = _.find(state.todos, function(t) { return t.editing });

            //cancel edit when you click anywhere except on the item you're editing
            if (edit
                && !(ev.target.className === "todo-label" && id === edit.id)
                && !(ev.target.className === "edit" && id === edit.id))
            {
              endEdit(edit);
            }

            if (ev.target.className === "destroy") {
              state.todos = _.reject(state.todos, function(t) { return t.id === id });
            } else if (ev.target.className === "toggle") {
              var todo = findTodo(ev.target);
              todo.completed = ev.target.checked;
            } else if (ev.target.className === "toggle-all") {
              var checked = ev.target.checked;
              _.each(state.todos, function(t) { t.completed = checked; });
            }
            break;

          case "dblclick":
            if (_.contains(ev.target.className.split(" "), "todo-label")) {
              var todo = findTodo(ev.target);
              todo.editing = true;
            }
            break;

          case "hashchange":
            var url = ev.newURL.split("#")[1];
            state.view = url;
            break;
        }
      }

      localStorage.setItem('state', JSON.stringify(state));

      var newTree = render(state);
      var patches = diff(tree, newTree);
      rootNode = patch(rootNode, patches);
      tree = newTree;
      requestAnimationFrame(update);
    }

    requestAnimationFrame(update);
  });
})(window, document);
<commit_msg>Fix Chrome bug<commit_after>(function(window, document) {
  var diff = require('virtual-dom/diff');
  var patch = require('virtual-dom/patch');
  var createElement = require('virtual-dom/create-element');
  var _ = require('underscore');
  var render = require('./view.js');

  document.addEventListener("DOMContentLoaded", function() {
    var eventQueue = [];

    document.body.addEventListener("click", function(e) { eventQueue.push(e); });
    document.body.addEventListener("dblclick", function(e) { eventQueue.push(e); });
    document.body.addEventListener("keydown", function(e) { eventQueue.push(e); });
    window.addEventListener("hashchange", function(e) { eventQueue.push(e); });

    var view = window.location.hash.split("#")[1] || "/";

    var stored = JSON.parse(localStorage.getItem('state'));
    var state;
    if (stored) {
      state = stored;
      state.view = view;
    } else {
      state = { todos: [], input: "", currentId: 1, view: view };
    }

    //populate DOM
    var tree = render(state);
    var rootNode = createElement(tree);
    document.body.appendChild(rootNode);

    function update() {
      function findTodo(target) {
        var id = parseInt(target.dataset.id);
        return _.find(state.todos, function(t) { return t.id === id });
      }

      function endEdit(todo) {
        if (todo !== null && todo !== undefined) {
          var text = todo.text.trim();
          if (text === "") {
            state.todos = _.reject(state.todos, function(t) { return t.id === todo.id });
          } else {
            todo.editing = false;
          }
        }
      }

      while (eventQueue.length > 0) {
        var ev = eventQueue.pop();
        switch (ev.type) {

          case "keydown":
            if (ev.target.id === "todo-input") {
              if (ev.key === "Enter" || ev.keyIdentifier === "Enter") {
                var text = ev.target.value.trim();
                if (text.length > 0) {
                  state.todos.push({
                    text: text,
                    completed: false,
                    editing: false,
                    id: state.currentId
                  });
                  state.currentId++;
                  state.input = "";
                }
              } else {
                state.input = ev.target.value;
              }
            } else if (ev.target.className === "edit") {
              if (ev.key === "Enter" || ev.keyIdentifier === "Enter") {
                var edit = _.find(state.todos, function(t) { return t.editing });
                endEdit(edit);
              } else {
                var todo = findTodo(ev.target);
                todo.text = ev.target.value;
              }
            }
            break;

          case "click":
            var id = parseInt(parseInt(ev.target.dataset.id));
            var edit = _.find(state.todos, function(t) { return t.editing });

            //cancel edit when you click anywhere except on the item you're editing
            if (edit
                && !(ev.target.className === "todo-label" && id === edit.id)
                && !(ev.target.className === "edit" && id === edit.id))
            {
              endEdit(edit);
            }

            if (ev.target.className === "destroy") {
              state.todos = _.reject(state.todos, function(t) { return t.id === id });
            } else if (ev.target.className === "toggle") {
              var todo = findTodo(ev.target);
              todo.completed = ev.target.checked;
            } else if (ev.target.className === "toggle-all") {
              var checked = ev.target.checked;
              _.each(state.todos, function(t) { t.completed = checked; });
            }
            break;

          case "dblclick":
            if (_.contains(ev.target.className.split(" "), "todo-label")) {
              var todo = findTodo(ev.target);
              todo.editing = true;
            }
            break;

          case "hashchange":
            var url = ev.newURL.split("#")[1];
            state.view = url;
            break;
        }
      }

      localStorage.setItem('state', JSON.stringify(state));

      var newTree = render(state);
      var patches = diff(tree, newTree);
      rootNode = patch(rootNode, patches);
      tree = newTree;
      requestAnimationFrame(update);
    }

    requestAnimationFrame(update);
  });
})(window, document);
<|endoftext|>


<commit_before>var fs = require('fs');
var Path = require('path');
var debug = require('debug')('express-dom');
var Pool = require('./pool');
var URL = require('url');
var BufferList = require('bl');

var dom = module.exports = function(input, opts) {
	if (!dom.pool) {
		dom.pool = new Pool(dom.settings.pool, dom); // do not use instance options
		dom.acquire = dom.pool.acquire.bind(dom.pool);
		dom.release = dom.pool.release.bind(dom.pool);
	}
	var h = new Handler(input, opts);
	return h.chainable;
};

dom.plugins = require('./plugins');

dom.settings = {
	plugins: [dom.plugins.nocss, dom.plugins.redirect, dom.plugins.html],
	display: process.env.DISPLAY || 0,
	pool: {
		max: 16,
		destroyTimeout: 600000,
		idleTimeout: 180000
	},
	style: `/* disable viewport repaints */
		html {
			display:none !important;
		}
		/* do not animate as far as possible */
		* {
			-webkit-transition:none !important;
			transition:none !important;
			-webkit-transition-property: none !important;
			transition-property: none !important;
			-webkit-transform: none !important;
			transform: none !important;
			-webkit-animation: none !important;
			animation: none !important;
		}`,
	console: !!process.env.DEBUG,
	'auto-load-images': false,
	stall: 15000,
	allow: "same-origin",
	navigation: false,
	develop: !!process.env.DEVELOP
};

function Handler(input) {
	debug("new handler", input);
	var h = this;
	h.input = input;
	h.settings = {};

	h.chainable = h.middleware.bind(h);
	h.chainable.prepare = function(opts) {
		h.settings.prepare = initOpts(opts, Array.from(arguments));
		return h.chainable;
	};
	h.chainable.load = function(opts) {
		h.settings.load = initOpts(opts, Array.from(arguments));
		return h.chainable;
	};
}

function initOpts(opts, args) {
	if (typeof opts == "function") opts = null;
	else args.shift();

	opts = Object.assign({filters: []}, dom.settings, opts);
	var plugins = opts.plugins;
	if (typeof plugins == "function") plugins = [plugins];
	opts.plugins = args.concat(plugins || dom.settings.plugins);

	return opts;
}

Handler.prototype.middleware = function(req, res, next) {
	var h = this;
	var input = h.input || req.path;
	var statics = req.app.get('statics');

	h.getView(input, statics, function(err, data) {
		if (err) return next(err);
		var request = {
			location: {
				protocol: req.protocol,
				host: req.headers.host,
				pathname: req.path,
				query: req.query
			},
			input: data,
			statics: statics,
			headers: req.headers
		};
		var response = {
			output: null,
			headers: {},
			status: null
		};
		debug('view loaded', request.location.pathname);
		if (h.settings.prepare) {
			h.runMethod('prepare', h.settings.prepare, request, response, function(err) {
				if (err) return next(err);
				between();
			});
		} else {
			between();
		}
		function between() {
			if (h.settings.load) {
				if (h.settings.load.develop) {
					console.warn("develop mode is ON");
				} else {
					if (response.output) {
						request.input = response.output;
						response.output = null;
					}
					return h.runMethod('load', h.settings.load, request, response, function(err) {
						if (err) return next(err);
						finalize();
					});
				}
			}
			finalize();
		}
		function finalize() {
			var data = response.output || request.input;
			if (!response.headers['Content-Type']) {
				response.headers['Content-Type'] = "text/html";
			}
			for (var header in response.headers) {
				res.setHeader(header, response.headers[header]);
			}
			// hopefully free faster that memory
			delete request.input;
			delete response.output;
			var status = response.status;
			if (data) {
				var isPath = true, isStream = false;
				if (Buffer.isBuffer(data)) {
					isPath = false;
				} else if (typeof data.pipe == "function") {
					isPath = false;
					isStream = true;
				} else if (typeof data != "string") {
					data = data.toString();
				}
				if (isPath && data.startsWith('<')) {
					isPath = false;
				}
				if (isPath) {
					res.sendFile(data);
				} else {
					if (status) res.status(status);
					if (isStream) {
						data.pipe(res);
					} else {
						res.send(data);
					}
				}
			} else {
				res.sendStatus(status || 400);
			}
		}
	});
};

Handler.prototype.getView = function(input, root, cb) {
	if (Buffer.isBuffer(input)) return cb(null, input);
	if (typeof input.pipe == "function") return input.pipe(BufferList(cb));
	if (typeof input != "string") return cb(new Error("unknown input type"));
	if (input.startsWith('<')) return cb(null, input); // html string
	if (!root) return cb(new Error("Please app.set('statics', rootDir)"));
	var path = Path.join(root, input);
	if (path.indexOf(root) !== 0) return cb(new Error("Path outside statics dir\n" + path));
	if (Path.extname(path) != ".html") path += ".html";
	debug("read view from", path);
	fs.readFile(path, cb);
};

Handler.prototype.runMethod = function(method, settings, request, response, cb) {
	var h = this;
	dom.pool.acquire(function(err, page) {
		if (err) return next(err);
		processMw(page, settings, request, response);
		page.when('idle', function(wcb) {
			debug("release idle page", page.uri);
			page.pingTime = Date.now();
			wcb();
			dom.pool.release(page);
			cb();
		});
		settings.content = request.input;
		page[method](URL.format(request.location), settings);
		delete settings.content;
	});
};

function processMw(page, settings, request, response) {
	var list = settings.plugins;
	for (var i=0; i < list.length; i++) {
		list[i](page, settings, request, response);
	}
}

<commit_msg>Add debug stanzas<commit_after>var fs = require('fs');
var Path = require('path');
var debug = require('debug')('express-dom');
var Pool = require('./pool');
var URL = require('url');
var BufferList = require('bl');

var dom = module.exports = function(input, opts) {
	if (!dom.pool) {
		dom.pool = new Pool(dom.settings.pool, dom); // do not use instance options
		dom.acquire = dom.pool.acquire.bind(dom.pool);
		dom.release = dom.pool.release.bind(dom.pool);
	}
	var h = new Handler(input, opts);
	return h.chainable;
};

dom.plugins = require('./plugins');

dom.settings = {
	plugins: [dom.plugins.nocss, dom.plugins.redirect, dom.plugins.html],
	display: process.env.DISPLAY || 0,
	pool: {
		max: 16,
		destroyTimeout: 600000,
		idleTimeout: 180000
	},
	style: `/* disable viewport repaints */
		html {
			display:none !important;
		}
		/* do not animate as far as possible */
		* {
			-webkit-transition:none !important;
			transition:none !important;
			-webkit-transition-property: none !important;
			transition-property: none !important;
			-webkit-transform: none !important;
			transform: none !important;
			-webkit-animation: none !important;
			animation: none !important;
		}`,
	console: !!process.env.DEBUG,
	'auto-load-images': false,
	stall: 15000,
	allow: "same-origin",
	navigation: false,
	develop: !!process.env.DEVELOP
};

function Handler(input) {
	debug("new handler", input);
	var h = this;
	h.input = input;
	h.settings = {};

	h.chainable = h.middleware.bind(h);
	h.chainable.prepare = function(opts) {
		h.settings.prepare = initOpts(opts, Array.from(arguments));
		return h.chainable;
	};
	h.chainable.load = function(opts) {
		h.settings.load = initOpts(opts, Array.from(arguments));
		return h.chainable;
	};
}

function initOpts(opts, args) {
	if (typeof opts == "function") opts = null;
	else args.shift();

	opts = Object.assign({filters: []}, dom.settings, opts);
	var plugins = opts.plugins;
	if (typeof plugins == "function") plugins = [plugins];
	opts.plugins = args.concat(plugins || dom.settings.plugins);

	return opts;
}

Handler.prototype.middleware = function(req, res, next) {
	var h = this;
	var input = h.input || req.path;
	var statics = req.app.get('statics');

	h.getView(input, statics, function(err, data) {
		if (err) return next(err);
		var request = {
			location: {
				protocol: req.protocol,
				host: req.headers.host,
				pathname: req.path,
				query: req.query
			},
			input: data,
			statics: statics,
			headers: req.headers
		};
		var response = {
			output: null,
			headers: {},
			status: null
		};
		debug('view loaded', request.location.pathname);
		if (h.settings.prepare) {
			h.runMethod('prepare', h.settings.prepare, request, response, function(err) {
				if (err) return next(err);
				between();
			});
		} else {
			between();
		}
		function between() {
			if (h.settings.load) {
				if (h.settings.load.develop) {
					console.warn("develop mode is ON");
				} else {
					if (response.output) {
						request.input = response.output;
						response.output = null;
					}
					return h.runMethod('load', h.settings.load, request, response, function(err) {
						if (err) return next(err);
						finalize();
					});
				}
			}
			finalize();
		}
		function finalize() {
			var data = response.output || request.input;
			if (!response.headers['Content-Type']) {
				response.headers['Content-Type'] = "text/html";
			}
			for (var header in response.headers) {
				res.setHeader(header, response.headers[header]);
			}
			// hopefully free faster that memory
			delete request.input;
			delete response.output;
			var status = response.status;
			if (data) {
				var isPath = true, isStream = false;
				if (Buffer.isBuffer(data)) {
					isPath = false;
				} else if (typeof data.pipe == "function") {
					isPath = false;
					isStream = true;
				} else if (typeof data != "string") {
					data = data.toString();
				}
				if (isPath && data.startsWith('<')) {
					isPath = false;
				}
				if (isPath) {
					res.sendFile(data);
				} else {
					if (status) res.status(status);
					if (isStream) {
						data.pipe(res);
					} else {
						res.send(data);
					}
				}
			} else {
				res.sendStatus(status || 400);
			}
		}
	});
};

Handler.prototype.getView = function(input, root, cb) {
	if (Buffer.isBuffer(input)) return cb(null, input);
	if (typeof input.pipe == "function") return input.pipe(BufferList(cb));
	if (typeof input != "string") return cb(new Error("unknown input type"));
	if (input.startsWith('<')) return cb(null, input); // html string
	if (!root) return cb(new Error("Please app.set('statics', rootDir)"));
	var path = Path.join(root, input);
	if (path.indexOf(root) !== 0) return cb(new Error("Path outside statics dir\n" + path));
	if (Path.extname(path) != ".html") path += ".html";
	debug("read view from", path);
	fs.readFile(path, cb);
};

Handler.prototype.runMethod = function(method, settings, request, response, cb) {
	var h = this;
	dom.pool.acquire(function(err, page) {
		if (err) return next(err);
		processMw(page, settings, request, response);
		page.when('idle', function(wcb) {
			debug("release idle page", method, page.uri);
			page.pingTime = Date.now();
			wcb();
			dom.pool.release(page);
			cb();
		});
		var url = URL.format(request.location);
		debug(method, url);
		settings.content = request.input;
		page[method](url, settings);
		delete settings.content;
	});
};

function processMw(page, settings, request, response) {
	var list = settings.plugins;
	for (var i=0; i < list.length; i++) {
		list[i](page, settings, request, response);
	}
}

<|endoftext|>


<commit_before>/* Copyright 2013 Chris Wilson

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

window.AudioContext = window.AudioContext || window.webkitAudioContext;

var audioContext = new AudioContext();
var audioInput = null,
    realAudioInput = null,
    inputPoint = null,
    audioRecorder = null;
var rafID = null;
var analyserContext = null;
var canvasWidth, canvasHeight;
var recIndex = 0;

/* TODO:

- offer mono option
- "Monitor input" switch
*/

function saveAudio() {
    audioRecorder.exportWAV( doneEncoding );
    // could get mono instead by saying
    // audioRecorder.exportMonoWAV( doneEncoding );
}

function gotBuffers( buffers ) {
    var canvas = document.getElementById( "wavedisplay" );

    drawBuffer( canvas.width, canvas.height, canvas.getContext('2d'), buffers[0] );

    // the ONLY time gotBuffers is called is right after a new recording is completed -
    // so here's where we should set up the download.
    audioRecorder.exportWAV( doneEncoding );
}

function doneEncoding( blob ) {
    Recorder.setupDownload( blob, "myRecording" + ((recIndex<10)?"0":"") + recIndex + ".wav" );
    recIndex++;
}

function toggleRecording( e ) {
    if (e.classList.contains("recording")) {
        // stop recording
        audioRecorder.stop();
        e.classList.remove("recording");
        audioRecorder.getBuffers( gotBuffers );
    } else {
        // start recording
        if (!audioRecorder)
            return;
        e.classList.add("recording");
        audioRecorder.clear();
        audioRecorder.record();
    }
}

function convertToMono( input ) {
    var splitter = audioContext.createChannelSplitter(2);
    var merger = audioContext.createChannelMerger(2);

    input.connect( splitter );
    splitter.connect( merger, 0, 0 );
    splitter.connect( merger, 0, 1 );
    return merger;
}

function cancelAnalyserUpdates() {
    window.cancelAnimationFrame( rafID );
    rafID = null;
}

function updateAnalysers(time) {
    if (!analyserContext) {
        var canvas = document.getElementById("analyser");
        canvasWidth = canvas.width;
        canvasHeight = canvas.height;
        analyserContext = canvas.getContext('2d');
    }

    // analyzer draw code here
    {
        var SPACING = 3;
        var BAR_WIDTH = 1;
        var numBars = Math.round(canvasWidth / SPACING);
        var freqByteData = new Uint8Array(analyserNode.frequencyBinCount);

        analyserNode.getByteFrequencyData(freqByteData);

        analyserContext.clearRect(0, 0, canvasWidth, canvasHeight);
        analyserContext.fillStyle = '#F6D565';
        analyserContext.lineCap = 'round';
        var multiplier = analyserNode.frequencyBinCount / numBars;

        // Draw rectangle for each frequency bin.
        for (var i = 0; i < numBars; ++i) {
            var magnitude = 0;
            var offset = Math.floor( i * multiplier );
            // gotta sum/average the block, or we miss narrow-bandwidth spikes
            for (var j = 0; j< multiplier; j++)
                magnitude += freqByteData[offset + j];
            magnitude = magnitude / multiplier;
            var magnitude2 = freqByteData[i * multiplier];
            analyserContext.fillStyle = "hsl( " + Math.round((i*360)/numBars) + ", 100%, 50%)";
            analyserContext.fillRect(i * SPACING, canvasHeight, BAR_WIDTH, -magnitude);
        }
    }

    rafID = window.requestAnimationFrame( updateAnalysers );
}

function toggleMono() {
    if (audioInput != realAudioInput) {
        audioInput.disconnect();
        realAudioInput.disconnect();
        audioInput = realAudioInput;
    } else {
        realAudioInput.disconnect();
        audioInput = convertToMono( realAudioInput );
    }

    audioInput.connect(inputPoint);
}

function gotStream(stream) {
    inputPoint = audioContext.createGain();

    // Create an AudioNode from the stream.
    realAudioInput = audioContext.createMediaStreamSource(stream);
    audioInput = realAudioInput;
    audioInput.connect(inputPoint);

//    audioInput = convertToMono( input );

    analyserNode = audioContext.createAnalyser();
    analyserNode.fftSize = 2048;
    inputPoint.connect( analyserNode );

    audioRecorder = new Recorder( inputPoint );

    zeroGain = audioContext.createGain();
    zeroGain.gain.value = 0.0;
    inputPoint.connect( zeroGain );
    zeroGain.connect( audioContext.destination );
    updateAnalysers();
}

function initAudio() {
        if (!navigator.getUserMedia)
            navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
        if (!navigator.cancelAnimationFrame)
            navigator.cancelAnimationFrame = navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
        if (!navigator.requestAnimationFrame)
            navigator.requestAnimationFrame = navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;

    navigator.getUserMedia({audio:true}, gotStream, function(e) {
            alert('Error getting audio');
            console.log(e);
        });
}

window.addEventListener('load', initAudio );
<commit_msg>Constraints updated to remove AEC/AGC<commit_after>/* Copyright 2013 Chris Wilson

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

window.AudioContext = window.AudioContext || window.webkitAudioContext;

var audioContext = new AudioContext();
var audioInput = null,
    realAudioInput = null,
    inputPoint = null,
    audioRecorder = null;
var rafID = null;
var analyserContext = null;
var canvasWidth, canvasHeight;
var recIndex = 0;

/* TODO:

- offer mono option
- "Monitor input" switch
*/

function saveAudio() {
    audioRecorder.exportWAV( doneEncoding );
    // could get mono instead by saying
    // audioRecorder.exportMonoWAV( doneEncoding );
}

function gotBuffers( buffers ) {
    var canvas = document.getElementById( "wavedisplay" );

    drawBuffer( canvas.width, canvas.height, canvas.getContext('2d'), buffers[0] );

    // the ONLY time gotBuffers is called is right after a new recording is completed -
    // so here's where we should set up the download.
    audioRecorder.exportWAV( doneEncoding );
}

function doneEncoding( blob ) {
    Recorder.setupDownload( blob, "myRecording" + ((recIndex<10)?"0":"") + recIndex + ".wav" );
    recIndex++;
}

function toggleRecording( e ) {
    if (e.classList.contains("recording")) {
        // stop recording
        audioRecorder.stop();
        e.classList.remove("recording");
        audioRecorder.getBuffers( gotBuffers );
    } else {
        // start recording
        if (!audioRecorder)
            return;
        e.classList.add("recording");
        audioRecorder.clear();
        audioRecorder.record();
    }
}

function convertToMono( input ) {
    var splitter = audioContext.createChannelSplitter(2);
    var merger = audioContext.createChannelMerger(2);

    input.connect( splitter );
    splitter.connect( merger, 0, 0 );
    splitter.connect( merger, 0, 1 );
    return merger;
}

function cancelAnalyserUpdates() {
    window.cancelAnimationFrame( rafID );
    rafID = null;
}

function updateAnalysers(time) {
    if (!analyserContext) {
        var canvas = document.getElementById("analyser");
        canvasWidth = canvas.width;
        canvasHeight = canvas.height;
        analyserContext = canvas.getContext('2d');
    }

    // analyzer draw code here
    {
        var SPACING = 3;
        var BAR_WIDTH = 1;
        var numBars = Math.round(canvasWidth / SPACING);
        var freqByteData = new Uint8Array(analyserNode.frequencyBinCount);

        analyserNode.getByteFrequencyData(freqByteData);

        analyserContext.clearRect(0, 0, canvasWidth, canvasHeight);
        analyserContext.fillStyle = '#F6D565';
        analyserContext.lineCap = 'round';
        var multiplier = analyserNode.frequencyBinCount / numBars;

        // Draw rectangle for each frequency bin.
        for (var i = 0; i < numBars; ++i) {
            var magnitude = 0;
            var offset = Math.floor( i * multiplier );
            // gotta sum/average the block, or we miss narrow-bandwidth spikes
            for (var j = 0; j< multiplier; j++)
                magnitude += freqByteData[offset + j];
            magnitude = magnitude / multiplier;
            var magnitude2 = freqByteData[i * multiplier];
            analyserContext.fillStyle = "hsl( " + Math.round((i*360)/numBars) + ", 100%, 50%)";
            analyserContext.fillRect(i * SPACING, canvasHeight, BAR_WIDTH, -magnitude);
        }
    }

    rafID = window.requestAnimationFrame( updateAnalysers );
}

function toggleMono() {
    if (audioInput != realAudioInput) {
        audioInput.disconnect();
        realAudioInput.disconnect();
        audioInput = realAudioInput;
    } else {
        realAudioInput.disconnect();
        audioInput = convertToMono( realAudioInput );
    }

    audioInput.connect(inputPoint);
}

function gotStream(stream) {
    inputPoint = audioContext.createGain();

    // Create an AudioNode from the stream.
    realAudioInput = audioContext.createMediaStreamSource(stream);
    audioInput = realAudioInput;
    audioInput.connect(inputPoint);

//    audioInput = convertToMono( input );

    analyserNode = audioContext.createAnalyser();
    analyserNode.fftSize = 2048;
    inputPoint.connect( analyserNode );

    audioRecorder = new Recorder( inputPoint );

    zeroGain = audioContext.createGain();
    zeroGain.gain.value = 0.0;
    inputPoint.connect( zeroGain );
    zeroGain.connect( audioContext.destination );
    updateAnalysers();
}

function initAudio() {
        if (!navigator.getUserMedia)
            navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
        if (!navigator.cancelAnimationFrame)
            navigator.cancelAnimationFrame = navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
        if (!navigator.requestAnimationFrame)
            navigator.requestAnimationFrame = navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;

    navigator.getUserMedia(
        {
            "audio": {
                "mandatory": {
                    "googEchoCancellation": "false",
                    "googAutoGainControl": "false",
                    "googNoiseSuppression": "false",
                    "googHighpassFilter": "false"
                },
                "optional": []
            },
        }, gotStream, function(e) {
            alert('Error getting audio');
            console.log(e);
        });
}

window.addEventListener('load', initAudio );
<|endoftext|>


<commit_before>var fs = require('fs');
var Path = require('path');
var debug = require('debug')('express-dom');
var Pool = require('./pool');
var URL = require('url');
var BufferList = require('bl');

var dom = module.exports = function(input, opts) {
	if (!dom.pool) {
		dom.pool = new Pool(dom.settings.pool, dom); // do not use instance options
		dom.acquire = dom.pool.acquire.bind(dom.pool);
		dom.release = dom.pool.release.bind(dom.pool);
	}
	var h = new Handler(input, opts);
	return h.chainable;
};

dom.plugins = require('./plugins');

dom.settings = {
	plugins: [dom.plugins.nocss, dom.plugins.redirect, dom.plugins.html],
	display: process.env.DISPLAY || 0,
	pool: {
		max: 16,
		destroyTimeout: 600000,
		idleTimeout: 180000
	},
	style: `/* disable viewport repaints */
		html {
			display:none !important;
		}
		/* do not animate as far as possible */
		* {
			-webkit-transition:none !important;
			transition:none !important;
			-webkit-transition-property: none !important;
			transition-property: none !important;
			-webkit-transform: none !important;
			transform: none !important;
			-webkit-animation: none !important;
			animation: none !important;
		}`,
	console: !!process.env.DEBUG,
	'auto-load-images': false,
	stall: 15000,
	allow: "same-origin",
	navigation: false,
	develop: !!process.env.DEVELOP
};

function Handler(input) {
	debug("new handler", input);
	var h = this;
	h.input = input;
	h.settings = {};

	h.chainable = h.middleware.bind(h);
	h.chainable.prepare = function(opts) {
		h.settings.prepare = initOpts(opts, Array.from(arguments));
		return h.chainable;
	};
	h.chainable.load = function(opts) {
		h.settings.load = initOpts(opts, Array.from(arguments));
		return h.chainable;
	};
}

function initOpts(opts, args) {
	if (typeof opts == "function") opts = null;
	else args.shift();

	opts = Object.assign({filters: []}, dom.settings, opts);
	var plugins = opts.plugins;
	if (typeof plugins == "function") plugins = [plugins];
	opts.plugins = args.concat(plugins || dom.settings.plugins);

	return opts;
}

Handler.prototype.middleware = function(req, res, next) {
	var h = this;
	if (!h.input) h.input = req.path;
	var statics = req.app.get('statics');

	h.getView(statics, function(err, data) {
		if (err) return next(err);
		var request = {
			location: {
				protocol: req.protocol,
				host: req.headers.host,
				pathname: req.path,
				query: req.query
			},
			input: data,
			statics: statics,
			headers: req.headers
		};
		var response = {
			output: null,
			headers: {},
			status: null
		};
		debug('view loaded', request.location.pathname);
		if (h.settings.prepare) {
			h.runMethod('prepare', h.settings.prepare, request, response, function(err) {
				if (err) return next(err);
				between();
			});
		} else {
			between();
		}
		function between() {
			if (h.settings.load) {
				if (h.settings.load.develop) {
					console.warn("develop mode is ON");
				} else {
					if (response.output) {
						request.input = response.output;
						response.output = null;
					}
					return h.runMethod('load', h.settings.load, request, response, function(err) {
						if (err) return next(err);
						finalize();
					});
				}
			}
			finalize();
		}
		function finalize() {
			var data = response.output || request.input;
			if (!response.headers['Content-Type']) {
				response.headers['Content-Type'] = "text/html";
			}
			for (var header in response.headers) {
				res.setHeader(header, response.headers[header]);
			}
			// hopefully free faster that memory
			delete request.input;
			delete response.output;
			var status = response.status;
			if (data) {
				var isPath = true, isStream = false;
				if (Buffer.isBuffer(data)) {
					isPath = false;
				} else if (typeof data.pipe == "function") {
					isPath = false;
					isStream = true;
				} else if (typeof data != "string") {
					data = data.toString();
				}
				if (isPath && data.startsWith('<')) {
					isPath = false;
				}
				if (isPath) {
					res.sendFile(data);
				} else {
					if (status) res.status(status);
					if (isStream) {
						data.pipe(res);
					} else {
						res.send(data);
					}
				}
			} else if (status) {
				res.sendStatus(status);
			}
		}
	});
};

Handler.prototype.getView = function(root, cb) {
	var input = this.input;
	if (Buffer.isBuffer(input)) return cb(null, input);
	if (typeof input.pipe == "function") return input.pipe(BufferList(cb));
	if (typeof input != "string") return cb(new Error("unknown input type"));
	if (input.startsWith('<')) return cb(null, input); // html string
	if (!root) return cb(new Error("Please app.set('statics', rootDir)"));
	var path = Path.join(root, input);
	if (path.indexOf(root) !== 0) return cb(new Error("Path outside statics dir\n" + path));
	if (Path.extname(path) != ".html") path += ".html";
	fs.readFile(path, cb);
};

Handler.prototype.runMethod = function(method, settings, request, response, cb) {
	var h = this;
	dom.pool.acquire(function(err, page) {
		if (err) return next(err);
		processMw(page, settings, request, response);
		page.when('idle', function(wcb) {
			debug("release idle page", page.uri);
			page.pingTime = Date.now();
			wcb();
			dom.pool.release(page);
			cb();
		});
		settings.content = request.input;
		page[method](URL.format(request.location), settings);
		delete settings.content;
	});
};

function processMw(page, settings, request, response) {
	var list = settings.plugins;
	for (var i=0; i < list.length; i++) {
		list[i](page, settings, request, response);
	}
}

<commit_msg>Return 400 if no status was set and no data was found<commit_after>var fs = require('fs');
var Path = require('path');
var debug = require('debug')('express-dom');
var Pool = require('./pool');
var URL = require('url');
var BufferList = require('bl');

var dom = module.exports = function(input, opts) {
	if (!dom.pool) {
		dom.pool = new Pool(dom.settings.pool, dom); // do not use instance options
		dom.acquire = dom.pool.acquire.bind(dom.pool);
		dom.release = dom.pool.release.bind(dom.pool);
	}
	var h = new Handler(input, opts);
	return h.chainable;
};

dom.plugins = require('./plugins');

dom.settings = {
	plugins: [dom.plugins.nocss, dom.plugins.redirect, dom.plugins.html],
	display: process.env.DISPLAY || 0,
	pool: {
		max: 16,
		destroyTimeout: 600000,
		idleTimeout: 180000
	},
	style: `/* disable viewport repaints */
		html {
			display:none !important;
		}
		/* do not animate as far as possible */
		* {
			-webkit-transition:none !important;
			transition:none !important;
			-webkit-transition-property: none !important;
			transition-property: none !important;
			-webkit-transform: none !important;
			transform: none !important;
			-webkit-animation: none !important;
			animation: none !important;
		}`,
	console: !!process.env.DEBUG,
	'auto-load-images': false,
	stall: 15000,
	allow: "same-origin",
	navigation: false,
	develop: !!process.env.DEVELOP
};

function Handler(input) {
	debug("new handler", input);
	var h = this;
	h.input = input;
	h.settings = {};

	h.chainable = h.middleware.bind(h);
	h.chainable.prepare = function(opts) {
		h.settings.prepare = initOpts(opts, Array.from(arguments));
		return h.chainable;
	};
	h.chainable.load = function(opts) {
		h.settings.load = initOpts(opts, Array.from(arguments));
		return h.chainable;
	};
}

function initOpts(opts, args) {
	if (typeof opts == "function") opts = null;
	else args.shift();

	opts = Object.assign({filters: []}, dom.settings, opts);
	var plugins = opts.plugins;
	if (typeof plugins == "function") plugins = [plugins];
	opts.plugins = args.concat(plugins || dom.settings.plugins);

	return opts;
}

Handler.prototype.middleware = function(req, res, next) {
	var h = this;
	if (!h.input) h.input = req.path;
	var statics = req.app.get('statics');

	h.getView(statics, function(err, data) {
		if (err) return next(err);
		var request = {
			location: {
				protocol: req.protocol,
				host: req.headers.host,
				pathname: req.path,
				query: req.query
			},
			input: data,
			statics: statics,
			headers: req.headers
		};
		var response = {
			output: null,
			headers: {},
			status: null
		};
		debug('view loaded', request.location.pathname);
		if (h.settings.prepare) {
			h.runMethod('prepare', h.settings.prepare, request, response, function(err) {
				if (err) return next(err);
				between();
			});
		} else {
			between();
		}
		function between() {
			if (h.settings.load) {
				if (h.settings.load.develop) {
					console.warn("develop mode is ON");
				} else {
					if (response.output) {
						request.input = response.output;
						response.output = null;
					}
					return h.runMethod('load', h.settings.load, request, response, function(err) {
						if (err) return next(err);
						finalize();
					});
				}
			}
			finalize();
		}
		function finalize() {
			var data = response.output || request.input;
			if (!response.headers['Content-Type']) {
				response.headers['Content-Type'] = "text/html";
			}
			for (var header in response.headers) {
				res.setHeader(header, response.headers[header]);
			}
			// hopefully free faster that memory
			delete request.input;
			delete response.output;
			var status = response.status;
			if (data) {
				var isPath = true, isStream = false;
				if (Buffer.isBuffer(data)) {
					isPath = false;
				} else if (typeof data.pipe == "function") {
					isPath = false;
					isStream = true;
				} else if (typeof data != "string") {
					data = data.toString();
				}
				if (isPath && data.startsWith('<')) {
					isPath = false;
				}
				if (isPath) {
					res.sendFile(data);
				} else {
					if (status) res.status(status);
					if (isStream) {
						data.pipe(res);
					} else {
						res.send(data);
					}
				}
			} else {
				res.sendStatus(status || 400);
			}
		}
	});
};

Handler.prototype.getView = function(root, cb) {
	var input = this.input;
	if (Buffer.isBuffer(input)) return cb(null, input);
	if (typeof input.pipe == "function") return input.pipe(BufferList(cb));
	if (typeof input != "string") return cb(new Error("unknown input type"));
	if (input.startsWith('<')) return cb(null, input); // html string
	if (!root) return cb(new Error("Please app.set('statics', rootDir)"));
	var path = Path.join(root, input);
	if (path.indexOf(root) !== 0) return cb(new Error("Path outside statics dir\n" + path));
	if (Path.extname(path) != ".html") path += ".html";
	fs.readFile(path, cb);
};

Handler.prototype.runMethod = function(method, settings, request, response, cb) {
	var h = this;
	dom.pool.acquire(function(err, page) {
		if (err) return next(err);
		processMw(page, settings, request, response);
		page.when('idle', function(wcb) {
			debug("release idle page", page.uri);
			page.pingTime = Date.now();
			wcb();
			dom.pool.release(page);
			cb();
		});
		settings.content = request.input;
		page[method](URL.format(request.location), settings);
		delete settings.content;
	});
};

function processMw(page, settings, request, response) {
	var list = settings.plugins;
	for (var i=0; i < list.length; i++) {
		list[i](page, settings, request, response);
	}
}

<|endoftext|>


<commit_before>var $ = require('jquery');

module.exports = {

	$doc: $(document),

	setupDom: function () {

		this.$el = $(this.element);

		this.$el.addClass(this.options.classes.originalSelect);

		// Setup wrapper
		this.$wrapper = $('<div />', {
			'class': this.options.classes.wrapper
		});

		// Setup select
		this.$select = $('<button />', {
			type: 'button',
			'class': this.options.classes.select
		});

		// Setup option list
		this.$optionList = $('<ul />', {
			'class': [this.options.classes.optionList, this.options.classes.isHidden].join(' ')
		});

		this.renderOptions();
		this.renderSelect(this.getContent());
		this.setActiveOption(this.getValue(), true);

		// Go!
		this.$wrapper
			.insertBefore(this.$el)
			.append(this.$el, this.$select, this.$optionList);

	},

	destroyDom: function () {

		this.$el
			.removeClass(this.options.classes.originalSelect)
			.insertBefore(this.$wrapper);

		this.$wrapper.remove();

	}

};
<commit_msg>Set initial focused option item<commit_after>var $ = require('jquery');

module.exports = {

	$doc: $(document),

	setupDom: function () {

		this.$el = $(this.element);

		this.$el.addClass(this.options.classes.originalSelect);

		// Setup wrapper
		this.$wrapper = $('<div />', {
			'class': this.options.classes.wrapper
		});

		// Setup select
		this.$select = $('<button />', {
			type: 'button',
			'class': this.options.classes.select
		});

		// Setup option list
		this.$optionList = $('<ul />', {
			'class': [this.options.classes.optionList, this.options.classes.isHidden].join(' ')
		});

		this.renderOptions();
		this.renderSelect(this.getContent());
		this.setActiveOption(this.getValue(), true);
		this.setFocusedOption(this.getValue());

		// Go!
		this.$wrapper
			.insertBefore(this.$el)
			.append(this.$el, this.$select, this.$optionList);

	},

	destroyDom: function () {

		this.$el
			.removeClass(this.options.classes.originalSelect)
			.insertBefore(this.$wrapper);

		this.$wrapper.remove();

	}

};
<|endoftext|>


<commit_before>/*
 * dry
 * https://github.com/sellside/dry
 *
 * Copyright (c) 2012 Brian Woodward
 * Licensed under the MIT license.
 */

module.exports = (function() {

    var parserlib = require('./node-parserlib.js');
    var fs        = require('fs');

    var refactor = function(source, destination, done){
        destination = destination || appendExtension(getFilename(source), "less");

        console.log(source);
        console.log(destination);

        // read in the css document
        var sourceText = fs.readFileSync(source, 'utf8');

        // get a new parser
        var parser = new parserlib.css.Parser();

        // set up the tree
        var ast = {};
        var errorCount = 0;

        // set up all the events
        parser.addListener("startstylesheet", function() {
            console.log("Starting to parse style sheet");
        });

        parser.addListener("endstylesheet", function(){
            console.log("Finished parsing style sheet");
        });

        parser.addListener("error", function(event){
            errorCount++;
            console.log("Parse error: " + event.message + " (" + event.line + "," + event.col + ")", "error");
        });

        // run parser
        parser.parse(sourceText);

        if(done) {
            done(errorCount);
        }

    };

    var getFilename = function(filePath){
        // return just the filename without the directory structure
        // or extension
        return filePath;
    };

    var appendExtension = function(filename, extension){
        // return the given filename with the proper extension
        return filename + "." + extension; // add more logic to this
    };

    var awesome = function() {
      return 'awesome';
    };

    return {
        awesome: awesome,
        refactor: refactor
    };

}());
<commit_msg>Updating parselib options<commit_after>/*
 * dry
 * https://github.com/sellside/dry
 *
 * Copyright (c) 2012 Brian Woodward
 * Licensed under the MIT license.
 */

module.exports = (function() {

    var parserlib = require('./node-parserlib.js');
    var fs        = require('fs');

    var refactor = function(source, destination, done){
        destination = destination || appendExtension(getFilename(source), "less");

        console.log(source);
        console.log(destination);

        // read in the css document
        var sourceText = fs.readFileSync(source, 'utf8');

        // get a new parser
        var parser = new parserlib.css.Parser({
            starHack: true,
            underscoreHack: true,
            ieFilters: true
        });

        // set up the tree
        var ast = {};
        var errorCount = 0;

        // set up all the events
        parser.addListener("startstylesheet", function() {
            console.log("Starting to parse style sheet");
        });

        parser.addListener("endstylesheet", function(){
            console.log("Finished parsing style sheet");
        });

        parser.addListener("error", function(event){
            errorCount++;
            console.log("Parse error: " + event.message + " (" + event.line + "," + event.col + ")", "error");
        });

        // run parser
        parser.parse(sourceText);

        if(done) {
            done(errorCount);
        }

    };

    var getFilename = function(filePath){
        // return just the filename without the directory structure
        // or extension
        return filePath;
    };

    var appendExtension = function(filename, extension){
        // return the given filename with the proper extension
        return filename + "." + extension; // add more logic to this
    };

    var awesome = function() {
      return 'awesome';
    };

    return {
        awesome: awesome,
        refactor: refactor
    };

}());
<|endoftext|>


<commit_before>'use strict';

function repo_init(){
    core_repo_init({
      'events': {
        'fetch-keyinfo-key': {
          'onclick': fetch_keyinfo_key,
        },
        'fetch-keyinfo-keycode': {
          'onclick': fetch_keyinfo_keycode,
        },
        'generate': {
          'onclick': generate_list,
        },
      },
      'storage': {
        'base-keycode': 0,
        'key': 'H',
        'keycode': 72,
        'keycode-range': 1000,
      },
      'title': 'KeyInfo.htm',
    });

    document.getElementById('text').oninput = function(){
        // Fetch lowercase value.
        var value = this.value.toLowerCase();

        // Display length of inputted text.
        document.getElementById('length').innerHTML = value.length;

        // Reset characters.
        var characters = '0123456789abcdefghijklmnopqrstuvwxyz !@#$%^&*()_-+={}|:;"\'<,>.?/'.split('');
        var output = '';

        // Count how many times each character appears in inputted text.
        for(var character in characters){
            var character_count = value.replace(
              new RegExp(
                '[^' + characters[character] + ']',
                'g'// Global
              ),
              ''
            ).length;

            // Only display characters that appear in inputted text.
            if(character_count <= 0){
                continue;
            }

            output +=
              '
'
              + characters[character]
              + '	'
              + character_count
              + '	'
              + ((character_count / value.length) * 100).toFixed(7)
              + '%
';
        }

        core_html_modify({
          'id': 'characters',
          'properties': {
            'innerHTML': output,
          },
        });
    };
}
<commit_msg>moved event binds to events arg<commit_after>'use strict';

function repo_init(){
    core_repo_init({
      'events': {
        'fetch-keyinfo-key': {
          'onclick': fetch_keyinfo_key,
        },
        'fetch-keyinfo-keycode': {
          'onclick': fetch_keyinfo_keycode,
        },
        'generate': {
          'onclick': generate_list,
        },
        'text': {
          'oninput': function(){
              // Fetch lowercase value.
              var value = this.value.toLowerCase();

              // Display length of inputted text.
              document.getElementById('length').innerHTML = value.length;

              // Reset characters.
              var characters = '0123456789abcdefghijklmnopqrstuvwxyz !@#$%^&*()_-+={}|:;"\'<,>.?/'.split('');
              var output = '';

              // Count how many times each character appears in inputted text.
              for(var character in characters){
                  var character_count = value.replace(
                    new RegExp(
                      '[^' + characters[character] + ']',
                      'g'// Global
                    ),
                    ''
                  ).length;

                  // Only display characters that appear in inputted text.
                  if(character_count <= 0){
                      continue;
                  }

                  output +=
                    '
'
                    + characters[character]
                    + '	'
                    + character_count
                    + '	'
                    + ((character_count / value.length) * 100).toFixed(7)
                    + '%
';
              }

              core_html_modify({
                'id': 'characters',
                'properties': {
                  'innerHTML': output,
                },
              });
          },
        },
      },
      'storage': {
        'base-keycode': 0,
        'key': 'H',
        'keycode': 72,
        'keycode-range': 1000,
      },
      'title': 'TextInfo.htm',
    });
}
<|endoftext|>


<commit_before>// Wait until the form has loaded entirely.
var documentReady = new Promise($(document).ready);

// Load the year, month, and items values from localStorage,
// or get the current year and month and the default item set.
var loadFromCookiesOrDefaults = function (){

  return new Promise(function (resolve){
    if (localStorage.getItem('items')){
      resolve({
        items : localStorage.getItem('items'),
        year  : localStorage.getItem('year'),
        month : localStorage.getItem('month')
      });
    } else {
      $.get('default-item-list.txt', function (data) {
        var today = new Date();

        resolve({
          items : data,
          year  : today.getFullYear(),
          month : today.getMonth()
        });
      });
    }
  });

};

// Populate the form from the loaded data,
// generate the TaskPaper month from the items field, and
// store the results in localStorage.
var populateAndProcessAndRememberFormData = function (data){

  var yearField      = $('#year'),
      monthField     = $('#month'),
      itemsField     = $('#items'),
      taskpaperMonth = $('#taskpaper-month');

  var generateTaskPaperMonth = function (){

    // Read the form data; prepare to generate a month.
    var itemsText      = itemsField.val(),
        itemsArray     = [],
        items          = {},
        numberOfDays   = new Date(data.year, data.month, 0).getDate(),
        generatedMonth = '';

    console.log(itemsText);

    // Build an array of items from the contents of the textarea.
    // Split the textarea by digits followed by newlines.
    itemsArray = itemsText.split(/(\d+):?\n/m);

    // Hack off the first (empty) array item.
    itemsArray.shift()

    // Create an associative array by iterating through even and odd
    // array items. (Odd are day numbers, even are that day's items.)
    $.each(itemsArray, function(key, value) {
      if (key%2 === 0) {
        items[itemsArray[key]] = itemsArray[key+1];
      }
    });

    // Turn each 'items' value in the object into an array split by newlines.
    $.each(items, function(key, value) {
      items[key] = items[key].trim().split('\n');
    });

    // Loop through each of the days and include the items therein.
    for (var day = 0; day <= numberOfDays; day++) {

      // Get the day name.
      var dayName = getDayName(new Date(data.year, data.month, day).getDay());

      // Add the day heading:

      // Add one to the day, since Javascript days are 0-indexed.
      dayNumber = day + 1;

      // Add a newline if we're not on the first day.
      if (dayNumber > 1)
        generatedMonth += '\n';

      // Add a zero for days under 10.
      if (dayNumber < 10)
        generatedMonth += '0'

      // Add the day number itself, a colon, and a newline.
      generatedMonth += dayNumber + ' ' + dayName + ':';

      // If this day contains items, print them.
      if (items[dayNumber]) {
        $.each(items[dayNumber], function(key, value) {
          // If the line starts with two spaces, make it a comment.
          if (value.substring(0, 2) === '  ')
            generatedMonth += '\n\t\t' + value

          // If the line starts with a dash and a space, make it a todo.
          // (This is not the suggested syntax, but that's OK!)
          if (value.substring(0, 2) === '- ')
            generatedMonth += '\n\t' + value

          // Otherwise, make it a todo.
          else
            generatedMonth += '\n\t- ' + value
        });
      }

      // If we're on the last day of the month, generated a link back here!
      if (dayNumber === numberOfDays)
        generatedMonth += '\n\t- generate new Taskpaper month\n\t\thttp://matthewmcvickar.github.io/taskpaper-month-generator';

    }

    console.log('Fire!');

    // Print generated TaskPaper month to the screen.
    taskpaperMonth.html(generatedMonth);

    // Save values to localStorage.
    localStorage.setItem('year',  yearField.val()   );
    localStorage.setItem('month', monthField.val()  );
    localStorage.setItem('items', itemsField.html() );
  };

  // // // // // // // // // // // // // // // // // //

  // Initial setup:

  // 1. Populate year <select> with current and next year.
  var currentYear = new Date().getFullYear(),
      nextYear    = currentYear + 1,
      years       = [currentYear, nextYear];

 $.each(years, function (key, value){
    yearField.append(
      $('<option></option>').attr('value', value).text(value)
    );
  });

  // 2. Select the loaded year.
  $('#year').val(data.year);

  // 3. Select the loaded month.
  $('#month').val(data.month);

  // 4. Populate items field with loaded items.
  // 5. Give items field focus.
  itemsField.html(data.items).focus();

  // 6. Generate TaskPaper month for the first time.
  generateTaskPaperMonth();

  // // // // // // // // // // // // // // // // // //

  // Regenerate TaskPaper month on subsequent updates.
  itemsField.on('keyup', generateTaskPaperMonth);
};

documentReady
  .then(loadFromCookiesOrDefaults)
  .then(populateAndProcessAndRememberFormData);

// Get the name of the day.
function getDayName(number) {
  days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
  return days[number];
}<commit_msg>Fixed extra day appearing at the end of the month.<commit_after>// Wait until the form has loaded entirely.
var documentReady = new Promise($(document).ready);

// Load the year, month, and items values from localStorage,
// or get the current year and month and the default item set.
var loadFromCookiesOrDefaults = function (){

  return new Promise(function (resolve){
    if (localStorage.getItem('items')){
      resolve({
        items : localStorage.getItem('items'),
        year  : localStorage.getItem('year'),
        month : localStorage.getItem('month')
      });
    } else {
      $.get('default-item-list.txt', function (data) {
        var today = new Date();

        resolve({
          items : data,
          year  : today.getFullYear(),
          month : today.getMonth()
        });
      });
    }
  });

};

// Populate the form from the loaded data,
// generate the TaskPaper month from the items field, and
// store the results in localStorage.
var populateAndProcessAndRememberFormData = function (data){

  var yearField      = $('#year'),
      monthField     = $('#month'),
      itemsField     = $('#items'),
      taskpaperMonth = $('#taskpaper-month');

  var generateTaskPaperMonth = function (){

    // Read the form data; prepare to generate a month.
    var itemsText      = itemsField.val(),
        itemsArray     = [],
        items          = {},
        numberOfDays   = new Date(data.year, data.month, 0).getDate(),
        generatedMonth = '';

    console.log(itemsText);

    // Build an array of items from the contents of the textarea.
    // Split the textarea by digits followed by newlines.
    itemsArray = itemsText.split(/(\d+):?\n/m);

    // Hack off the first (empty) array item.
    itemsArray.shift()

    // Create an associative array by iterating through even and odd
    // array items. (Odd are day numbers, even are that day's items.)
    $.each(itemsArray, function(key, value) {
      if (key%2 === 0) {
        items[itemsArray[key]] = itemsArray[key+1];
      }
    });

    // Turn each 'items' value in the object into an array split by newlines.
    $.each(items, function(key, value) {
      items[key] = items[key].trim().split('\n');
    });

    // Loop through each of the days and include the items therein.
    for (var day = 0; day < numberOfDays; day++) {

      // Get the day name.
      var dayName = getDayName(new Date(data.year, data.month, day).getDay());

      // Add the day heading:

      // Add one to the day, since Javascript days are 0-indexed.
      dayNumber = day + 1;

      // Add a newline if we're not on the first day.
      if (dayNumber > 1)
        generatedMonth += '\n';

      // Add a zero for days under 10.
      if (dayNumber < 10)
        generatedMonth += '0'

      // Add the day number itself, a colon, and a newline.
      generatedMonth += dayNumber + ' ' + dayName + ':';

      // If this day contains items, print them.
      if (items[dayNumber]) {
        $.each(items[dayNumber], function(key, value) {
          // If the line starts with two spaces, make it a comment.
          if (value.substring(0, 2) === '  ')
            generatedMonth += '\n\t\t' + value

          // If the line starts with a dash and a space, make it a todo.
          // (This is not the suggested syntax, but that's OK!)
          if (value.substring(0, 2) === '- ')
            generatedMonth += '\n\t' + value

          // Otherwise, make it a todo.
          else
            generatedMonth += '\n\t- ' + value
        });
      }

      // If we're on the last day of the month, generated a link back here!
      if (dayNumber === numberOfDays)
        generatedMonth += '\n\t- generate new Taskpaper month\n\t\thttp://matthewmcvickar.github.io/taskpaper-month-generator';

    }

    console.log('Fire!');

    // Print generated TaskPaper month to the screen.
    taskpaperMonth.html(generatedMonth);

    // Save values to localStorage.
    localStorage.setItem('year',  yearField.val()   );
    localStorage.setItem('month', monthField.val()  );
    localStorage.setItem('items', itemsField.html() );
  };

  // // // // // // // // // // // // // // // // // //

  // Initial setup:

  // 1. Populate year <select> with current and next year.
  var currentYear = new Date().getFullYear(),
      nextYear    = currentYear + 1,
      years       = [currentYear, nextYear];

 $.each(years, function (key, value){
    yearField.append(
      $('<option></option>').attr('value', value).text(value)
    );
  });

  // 2. Select the loaded year.
  $('#year').val(data.year);

  // 3. Select the loaded month.
  $('#month').val(data.month);

  // 4. Populate items field with loaded items.
  // 5. Give items field focus.
  itemsField.html(data.items).focus();

  // 6. Generate TaskPaper month for the first time.
  generateTaskPaperMonth();

  // // // // // // // // // // // // // // // // // //

  // Regenerate TaskPaper month on subsequent updates.
  itemsField.on('keyup', generateTaskPaperMonth);
};

documentReady
  .then(loadFromCookiesOrDefaults)
  .then(populateAndProcessAndRememberFormData);

// Get the name of the day.
function getDayName(number) {
  days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
  return days[number];
}<|endoftext|>


<commit_before>import path from 'path';
import os from 'os';
import assignIn from 'lodash/assignIn';

const { join } = path;

/**
 * @class
 * @property {packagePaths} paths
 */
export default class Env {
    constructor(input, output, options) {
        this.options = options;

        if (this.isProductionBuild()) {
            process.env.NODE_ENV = 'production';
        }

        this.sys = {
            platform: process.platform,
            arch: process.arch
        };

        // Operational System.
        this.os = {
            isWindows: (process.platform === 'win32'),
            isLinux: (process.platform === 'linux'),
            isOsx: (process.platform === 'darwin')

        };
        this.stdio = 'inherit';

        this.os.name = (this.sys.platform === 'darwin' ? 'osx' : this.sys.platform);
        this.os.home = process.env[(this.os.isWindows ? 'USERPROFILE' : 'HOME')];
        this.os.tmp = os.tmpdir();

        /** @type {packagePaths} */
        this.paths = {};

        /** @type {meteorDesktopPaths} */
        this.paths.meteorDesktop = {
            root: path.resolve(__dirname, '..')
        };

        this.paths.meteorDesktop.skeleton = join(this.paths.meteorDesktop.root, 'skeleton');

        /** @type {meteorAppPaths} */
        this.paths.meteorApp = {
            root: input
        };

        /** @type {desktopPaths} */
        this.paths.desktop = {
            rootName: '.desktop',
            root: join(this.paths.meteorApp.root, '.desktop')
        };

        assignIn(this.paths.desktop, {
            modules: join(this.paths.desktop.root, 'modules'),
            import: join(this.paths.desktop.root, 'import'),
            assets: join(this.paths.desktop.root, 'assets'),
            settings: join(this.paths.desktop.root, 'settings.json'),
            desktop: join(this.paths.desktop.root, 'desktop.js')
        });

        this.paths.desktop.splashScreen = join(this.paths.desktop.assets, 'splashScreen.png');
        this.paths.desktop.loadingGif = join(this.paths.desktop.assets, 'loading.gif');
        this.paths.desktop.meteorIco = join(this.paths.desktop.assets, 'meteor.ico');

        /** @type {electronAppPaths} */
        this.paths.electronApp = {
            rootName: 'desktop-build',
        };
        this.paths.electronApp.root =
            join(this.paths.meteorApp.root, '.meteor', this.paths.electronApp.rootName);

        this.paths.electronApp.tmpNodeModules =
            join(this.paths.meteorApp.root, '.meteor', '.desktop_node_modules');

        this.paths.electronApp.appRoot =
            join(this.paths.electronApp.root, 'app');

        assignIn(this.paths.electronApp, {
            app: join(this.paths.electronApp.appRoot, 'app.js'),
            cordova: join(this.paths.electronApp.appRoot, 'cordova.js'),
            index: join(this.paths.electronApp.appRoot, 'index.js'),
            preload: join(this.paths.electronApp.appRoot, 'preload.js'),
            modules: join(this.paths.electronApp.appRoot, 'modules'),
            desktopAsar: join(this.paths.electronApp.root, 'desktop.asar'),
            extracted: join(this.paths.electronApp.root, 'extracted'),
            appAsar: join(this.paths.electronApp.root, 'app.asar'),
            import: join(this.paths.electronApp.root, 'import'),
            assets: join(this.paths.electronApp.root, 'assets'),
            packageJson: join(this.paths.electronApp.root, 'package.json'),
            settings: join(this.paths.electronApp.root, 'settings.json'),
            desktop: join(this.paths.electronApp.root, 'desktop.js'),
            desktopTmp: join(this.paths.electronApp.root, '__desktop'),
            nodeModules: join(this.paths.electronApp.root, 'node_modules'),
            meteorAsar: join(this.paths.electronApp.root, 'meteor.asar'),
            meteorApp: join(this.paths.electronApp.root, 'meteor'),
            meteorAppIndex: join(this.paths.electronApp.root, 'meteor', 'index.html'),
            meteorAppProgramJson: join(this.paths.electronApp.root, 'meteor', 'program.json'),
            skeleton: join(this.paths.electronApp.root, 'skeleton')
        });

        assignIn(this.paths.meteorApp, {
            platforms: join(this.paths.meteorApp.root, '.meteor', 'platforms'),
            packages: join(this.paths.meteorApp.root, '.meteor', 'packages'),
            versions: join(this.paths.meteorApp.root, '.meteor', 'versions'),
            release: join(this.paths.meteorApp.root, '.meteor', 'release'),
            packageJson: join(this.paths.meteorApp.root, 'package.json'),
            gitIgnore: join(this.paths.meteorApp.root, '.meteor', '.gitignore'),
            cordovaBuild: join(
                this.paths.meteorApp.root,
                '.meteor',
                'local',
                'cordova-build',
                'www',
                'application'
            ),
            webCordova: join(
                this.paths.meteorApp.root,
                '.meteor',
                'local',
                'build',
                'programs',
                'web.cordova'
            )
        });

        assignIn(this.paths.meteorApp, {
            cordovaBuildIndex: join(
                this.paths.meteorApp.cordovaBuild, 'index.html'
            ),
            cordovaBuildProgramJson: join(
                this.paths.meteorApp.cordovaBuild, 'program.json'
            )
        });

        assignIn(this.paths.meteorApp, {
            webCordovaProgramJson: join(
                this.paths.meteorApp.webCordova, 'program.json'
            )
        });

        /** @type {desktopTmpPaths} */
        this.paths.desktopTmp = {
            root: join(this.paths.electronApp.root, '__desktop'),
        };

        assignIn(this.paths.desktopTmp, {
            modules: join(this.paths.desktopTmp.root, 'modules'),
            settings: join(this.paths.desktopTmp.root, 'settings.json')
        });

        this.paths.packageDir = '.desktop-package';
        this.paths.installerDir = '.desktop-installer';

        // Scaffold
        this.paths.scaffold = join(__dirname, '..', 'scaffold');
    }

    /**
     * @returns {boolean|*}
     * @public
     */
    isProductionBuild() {
        return !!('production' in this.options && this.options.production);
    }
}

module.exports = Env;

/**
 * @typedef {Object} desktopPaths
 * @property {string} rootName
 * @property {string} root
 * @property {string} modules
 * @property {string} import
 * @property {string} assets
 * @property {string} settings
 * @property {string} desktop
 * @property {string} splashScreen
 * @property {string} loadingGif
 * @property {string} meteorIco
 */

/**
 * @typedef {Object} meteorAppPaths
 * @property {string} root
 * @property {string} platforms
 * @property {string} release
 * @property {string} packages
 * @property {string} versions
 * @property {string} gitIgnore
 * @property {string} packageJson
 * @property {string} cordovaBuild
 * @property {string} cordovaBuildIndex
 * @property {string} cordovaBuildProgramJson
 * @property {string} webCordova
 * @property {string} webCordovaIndex
 * @property {string} webCordovaProgramJson
 */

/**
 * @typedef {Object} electronAppPaths
 * @property {string} rootName
 * @property {string} root
 * @property {Object} appRoot
 * @property {string} appRoot.cordova
 * @property {string} appRoot.index
 * @property {string} appRoot.app
 * @property {string} appRoot.modules
 * @property {string} desktopAsar
 * @property {string} extracted
 * @property {string} appAsar
 * @property {string} preload
 * @property {string} import
 * @property {string} assets
 * @property {string} gitIgnore
 * @property {string} packageJson
 * @property {string} settings
 * @property {string} desktop
 * @property {string} desktopTmp
 * @property {string} nodeModules
 * @property {string} meteorAsar
 * @property {string} meteorApp
 * @property {string} meteorAppIndex
 * @property {string} meteorAppProgramJson
 * @property {string} skeleton
 * @property {string} tmpNodeModules
 */

/**
 * @typedef {Object} desktopTmpPaths
 * @property {string} root
 * @property {string} modules
 * @property {string} settings
 */

/**
 * @typedef {Object} meteorDesktopPaths
 * @property {string} root
 * @property {string} skeleton
 */

/**
 * @typedef {Object} packagePaths
 * @property {meteorAppPaths} meteorApp
 * @property {desktopPaths} desktop
 * @property {electronAppPaths} electronApp
 * @property {desktopTmpPaths} desktopTmp
 * @property {meteorDesktopPaths} meteorDesktop
 * @property {string} packageDir
 * @property {string} scaffold
 */
<commit_msg>Add extracted node modules path<commit_after>import path from 'path';
import os from 'os';
import assignIn from 'lodash/assignIn';

const { join } = path;

/**
 * @class
 * @property {packagePaths} paths
 */
export default class Env {
    constructor(input, output, options) {
        this.options = options;

        if (this.isProductionBuild()) {
            process.env.NODE_ENV = 'production';
        }

        this.sys = {
            platform: process.platform,
            arch: process.arch
        };

        // Operational System.
        this.os = {
            isWindows: (process.platform === 'win32'),
            isLinux: (process.platform === 'linux'),
            isOsx: (process.platform === 'darwin')

        };
        this.stdio = 'inherit';

        this.os.name = (this.sys.platform === 'darwin' ? 'osx' : this.sys.platform);
        this.os.home = process.env[(this.os.isWindows ? 'USERPROFILE' : 'HOME')];
        this.os.tmp = os.tmpdir();

        /** @type {packagePaths} */
        this.paths = {};

        /** @type {meteorDesktopPaths} */
        this.paths.meteorDesktop = {
            root: path.resolve(__dirname, '..')
        };

        this.paths.meteorDesktop.skeleton = join(this.paths.meteorDesktop.root, 'skeleton');

        /** @type {meteorAppPaths} */
        this.paths.meteorApp = {
            root: input
        };

        /** @type {desktopPaths} */
        this.paths.desktop = {
            rootName: '.desktop',
            root: join(this.paths.meteorApp.root, '.desktop')
        };

        assignIn(this.paths.desktop, {
            modules: join(this.paths.desktop.root, 'modules'),
            import: join(this.paths.desktop.root, 'import'),
            assets: join(this.paths.desktop.root, 'assets'),
            settings: join(this.paths.desktop.root, 'settings.json'),
            desktop: join(this.paths.desktop.root, 'desktop.js')
        });

        this.paths.desktop.splashScreen = join(this.paths.desktop.assets, 'splashScreen.png');
        this.paths.desktop.loadingGif = join(this.paths.desktop.assets, 'loading.gif');
        this.paths.desktop.meteorIco = join(this.paths.desktop.assets, 'meteor.ico');

        /** @type {electronAppPaths} */
        this.paths.electronApp = {
            rootName: 'desktop-build',
        };
        this.paths.electronApp.root =
            join(this.paths.meteorApp.root, '.meteor', this.paths.electronApp.rootName);

        this.paths.electronApp.tmpNodeModules =
            join(this.paths.meteorApp.root, '.meteor', '.desktop_node_modules');

        this.paths.electronApp.extractedNodeModules =
            join(this.paths.meteorApp.root, '.meteor', '.desktop_extracted_node_modules');

        this.paths.electronApp.appRoot =
            join(this.paths.electronApp.root, 'app');

        assignIn(this.paths.electronApp, {
            app: join(this.paths.electronApp.appRoot, 'app.js'),
            cordova: join(this.paths.electronApp.appRoot, 'cordova.js'),
            index: join(this.paths.electronApp.appRoot, 'index.js'),
            preload: join(this.paths.electronApp.appRoot, 'preload.js'),
            modules: join(this.paths.electronApp.appRoot, 'modules'),
            desktopAsar: join(this.paths.electronApp.root, 'desktop.asar'),
            extracted: join(this.paths.electronApp.root, 'extracted'),
            appAsar: join(this.paths.electronApp.root, 'app.asar'),
            import: join(this.paths.electronApp.root, 'import'),
            assets: join(this.paths.electronApp.root, 'assets'),
            packageJson: join(this.paths.electronApp.root, 'package.json'),
            settings: join(this.paths.electronApp.root, 'settings.json'),
            desktop: join(this.paths.electronApp.root, 'desktop.js'),
            desktopTmp: join(this.paths.electronApp.root, '__desktop'),
            nodeModules: join(this.paths.electronApp.root, 'node_modules'),
            meteorAsar: join(this.paths.electronApp.root, 'meteor.asar'),
            meteorApp: join(this.paths.electronApp.root, 'meteor'),
            meteorAppIndex: join(this.paths.electronApp.root, 'meteor', 'index.html'),
            meteorAppProgramJson: join(this.paths.electronApp.root, 'meteor', 'program.json'),
            skeleton: join(this.paths.electronApp.root, 'skeleton')
        });

        assignIn(this.paths.meteorApp, {
            platforms: join(this.paths.meteorApp.root, '.meteor', 'platforms'),
            packages: join(this.paths.meteorApp.root, '.meteor', 'packages'),
            versions: join(this.paths.meteorApp.root, '.meteor', 'versions'),
            release: join(this.paths.meteorApp.root, '.meteor', 'release'),
            packageJson: join(this.paths.meteorApp.root, 'package.json'),
            gitIgnore: join(this.paths.meteorApp.root, '.meteor', '.gitignore'),
            cordovaBuild: join(
                this.paths.meteorApp.root,
                '.meteor',
                'local',
                'cordova-build',
                'www',
                'application'
            ),
            webCordova: join(
                this.paths.meteorApp.root,
                '.meteor',
                'local',
                'build',
                'programs',
                'web.cordova'
            )
        });

        assignIn(this.paths.meteorApp, {
            cordovaBuildIndex: join(
                this.paths.meteorApp.cordovaBuild, 'index.html'
            ),
            cordovaBuildProgramJson: join(
                this.paths.meteorApp.cordovaBuild, 'program.json'
            )
        });

        assignIn(this.paths.meteorApp, {
            webCordovaProgramJson: join(
                this.paths.meteorApp.webCordova, 'program.json'
            )
        });

        /** @type {desktopTmpPaths} */
        this.paths.desktopTmp = {
            root: join(this.paths.electronApp.root, '__desktop'),
        };

        assignIn(this.paths.desktopTmp, {
            modules: join(this.paths.desktopTmp.root, 'modules'),
            settings: join(this.paths.desktopTmp.root, 'settings.json')
        });

        this.paths.packageDir = '.desktop-package';
        this.paths.installerDir = '.desktop-installer';

        // Scaffold
        this.paths.scaffold = join(__dirname, '..', 'scaffold');
    }

    /**
     * @returns {boolean|*}
     * @public
     */
    isProductionBuild() {
        return !!('production' in this.options && this.options.production);
    }
}

module.exports = Env;

/**
 * @typedef {Object} desktopPaths
 * @property {string} rootName
 * @property {string} root
 * @property {string} modules
 * @property {string} import
 * @property {string} assets
 * @property {string} settings
 * @property {string} desktop
 * @property {string} splashScreen
 * @property {string} loadingGif
 * @property {string} meteorIco
 */

/**
 * @typedef {Object} meteorAppPaths
 * @property {string} root
 * @property {string} platforms
 * @property {string} release
 * @property {string} packages
 * @property {string} versions
 * @property {string} gitIgnore
 * @property {string} packageJson
 * @property {string} cordovaBuild
 * @property {string} cordovaBuildIndex
 * @property {string} cordovaBuildProgramJson
 * @property {string} webCordova
 * @property {string} webCordovaIndex
 * @property {string} webCordovaProgramJson
 */

/**
 * @typedef {Object} electronAppPaths
 * @property {string} rootName
 * @property {string} root
 * @property {Object} appRoot
 * @property {string} appRoot.cordova
 * @property {string} appRoot.index
 * @property {string} appRoot.app
 * @property {string} appRoot.modules
 * @property {string} desktopAsar
 * @property {string} extracted
 * @property {string} appAsar
 * @property {string} preload
 * @property {string} import
 * @property {string} assets
 * @property {string} gitIgnore
 * @property {string} packageJson
 * @property {string} settings
 * @property {string} desktop
 * @property {string} desktopTmp
 * @property {string} nodeModules
 * @property {string} meteorAsar
 * @property {string} meteorApp
 * @property {string} meteorAppIndex
 * @property {string} meteorAppProgramJson
 * @property {string} skeleton
 * @property {string} tmpNodeModules
 * @property {string} extractedNodeModules
 */

/**
 * @typedef {Object} desktopTmpPaths
 * @property {string} root
 * @property {string} modules
 * @property {string} settings
 */

/**
 * @typedef {Object} meteorDesktopPaths
 * @property {string} root
 * @property {string} skeleton
 */

/**
 * @typedef {Object} packagePaths
 * @property {meteorAppPaths} meteorApp
 * @property {desktopPaths} desktop
 * @property {electronAppPaths} electronApp
 * @property {desktopTmpPaths} desktopTmp
 * @property {meteorDesktopPaths} meteorDesktop
 * @property {string} packageDir
 * @property {string} scaffold
 */
<|endoftext|>