<commit_before>// import * from './scripts/example';

// import './styles/style.css';
// import './styles/style.sass';
import 'normalize.css';
import './styles/style.scss';

import webfont from 'webfontloader';
import Analytics from 'analytics'
import googleAnalytics from '@analytics/google-analytics'
import 'focus-visible';

/* ---------- Webfont (asyncronously load fonts) ---------- */

webfont.load({
	google: {
		families: ['Montserrat:400,400i,600,700,800,800i&display=swap']
	}
});

/* ---------- Google Analytics ---------- */

const analytics = Analytics({
  app: 'hackupc-landing',
  plugins: [
    googleAnalytics({
			trackingId: 'UA-69542332-1',
			anonymizeIp: true,
    })
  ]
})

document.querySelectorAll('[data-ga-apply-button]').forEach((elem) => {
	elem.addEventListener('click', (event) => {
		const data = event.target.dataset;

		analytics.track('applyed', {
			category: 'Apply',
			label: 'Apply button clicked',
			value: data.location,
		});
	});
})

document.querySelectorAll('[data-ga-nav-item]').forEach((elem) => {
	elem.addEventListener('click', (event) => {
		analytics.track('navbar-clicked', {
			category: 'Navigation',
			label: 'Navbar link clicked',
			value: event.target.href,
		});
	});
})

// window.dataLayer = window.dataLayer || [];
// function gtag(){
// 	dataLayer.push(arguments);
// }
// gtag('js', new Date());
// gtag('config', 'UA-69542332-1');

/* ---------- Lax.js ---------- */
// import lax from 'lax.js'

// window.onload = function() {
// 	lax.setup() // init

// 	const updateLax = () => {
// 		lax.update(window.scrollY)
// 		window.requestAnimationFrame(updateLax)
// 	}

// 	window.requestAnimationFrame(updateLax)
// }

/* ---------- Real vh ---------- */
// https://css-tricks.com/the-trick-to-viewport-units-on-mobile/

// We listen to the resize event
// window.addEventListener('resize', () => {
//   // We execute the same script as before
//   let vh = window.innerHeight * 0.01;
//   document.documentElement.style.setProperty('--vh', `${vh}px`);
// });

/* ---------- Update hero perspective ---------- */
const heroElem = document.getElementsByClassName('hero-3d-space')[0];
const applyElem = document.getElementsByClassName('apply-button')[0];
let mouseX = 0.5;
let mouseY = 0.5;

let alpha = 0.5;
let beta = 0.5;
let gamma = 0.5;

let alphaOrig = 0.5;
let betaOrig = 0.5;
let gammaOrig = 0.5;

let perspectiveX = window.innerWidth/2;
let perspectiveY = window.innerHeight * 0.125;

window.addEventListener('scroll', updateHeroPerspective, {passive: true});
window.addEventListener('mousemove', updateHeroPerspective);
window.addEventListener('resize', updateHeroPerspective);
updateHeroPerspective();
let heroWaitingRefresh = false;

// iOS 13+ device orientation requestPermission
if (window.DeviceOrientationEvent && typeof window.DeviceOrientationEvent.requestPermission === 'function') {
	heroElem.addEventListener('click', (event) => {
		if(event.currentTarget !== applyElem){
			window.DeviceOrientationEvent.requestPermission()
			.then(permissionState => {
				if (permissionState === 'granted') {
					window.addEventListener('deviceorientation', updateHeroPerspective, false);
				}
			}).catch(console.error);
		}
	});
} else {
	window.addEventListener('deviceorientation', updateHeroPerspective, false);
}

document.addEventListener('visibilitychange', () => {
	alphaOrig = 0.5;
	betaOrig  = 0.5;
	gammaOrig = 0.5;
});

function updateHeroPerspective(event) {
	if(window.pageYOffset <= window.innerHeight && !heroWaitingRefresh) {
		if(event){
			// alpha [0,360]  -->[0,1]
			// beta  [-180,180]-->[0,1]
			// gamma [-90,90] -->[0,1]

			let newMouseX = mod(event.clientX/window.innerWidth);
			let newMouseY = mod(event.clientY/window.innerHeight);
			let newAlpha  = mod(event.alpha/360 + 0.5);
			let newBeta   = mod((event.beta + 180)/360 - 0.125);
			let newGamma  = mod((event.gamma + 90)/180);

			mouseX = smooth(newMouseX, mouseX);
			mouseY = smooth(newMouseY, mouseY);
			alpha  = smooth(newAlpha,  alpha);
			beta   = smooth(newBeta,   beta);
			gamma  = smooth(newGamma,  gamma);

			if(!isNaN(newAlpha) && alphaOrig === 0.5){ alpha = newAlpha; alphaOrig = newAlpha; }
			if(!isNaN(newBeta ) && betaOrig  === 0.5){ beta  = newBeta;  betaOrig  = newBeta;  }
			if(!isNaN(newGamma) && gammaOrig === 0.5){ gamma = newGamma; gammaOrig = newGamma; }
		}

		heroWaitingRefresh = true;
		window.requestAnimationFrame(() => {
			perspectiveX = 0
			+ window.innerWidth/2
			+ 250 * magnet((mod(alpha - alphaOrig + 0.5) - 0.5) * 2)
			+ 250 * magnet((mod(gamma - gammaOrig + 0.5) - 0.5) * 2)
			+ -window.innerWidth/40 * magnet((mouseX - 0.5) * 2)

			let height = Math.min(900, window.innerHeight);
			perspectiveY = 0
			+ window.pageYOffset
			+ height * 0.125
			+ 500 * magnet((mod(beta - betaOrig + 0.5) - 0.5) * 2)
			+ -height/40 * magnet((mouseY - 0.6667) * 2)

			heroElem.style.perspectiveOrigin = `${perspectiveX}px ${perspectiveY}px`;
			heroWaitingRefresh = false;
		});
	}
}

function mod(n,m=1){
	return ((n % m) + m) % m;
}
function magnet(x=0.5) {
	return Math.sin(Math.PI/2*x);
}

function smooth(final, initial=0) {
	if(isNaN(final)) return initial;

	let dif = final - initial;
	let s = dif >= 0 ? +1 : -1;
	return (initial + s * dif**2);
}
// function smooth(final, initial=0) {
// 	let dif = final - initial;
// 	if(dif < 0.01 && dif > -0.01) return initial;
// 	else return (initial + dif);
// }
// function smooth(final, initial=0) {
// 	let dif = final - initial;
// 	dif = Math.min(dif, 0.1)
// 	dif = Math.max(dif, -0.1)
// 	return (initial + dif);
// }
// function smooth(final, initial=0) {
//   return (initial + final)/2;
// }
// function smooth(final, initial=0) {
//   return final;
// }
/* ---------- Animations ---------- */

// Animation Lamp
const lampOnElem = document.getElementById('lamp-on');
let lampIsOn = 1;
lampOnElem.addEventListener('mousedown', event => {
	lampIsOn = !lampIsOn;
	lampOnElem.style.opacity = lampIsOn + 0;
});

// Animation countdown
const countdownNumElem = {
	day:    document.querySelector('.countdown__cell[data-unit="day"] .countdown__number'),
	hour:   document.querySelector('.countdown__cell[data-unit="hour"] .countdown__number'),
	minute: document.querySelector('.countdown__cell[data-unit="minute"] .countdown__number'),
	second: document.querySelector('.countdown__cell[data-unit="second"] .countdown__number'),
}
const countdownPluralElem = {
	day:    document.querySelector('.countdown__cell[data-unit="day"] .countdown__label-plural'),
	hour:   document.querySelector('.countdown__cell[data-unit="hour"] .countdown__label-plural'),
	minute: document.querySelector('.countdown__cell[data-unit="minute"] .countdown__label-plural'),
	second: document.querySelector('.countdown__cell[data-unit="second"] .countdown__label-plural'),
}

const countdownDate = new Date(2020,9,11,19,0,0); // Notice: January is 0 and December 11
let secondsLeft = Math.floor((countdownDate - new Date()) / 1000);

const countdownInterval = setInterval(updateCountdown, 1000);
updateCountdown();

function updateCountdown() {
	if(secondsLeft > 0){

		secondsLeft -= 1;

		countdownNumElem.day.textContent    = Math.floor(secondsLeft / 60 / 60 / 24);
		countdownNumElem.hour.textContent   = Math.floor(secondsLeft / 60 / 60) % 24;
		countdownNumElem.minute.textContent = Math.floor(secondsLeft / 60) % 60;
		countdownNumElem.second.textContent = Math.floor(secondsLeft) % 60;

		countdownPluralElem.day.style.display    = countdownNumElem.day.textContent === '1' ? 'none' : 'inline-block';
		countdownPluralElem.hour.style.display   = countdownNumElem.hour.textContent === '1' ? 'none' : 'inline-block';
		countdownPluralElem.minute.style.display = countdownNumElem.minute.textContent === '1' ? 'none' : 'inline-block';
		countdownPluralElem.second.style.display = countdownNumElem.second.textContent === '1' ? 'none' : 'inline-block';

	}else{
		clearInterval(countdownInterval);
	}
}

// Animation rocket

const rocketElem = document.querySelector('.object--rocket');
let rocketOn = 1;
rocketElem.addEventListener('click', event => {
	if(rocketElem.classList.contains('stop-animation')){
		rocketElem.classList.remove('stop-animation');
		setTimeout(() => {
			rocketElem.classList.add('stop-animation');
		}, (4+3+1+1) * 1000);
	}
});

// Animation duck

const duckElem = document.getElementsByClassName('object--rubber-duck')[0];
const duckSilhouetteElem = document.getElementsByClassName('wanted__duck-silhouette--missing')[0];
const duckSignElem = document.getElementsByClassName('wanted__sign')[0];
const duckListElem = document.getElementsByClassName('wanted__list')[0];
duckElem.addEventListener('click', (event) => {
	duckElem.classList.add('duck-cliked');
	duckElem.style.pointerEvents = 'none';
	setTimeout(() => {
		duckSilhouetteElem.classList.remove('wanted__duck-silhouette--missing')
		duckSilhouetteElem.classList.add('wanted__duck-silhouette--found')
		duckListElem.style.pointerEvents = 'none';
		setTimeout(() => {
			duckSignElem.textContent = 'FOUND';
		}, 200);
	}, 1000);
});

// Plot animation

const plotLinesSteps = 5;
const plotWidth = 200;
const plotHandle = Math.floor(plotWidth/plotLinesSteps/3);

const plotLines = [
	document.getElementsByClassName('plot__plot-line--1')[0],
	document.getElementsByClassName('plot__plot-line--2')[0],
	document.getElementsByClassName('plot__plot-line--3')[0],
	document.getElementsByClassName('plot__plot-line--4')[0],
];
const barContents = [
	document.getElementsByClassName('plot__bar-content--1')[0],
	document.getElementsByClassName('plot__bar-content--2')[0],
	document.getElementsByClassName('plot__bar-content--3')[0],
	document.getElementsByClassName('plot__bar-content--4')[0],
];

for (const i in plotLines) {
	animatePlotLine(i);
}

function animatePlotLine(i){
	plotLines[i].style.d = `path("${generatePattern()}")`;
	barContents[i].style.transform = `scaleY(${Math.random()})`;

	setTimeout(() => {
		animatePlotLine(i);
	}, Math.random()*5000+5500);
}

function generatePattern(){
	// If you want to understand whow the curve is build read this article:
	// https://css-tricks.com/svg-path-syntax-illustrated-guide/

	let pattern = `M${plotWidth},${Math.floor(Math.random()*100.99)}`;

	for (let i = plotLinesSteps-1; i >= 0 ; i--) {
		let x = Math.floor(plotWidth/plotLinesSteps*i);
		let y = Math.floor(Math.random()*100.99);

		pattern += ` S${x+plotHandle},${y} ${x},${y}`;
	}
	return pattern;
}

// FAQ

const faqQuestionTitleElems = document.querySelectorAll('.faq__question-title');

for (const faqQuestionTitleElem of faqQuestionTitleElems) {
	faqQuestionTitleElem.addEventListener('click', function(event) {
		const faqQuestionElem = this.closest('.faq__question');
		const faqAnswerElem = faqQuestionElem.querySelector('.faq__question-answer');
		// const faqLinksElems = faqQuestionElem.querySelectorAll('a');

    if (faqQuestionTitleElem.getAttribute('aria-expanded') === 'true') {
			faqQuestionElem.classList.remove('faq__question--expanded');
			faqQuestionTitleElem.setAttribute('aria-expanded', 'false');
			faqAnswerElem.setAttribute('aria-hidden', 'true');
			faqAnswerElem.style.maxHeight = null;
    } else {
			faqQuestionElem.classList.add('faq__question--expanded');
			faqAnswerElem.setAttribute('aria-hidden', 'false');
			faqQuestionTitleElem.setAttribute('aria-expanded', 'true');
			faqAnswerElem.style.maxHeight = `${faqAnswerElem.scrollHeight}px`;
		}

		if(!faqQuestionTitleElem.dataset.clicked) {
			faqQuestionTitleElem.dataset.clicked = true;

			analytics.track('faq-expanded', {
				category: 'FAQ',
				label: 'FAQ question expanded',
				value: faqQuestionTitleElem.textContent.trim(),
			});
		}
	});
}
<commit_msg>Fix perspective in safari<commit_after>// import * from './scripts/example';

// import './styles/style.css';
// import './styles/style.sass';
import 'normalize.css';
import './styles/style.scss';

import webfont from 'webfontloader';
import Analytics from 'analytics'
import googleAnalytics from '@analytics/google-analytics'
import 'focus-visible';

/* ---------- Webfont (asyncronously load fonts) ---------- */

webfont.load({
	google: {
		families: ['Montserrat:400,400i,600,700,800,800i&display=swap']
	}
});

/* ---------- Google Analytics ---------- */

const analytics = Analytics({
  app: 'hackupc-landing',
  plugins: [
    googleAnalytics({
			trackingId: 'UA-69542332-1',
			anonymizeIp: true,
    })
  ]
})

document.querySelectorAll('[data-ga-apply-button]').forEach((elem) => {
	elem.addEventListener('click', (event) => {
		const data = event.target.dataset;

		analytics.track('applyed', {
			category: 'Apply',
			label: 'Apply button clicked',
			value: data.location,
		});
	});
})

document.querySelectorAll('[data-ga-nav-item]').forEach((elem) => {
	elem.addEventListener('click', (event) => {
		analytics.track('navbar-clicked', {
			category: 'Navigation',
			label: 'Navbar link clicked',
			value: event.target.href,
		});
	});
})

// window.dataLayer = window.dataLayer || [];
// function gtag(){
// 	dataLayer.push(arguments);
// }
// gtag('js', new Date());
// gtag('config', 'UA-69542332-1');

/* ---------- Lax.js ---------- */
// import lax from 'lax.js'

// window.onload = function() {
// 	lax.setup() // init

// 	const updateLax = () => {
// 		lax.update(window.scrollY)
// 		window.requestAnimationFrame(updateLax)
// 	}

// 	window.requestAnimationFrame(updateLax)
// }

/* ---------- Real vh ---------- */
// https://css-tricks.com/the-trick-to-viewport-units-on-mobile/

// We listen to the resize event
// window.addEventListener('resize', () => {
//   // We execute the same script as before
//   let vh = window.innerHeight * 0.01;
//   document.documentElement.style.setProperty('--vh', `${vh}px`);
// });

/* ---------- Update hero perspective ---------- */
const heroElem = document.getElementsByClassName('hero-3d-space')[0];
const applyElem = document.getElementsByClassName('apply-button')[0];
let mouseX = 0.5;
let mouseY = 0.5;

let alpha = 0.5;
let beta = 0.5;
let gamma = 0.5;

let alphaOrig = 0.5;
let betaOrig = 0.5;
let gammaOrig = 0.5;

let perspectiveX = window.innerWidth/2;
let perspectiveY = window.innerHeight * 0.125;

let translateZ = false;

window.addEventListener('scroll', updateHeroPerspective, {passive: true});
window.addEventListener('mousemove', updateHeroPerspective);
window.addEventListener('resize', updateHeroPerspective);
updateHeroPerspective();
let heroWaitingRefresh = false;

// iOS 13+ device orientation requestPermission
if (window.DeviceOrientationEvent && typeof window.DeviceOrientationEvent.requestPermission === 'function') {
	heroElem.addEventListener('click', (event) => {
		if(event.currentTarget !== applyElem){
			window.DeviceOrientationEvent.requestPermission()
			.then(permissionState => {
				if (permissionState === 'granted') {
					window.addEventListener('deviceorientation', updateHeroPerspective, false);
				}
			}).catch(console.error);
		}
	});
} else {
	window.addEventListener('deviceorientation', updateHeroPerspective, false);
}

document.addEventListener('visibilitychange', () => {
	alphaOrig = 0.5;
	betaOrig  = 0.5;
	gammaOrig = 0.5;
});

function updateHeroPerspective(event) {
	if(window.pageYOffset <= window.innerHeight && !heroWaitingRefresh) {
		if(event){
			// alpha [0,360]  -->[0,1]
			// beta  [-180,180]-->[0,1]
			// gamma [-90,90] -->[0,1]

			let newMouseX = mod(event.clientX/window.innerWidth);
			let newMouseY = mod(event.clientY/window.innerHeight);
			let newAlpha  = mod(event.alpha/360 + 0.5);
			let newBeta   = mod((event.beta + 180)/360 - 0.125);
			let newGamma  = mod((event.gamma + 90)/180);

			mouseX = smooth(newMouseX, mouseX);
			mouseY = smooth(newMouseY, mouseY);
			alpha  = smooth(newAlpha,  alpha);
			beta   = smooth(newBeta,   beta);
			gamma  = smooth(newGamma,  gamma);

			if(!isNaN(newAlpha) && alphaOrig === 0.5){ alpha = newAlpha; alphaOrig = newAlpha; }
			if(!isNaN(newBeta ) && betaOrig  === 0.5){ beta  = newBeta;  betaOrig  = newBeta;  }
			if(!isNaN(newGamma) && gammaOrig === 0.5){ gamma = newGamma; gammaOrig = newGamma; }
		}

		heroWaitingRefresh = true;
		window.requestAnimationFrame(() => {
			perspectiveX = 0
			+ window.innerWidth/2
			+ 250 * magnet((mod(alpha - alphaOrig + 0.5) - 0.5) * 2)
			+ 250 * magnet((mod(gamma - gammaOrig + 0.5) - 0.5) * 2)
			+ -window.innerWidth/40 * magnet((mouseX - 0.5) * 2)

			let height = Math.min(900, window.innerHeight);
			perspectiveY = 0
			+ window.pageYOffset
			+ height * 0.125
			+ 500 * magnet((mod(beta - betaOrig + 0.5) - 0.5) * 2)
			+ -height/40 * magnet((mouseY - 0.6667) * 2)

			heroElem.style.perspectiveOrigin = `${perspectiveX}px ${perspectiveY}px`;
      heroElem.style.transform = `translateZ(${(translateZ = !translateZ) ? 1 : 0}px)`; // Fix firefox and safari
			heroWaitingRefresh = false;
		});
	}
}

function mod(n,m=1){
	return ((n % m) + m) % m;
}
function magnet(x=0.5) {
	return Math.sin(Math.PI/2*x);
}

function smooth(final, initial=0) {
	if(isNaN(final)) return initial;

	let dif = final - initial;
	let s = dif >= 0 ? +1 : -1;
	return (initial + s * dif**2);
}
// function smooth(final, initial=0) {
// 	let dif = final - initial;
// 	if(dif < 0.01 && dif > -0.01) return initial;
// 	else return (initial + dif);
// }
// function smooth(final, initial=0) {
// 	let dif = final - initial;
// 	dif = Math.min(dif, 0.1)
// 	dif = Math.max(dif, -0.1)
// 	return (initial + dif);
// }
// function smooth(final, initial=0) {
//   return (initial + final)/2;
// }
// function smooth(final, initial=0) {
//   return final;
// }
/* ---------- Animations ---------- */

// Animation Lamp
const lampOnElem = document.getElementById('lamp-on');
let lampIsOn = 1;
lampOnElem.addEventListener('mousedown', event => {
	lampIsOn = !lampIsOn;
	lampOnElem.style.opacity = lampIsOn + 0;
});

// Animation countdown
const countdownNumElem = {
	day:    document.querySelector('.countdown__cell[data-unit="day"] .countdown__number'),
	hour:   document.querySelector('.countdown__cell[data-unit="hour"] .countdown__number'),
	minute: document.querySelector('.countdown__cell[data-unit="minute"] .countdown__number'),
	second: document.querySelector('.countdown__cell[data-unit="second"] .countdown__number'),
}
const countdownPluralElem = {
	day:    document.querySelector('.countdown__cell[data-unit="day"] .countdown__label-plural'),
	hour:   document.querySelector('.countdown__cell[data-unit="hour"] .countdown__label-plural'),
	minute: document.querySelector('.countdown__cell[data-unit="minute"] .countdown__label-plural'),
	second: document.querySelector('.countdown__cell[data-unit="second"] .countdown__label-plural'),
}

const countdownDate = new Date(2020,9,11,19,0,0); // Notice: January is 0 and December 11
let secondsLeft = Math.floor((countdownDate - new Date()) / 1000);

const countdownInterval = setInterval(updateCountdown, 1000);
updateCountdown();

function updateCountdown() {
	if(secondsLeft > 0){

		secondsLeft -= 1;

		countdownNumElem.day.textContent    = Math.floor(secondsLeft / 60 / 60 / 24);
		countdownNumElem.hour.textContent   = Math.floor(secondsLeft / 60 / 60) % 24;
		countdownNumElem.minute.textContent = Math.floor(secondsLeft / 60) % 60;
		countdownNumElem.second.textContent = Math.floor(secondsLeft) % 60;

		countdownPluralElem.day.style.display    = countdownNumElem.day.textContent === '1' ? 'none' : 'inline-block';
		countdownPluralElem.hour.style.display   = countdownNumElem.hour.textContent === '1' ? 'none' : 'inline-block';
		countdownPluralElem.minute.style.display = countdownNumElem.minute.textContent === '1' ? 'none' : 'inline-block';
		countdownPluralElem.second.style.display = countdownNumElem.second.textContent === '1' ? 'none' : 'inline-block';

	}else{
		clearInterval(countdownInterval);
	}
}

// Animation rocket

const rocketElem = document.querySelector('.object--rocket');
let rocketOn = 1;
rocketElem.addEventListener('click', event => {
	if(rocketElem.classList.contains('stop-animation')){
		rocketElem.classList.remove('stop-animation');
		setTimeout(() => {
			rocketElem.classList.add('stop-animation');
		}, (4+3+1+1) * 1000);
	}
});

// Animation duck

const duckElem = document.getElementsByClassName('object--rubber-duck')[0];
const duckSilhouetteElem = document.getElementsByClassName('wanted__duck-silhouette--missing')[0];
const duckSignElem = document.getElementsByClassName('wanted__sign')[0];
const duckListElem = document.getElementsByClassName('wanted__list')[0];
duckElem.addEventListener('click', (event) => {
	duckElem.classList.add('duck-cliked');
	duckElem.style.pointerEvents = 'none';
	setTimeout(() => {
		duckSilhouetteElem.classList.remove('wanted__duck-silhouette--missing')
		duckSilhouetteElem.classList.add('wanted__duck-silhouette--found')
		duckListElem.style.pointerEvents = 'none';
		setTimeout(() => {
			duckSignElem.textContent = 'FOUND';
		}, 200);
	}, 1000);
});

// Plot animation

const plotLinesSteps = 5;
const plotWidth = 200;
const plotHandle = Math.floor(plotWidth/plotLinesSteps/3);

const plotLines = [
	document.getElementsByClassName('plot__plot-line--1')[0],
	document.getElementsByClassName('plot__plot-line--2')[0],
	document.getElementsByClassName('plot__plot-line--3')[0],
	document.getElementsByClassName('plot__plot-line--4')[0],
];
const barContents = [
	document.getElementsByClassName('plot__bar-content--1')[0],
	document.getElementsByClassName('plot__bar-content--2')[0],
	document.getElementsByClassName('plot__bar-content--3')[0],
	document.getElementsByClassName('plot__bar-content--4')[0],
];

for (const i in plotLines) {
	animatePlotLine(i);
}

function animatePlotLine(i){
	plotLines[i].style.d = `path("${generatePattern()}")`;
	barContents[i].style.transform = `scaleY(${Math.random()})`;

	setTimeout(() => {
		animatePlotLine(i);
	}, Math.random()*5000+5500);
}

function generatePattern(){
	// If you want to understand whow the curve is build read this article:
	// https://css-tricks.com/svg-path-syntax-illustrated-guide/

	let pattern = `M${plotWidth},${Math.floor(Math.random()*100.99)}`;

	for (let i = plotLinesSteps-1; i >= 0 ; i--) {
		let x = Math.floor(plotWidth/plotLinesSteps*i);
		let y = Math.floor(Math.random()*100.99);

		pattern += ` S${x+plotHandle},${y} ${x},${y}`;
	}
	return pattern;
}

// FAQ

const faqQuestionTitleElems = document.querySelectorAll('.faq__question-title');

for (const faqQuestionTitleElem of faqQuestionTitleElems) {
	faqQuestionTitleElem.addEventListener('click', function(event) {
		const faqQuestionElem = this.closest('.faq__question');
		const faqAnswerElem = faqQuestionElem.querySelector('.faq__question-answer');
		// const faqLinksElems = faqQuestionElem.querySelectorAll('a');

    if (faqQuestionTitleElem.getAttribute('aria-expanded') === 'true') {
			faqQuestionElem.classList.remove('faq__question--expanded');
			faqQuestionTitleElem.setAttribute('aria-expanded', 'false');
			faqAnswerElem.setAttribute('aria-hidden', 'true');
			faqAnswerElem.style.maxHeight = null;
    } else {
			faqQuestionElem.classList.add('faq__question--expanded');
			faqAnswerElem.setAttribute('aria-hidden', 'false');
			faqQuestionTitleElem.setAttribute('aria-expanded', 'true');
			faqAnswerElem.style.maxHeight = `${faqAnswerElem.scrollHeight}px`;
		}

		if(!faqQuestionTitleElem.dataset.clicked) {
			faqQuestionTitleElem.dataset.clicked = true;

			analytics.track('faq-expanded', {
				category: 'FAQ',
				label: 'FAQ question expanded',
				value: faqQuestionTitleElem.textContent.trim(),
			});
		}
	});
}
<|endoftext|>


<commit_before>const path = require('path')
const babylon = require('babylon')
const traverse = require('babel-traverse').default
const isStyled = require('./utils/styled').isStyled
const isHelper = require('./utils/styled').isHelper
const isStyledImport = require('./utils/styled').isStyledImport

const wrapSelector = require('./utils/general').wrapSelector
const wrapKeyframes = require('./utils/general').wrapKeyframes
const fixIndentation = require('./utils/general').fixIndentation

const getTTLContent = require('./utils/tagged-template-literal.js').getTaggedTemplateLiteralContent
const parseImports = require('./utils/parse').parseImports
const getSourceMap = require('./utils/parse').getSourceMap

// TODO Fix ampersand in selectors
// TODO ENFORCE THESE RULES
// value-no-vendor-prefix – don't allow vendor prefixes
// property-no-vendor-prefix – don't allow vendor prefixes

const ignoredRules = [
  // Don't throw if there's no styled-components in a file
  'no-empty-source',
  // We don't care about end-of-source newlines, users cannot control them
  'no-missing-end-of-source-newline',
]

const sourceMapsCorrections = {}

module.exports = (/* options */) => ({
  // Get string for stylelint to lint
  code(input, filepath) {
    const absolutePath = path.resolve(process.cwd(), filepath)
    sourceMapsCorrections[absolutePath] = {}
    const ast = babylon.parse(input, {
      sourceType: 'module',
      plugins: [
        'jsx',
        'flow',
        'objectRestSpread',
        'decorators',
        'classProperties',
        'exportExtensions',
        'asyncGenerators',
        'functionBind',
        'functionSent',
        'dynamicImport',
      ],
    })

    const extractedCSS = []
    let importedNames = {
      default: 'styled',
      css: 'css',
      keyframes: 'keyframes',
      injectGlobal: 'injectGlobal',
    }
    traverse(ast, {
      enter({ node }) {
        if (isStyledImport(node)) {
          importedNames = parseImports(node)
          return
        }

        const helper = isHelper(node, importedNames)

        if (!helper && !isStyled(node, importedNames.default)) return

        const content = getTTLContent(node)
        const fixedContent = fixIndentation(content).text
        const wrapperFn = helper === 'keyframes' ? wrapKeyframes : wrapSelector
        const wrappedContent = wrapperFn(fixedContent)
        extractedCSS.push(wrappedContent)
        // Save source location, merging existing corrections with current corrections
        sourceMapsCorrections[absolutePath] = Object.assign(
          sourceMapsCorrections[absolutePath],
          getSourceMap(extractedCSS.join('\n'), wrappedContent, node.loc.start.line)
        )
      },
    })

    return extractedCSS.join('\n')
  },
  // Fix sourcemaps
  result(stylelintResult, filepath) {
    const lineCorrection = sourceMapsCorrections[filepath]
    const newWarnings = stylelintResult.warnings.reduce((prevWarnings, warning) => {
      if (ignoredRules.includes(warning.rule)) return prevWarnings
      const correctedWarning = Object.assign(warning, {
        // Replace "brace" with "backtick" in warnings, e.g.
        // "Unexpected empty line before closing backtick" (instead of "brace")
        text: warning.text.replace(/brace/, 'backtick'),
        line: lineCorrection[warning.line],
      })
      prevWarnings.push(correctedWarning)
      return prevWarnings
    }, [])

    if (newWarnings.length === 0) {
      stylelintResult.errored = false
    }

    return Object.assign(stylelintResult, { warnings: newWarnings })
  },
})
<commit_msg>Fix linting errors<commit_after>const path = require('path')
const babylon = require('babylon')
const traverse = require('babel-traverse').default
const isStyled = require('./utils/styled').isStyled
const isHelper = require('./utils/styled').isHelper
const isStyledImport = require('./utils/styled').isStyledImport

const wrapSelector = require('./utils/general').wrapSelector
const wrapKeyframes = require('./utils/general').wrapKeyframes
const fixIndentation = require('./utils/general').fixIndentation

const getTTLContent = require('./utils/tagged-template-literal.js').getTaggedTemplateLiteralContent
const parseImports = require('./utils/parse').parseImports
const getSourceMap = require('./utils/parse').getSourceMap

// TODO Fix ampersand in selectors
// TODO ENFORCE THESE RULES
// value-no-vendor-prefix – don't allow vendor prefixes
// property-no-vendor-prefix – don't allow vendor prefixes

const ignoredRules = [
  // Don't throw if there's no styled-components in a file
  'no-empty-source',
  // We don't care about end-of-source newlines, users cannot control them
  'no-missing-end-of-source-newline',
]

const sourceMapsCorrections = {}

module.exports = (/* options */) => ({
  // Get string for stylelint to lint
  code(input, filepath) {
    const absolutePath = path.resolve(process.cwd(), filepath)
    sourceMapsCorrections[absolutePath] = {}
    const ast = babylon.parse(input, {
      sourceType: 'module',
      plugins: [
        'jsx',
        'flow',
        'objectRestSpread',
        'decorators',
        'classProperties',
        'exportExtensions',
        'asyncGenerators',
        'functionBind',
        'functionSent',
        'dynamicImport',
      ],
    })

    const extractedCSS = []
    let importedNames = {
      default: 'styled',
      css: 'css',
      keyframes: 'keyframes',
      injectGlobal: 'injectGlobal',
    }
    traverse(ast, {
      enter({ node }) {
        if (isStyledImport(node)) {
          importedNames = parseImports(node)
          return
        }

        const helper = isHelper(node, importedNames)

        if (!helper && !isStyled(node, importedNames.default)) return

        const content = getTTLContent(node)
        const fixedContent = fixIndentation(content).text
        const wrapperFn = helper === 'keyframes' ? wrapKeyframes : wrapSelector
        const wrappedContent = wrapperFn(fixedContent)
        extractedCSS.push(wrappedContent)
        // Save source location, merging existing corrections with current corrections
        sourceMapsCorrections[absolutePath] = Object.assign(
          sourceMapsCorrections[absolutePath],
          getSourceMap(extractedCSS.join('\n'), wrappedContent, node.loc.start.line)
        )
      },
    })

    return extractedCSS.join('\n')
  },
  // Fix sourcemaps
  result(stylelintResult, filepath) {
    const lineCorrection = sourceMapsCorrections[filepath]
    const newWarnings = stylelintResult.warnings.reduce((prevWarnings, warning) => {
      if (ignoredRules.includes(warning.rule)) return prevWarnings
      const correctedWarning = Object.assign(warning, {
        // Replace "brace" with "backtick" in warnings, e.g.
        // "Unexpected empty line before closing backtick" (instead of "brace")
        text: warning.text.replace(/brace/, 'backtick'),
        line: lineCorrection[warning.line],
      })
      prevWarnings.push(correctedWarning)
      return prevWarnings
    }, [])

    if (newWarnings.length === 0) {
      // eslint-disable-next-line no-param-reassign
      stylelintResult.errored = false
    }

    return Object.assign(stylelintResult, { warnings: newWarnings })
  },
})
<|endoftext|>


<commit_before>export function onConnect(init, responses, connections, tab, error) {
  if (typeof connections === 'undefined' && !window.bgConnections) {
    window.bgConnections = {}; connections = window.bgConnections;
  }

  chrome.runtime.onConnect.addListener(function(port) {
    function extensionListener(message) {
      if (message.name === 'init') {
        connections[message.tabId || port.sender.tab.id] = port;

        if (tab && message.tabId !== tab.id) {
          error(port);
          return;
        }
        port.postMessage(init());
      }
      else if(responses[message.name]) {
        const res = responses[message.name](message);
        if (res) port.postMessage(res);
      }
    }

    port.onMessage.addListener(extensionListener);
    port.onDisconnect.addListener(function(portDiscon) {
      portDiscon.onMessage.removeListener(extensionListener);
      Object.keys(connections).forEach(function(id) {
        if (connections[id] === portDiscon) {
          delete connections[id];
        }
      });
    });

  });
}

export function connect(arg) {
  if (!arg) return chrome.runtime.connect();
  if (typeof arg === 'boolean' && arg) {
    window.bgConnection = chrome.runtime.connect();
    return window.bgConnection;
  }
  return chrome.runtime.connect(arg);
}

export function onMessage(messaging) {
  if (chrome.runtime.onMessage) chrome.runtime.onMessage.addListener(messaging);
}

export function sendToBg(...args) {
  if (!window.bgConnection) chrome.runtime.sendMessage(...args);
  else {
    window.bgConnection.postMessage(...args);
  }
}

export function sendToTab(...args) {
  chrome.tabs.sendMessage(...args);
}

export function sendToTabs(message, connections) {
  if (!connections) {
    if (window.bgConnections) connections = window.bgConnections;
    else return;
  }
  Object.keys(connections).forEach(function(id) {
    connections[id].postMessage(message);
  });
}

export function sendMessage(message) {
  if (window.bgConnection) window.bgConnection.postMessage(message);
  else sendToTabs(message);
}
<commit_msg>If the background page not respond to the content script message, the message will be relayed to the rest of content scripts (from global connection list)<commit_after>export function onConnect(init, responses, connections, tab, error) {
  if (typeof connections === 'undefined' && !window.bgConnections) {
    window.bgConnections = {}; connections = window.bgConnections;
  }

  chrome.runtime.onConnect.addListener(function(port) {
    function extensionListener(message) {
      if (message.name === 'init') {
        connections[message.tabId || port.sender.tab.id] = port;

        if (tab && message.tabId !== tab.id) {
          error(port);
          return;
        }
        port.postMessage(init());
      }
      else if(responses[message.name]) {
        const res = responses[message.name](message);
        if (res) port.postMessage(res);
        else if (window.bgConnections) {
          sendToTabsExcept(message, port, window.bgConnections);
        }
      }
    }

    port.onMessage.addListener(extensionListener);
    port.onDisconnect.addListener(function(portDiscon) {
      portDiscon.onMessage.removeListener(extensionListener);
      Object.keys(connections).forEach(function(id) {
        if (connections[id] === portDiscon) {
          delete connections[id];
        }
      });
    });

  });
}

export function connect(arg) {
  if (!arg) return chrome.runtime.connect();
  if (typeof arg === 'boolean' && arg) {
    window.bgConnection = chrome.runtime.connect();
    return window.bgConnection;
  }
  return chrome.runtime.connect(arg);
}

export function onMessage(messaging) {
  if (chrome.runtime.onMessage) chrome.runtime.onMessage.addListener(messaging);
}

export function sendToBg(...args) {
  if (!window.bgConnection) chrome.runtime.sendMessage(...args);
  else {
    window.bgConnection.postMessage(...args);
  }
}

export function sendToTab(...args) {
  chrome.tabs.sendMessage(...args);
}

export function sendToTabs(message, connections) {
  if (!connections) {
    if (window.bgConnections) connections = window.bgConnections;
    else return;
  }
  Object.keys(connections).forEach(function(id) {
    connections[id].postMessage(message);
  });
}

export function sendToTabsExcept(message, port, connections) {
  Object.keys(connections).forEach(function(id) {
    if (connections[id] !== port) {
      connections[id].postMessage(message);
    }
  });
}

export function sendMessage(message) {
  if (window.bgConnection) window.bgConnection.postMessage(message);
  else sendToTabs(message);
}
<|endoftext|>


<commit_before>'use strict';

require("bootstrap-loader");
import * as agave from '../node_modules/agave-file-browser/AgaveFileBrowser.js';
import * as simplots from '../node_modules/sim-plots/heatmap.js';
import 'jstree';

// Require these files so they get copied to dist
require('../index.html');
require("../img/nav-header.png");
require('../css/imicrobe.css');
//require('../css/readable.min.css');
require('../css/spinner.css');
require('../node_modules/agave-file-browser/spinner.gif');
require.context("../plugins/landing-page", true, /^\.\/.*\.(jpg|png|html|css)/);

// Load config file
var config = require('../config.json');

// Start up Elm app
var Elm = require('./Main.elm');
var mountNode = document.getElementById('main');
var app = Elm.Main.embed(mountNode, {
    session: localStorage.session || ""
});

/*
 * Initialize Google Maps and define ports
 */

var GoogleMapsLoader = require("google-maps");
GoogleMapsLoader.KEY = config.googleApiKey;
var Google;
GoogleMapsLoader.load(function(google) {
    Google = google;
});

app.ports.loadMap.subscribe(function(model) {
    var mapDiv = document.getElementsByTagName('gmap')[0];

    var myLatlng = new Google.maps.LatLng(model.lat, model.lng);
    var mapOptions = {
      zoom: 6,
      center: myLatlng
    };
    var gmap = new Google.maps.Map(mapDiv, mapOptions);
    app.ports.receiveMap.send(gmap);
});

app.ports.setCenter.subscribe(function(model) {
    var myLatlng = new Google.maps.LatLng(model.center.lat, model.center.lng);
    model.gmap.setCenter(myLatlng);
});

/*
 * Define ports for storing/watching session
 */

app.ports.storeSession.subscribe(function(session) {
    console.log("storeSession: ", session);
    localStorage.session = session;
});

// This event is only triggered when localStorage is modifed from another window
window.addEventListener("storage",
    function(event) {
        if (event.storageArea === localStorage && event.key === "session") {
            console.log("storage listener:", event.newValue);
            app.ports.onSessionChange.send(event.newValue);
        }
    },
    false
);

/*
 * Define ports for Agave File Browser
 */

var fileBrowser;
app.ports.createFileBrowser.subscribe(function(input) { // TODO get username/token from localStorage.session instead of passing in
    var dialog = $('#file-browser-dialog');

    if (typeof fileBrowser == 'undefined') {
        fileBrowser = new agave.AgaveFileBrowser({
            elementId:   'file-browser',
            baseUrl:     config.agaveFilesUrl,
            path:        input.username,
            authToken:   input.token,
            busyIconUrl: 'img/spinner.gif'
        });
    }

    // Needs to be redefined for each call as input changes
    dialog.find('button.btn-primary').unbind().click(function() {
        var files = fileBrowser.getSelectedNodes();
        console.log('selected:', files);

        dialog.modal('hide');

        app.ports.onFileSelect.send({
            id: input.id,
            username: input.username,
            token: input.token,
            path: files.map(f => f.id).join(';')
        });
    });

    dialog.modal('show');
});

/*
 * Initialize Google Analytics and define port
 */

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

var analyticsInitialized = false;
app.ports.updateAnalytics.subscribe(function (page) {
    if (!analyticsInitialized) {
        analyticsInitialized = true;
        ga('create', config.googleAnalyticsId, 'auto');
        console.log("updateAnalytics: Initialized Google Analytics:", config.googleAnalyticsId)
    }

    console.log("updateAnalytics:", page);
    ga('set', 'page', page);
    ga('send', 'pageview');
});

/*
 * Define ports for Sequence Similarity Plots
 */

app.ports.createSimPlot.subscribe(function(args) {
    simplots.heatmap(args[0], args[1]);
});
<commit_msg>Add edge-boundary plot to Job results<commit_after>'use strict';

require("bootstrap-loader");
import * as agave from '../node_modules/agave-file-browser/AgaveFileBrowser.js';
import * as simplots from '../node_modules/sim-plots/sim-plots.js';
import 'jstree';

// Require these files so they get copied to dist
require('../index.html');
require("../img/nav-header.png");
require('../css/imicrobe.css');
//require('../css/readable.min.css');
require('../css/spinner.css');
require('../node_modules/sim-plots/main.css');
require('../node_modules/agave-file-browser/spinner.gif');
require.context("../plugins/landing-page", true, /^\.\/.*\.(jpg|png|html|css)/);

// Load config file
var config = require('../config.json');

// Start up Elm app
var Elm = require('./Main.elm');
var mountNode = document.getElementById('main');
var app = Elm.Main.embed(mountNode, {
    session: localStorage.session || ""
});

/*
 * Initialize Google Maps and define ports
 */

var GoogleMapsLoader = require("google-maps");
GoogleMapsLoader.KEY = config.googleApiKey;
var Google;
GoogleMapsLoader.load(function(google) {
    Google = google;
});

app.ports.loadMap.subscribe(function(model) {
    var mapDiv = document.getElementsByTagName('gmap')[0];

    var myLatlng = new Google.maps.LatLng(model.lat, model.lng);
    var mapOptions = {
      zoom: 6,
      center: myLatlng
    };
    var gmap = new Google.maps.Map(mapDiv, mapOptions);
    app.ports.receiveMap.send(gmap);
});

app.ports.setCenter.subscribe(function(model) {
    var myLatlng = new Google.maps.LatLng(model.center.lat, model.center.lng);
    model.gmap.setCenter(myLatlng);
});

/*
 * Define ports for storing/watching session
 */

app.ports.storeSession.subscribe(function(session) {
    console.log("storeSession: ", session);
    localStorage.session = session;
});

// This event is only triggered when localStorage is modifed from another window
window.addEventListener("storage",
    function(event) {
        if (event.storageArea === localStorage && event.key === "session") {
            console.log("storage listener:", event.newValue);
            app.ports.onSessionChange.send(event.newValue);
        }
    },
    false
);

/*
 * Define ports for Agave File Browser
 */

var fileBrowser;
app.ports.createFileBrowser.subscribe(function(input) { // TODO get username/token from localStorage.session instead of passing in
    var dialog = $('#file-browser-dialog');

    if (typeof fileBrowser == 'undefined') {
        fileBrowser = new agave.AgaveFileBrowser({
            elementId:   'file-browser',
            baseUrl:     config.agaveFilesUrl,
            path:        input.username,
            authToken:   input.token,
            busyIconUrl: 'img/spinner.gif'
        });
    }

    // Needs to be redefined for each call as input changes
    dialog.find('button.btn-primary').unbind().click(function() {
        var files = fileBrowser.getSelectedNodes();
        console.log('selected:', files);

        dialog.modal('hide');

        app.ports.onFileSelect.send({
            id: input.id,
            username: input.username,
            token: input.token,
            path: files.map(f => f.id).join(';')
        });
    });

    dialog.modal('show');
});

/*
 * Initialize Google Analytics and define port
 */

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

var analyticsInitialized = false;
app.ports.updateAnalytics.subscribe(function (page) {
    if (!analyticsInitialized) {
        analyticsInitialized = true;
        ga('create', config.googleAnalyticsId, 'auto');
        console.log("updateAnalytics: Initialized Google Analytics:", config.googleAnalyticsId)
    }

    console.log("updateAnalytics:", page);
    ga('set', 'page', page);
    ga('send', 'pageview');
});

/*
 * Define ports for Sequence Similarity Plots
 */

app.ports.createSimPlot.subscribe(function(args) {
    console.log("createSimPlot: ", args);
    simplots.heatmap(args[0], args[1]);
    simplots.edgeboundary(args[0], args[1]);
});
<|endoftext|>


<commit_before>// @flow

import Accordion from './Accordion/accordion';
import AccordionItem from './AccordionItem/accordion-item';
import AccordionItemTitle from './AccordionItemTitle/accordion-item-title';
import AccordionItemBody from './AccordionItemBody/accordion-item-body';

export { Accordion, AccordionItem, AccordionItemTitle, AccordionItemBody };
<commit_msg>Export 'resetNextId'.<commit_after>// @flow

import Accordion from './Accordion/accordion';
import AccordionItem, { resetNextUuid } from './AccordionItem/accordion-item';
import AccordionItemTitle from './AccordionItemTitle/accordion-item-title';
import AccordionItemBody from './AccordionItemBody/accordion-item-body';

export {
    Accordion,
    AccordionItem,
    AccordionItemTitle,
    AccordionItemBody,
    resetNextUuid,
};
<|endoftext|>


<commit_before>// @flow

// eslint-disable-next-line no-unused-vars
export type Command<Effect, Action, State> = {
  type: 'Effect',
  effect: Effect,
} | {
  type: 'Dispatch',
  action: Action,
} | {
  type: 'GetState',
};

export type Yield<Effect, Action, State> = {
  type: 'Command',
  command: Command<Effect, Action, State>,
} | {
  type: 'All',
  ships: Generator<Yield<Effect, Action, State>, any, any>[],
};

export type t<Effect, Action, State, A> = Generator<Yield<Effect, Action, State>, A, any>;

function runCommand<Effect, Action, State>(
  runEffect: (effect: Effect) => any,
  runDispatch: (action: Action) => void | Promise<void>,
  runGetState: () => State,
  command: Command<Effect, Action, State>
): Promise<any> {
  return Promise.resolve((() => {
    switch (command.type) {
    case 'Effect':
      return runEffect(command.effect);
    case 'Dispatch':
      return runDispatch(command.action);
    case 'GetState':
      return runGetState();
    default:
      return command;
    }
  })());
}

function runWithAnswer<Effect, Action, State, A>(
  runEffect: (effect: Effect) => any,
  runDispatch: (action: Action) => void | Promise<void>,
  runGetState: () => State,
  ship: t<Effect, Action, State, A>,
  answer?: any
): Promise<A> {
  const result = ship.next(answer);
  if (result.done) {
    return Promise.resolve((result.value: any));
  }
  switch (result.value.type) {
  case 'Command':
    return runCommand(runEffect, runDispatch, runGetState, result.value.command).then((newAnswer) =>
      runWithAnswer(runEffect, runDispatch, runGetState, ship, newAnswer)
    );
  case 'All':
    return Promise.all(result.value.ships.map(currentShip =>
      runWithAnswer(runEffect, runDispatch, runGetState, currentShip))
    ).then(newAnswer =>
      runWithAnswer(runEffect, runDispatch, runGetState, ship, newAnswer)
    );
  default:
    return result.value;
  }
}

/* eslint-disable no-undef */
export const run: <Effect, Action, State, A>(
  runEffect: (effect: Effect) => any,
  runDispatch: (action: Action) => void | Promise<void>,
  runGetState: () => State,
  ship: t<Effect, Action, State, A>
) => Promise<A> =
  runWithAnswer;
/* eslint-enable no-undef */

export function* call<Effect, Action, State>(effect: Effect): t<Effect, Action, State, any> {
  const result: any = yield {
    type: 'Command',
    command: {
      type: 'Effect',
      effect,
    },
  };
  return result;
}

function* allAny<Effect, Action, State>(
  ...ships: t<Effect, Action, State, any>[]
): t<Effect, Action, State, any[]> {
  const result: any = yield {
    type: 'All',
    ships,
  };
  return result;
}

export function all<Effect, Action, State, A>(
  ships: t<Effect, Action, State, A>[]
): t<Effect, Action, State, A[]> {
  return allAny(...ships);
}

/* eslint-disable no-undef */
export const all2: <Effect, Action, State, A1, A2>(
  ship1: t<Effect, Action, State, A1>,
  ship2: t<Effect, Action, State, A2>
) => t<Effect, Action, State, [A1, A2]> =
  allAny;

export const all3: <Effect, Action, State, A1, A2, A3>(
  ship1: t<Effect, Action, State, A1>,
  ship2: t<Effect, Action, State, A2>,
  ship3: t<Effect, Action, State, A3>
) => t<Effect, Action, State, [A1, A2, A3]> =
  allAny;

export const all4: <Effect, Action, State, A1, A2, A3, A4>(
  ship1: t<Effect, Action, State, A1>,
  ship2: t<Effect, Action, State, A2>,
  ship3: t<Effect, Action, State, A3>,
  ship4: t<Effect, Action, State, A4>
) => t<Effect, Action, State, [A1, A2, A3, A4]> =
  allAny;

export const all5: <Effect, Action, State, A1, A2, A3, A4, A5>(
  ship1: t<Effect, Action, State, A1>,
  ship2: t<Effect, Action, State, A2>,
  ship3: t<Effect, Action, State, A3>,
  ship4: t<Effect, Action, State, A4>,
  ship4: t<Effect, Action, State, A5>
) => t<Effect, Action, State, [A1, A2, A3, A4, A5]> =
  allAny;

export const all6: <Effect, Action, State, A1, A2, A3, A4, A5, A6>(
  ship1: t<Effect, Action, State, A1>,
  ship2: t<Effect, Action, State, A2>,
  ship3: t<Effect, Action, State, A3>,
  ship4: t<Effect, Action, State, A4>,
  ship4: t<Effect, Action, State, A5>,
  ship4: t<Effect, Action, State, A6>
) => t<Effect, Action, State, [A1, A2, A3, A4, A5, A6]> =
  allAny;

export const all7: <Effect, Action, State, A1, A2, A3, A4, A5, A6, A7>(
  ship1: t<Effect, Action, State, A1>,
  ship2: t<Effect, Action, State, A2>,
  ship3: t<Effect, Action, State, A3>,
  ship4: t<Effect, Action, State, A4>,
  ship4: t<Effect, Action, State, A5>,
  ship4: t<Effect, Action, State, A6>,
  ship4: t<Effect, Action, State, A7>
) => t<Effect, Action, State, [A1, A2, A3, A4, A5, A6, A7]> =
  allAny;
/* eslint-enable no-undef */

export function* dispatch<Effect, Action, State>(action: Action): t<Effect, Action, State, void> {
  yield {
    type: 'Command',
    command: {
      type: 'Dispatch',
      action,
    },
  };
}

export function* getState<Effect, Action, State>(): t<Effect, Action, State, State> {
  const state: any = yield {
    type: 'Command',
    command: {
      type: 'GetState',
    },
  };
  return state;
}

function* mapCommand<Effect1, Action1, State1, Effect2, Action2, State2>(
  mapEffect: (effect1: Effect1) => t<Effect2, Action2, State2, any>,
  mapAction: (action1: Action1) => Action2,
  mapState: (state2: State2) => State1,
  command: Command<Effect1, Action1, State1>
): t<Effect2, Action2, State2, any> {
  switch (command.type) {
  case 'Effect':
    return yield* mapEffect(command.effect);
  case 'Dispatch':
    return yield* dispatch(mapAction(command.action));
  case 'GetState':
    return mapState(yield* getState());
  default:
    return command;
  }
}

function* mapWithAnswer<Effect1, Action1, State1, Effect2, Action2, State2, A>(
  mapEffect: (effect1: Effect1) => t<Effect2, Action2, State2, any>,
  mapAction: (action1: Action1) => Action2,
  mapState: (state2: State2) => State1,
  ship: t<Effect1, Action1, State1, A>,
  answer?: any
): t<Effect2, Action2, State2, A> {
  const result = ship.next(answer);
  if (result.done) {
    return (result.value: any);
  }
  switch (result.value.type) {
  case 'Command': {
    const newAnswer = yield* mapCommand(mapEffect, mapAction, mapState, result.value.command);
    return yield* mapWithAnswer(mapEffect, mapAction, mapState, ship, newAnswer);
  }
  case 'All': {
    const newAnswer = yield* allAny(...result.value.ships.map((currenyShip) =>
      mapWithAnswer(mapEffect, mapAction, mapState, currenyShip)
    ));
    return yield* mapWithAnswer(mapEffect, mapAction, mapState, ship, newAnswer);
  }
  default:
    return result.value;
  }
}

export function map<Effect, Action1, State1, Action2, State2, A>(
  mapAction: (action1: Action1) => Action2,
  mapState: (state2: State2) => State1,
  ship: t<Effect, Action1, State1, A>
): t<Effect, Action2, State2, A> {
  return mapWithAnswer((effect) => call(effect), mapAction, mapState, ship);
}
<commit_msg>Add an updated snapshot mechanism<commit_after>// @flow

// eslint-disable-next-line no-unused-vars
export type Command<Effect, Action, State> = {
  type: 'Effect',
  effect: Effect,
} | {
  type: 'Dispatch',
  action: Action,
} | {
  type: 'GetState',
};

export type Yield<Effect, Action, State> = {
  type: 'Command',
  command: Command<Effect, Action, State>,
} | {
  type: 'All',
  ships: Generator<Yield<Effect, Action, State>, any, any>[],
};

export type t<Effect, Action, State, A> = Generator<Yield<Effect, Action, State>, A, any>;

function runCommand<Effect, Action, State>(
  runEffect: (effect: Effect) => any,
  runDispatch: (action: Action) => void | Promise<void>,
  runGetState: () => State,
  command: Command<Effect, Action, State>
): Promise<any> {
  return Promise.resolve((() => {
    switch (command.type) {
    case 'Effect':
      return runEffect(command.effect);
    case 'Dispatch':
      return runDispatch(command.action);
    case 'GetState':
      return runGetState();
    default:
      return command;
    }
  })());
}

function runWithAnswer<Effect, Action, State, A>(
  runEffect: (effect: Effect) => any,
  runDispatch: (action: Action) => void | Promise<void>,
  runGetState: () => State,
  ship: t<Effect, Action, State, A>,
  answer?: any
): Promise<A> {
  const result = ship.next(answer);
  if (result.done) {
    return Promise.resolve((result.value: any));
  }
  switch (result.value.type) {
  case 'Command':
    return runCommand(runEffect, runDispatch, runGetState, result.value.command).then((newAnswer) =>
      runWithAnswer(runEffect, runDispatch, runGetState, ship, newAnswer)
    );
  case 'All':
    return Promise.all(result.value.ships.map(currentShip =>
      runWithAnswer(runEffect, runDispatch, runGetState, currentShip))
    ).then(newAnswer =>
      runWithAnswer(runEffect, runDispatch, runGetState, ship, newAnswer)
    );
  default:
    return result.value;
  }
}

/* eslint-disable no-undef */
export const run: <Effect, Action, State, A>(
  runEffect: (effect: Effect) => any,
  runDispatch: (action: Action) => void | Promise<void>,
  runGetState: () => State,
  ship: t<Effect, Action, State, A>
) => Promise<A> =
  runWithAnswer;
/* eslint-enable no-undef */

export function* call<Effect, Action, State>(effect: Effect): t<Effect, Action, State, any> {
  const result: any = yield {
    type: 'Command',
    command: {
      type: 'Effect',
      effect,
    },
  };
  return result;
}

function* allAny<Effect, Action, State>(
  ...ships: t<Effect, Action, State, any>[]
): t<Effect, Action, State, any[]> {
  const result: any = yield {
    type: 'All',
    ships,
  };
  return result;
}

export function all<Effect, Action, State, A>(
  ships: t<Effect, Action, State, A>[]
): t<Effect, Action, State, A[]> {
  return allAny(...ships);
}

/* eslint-disable no-undef */
export const all2: <Effect, Action, State, A1, A2>(
  ship1: t<Effect, Action, State, A1>,
  ship2: t<Effect, Action, State, A2>
) => t<Effect, Action, State, [A1, A2]> =
  allAny;

export const all3: <Effect, Action, State, A1, A2, A3>(
  ship1: t<Effect, Action, State, A1>,
  ship2: t<Effect, Action, State, A2>,
  ship3: t<Effect, Action, State, A3>
) => t<Effect, Action, State, [A1, A2, A3]> =
  allAny;

export const all4: <Effect, Action, State, A1, A2, A3, A4>(
  ship1: t<Effect, Action, State, A1>,
  ship2: t<Effect, Action, State, A2>,
  ship3: t<Effect, Action, State, A3>,
  ship4: t<Effect, Action, State, A4>
) => t<Effect, Action, State, [A1, A2, A3, A4]> =
  allAny;

export const all5: <Effect, Action, State, A1, A2, A3, A4, A5>(
  ship1: t<Effect, Action, State, A1>,
  ship2: t<Effect, Action, State, A2>,
  ship3: t<Effect, Action, State, A3>,
  ship4: t<Effect, Action, State, A4>,
  ship4: t<Effect, Action, State, A5>
) => t<Effect, Action, State, [A1, A2, A3, A4, A5]> =
  allAny;

export const all6: <Effect, Action, State, A1, A2, A3, A4, A5, A6>(
  ship1: t<Effect, Action, State, A1>,
  ship2: t<Effect, Action, State, A2>,
  ship3: t<Effect, Action, State, A3>,
  ship4: t<Effect, Action, State, A4>,
  ship4: t<Effect, Action, State, A5>,
  ship4: t<Effect, Action, State, A6>
) => t<Effect, Action, State, [A1, A2, A3, A4, A5, A6]> =
  allAny;

export const all7: <Effect, Action, State, A1, A2, A3, A4, A5, A6, A7>(
  ship1: t<Effect, Action, State, A1>,
  ship2: t<Effect, Action, State, A2>,
  ship3: t<Effect, Action, State, A3>,
  ship4: t<Effect, Action, State, A4>,
  ship4: t<Effect, Action, State, A5>,
  ship4: t<Effect, Action, State, A6>,
  ship4: t<Effect, Action, State, A7>
) => t<Effect, Action, State, [A1, A2, A3, A4, A5, A6, A7]> =
  allAny;
/* eslint-enable no-undef */

export function* dispatch<Effect, Action, State>(action: Action): t<Effect, Action, State, void> {
  yield {
    type: 'Command',
    command: {
      type: 'Dispatch',
      action,
    },
  };
}

export function* getState<Effect, Action, State>(): t<Effect, Action, State, State> {
  const state: any = yield {
    type: 'Command',
    command: {
      type: 'GetState',
    },
  };
  return state;
}

function* mapCommand<Effect1, Action1, State1, Effect2, Action2, State2>(
  mapEffect: (effect1: Effect1) => t<Effect2, Action2, State2, any>,
  mapAction: (action1: Action1) => Action2,
  mapState: (state2: State2) => State1,
  command: Command<Effect1, Action1, State1>
): t<Effect2, Action2, State2, any> {
  switch (command.type) {
  case 'Effect':
    return yield* mapEffect(command.effect);
  case 'Dispatch':
    return yield* dispatch(mapAction(command.action));
  case 'GetState':
    return mapState(yield* getState());
  default:
    return command;
  }
}

function* mapWithAnswer<Effect1, Action1, State1, Effect2, Action2, State2, A>(
  mapEffect: (effect1: Effect1) => t<Effect2, Action2, State2, any>,
  mapAction: (action1: Action1) => Action2,
  mapState: (state2: State2) => State1,
  ship: t<Effect1, Action1, State1, A>,
  answer?: any
): t<Effect2, Action2, State2, A> {
  const result = ship.next(answer);
  if (result.done) {
    return (result.value: any);
  }
  switch (result.value.type) {
  case 'Command': {
    const newAnswer = yield* mapCommand(mapEffect, mapAction, mapState, result.value.command);
    return yield* mapWithAnswer(mapEffect, mapAction, mapState, ship, newAnswer);
  }
  case 'All': {
    const newAnswer = yield* allAny(...result.value.ships.map((currenyShip) =>
      mapWithAnswer(mapEffect, mapAction, mapState, currenyShip)
    ));
    return yield* mapWithAnswer(mapEffect, mapAction, mapState, ship, newAnswer);
  }
  default:
    return result.value;
  }
}

export function map<Effect, Action1, State1, Action2, State2, A>(
  mapAction: (action1: Action1) => Action2,
  mapState: (state2: State2) => State1,
  ship: t<Effect, Action1, State1, A>
): t<Effect, Action2, State2, A> {
  return mapWithAnswer((effect) => call(effect), mapAction, mapState, ship);
}

export type SnapshotItem<Effect, Action, State> = {
  type: 'Return',
  result: any,
} | {
  type: 'Effect',
  effect: Effect,
  result?: any,
} | {
  type: 'Dispatch',
  action: Action
} | {
  type: 'GetState',
  state: State,
} | {
  type: 'All',
  snapshots: (SnapshotItem<Effect, Action, State>[])[],
}

export type Snapshot<Effect, Action, State> = SnapshotItem<Effect, Action, State>[];

function* snapshotCommand<Effect, Action, State>(
  command: Command<Effect, Action, State>
): t<Effect, Action, State, {result: any, snapshotItem: SnapshotItem<Effect, Action, State>}> {
  switch (command.type) {
  case 'Effect': {
    const result = yield* call(command.effect);
    return {
      result,
      snapshotItem: result === undefined ? {
        type: 'Effect',
        effect: command.effect,
      } : {
        type: 'Effect',
        effect: command.effect,
        result,
      },
    };
  }
  case 'Dispatch': {
    yield* dispatch(command.action);
    return {
      result: undefined,
      snapshotItem: {
        type: 'Dispatch',
        action: command.action,
      },
    };
  }
  case 'GetState': {
    const state = yield* getState();
    return {
      result: state,
      snapshotItem: {
        type: 'GetState',
        state,
      },
    };
  }
  default:
    return command;
  }
}

function* snapshotWithAnswer<Effect, Action, State, A>(
  ship: t<Effect, Action, State, A>,
  answer?: any
): t<Effect, Action, State, {result: A, snapshot: Snapshot<Effect, Action, State>}> {
  const result = ship.next(answer);
  if (result.done) {
    return {
      result: (result.value: any),
      snapshot: result.value === undefined ? [] : [{
        type: 'Return',
        result: result.value,
      }],
    };
  }
  switch (result.value.type) {
  case 'Command': {
    const newAnswer = yield* snapshotCommand(result.value.command);
    const next = yield* snapshotWithAnswer(ship, newAnswer.result);
    return {
      result: next.result,
      snapshot: [
        newAnswer.snapshotItem,
        ...next.snapshot,
      ],
    };
  }
  case 'All': {
    const newAnswer = yield* allAny(...result.value.ships.map((currentShip) =>
      snapshotWithAnswer(currentShip)
    ));
    const next = yield* snapshotWithAnswer(ship, newAnswer.map((currentAnswer) =>
      currentAnswer.result
    ));
    return {
      result: next.result,
      snapshot: [
        {
          type: 'All',
          snapshots: newAnswer.map((currentAnswer) => currentAnswer.snapshot),
        },
        ...next.snapshot,
      ],
    };
  }
  default:
    return result.value;
  }
}

/* eslint-disable no-undef */
export const snapshot: <Effect, Action, State, A>(
  ship: t<Effect, Action, State, A>
) => t<Effect, Action, State, {result: A, snapshot: Snapshot<Effect, Action, State>}> =
  snapshotWithAnswer;
/* eslint-enable no-undef */
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'

let count = 0
const ignore = () => {}

/**
 * @param {Object} config.
 * @param {Function} config.test The testing callback. Should return 'true' if the test
 *                               passed and 'false' otherwise. Can also return a promise.
 *                               Can also throw errors, which will be taken as failure.
 * @param {Function} [config.failure] An optional failure callback.
 * @param {Boolean} [preview=false] If set to 'true' will render the component while
 *                                  the testing process is not finished. Defaults to
 *                                  'false', which means 'placeholder' or 'empty'
 *                                  component will be used instead.
 * @param {Object} [empty=<div />] A component to be rendered when the test fails.
 * @param {Object} [placeholder=null] A component to be redered while the testing process
 *                                    is not finished.
 * @param {Function} [config.shouldTest] A callback to determine if policy testing
 *                                       should be re-executed or note. This callback
 *                                       receives two arguments: 'to' and 'from', where
 *                                       'to' equals nextProps and 'from' equals current.
 * @return {Function} A policy decorator.
 */
const Policy = (...configs) => {
  const config = configs
    .map(config => typeof config === 'function' ? { test: config } : config)
    .reduce((prev, next) => ({ ...prev, ...next }), {})

  const {
    name,
    test,
    failure = () => {},
    preview = false,
    empty = <div />,
    placeholder = null,
    shouldTest = () => true,
  } = config

  const _name = name || (test.name !== 'test' && test.name) || 'policy' + count++

  const _test = props => (async () => test(props))().then(result => {
    if (!result || result instanceof Error) throw result
    return result
  })

  const _shouldTest = (to, from) => (async () => shouldTest(to, from))().then(result => {
    if (!result || result instanceof Error) throw result
    return result
  })

  const HOC = Composed => {
    const displayName = Composed.displayName || 'Composed'

    return class PoliciedComponent extends Component {
      static displayName = `PoliciedComponent(${displayName})`

      static childContextTypes = {
        policy: PropTypes.object
      }

      static contextTypes = {
        policy: PropTypes.object,
      }

      constructor (props, foo, bar) {
        super(props)
        this.state = { tested: false, testing: null, failed: null }
      }

      async test (props) {
        try {
          this.setState({ tested: false, testing: true, failed: false })
          await _test(props)
          this.setState({ tested: true, testing: false, failed: false })
        } catch (e) {
          this.setState({ tested: true, testing: false, failed: true })
          failure(e)
          throw e
        }
      }

      componentDidMount () {
        this.test(this.props).catch(ignore)
      }

      componentWillReceiveProps (nextProps) {
        _shouldTest(nextProps, this.props).then(() => this.test(nextProps)).catch(ignore)
      }

      getChildContext () {
        return {
          policy: {
            ...this.context.policy || {},
            [_name]: this.state
          }
        }
      }

      render () {
        const { tested, testing, failed } = this.state

        // 1. In case still testing, not failed, and allowing preview.
        if (testing && !failed && preview) return <Composed { ...this.props } />

        // 2. In case still testing and placeholder component available,
        // show placeholder component.
        if (!tested && !failed && placeholder) return placeholder

        // 3. In case finished testing and not failed, render component.
        if (tested && !failed) return <Composed { ...this.props } />

        // 4. In case finished testing or failed or not previewing,
        // return empty component or null if none given.
        return empty || null
      }
    }
  }

  HOC.derivate = override => Policy(config, override)

  return HOC
}

export default Policy

export const combine = (...policies) => component => [].concat(policies)
  .reduce((component, policy) => policy(component), component)
<commit_msg>Simplified callbacks.<commit_after>import React, { Component, PropTypes } from 'react'

let count = 0
const ignore = () => {}

/**
 * @param {Object} config.
 * @param {Function} config.test The testing callback. Should return 'true' if the test
 *                               passed and 'false' otherwise. Can also return a promise.
 *                               Can also throw errors, which will be taken as failure.
 * @param {Function} [config.failure] An optional failure callback.
 * @param {Boolean} [preview=false] If set to 'true' will render the component while
 *                                  the testing process is not finished. Defaults to
 *                                  'false', which means 'placeholder' or 'empty'
 *                                  component will be used instead.
 * @param {Object} [empty=<div />] A component to be rendered when the test fails.
 * @param {Object} [placeholder=null] A component to be redered while the testing process
 *                                    is not finished.
 * @param {Function} [config.shouldTest] A callback to determine if policy testing
 *                                       should be re-executed or note. This callback
 *                                       receives two arguments: 'to' and 'from', where
 *                                       'to' equals nextProps and 'from' equals current.
 * @return {Function} A policy decorator.
 */
const Policy = (...configs) => {
  const config = configs
    .map(config => typeof config === 'function' ? { test: config } : config)
    .reduce((prev, next) => ({ ...prev, ...next }), {})

  const {
    name,
    test,
    failure = () => {},
    preview = false,
    empty = <div />,
    placeholder = null,
    shouldTest = () => true,
  } = config

  const _name = name || (test.name !== 'test' && test.name) || 'policy' + count++

  const _test = props => (async () => test(props))().then(result => {
    if (!result || result instanceof Error) throw result
    return result
  })

  const _shouldTest = (to, from) => (async () => shouldTest(to, from))().then(result => {
    if (!result || result instanceof Error) throw result
    return result
  })

  const HOC = Composed => class PoliciedComponent extends Component {
    static displayName = `PoliciedComponent(${_name}/${Composed.displayName || 'Composed'})`

    static childContextTypes = {
      policy: PropTypes.object
    }

    static contextTypes = {
      policy: PropTypes.object,
    }

    constructor (props, foo, bar) {
      super(props)
      this.state = { tested: false, testing: null, failed: null }
    }

    async test (props) {
      try {
        this.setState({ tested: false, testing: true, failed: false })
        await _test(props)
        this.setState({ tested: true, testing: false, failed: false })
      } catch (error) {
        this.setState({ tested: true, testing: false, failed: true })
        failure({ ...this, props, error })
        throw error
      }
    }

    componentDidMount () {
      this.test(this.props).catch(ignore)
    }

    componentWillReceiveProps (nextProps) {
      _shouldTest(nextProps, this.props).then(() => this.test(nextProps)).catch(ignore)
    }

    getChildContext () {
      return {
        policy: {
          ...this.context.policy || {},
          [_name]: this.state
        }
      }
    }

    render () {
      const { tested, testing, failed } = this.state

      // 1. In case still testing, not failed, and allowing preview.
      if (testing && !failed && preview) return <Composed { ...this.props } />

      // 2. In case still testing and placeholder component available,
      // show placeholder component.
      if (!tested && !failed && placeholder) return placeholder

      // 3. In case finished testing and not failed, render component.
      if (tested && !failed) return <Composed { ...this.props } />

      // 4. In case finished testing or failed or not previewing,
      // return empty component or null if none given.
      return empty || null
    }
  }

  HOC.derivate = override => Policy(config, override)

  return HOC
}

export default Policy

export const combine = (...policies) => component => [].concat(policies)
  .reduce((component, policy) => policy(component), component)
<|endoftext|>


<commit_before>'use strict';

import Promise from 'bluebird';
import rethinkdb from 'rethinkdb';
import {configureTcpPolyfill} from './TcpPolyfill';

function connect({host, port, path, secure, wsProtocols, db, simulatedLatencyMs}) {
  configureTcpPolyfill({path, secure, wsProtocols, simulatedLatencyMs});
  // Temporarily unset process.browser so rethinkdb uses a TcpConnection
  const oldProcessDotBrowser = process.browser;
  process.browser = false;
  const connectOptions = {host, port, db};
  const connectionPromise = Promise.promisify(rethinkdb.connect)(connectOptions);
  process.browser = oldProcessDotBrowser;
  return connectionPromise;
}

export {
  rethinkdb,
  Promise,
  connect,
};
<commit_msg>Export protodef from rethinkdb<commit_after>'use strict';

import Promise from 'bluebird';
import rethinkdb from 'rethinkdb';
import protodef from 'rethinkdb/proto-def';
import {configureTcpPolyfill} from './TcpPolyfill';

function connect({host, port, path, secure, wsProtocols, db, simulatedLatencyMs}) {
  configureTcpPolyfill({path, secure, wsProtocols, simulatedLatencyMs});
  // Temporarily unset process.browser so rethinkdb uses a TcpConnection
  const oldProcessDotBrowser = process.browser;
  process.browser = false;
  const connectOptions = {host, port, db};
  const connectionPromise = Promise.promisify(rethinkdb.connect)(connectOptions);
  process.browser = oldProcessDotBrowser;
  return connectionPromise;
}

export {
  rethinkdb,
  protodef,
  Promise,
  connect,
};
<|endoftext|>


<commit_before>'use strict';

const ViberBot = require('viber-bot').Bot;
const BotEvents = require('viber-bot').Events;
const TextMessage = require('viber-bot').Message.Text;

const winston = require('winston');
const toYAML = require('winston-console-formatter');
require('dotenv').config();

var request = require('request');

function createLogger() {
    const logger = new winston.Logger({
        level: "debug" // We recommend using the debug level for development
    });

    logger.add(winston.transports.Console, toYAML.config());
    return logger;
}

function say(response, message) {
    response.send(new TextMessage(message));
}

function checkUrlAvailability(botResponse, urlToCheck) {

    if (urlToCheck === '') {
        say(botResponse, 'I need a URL to check');
        return;
    }

    say(botResponse, 'One second...Let me check!');

    var url = urlToCheck.replace(/^http:\/\//, '');
    request('http://isup.me/' + url, function(error, requestResponse, body) {
        if (error || requestResponse.statusCode !== 200) {
            say(botResponse, 'Something is wrong with isup.me.');
            return;
        }

        if (!error && requestResponse.statusCode === 200) {
            if (body.search('is up') !== -1) {
                say(botResponse, 'Hooray! ' + urlToCheck + '. looks good to me.');
            } else if (body.search('Huh') !== -1) {
                say(botResponse, 'Hmmmmm ' + urlToCheck + '. does not look like a website to me. Typo? please follow the format `test.com`');
            } else if (body.search('down from here') !== -1) {
                say(botResponse, 'Oh no! ' + urlToCheck + '. is broken.');
            } else {
                say(botResponse, 'Snap...Something is wrong with isup.me.');
            }
        }
    })
}

const logger = createLogger();

// Creating the bot with access token, name and avatar
const bot = new ViberBot(logger, {
    authToken: process.env.VIBER_PUBLIC_ACCOUNT_ACCESS_TOKEN_KEY, // Learn how to get your access token at developers.viber.com
    name: "Viber Chat",
    avatar: "https://raw.githubusercontent.com/devrelv/drop/master/151-icon.png" // Just a placeholder avatar to display the user
});

            // The user will get those ` on first registration
bot.onSubscribe(response => {
    say(response, `Hi there ${response.userProfile.name}. I am ${bot.name}! Feel free to ask me if a web site is down for everyone or just you. Just send me a name of a website and I'll do the rest!`);
});

bot.on(BotEvents.MESSAGE_RECEIVED, (message, response) => {
    // This sample bot can answer only text messages, let's make sure the user is aware of that.
    if (!(message instanceof TextMessage)) {
        say(response, `Sorry. I can only understand text messages.`);
    }
});

bot.onTextMessage(/./, (message, response) => {
    checkUrlAvailability(response, message.text);
});

if (process.env.NOW_URL || process.env.HEROKU_URL) {
    const http = require('http');
    const port = process.env.PORT || 8080;

    http.createServer(bot.middleware()).listen(port, () => bot.setWebhook(process.env.NOW_URL || process.env.HEROKU_URL));
} else {
    logger.debug('Could not find the now.sh/Heroku environment variables. Please make sure you followed readme guide.');
}
<commit_msg>#init<commit_after>'use strict';

const ViberBot = require('viber-bot').Bot;
const BotEvents = require('viber-bot').Events;
const TextMessage = require('viber-bot').Message.Text;

const winston = require('winston');
const toYAML = require('winston-console-formatter');
require('dotenv').config();

var request = require('request');

function createLogger() {
    const logger = new winston.Logger({
        level: "debug" // We recommend using the debug level for development
    });

    logger.add(winston.transports.Console, toYAML.config());
    return logger;
}

function say(response, message) {
    response.send(new TextMessage(message));
}

function checkUrlAvailability(botResponse, urlToCheck) {

    if (urlToCheck === '') {
        say(botResponse, 'I need a URL to check');
        return;
    }

    say(botResponse, 'One second...Let me check!');

    var url = urlToCheck.replace(/^http:\/\//, '');
    request('http://isup.me/' + url, function(error, requestResponse, body) {
        if (error || requestResponse.statusCode !== 200) {
            say(botResponse, 'Something is wrong with isup.me.');
            return;
        }

        if (!error && requestResponse.statusCode === 200) {
            if (body.search('is up') !== -1) {
                say(botResponse, 'Hooray! ' + urlToCheck + '. looks good to me.');
            } else if (body.search('Huh') !== -1) {
                say(botResponse, 'Hmmmmm ' + urlToCheck + '. does not look like a website to me. Typo? please follow the format `test.com`');
            } else if (body.search('down from here') !== -1) {
                say(botResponse, 'Oh no! ' + urlToCheck + '. is broken.');
            } else {
                say(botResponse, 'Snap...Something is wrong with isup.me.');
            }
        }
    })
}

const logger = createLogger();

// Creating the bot with access token, name and avatar
const bot = new ViberBot(logger, {
    authToken: process.env.VIBER_PUBLIC_ACCOUNT_ACCESS_TOKEN_KEY, // Learn how to get your access token at developers.viber.com
    name: "Viber Chat",
    avatar: "https://raw.githubusercontent.com/devrelv/drop/master/151-icon.png" // Just a placeholder avatar to display the user
});

            // The user will get those ` on first registration
bot.onSubscribe(response => {
    say(response, `Hi there ${response.userProfile.name}. I am ${bot.name}! Feel free to ask me if a web site is down for everyone or just you. Just send me a name of a website and I'll do the rest!`);
});

bot.on(BotEvents.MESSAGE_RECEIVED, (message, response) => {
    // This sample bot can answer only text messages, let's make sure the user is aware of that.
    if (!(message instanceof TextMessage)) {
        say(response, `Sorry. I can only understand text messages.`);
    }
});

bot.onTextMessage(/./, (message, response) => {
    checkUrlAvailability(response, message.text);
});

if (process.env.NOW_URL || process.env.HEROKU_URL) {
    const http = require('http');
    const port = process.env.PORT || 8080;

    http.createServer(bot.middleware()).listen(port, () => bot.setWebhook(process.env.NOW_URL || process.env.HEROKU_URL));
} else {
    logger.debug('Could not find the now.sh/Heroku environment variables. Please make sure you followed readme guide.');
}
<|endoftext|>


<commit_before>export * from './type'
export * from './probe'
export * from './url'
export * from './query'
export * from './clone'
export * from './each'
export * from './extend'
export * from './event'
export * from './func'
export * from './promise'
export * from './ajax'
export * from './convert'
export * from './prop'
export * from './compose'
export * from './handle'
export * from '../lib/crc32.js'
export * from '../lib/md5.js'
export * from '../lib/tmpl.js'
<commit_msg>fix tmpl<commit_after>export * from './type'
export * from './probe'
export * from './url'
export * from './query'
export * from './clone'
export * from './each'
export * from './extend'
export * from './event'
export * from './func'
export * from './promise'
export * from './ajax'
export * from './convert'
export * from './prop'
export * from './compose'
export * from './handle'
export * from '../lib/crc32.js'
export * from '../lib/md5.js'
export * from '../tmpl.js'
<|endoftext|>


<commit_before>var express    = require('express');
var chalk      = require('chalk');
var bodyParser = require('body-parser');
var nconf      = require('nconf');
var path       = require('path');
var authLayer  = require('./authentication');

nconf.argv().env();

const ENV = nconf.get('ENV') || 'dev';

// /depot/config/<env>.json
nconf.file(path.join('config', ENV.toLowerCase() + '.json'));

// Dynamically load store: connections/<store>-connection
var Connection = require(
  './connections/' + nconf.get('store') + '-connection'
);
connection = new Connection().connect(nconf, function(err, details) {
  if (err) {
    console.error(chalk.red('error connecting to database'));
  } else {
    console.log(
      chalk.green('successfully connected to ' + details.store + ' (' + details.connectionString + ')')
    );
  }
});

var app = express()
  .use(bodyParser.urlencoded({
    extended: true
  }))
  .use(bodyParser.json())
  .use(authLayer(nconf, {
    noAuthPatterns: [/^\/serve/]  // no auth required to serve apps
  }))
;

// list available apps
app.get('/apps', require('./routes/list-apps')(connection));

// app/update a version
var addUpdateRoute = require('./routes/update-version')(connection);
app.post('/apps/:appId/versions/:versionId', addUpdateRoute);
app.put('/apps/:appId/versions/:versionId', addUpdateRoute);

// list individual app version information
app.get('/apps/:appId/versions/:versionId', require('./routes/show-version')(connection));

// list available app versions
app.get('/apps/:id/versions', require('./routes/list-versions')(connection));

// get individual app information
app.get('/apps/:id', require('./routes/show-app')(connection));

// app/update an application
var addUpdateRoute = require('./routes/update-app')(connection);
app.post('/apps/:id', addUpdateRoute);
app.put('/apps/:id', addUpdateRoute);

// serve latest index.html of app listed
// use ?version=<versionId> to request a specific version
app.get('/serve/:appId*', require('./routes/serve-app')(connection));

// deploy the app version by setting it as the latest version
app.post('/deploy/:appId/:versionId', require('./routes/deploy-app')(connection));

var server = app.listen(nconf.get('port'), function() {
  console.log(
    chalk.red(
      'depot',
      chalk.yellow('listening'),
      chalk.green('on'),
      chalk.blue(nconf.get('port'))
    )
  );
});
<commit_msg>Better error logging for connections<commit_after>var express    = require('express');
var chalk      = require('chalk');
var bodyParser = require('body-parser');
var nconf      = require('nconf');
var path       = require('path');
var authLayer  = require('./authentication');

nconf.argv().env();

const ENV = nconf.get('ENV') || 'dev';

// /depot/config/<env>.json
nconf.file(path.join('config', ENV.toLowerCase() + '.json'));

// Dynamically load store: connections/<store>-connection
var Connection = require(
  './connections/' + nconf.get('store') + '-connection'
);
connection = new Connection().connect(nconf, function(err, details) {
  if (err) {
    console.error(chalk.red('error connecting to database'));
    console.log(err);
  } else {
    console.log(
      chalk.green('successfully connected to ' + details.store + ' (' + details.connectionString + ')')
    );
  }
});

var app = express()
  .use(bodyParser.urlencoded({
    extended: true
  }))
  .use(bodyParser.json())
  .use(authLayer(nconf, {
    noAuthPatterns: [/^\/serve/]  // no auth required to serve apps
  }))
;

// list available apps
app.get('/apps', require('./routes/list-apps')(connection));

// app/update a version
var addUpdateRoute = require('./routes/update-version')(connection);
app.post('/apps/:appId/versions/:versionId', addUpdateRoute);
app.put('/apps/:appId/versions/:versionId', addUpdateRoute);

// list individual app version information
app.get('/apps/:appId/versions/:versionId', require('./routes/show-version')(connection));

// list available app versions
app.get('/apps/:id/versions', require('./routes/list-versions')(connection));

// get individual app information
app.get('/apps/:id', require('./routes/show-app')(connection));

// app/update an application
var addUpdateRoute = require('./routes/update-app')(connection);
app.post('/apps/:id', addUpdateRoute);
app.put('/apps/:id', addUpdateRoute);

// serve latest index.html of app listed
// use ?version=<versionId> to request a specific version
app.get('/serve/:appId*', require('./routes/serve-app')(connection));

// deploy the app version by setting it as the latest version
app.post('/deploy/:appId/:versionId', require('./routes/deploy-app')(connection));

var server = app.listen(nconf.get('port'), function() {
  console.log(
    chalk.red(
      'depot',
      chalk.yellow('listening'),
      chalk.green('on'),
      chalk.blue(nconf.get('port'))
    )
  );
});
<|endoftext|>


<commit_before>/* @flow */

import assert from 'assert'
import { getClass, getIncompleteClass } from './helpers'

const REGEX = {
  i: /i:([\d]+);/,
  d: /d:([\d\.]+);/,
  C: /C:[\d]+:"([\S ]+?)":([\d]+):/,
  O: /O:[\d]+:"([\S ]+?)":([\d]+):/,
}

type Options = {
  strict: boolean
}

function serialize(item: any): string {
  const type = typeof item
  if (item === null) {
    return 'N;'
  }
  if (type === 'number') {
    if (item % 1 === 0) {
      return `i:${item};`
    }
    return `d:${item};`
  }
  if (type === 'string') {
    return `s:${item.length}:"${item}";`
  }
  if (type === 'boolean') {
    return `b:${item ? '1' : '0'};`
  }
  if (type !== 'object') {
    throw new TypeError()
  }

  const isArray = Array.isArray(item)
  if (isArray || item.constructor.name === 'Object') {
    // Array or raw object
    const toReturn = []
    let size = 0
    for (const key in item) {
      if ({}.hasOwnProperty.call(item, key) && (key !== 'length' || isArray)) {
        size++
        const value = item[key]
        const saneKey = isArray ? parseInt(key, 10) : key
        toReturn.push(serialize(saneKey), serialize(value))
      }
    }
    toReturn.unshift(`a:${size}:{`)
    toReturn.push('}')
    return toReturn.join('')
  }
  if (typeof item.serialize === 'function') {
    const serialized = item.serialize()
    assert(typeof serialized === 'string', `${item.constructor.name}.serialize should return a string`)
    return `C:${item.constructor.name.length}:"${item.constructor.name}":${serialized.length}:{${serialized}}`
  }
  const items = []
  const constructorName = item.__PHP_Incomplete_Class_Name || item.constructor.name.length
  for (const key in item) {
    if ({}.hasOwnProperty.call(item, key) && typeof item[key] !== 'function') {
      const value = item[key]
      items.push(serialize(key))
      items.push(serialize(value))
    }
  }
  return `O:${constructorName}:"${item.constructor.name}":${items.length / 2}:{${items.join('')}}`
}

function unserializeItem(item: string, scope: Object, options: Options): { index: number, value: any } {
  const type = item.substr(0, 1)
  if (type === 'i' || type === 'd') {
    const match = REGEX[type].exec(item)
    assert(Array.isArray(match), 'Syntax Error')
    return { index: match[0].length, value: type === 'i' ? parseInt(match[1], 10) : parseFloat(match[1]) }
  }
  if (type === 'N') {
    return { index: 2, value: null }
  }
  if (type === 'b') {
    return { index: 4, value: item.substr(2, 1) === '1' }
  }
  if (type === 's') {
    const lengthEnd = item.indexOf(':', 2)
    const length = parseInt(item.slice(2, lengthEnd), 10) || 0
    const sliced = item.substr(4 + (lengthEnd - 2), length)
    return { index: 4 + lengthEnd + length, value: sliced }
  }
  if (type === 'C') {
    const info = REGEX.C.exec(item)
    assert(Array.isArray(info), 'Syntax Error')
    const className = info[1]
    const contentLength = parseInt(info[2], 10)
    const contentOffset = info.index + info[0].length + 1
    const classContent = item.slice(contentOffset, contentOffset + contentLength)
    const classReference = scope[className]
    let container
    if (!classReference) {
      if (options.strict) {
        assert(false, `Class ${className} not found in given scope`)
      }
      container = getIncompleteClass(className)
    } else {
      assert(typeof scope[className].prototype.unserialize === 'function',
        `${className}.prototype.unserialize is not a function`)
      container = new (getClass(scope[className].prototype))()
      container.unserialize(classContent)
    }
    return { index: contentOffset + contentLength + 1, value: container }
  }
  if (type === 'a') {
    let first = true
    let container
    const lengthEnd = item.indexOf(':', 2)
    const length = parseInt(item.slice(2, lengthEnd), 10) || 0
    const index = unserializeObject(length, item.slice(4 + (lengthEnd - 2)), scope, function(key, value) {
      if (first) {
        container = parseInt(key, 10) === 0 ? [] : {}
        first = false
      }
      if (container.constructor.name === 'Array') {
        container.push(value)
      } else container[key] = value
    }, options)
    return { index: 4 + (lengthEnd - 2) + index + 1, value: container }
  }
  if (type === 'O') {
    const info = REGEX.O.exec(item)
    assert(Array.isArray(info), 'Syntax Error')
    const className = info[1]
    const contentLength = parseInt(info[2], 10)
    const contentOffset = info.index + info[0].length + 1
    const classReference = scope[className]
    let container
    if (!classReference) {
      if (options.strict) {
        assert(false, `Class ${className} not found in given scope`)
      }
      container = getIncompleteClass(className)
    } else {
      container = new (getClass(scope[className].prototype))()
    }
    const index = unserializeObject(contentLength, item.slice(contentOffset), scope, function(key, value) {
      container[key] = value
    }, options)
    return { index: contentOffset + index + 1, value: container }
  }
  throw new SyntaxError()
}

function unserializeObject(count: number, content: string, scope: Object, valueCallback: Function, options: Options): number {
  const realCount = count * 2
  let index = 0
  let key = null
  for (let i = 0; i < realCount; ++i) {
    const item = unserializeItem(content.slice(index), scope, options)
    if (key !== null) {
      valueCallback(key, item.value)
      key = null
    } else {
      key = item.value
    }
    index += item.index
  }
  return index
}

function unserialize(item: string, scope: Object = {}, givenOptions: Object = {}): any {
  const options = Object.assign({}, givenOptions)
  if (typeof options.strict === 'undefined') {
    options.strict = true
  }
  return unserializeItem(item, scope, options).value
}

module.exports = { serialize, unserialize }
<commit_msg>[Fix]String length wrang on some char code like utf-8.<commit_after>/* @flow */

import assert from 'assert'
import { getClass, getIncompleteClass } from './helpers'

const REGEX = {
  i: /i:([\d]+);/,
  d: /d:([\d\.]+);/,
  C: /C:[\d]+:"([\S ]+?)":([\d]+):/,
  O: /O:[\d]+:"([\S ]+?)":([\d]+):/,
}

type Options = {
  strict: boolean
}

// Get string length.
function getStrLeng(str) {
  let buffer = new Buffer(str)
  return buffer.length;
}

function serialize(item: any): string {
  const type = typeof item
  if (item === null) {
    return 'N;'
  }
  if (type === 'number') {
    if (item % 1 === 0) {
      return `i:${item};`
    }
    return `d:${item};`
  }
  if (type === 'string') {
     return `s:${getStrLeng(item)}:"${item}";`
  }
  if (type === 'boolean') {
    return `b:${item ? '1' : '0'};`
  }
  if (type !== 'object') {
    throw new TypeError()
  }

  const isArray = Array.isArray(item)
  if (isArray || item.constructor.name === 'Object') {
    // Array or raw object
    const toReturn = []
    let size = 0
    for (const key in item) {
      if ({}.hasOwnProperty.call(item, key) && (key !== 'length' || isArray)) {
        size++
        const value = item[key]
        const saneKey = isArray ? parseInt(key, 10) : key
        toReturn.push(serialize(saneKey), serialize(value))
      }
    }
    toReturn.unshift(`a:${size}:{`)
    toReturn.push('}')
    return toReturn.join('')
  }
  if (typeof item.serialize === 'function') {
    const serialized = item.serialize()
    assert(typeof serialized === 'string', `${item.constructor.name}.serialize should return a string`)
    return `C:${item.constructor.name.length}:"${item.constructor.name}":${serialized.length}:{${serialized}}`
  }
  const items = []
  const constructorName = item.__PHP_Incomplete_Class_Name || item.constructor.name.length
  for (const key in item) {
    if ({}.hasOwnProperty.call(item, key) && typeof item[key] !== 'function') {
      const value = item[key]
      items.push(serialize(key))
      items.push(serialize(value))
    }
  }
  return `O:${constructorName}:"${item.constructor.name}":${items.length / 2}:{${items.join('')}}`
}

function unserializeItem(item: string, scope: Object, options: Options): { index: number, value: any } {
  const type = item.substr(0, 1)
  if (type === 'i' || type === 'd') {
    const match = REGEX[type].exec(item)
    assert(Array.isArray(match), 'Syntax Error')
    return { index: match[0].length, value: type === 'i' ? parseInt(match[1], 10) : parseFloat(match[1]) }
  }
  if (type === 'N') {
    return { index: 2, value: null }
  }
  if (type === 'b') {
    return { index: 4, value: item.substr(2, 1) === '1' }
  }
  if (type === 's') {
    const lengthEnd = item.indexOf(':', 2)
    const length = parseInt(item.slice(2, lengthEnd), 10) || 0
    const sliced = item.substr(4 + (lengthEnd - 2), length)
    return { index: 4 + lengthEnd + length, value: sliced }
  }
  if (type === 'C') {
    const info = REGEX.C.exec(item)
    assert(Array.isArray(info), 'Syntax Error')
    const className = info[1]
    const contentLength = parseInt(info[2], 10)
    const contentOffset = info.index + info[0].length + 1
    const classContent = item.slice(contentOffset, contentOffset + contentLength)
    const classReference = scope[className]
    let container
    if (!classReference) {
      if (options.strict) {
        assert(false, `Class ${className} not found in given scope`)
      }
      container = getIncompleteClass(className)
    } else {
      assert(typeof scope[className].prototype.unserialize === 'function',
        `${className}.prototype.unserialize is not a function`)
      container = new (getClass(scope[className].prototype))()
      container.unserialize(classContent)
    }
    return { index: contentOffset + contentLength + 1, value: container }
  }
  if (type === 'a') {
    let first = true
    let container
    const lengthEnd = item.indexOf(':', 2)
    const length = parseInt(item.slice(2, lengthEnd), 10) || 0
    const index = unserializeObject(length, item.slice(4 + (lengthEnd - 2)), scope, function(key, value) {
      if (first) {
        container = parseInt(key, 10) === 0 ? [] : {}
        first = false
      }
      if (container.constructor.name === 'Array') {
        container.push(value)
      } else container[key] = value
    }, options)
    return { index: 4 + (lengthEnd - 2) + index + 1, value: container }
  }
  if (type === 'O') {
    const info = REGEX.O.exec(item)
    assert(Array.isArray(info), 'Syntax Error')
    const className = info[1]
    const contentLength = parseInt(info[2], 10)
    const contentOffset = info.index + info[0].length + 1
    const classReference = scope[className]
    let container
    if (!classReference) {
      if (options.strict) {
        assert(false, `Class ${className} not found in given scope`)
      }
      container = getIncompleteClass(className)
    } else {
      container = new (getClass(scope[className].prototype))()
    }
    const index = unserializeObject(contentLength, item.slice(contentOffset), scope, function(key, value) {
      container[key] = value
    }, options)
    return { index: contentOffset + index + 1, value: container }
  }
  throw new SyntaxError()
}

function unserializeObject(count: number, content: string, scope: Object, valueCallback: Function, options: Options): number {
  const realCount = count * 2
  let index = 0
  let key = null
  for (let i = 0; i < realCount; ++i) {
    const item = unserializeItem(content.slice(index), scope, options)
    if (key !== null) {
      valueCallback(key, item.value)
      key = null
    } else {
      key = item.value
    }
    index += item.index
  }
  return index
}

function unserialize(item: string, scope: Object = {}, givenOptions: Object = {}): any {
  const options = Object.assign({}, givenOptions)
  if (typeof options.strict === 'undefined') {
    options.strict = true
  }
  return unserializeItem(item, scope, options).value
}

module.exports = { serialize, unserialize }
<|endoftext|>