<commit_before>var listModel = require('../models/listModel');
var itemCtrl = require('./itemCtrl');
var userCtrl = require('./userCtrl');

module.exports = {
	findOrCreate: function(req, res){
		listModel.findOne({'name':req.name, 'user_id': req.user_id}, function(err, found){
			var hold;
			if(err){
				//return "this is not wokring";
			} else{
				if(found){
					hold = found.items;
					if(res) return res.send(JSON.stringify(found));
				}else{
					var list = new listModel({
						user_id: req.user_id,
						created: new Date(),
						name: req.name,
						items: []
					});
					userCtrl.addList({list_id: req.name, user_id: req.user_id});
					list.save(function(err, newlist){
						hold = newlist;
						if(res) return res.send(JSON.stringify(newlist));
					});
				}
			}

		});
	},
	addItem: function(req, res){
		listModel.findOne({'name':req.name, 'user_id': req.user_id}, function(err, found){
			if(err){
				return null;
			}else{
				if(found){
					found.items.push(req.api_id);
					found.save();
				}
			}
		});
	},
	showAllLists: function(req, res){
		listModel.find({'user_id': req.user_id}, function(err, lists){
			var allLists = {}
			lists.forEach(function(list){
				allLists[list._id] = list;
			});
			res.send(allLists);
		});
	},
	delete: function(req,res){
		listModel.remove({
			'name' : req.name,
			'user_id': req.user_id
		}, function(err, list){
			if(err){
				return null;
			}
			return list;
		});
	}
};<commit_msg>Cleaned up comments in listCtrl<commit_after>var listModel = require('../models/listModel');
var itemCtrl = require('./itemCtrl');
var userCtrl = require('./userCtrl');

module.exports = {
	findOrCreate: function(req, res){
		listModel.findOne({'name':req.name, 'user_id': req.user_id}, function(err, found){
			if(err){
				return err;
			} else{
				if(found){
					hold = found.items;
					if(res) return res.send(JSON.stringify(found));
				}else{
					var list = new listModel({
						user_id: req.user_id,
						created: new Date(),
						name: req.name,
						items: []
					});
					userCtrl.addList({list_id: req.name, user_id: req.user_id});
					list.save(function(err, newlist){
						if(err) return err;
						if(res) return res.send(JSON.stringify(newlist));
					});
				}
			}

		});
	},
	addItem: function(req, res){
		listModel.findOne({'name':req.name, 'user_id': req.user_id}, function(err, found){
			if(err){
				return null;
			}else{
				if(found){
					found.items.push(req.api_id);
					found.save();
				}
			}
		});
	},
	showAllLists: function(req, res){
		listModel.find({'user_id': req.user_id}, function(err, lists){
			var allLists = {}
			lists.forEach(function(list){
				allLists[list._id] = list;
			});
			res.send(allLists);
		});
	},
	delete: function(req,res){
		listModel.remove({
			'name' : req.name,
			'user_id': req.user_id
		}, function(err, list){
			if(err){
				return null;
			}
			return list;
		});
	}
};<|endoftext|>


<commit_before>const setUserState = require("../model/setUserState")

const setUserWeChat = require("../model/setUserWeChat")

const setUserName = require("../model/setUserName")

const setUserReadyState = require("../model/setUserReadyState")

const registerString = `欢迎进入注册流程：

请根据下列步骤进行注册
回复菜单项前的字母进行操作
=================

a 输入您的微信ID
b 输入您的昵称
c 查看并确认您输入的微信ID和昵称
d 退出注册流程

`
const makeSure = rData => `您的微信号为${rData.wechat},您的昵称为${rData.name}

输入Y确认

输入N放弃

之后可以回复a
===========
输入d退出注册流程`
/**
 * 0 - 回复注册，还没有进行后续操作
 * 1 - 回复a，还没有进行后续操作
 * 2 - 微信号输入完毕
 * 3 - 回复b，还没有进行后续操作
 * 4 - 用户名设置完毕
 * 5 - 回复c，还没有进行后续操作
 * null - 没有在注册流程中
 *
 * 检查用户是否注册
 * @param  {Array} content 用户回复内容数组
 * @param  {Object} rData   用户信息
 * @return {String}         公众号回复内容
 */
const checkReg = data => {
    if (/注册/.test(data.Content[0])) {
        setUserState(data.ToUserName[0], "0")
        return registerString
    } else {
        return "暂不支持未注册用户，回复【注册】进入注册流程"
    }
}

const quit = data => data.Content[0] === "d" || data.Content[1] === "D" && setUserState(data.ToUserName[0], "null")

const checkWechatId = data => {
    if (data.Content[0] === "a" || data.Content[0] === "A") {
        setUserState(data.ToUserName[0], "1")
        return "请输入您的微信ID"
    }

    return quit(data) || registerString
}

const changeWechatId = data => {
    const testWechatId = /^[a-zA-Z][a-zA-Z0-9_-]{5,19}/g
    if (testWechatId.test(data.Content[0])) {
        setUserWeChat(data.ToUserName[0], data.Content[0])
        setUserState(data.ToUserName[0], "2")
        return `您的微信号为${data.Content[0]}, 输入b进入下一步`
    }

    return quit(data) || "请输入正确的微信号"
}

const checkUserName = data => {
    if (data.Content[0] === "b" || data.Content[0] === "B") {
        setUserState(data.ToUserName[0], "3")
        return "请输入您的昵称"
    }

    return quit(data) || "输入b进入下一步"
}

const changeUserName = data => {
    setUserName(data.ToUserName[0], data.Content[0])
    setUserState(data.ToUserName[0], "4")

    return quit(data) || `您的昵称为${data.Content[0]}, 输入c进入下一步`
};

const checkUserInfo = (data, rData) => {
    if (data.Content[0] === "c" || data.Content[0] === "C") {
        setUserState(data.ToUserName[0], "5")
        return makeSure(rData)
    }

    return quit(data) || "输入c进入下一步"
}

const changeUserInfo = (data, rData) => {
    if (data.Content[0] === "y" || data.Content[0] === "Y") {
        setUserReadyState(data.ToUserName[0], "true")
        return "注册完成！"
    } else if (data.Content[0] === "n" || data.Content[0] === "N") {
        setUserState(data.ToUserName[0], "0")
        return registerString
    }

    return quit(data) || makeSure(rData)
}

const register = (data, rData) => {
    const userId = data.ToUserName[0]
    switch(rData.status){
        case "0":
            return checkWechatId(data)
        case "1":
            return changeWechatId(data)
        case "2":
            return checkUserName(data)
        case "3":
            return changeUserName(data)
        case "4":
            return checkUserInfo(data, rData)
        case "6":
            return changeUserInfo(data, rData)
        default:
            return checkReg(data)
    }
}

module.exports = register;<commit_msg>注册逻辑基本走通 部分bug修改<commit_after>const setUserState = require("../model/setUserState")

const setUserWeChat = require("../model/setUserWeChat")

const setUserName = require("../model/setUserName")

const setUserReadyState = require("../model/setUserReadyState")

const registerString = `欢迎进入注册流程：

请根据下列步骤进行注册
回复菜单项前的字母进行操作
=================

a 输入您的微信ID
b 输入您的昵称
c 查看并确认您输入的微信ID和昵称
d 退出注册流程

`
const makeSure = rData => `您的微信号为${rData.wechat},您的昵称为${rData.name}

输入Y确认

输入N放弃

之后可以回复a
===========
输入d退出注册流程`
/**
 * 0 - 回复注册，还没有进行后续操作
 * 1 - 回复a，还没有进行后续操作
 * 2 - 微信号输入完毕
 * 3 - 回复b，还没有进行后续操作
 * 4 - 用户名设置完毕
 * 5 - 回复c，还没有进行后续操作
 * null - 没有在注册流程中
 *
 * 检查用户是否注册
 * @param  {Array} content 用户回复内容数组
 * @param  {Object} rData   用户信息
 * @return {String}         公众号回复内容
 */
const checkReg = data => {
    if (/注册/.test(data.Content[0])) {
        setUserState(data.ToUserName[0], "0")
        return registerString
    } else {
        return "暂不支持未注册用户，回复【注册】进入注册流程"
    }
}

const quit = data => (data.Content[0] === "d" || data.Content[1] === "D") && setUserState(data.ToUserName[0], "null")

const checkWechatId = data => {
    if (data.Content[0] === "a" || data.Content[0] === "A") {
        setUserState(data.ToUserName[0], "1")
        return "请输入您的微信ID"
    }

    return quit(data) || registerString
}

const changeWechatId = data => {
    const testWechatId = /^[a-zA-Z][a-zA-Z0-9_-]{5,19}/g
    if (testWechatId.test(data.Content[0])) {
        setUserWeChat(data.ToUserName[0], data.Content[0])
        setUserState(data.ToUserName[0], "2")
        return `您的微信号为${data.Content[0]}, 输入b进入下一步`
    }

    return quit(data) || "请输入正确的微信号"
}

const checkUserName = data => {
    if (data.Content[0] === "b" || data.Content[0] === "B") {
        setUserState(data.ToUserName[0], "3")
        return "请输入您的昵称"
    }

    return quit(data) || "输入b进入下一步"
}

const changeUserName = data => {
    setUserName(data.ToUserName[0], data.Content[0])
    setUserState(data.ToUserName[0], "4")

    return quit(data) || `您的昵称为${data.Content[0]}, 输入c进入下一步`
};

const checkUserInfo = (data, rData) => {
    if (data.Content[0] === "c" || data.Content[0] === "C") {
        setUserState(data.ToUserName[0], "5")
        return makeSure(rData)
    }

    return quit(data) || "输入c进入下一步"
}

const changeUserInfo = (data, rData) => {
    if (data.Content[0] === "y" || data.Content[0] === "Y") {
        setUserReadyState(data.ToUserName[0], "true")
        return "注册完成！"
    } else if (data.Content[0] === "n" || data.Content[0] === "N") {
        setUserState(data.ToUserName[0], "0")
        return registerString
    }

    return quit(data) || makeSure(rData)
}

const register = (data, rData) => {
    const userId = data.ToUserName[0]
    switch(rData.status){
        case "0":
            return checkWechatId(data)
        case "1":
            return changeWechatId(data)
        case "2":
            return checkUserName(data)
        case "3":
            return changeUserName(data)
        case "4":
            return checkUserInfo(data, rData)
        case "5":
            return changeUserInfo(data, rData)
        default:
            return checkReg(data)
    }
}

module.exports = register;<|endoftext|>


<commit_before>var express = require('express'),
	router = express.Router();
var fs = require('fs');
var parseXml = require('xml2js').parseString;

var db = require('../db');
var c = require('../appConfig');
var util = require('../util');
var Executor = require('../Executor');
var synchronize = require('../synchronizer').synchronize;

var testRunned = false;
var testFailed = false;

router.get('/checkStatus', function(req, res) {
	if(testRunned) {
		res.end('Running');
	} else if (testFailed) {
		res.end('Failed');
	} else {
		res.end('Success');
	}
});

router.get('/:id', function(req, res) {
	var configs = db.get().collection('configs');
	configs.findOne({name: req.params.id}, function(err, obj) {
		synchronize(obj, function(obj) {
			res.render('pages/configPage', {
				testInfoName: obj.name,
				fixtures: obj.data.fixtures,
				browsers: c.browsers
			});
		});
	});
});

router.get('/run/:id', function(req, res) {
	var configs = db.get().collection('configs');
	configs.findOne({name: req.params.id}, function(err, obj) {
		executeTests(obj.data);
		res.end("Started");
	});
});

router.post('/run/:id', function(req, res) {
	updateConfig(req.params.id, req.body, function(data) {
		executeTests(data);
		res.end("Started");
	});
});

router.post('/save/:id', function(req, res) {
	updateConfig(req.params.id, req.body, function() {
		res.end('Saved');
	});
});

function updateConfig(configName, data, callback) {
	var configs = db.get().collection('configs');
	if(data) {
		var newObj = {
			name: configName,
			data: data
		};
		configs.update(
			{name: configName},
			newObj,
			{upsert: true},
			function(err, results) {
				if(err)
					return console.log(err);
				callback(newObj.data);
			}
		);
	} else {
		configs.findOne({name: configName}, function(err, obj) {
			if(err)
				return console.log(err);

			callback(obj);
		});
	}
}

function executeTests(data) {
	testRunned = true;
	testFailed = false;

	prepareTempFiles();
	buildTestListFromDB(data, function(testList) {
		// run selected tests
		runTests(testList, c.testList, "FirstPhase", function(reportPath) {
			if(c.rerunFailedTests) {
				// rerun failed tests if setting enabled
				rerunFailed(reportPath);
			} else {
				generateReport();
			}
		});
	});
}

function rerunFailed(reportPath) {
	// get test list from report
	getFailedTests(reportPath, function(tests) {
		buildTestListFromArray(tests, function(testList) {
			// if there is failed tests
			if(tests.length !== 0) {
				// generate test-list file and rerun tests
				runTests(testList, c.testListError, "SecondPhase", function() {
					// rerun tests second time
					runTestList(c.testListError, "ThirdPhase", function() {
						generateReport();
					});
				});
			} else {
				generateReport();
			}
		});
	});
}

function runTests(testList, testListPath, xmlReportName, callback) {
	createTestListFile(testList, testListPath, function() {
		runTestList(testListPath, xmlReportName, function(reportPath) {
			callback(reportPath);
		});
	});
}

function getFailedTests(reportPath, callback) {
	fs.readFile(reportPath, function(err, data) {
		parseXml(data, function(err, result) {
			fixtures = result["test-run"]['test-suite'][0]['test-suite'][0]['test-suite'][0]['test-suite'][0]['test-suite'];
			var failedTests = [];
			fixtures.forEach(fixture => {
				failedTests = fixture['test-case'].filter(test => {
					return test.$.result === 'Failed';
				}).map(test => {
					return test.$.fullname;
				}).concat(failedTests);
			});
			callback(failedTests);
		});
	});
}

function createTestListFile(testList, fileName, callback) {
	fs.writeFile(fileName, testList, function(err) {
		if(err)
			return console.log(err);

		callback();
	});
}

function buildTestListFromArray(array, callback) {
	callback(array.join('\n'));
}

function buildTestListFromDB(obj, callback) {
	var testList = [];
	obj.fixtures.forEach(fixture => {
		fixture.tests.filter(test => {
			return test.active === true;
		}).forEach(test => {
			test.browsers.forEach(browser => {
				testList.push(test.assembly + "(\"" + browser + "\")." + test.name);
			});
		});
	});
	callback(testList.join('\n'));
}

function runTestList(testList, name, callback) {
	var reportPath = "testResultsXml/" + name + ".xml";

	new Executor({
		program: util.getPath(c.nunitApp),
		args: {
			tests: "--testlist=" + testList,
			workers: "--workers=10",
			assembly: util.getPath(c.testAssemblyPath),
			output: "--result="+reportPath
		},
		errorAction: function(err) {
			testFailed = true;
		},
		anywayAction: function() {
			callback(reportPath);
		}
	});
}

function generateReport() {
	testRunned = false;
	new Executor({
		program: util.getPath(c.HTMLReportApp),
		args: {
			inputFolder: "testResultsXml",
			outputFolder: "views/testResults"
		},
		errorAction: function(err) {
			console.log(err);
		}
	});
}

function cleanFolder(path) {
	new Executor({
		program: "del",
		args: {
			path: path,
			mode: "/Q"
		},
		errorAction: function(err) {
			console.log(err);
		}
	});
}

function cleanReportFolder() {
	cleanFolder("views\\testResults\\*");
}

function removeXmlReports() {
	cleanFolder("testResultsXml\\*");
}

function prepareTempFiles() {
	cleanReportFolder();
	removeXmlReports();
}

module.exports = router;<commit_msg>Fixed CheckStatus api<commit_after>var express = require('express'),
	router = express.Router();
var fs = require('fs');
var parseXml = require('xml2js').parseString;

var db = require('../db');
var c = require('../appConfig');
var util = require('../util');
var Executor = require('../Executor');
var synchronize = require('../synchronizer').synchronize;

var testRunning = false;
var testFailed = false;

router.get('/checkStatus', function(req, res) {
	if(testRunning) {
		res.end('Running');
	} else if (testFailed) {
		res.end('Failed');
	} else {
		res.end('Success');
	}
});

router.get('/:id', function(req, res) {
	var configs = db.get().collection('configs');
	configs.findOne({name: req.params.id}, function(err, obj) {
		synchronize(obj, function(obj) {
			res.render('pages/configPage', {
				testInfoName: obj.name,
				fixtures: obj.data.fixtures,
				browsers: c.browsers
			});
		});
	});
});

router.get('/run/:id', function(req, res) {
	var configs = db.get().collection('configs');
	configs.findOne({name: req.params.id}, function(err, obj) {
		executeTests(obj.data, res);
	});
});

router.post('/run/:id', function(req, res) {
	updateConfig(req.params.id, req.body, function(data) {
		executeTests(data, res);
	});
});

router.post('/save/:id', function(req, res) {
	updateConfig(req.params.id, req.body, function() {
		res.end('Saved');
	});
});

function updateConfig(configName, data, callback) {
	var configs = db.get().collection('configs');
	if(data) {
		var newObj = {
			name: configName,
			data: data
		};
		configs.update(
			{name: configName},
			newObj,
			{upsert: true},
			function(err, results) {
				if(err)
					return console.log(err);
				callback(newObj.data);
			}
		);
	} else {
		configs.findOne({name: configName}, function(err, obj) {
			if(err)
				return console.log(err);

			callback(obj);
		});
	}
}

function executeTests(data, res) {
	if(!testRunning) {
		res.end("Started");

		testRunning = true;
		testFailed = false;

		prepareTempFiles();
		buildTestListFromDB(data, function(testList) {
			// run selected tests
			runTests(testList, c.testList, "FirstPhase", function(reportPath) {
				if(c.rerunFailedTests) {
					// rerun failed tests if setting enabled
					rerunFailedTests(reportPath);
				} else {
					checkFailedTests(reportPath, function() {
						testFailed = true;
					});
					generateReport();
				}
			});
		});
	} else {
		res.end("Tests already are running");
	}
}

function rerunFailedTests(sourceReport) {
	checkFailedTests(sourceReport, function(tests) {
		buildTestListFromArray(tests, function(testList) {
			// generate test-list file and rerun tests
			runTests(testList, c.testListError, "SecondPhase", function(secondReportPath) {
				// rerun same failed tests second time
				runTestList(c.testListError, "ThirdPhase", function(thirdReportPath) {
					// check results
					checkFailedTests(secondReportPath, function() {
						testFailed = true;
					}, checkFailedTests(thirdReportPath, function() {
						testFailed = true;
					}));
					generateReport();
				});
			});
		});
	}, function() {
		generateReport();
	});
}

function runTests(testList, testListPath, xmlReportName, callback) {
	createTestListFile(testList, testListPath, function() {
		runTestList(testListPath, xmlReportName, function(reportPath) {
			callback(reportPath);
		});
	});
}

function getFailedTests(sourceReport, callback) {
	fs.readFile(sourceReport, function(err, data) {
		parseXml(data, function(err, result) {
			fixtures = result["test-run"]['test-suite'][0]['test-suite'][0]['test-suite'][0]['test-suite'][0]['test-suite'];
			var failedTests = [];
			fixtures.forEach(fixture => {
				failedTests = fixture['test-case'].filter(test => {
					return test.$.result === 'Failed';
				}).map(test => {
					return test.$.fullname;
				}).concat(failedTests);
			});
			callback(failedTests);
		});
	});
}

function checkFailedTests(sourceReport, existAction, nonExistAction) {
	// get test list from report
	getFailedTests(sourceReport, function(failedTests) {
		if(failedTests.length !== 0) {
			existAction(failedTests);
		} else {
			if(nonExistAction)
				nonExistAction();
		}
	});
}

function createTestListFile(testList, fileName, callback) {
	fs.writeFile(fileName, testList, function(err) {
		if(err)
			return console.log(err);

		callback();
	});
}

function buildTestListFromArray(array, callback) {
	callback(array.join('\n'));
}

function buildTestListFromDB(obj, callback) {
	var testList = [];
	obj.fixtures.forEach(fixture => {
		fixture.tests.filter(test => {
			return test.active === true;
		}).forEach(test => {
			test.browsers.forEach(browser => {
				testList.push(test.assembly + "(\"" + browser + "\")." + test.name);
			});
		});
	});
	callback(testList.join('\n'));
}

function runTestList(testList, name, callback) {
	var reportPath = "testResultsXml/" + name + ".xml";

	new Executor({
		program: util.getPath(c.nunitApp),
		args: {
			tests: "--testlist=" + testList,
			workers: "--workers=10",
			assembly: util.getPath(c.testAssemblyPath),
			output: "--result="+reportPath
		},
		anywayAction: function() {
			callback(reportPath);
		}
	});
}

function generateReport() {
	testRunning = false;
	new Executor({
		program: util.getPath(c.HTMLReportApp),
		args: {
			inputFolder: "testResultsXml",
			outputFolder: "views/testResults"
		},
		errorAction: function(err) {
			console.log(err);
		}
	});
}

function cleanFolder(path) {
	new Executor({
		program: "del",
		args: {
			path: path,
			mode: "/Q"
		},
		errorAction: function(err) {
			console.log(err);
		}
	});
}

function cleanReportFolder() {
	cleanFolder("views\\testResults\\*");
}

function removeXmlReports() {
	cleanFolder("testResultsXml\\*");
}

function prepareTempFiles() {
	cleanReportFolder();
	removeXmlReports();
}

module.exports = router;<|endoftext|>


<commit_before>(function($) {
"use strict";

var card = Echo.App.manifest("Echo.Conversations.NestedCard");

if (Echo.App.isDefined(card)) return;

card.templates.photo =
	'
' +
		'
' +
			'
' +
				'
' +
					'
' +
						'

{data:author_name}' +
					'
' +
				'
' +
				'' +
					'' +
				'' +
				'
' +
					'
' +
						'
' +
							'{data:title}' +
						'
' +
						'
{data:description}
' +
					'
' +
				'
' +
			'
' +
			'

' +
		'
' +
	'
';

card.templates.video =
	'
' +
		'
' +
			'
' +
				'
' +
					'

{data:author_name}' +
				'
' +
				'
' +
					'

' +
					'' +
				'
' +
				'
{data:title}
' +
				'
{data:description}
' +
				'

' +
			'
' +
		'
' +
	'
';

card.templates.link =
	'
' +
		'
' +
			'
' +
				'
' +
					'' +
				'
' +
				'
' +
					'
' +
						'{data:title}' +
					'
' +
					'
' +
						'
{data:description}
' +
					'
' +
				'
' +
				'

' +
				'

' +
			'
' +
		'
' +
	'
';

card.templates.main = function() {
	var data = this.get("data");
	var handlers = {
		"link": function(data) {
			return (data.thumbnail_width >= this.config.get("minArticleImageWidth"))
				? this.templates["photo"]
				: this.templates["link"];
		}
	};
	return handlers[data.type]
		? handlers[data.type].call(this, data)
		: this.templates[data.type];
};

card.init = function() {
	this.render();
	this.ready();
};

card.config = {
	"minArticleImageWidth": 250
};

card.renderers.sourceIcon = function(element) {
	var proviredURL = element.data("url");

	if (!proviredURL) return;

	var icon;
	var sourceIcons = [{
		"pattern": /http:\/\/instagram\.com/i,
		"url": "http://cdn.echoenabled.com/images/favicons/instagram.png"
	}];

	$.map(sourceIcons, function(item) {
		if (item.pattern.test(proviredURL)) {
			icon = item.url;
			return false;
		}
	});

	icon = icon || proviredURL +
		(proviredURL.substr(-1) === "/" ? "" : "/") + "favicon.ico";

	Echo.Utils.loadImage({
		"image": icon,
		"onerror": $.noop,
		"onload": function() {
			$(this).attr("title", element.data("name")).appendTo(element);
		}
	});
};

card.renderers.avatar = function(element) {
	// we have to do it because filter must work in IE8 only
	// in other cases we will have square avatar in IE 9
	var isIE8 = document.all && document.querySelector && !document.addEventListener;
	if (isIE8) {
		element.children()[0].style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.config.get("defaultAvatar") + "', sizingMethod='scale')";
	}
	return this.get("data.author_name") ? element : element.hide();
};

card.renderers.title = function(element) {
	return this.get("data.title") ? element : element.hide();
};

card.renderers.description = function(element) {
	return this.get("data.description") ? element : element.hide();
};

/**
 * Video
 */
card.renderers.playButton = function(element) {
	var self = this;
	var oembed = this.get("data");
	element.on("click", function() {
		self.view.get("videoPlaceholder").empty().append($(oembed.html));
	});
	return element;
};

card.renderers.videoPlaceholder = function(element) {
	var oembed = this.get("data");

	if (!oembed.thumbnail_url) {
		element.empty().append($(oembed.html));
	}

	return element.css({
		"width": oembed.width,
		"padding-bottom": oembed.height / oembed.width * 100 + "%"
	});
};

/**
 *  Photo
 */
card.renderers.photoThumbnail = function(element) {
	if (this.get("data.type") === "link") {
		element.attr("src", this.get("data.thumbnail_url"));
	} else {
		element.attr("src", this.get("data.url"));
	}
	return element;
};

card.renderers.photoLabelContainer = function(element) {
	return this.get("data.description") || this.get("data.title")
		? element
		: element.hide();
};

// calculate photoLabel max-height
var photoLabelHeight = 20 // photoLabelContainer padding
	+ 16 // photoTitle width
	+ 5 // photoTitle margin
	+ 3*16; // photoDescription line-height * lines count

card.css =
	'.{class:title} { font-weight: bold; margin: 5px 0; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; }' +
	'.{class:item} { font-family: "Helvetica Neue", arial, sans-serif; color: #42474A; font-size: 13px; line-height: 16px; display: inline-block; max-width: 100%; vertical-align: top; }' +
	'.{class:border} { white-space: normal; word-break: break-word; background-color: #FFFFFF; border: 1px solid #D2D2D2; border-bottom-width: 2px; }' +
	'.{class:item} .{class:sourceIcon} > img { max-width: 20px; }' +
	'.echo-sdk-ui .{class:avatar} > div { width: 28px; height: 28px; background-size:cover; display:inline-block; background-position:center; border-radius: 50%; margin-right: 6px; }' +
	'.{class:description} { overflow: hidden; }' +

	// photo
	'.{class:photoAvatarWrapper} { position: absolute; width: 100%; }' +
	'.{class:photoAvatar} { color: #FFF; white-space: nowrap; padding: 12px; text-overflow: ellipsis; overflow: hidden; }' +
	'.{class:photoAvatar} > div { background-image: url("{config:defaultAvatar}"); vertical-align: middle; }' +
	'.{class:photo} { position: relative; }' +
	'.{class:photo} + .{class:sourceIcon} > img { padding: 10px; }' +
	'.{class:photoLabel} { position: absolute; bottom: 0; color: #FFF; width: 100%; background-color: rgb(0, 0, 0); background-color: rgba(0, 0, 0, 0.5); }' +

	'.echo-sdk-ui .{class:photoLabel} a:link, .echo-sdk-ui .{class:photoLabel} a:visited, .echo-sdk-ui .{class:photoLabel} a:hover, .echo-sdk-ui .{class:photoLabel} a:active { color: #fff; }' +
	'.{class:photoLabelContainer} { padding: 10px; }' +
	'.{class:photoTitle} { margin: 0 0 5px 0; }' +

	'.{class:photoLabel} { overflow: hidden; max-height: ' + photoLabelHeight + 'px; }' +
	'.{class:photo}:hover .{class:photoLabel} { max-height: 100%; }' +
	$.map(["transition", "-o-transition", "-ms-transition", "-moz-transition", "-webkit-transition"], function(propertyName) {
		return '.{class:photoLabel} { ' + propertyName +': max-height ease 300ms}';
	}).join("") +

	// play button
	'.{class:playButton} { cursor: pointer; position: absolute; top: 0; left: 0; bottom: 0; right: 0; z-index: 10; }' +
	'.{class:playButton}:after { content: ""; position: absolute; top: 10px; left: 20px; border-left: 30px solid #FFF; border-top: 20px solid transparent; border-bottom: 20px solid transparent; }' +
	'.{class:playButton} { box-shadow: 0px 0px 40px #000; margin: auto; width: 60px; height: 60px; border-radius: 50%; background-color: rgb(0, 0, 0); background-color: rgba(0, 0, 0, 0.7); }' +
	'.{class:playButton}:hover { background-color: #3498DB; }' +

	// video
	'.{class:video} { padding: 10px; }' +
	'.{class:video} .{class:sourceIcon} > img { padding: 10px 0 0 0; }' +
	'.{class:videoAvatar} { margin-bottom: 8px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; }' +
	'.{class:videoTitle} { margin: 10px 0 0 0; }' +
	'.{class:videoAvatar} > div { background-image: url("{config:defaultAvatar}"); vertical-align: middle; }' +
	'.{class:videoDescription} { margin: 5px 0 0 0; }' +

	'.{class:videoPlaceholder} img { position: absolute; top: 0; left: 0; right: 0; bottom: 0; margin: auto; }' +
	'.{class:videoPlaceholder} { max-width: 100%; position: relative; padding-bottom: 75%; height: 0; float: none; margin: 0px; background: #000000; overflow: hidden; }' +
	'.{class:videoPlaceholder} > iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }' +
	'.{class:videoPlaceholder} > video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }' +
	'.{class:videoPlaceholder} > object { position: absolute; top: 0; left: 0; width: 100%;100 height: 100%; }' +

	// article
	'.{class:article} { padding: 10px; min-width: 200px; }' +
	'.{class:article} .{class:sourceIcon} > img { padding: 10px 0 0 0; }' +
	'.{class:article} .{class:articleTitle} > a { color: #42474A; font-weight: bold; }' +
	'.{class:article} .{class:articleTitle} > a:hover { color: #42474A; }' +
	'.{class:articleTitle} { padding: 0 0 5px 0; margin-left: 10px; }' +
	'.{class:articleDescription} { margin-left: 10px; font-size: 13px; line-height: 16px; }' +
	'.{class:articleThumbnail} { width: 30%; float: left; max-width: 120px; max-height: 120px; text-align:center; overflow:hidden; }' +
	'.{class:articleThumbnail} img { width: auto; height: auto; max-height:120px; max-width:120px; }' +
	'.{class:articleTemplate} { width: 70%; float: left; }';

Echo.App.create(card);

})(Echo.jQuery);
<commit_msg>Set max-height for photo card layout<commit_after>(function($) {
"use strict";

var card = Echo.App.manifest("Echo.Conversations.NestedCard");

if (Echo.App.isDefined(card)) return;

card.templates.photo =
	'
' +
		'
' +
			'
' +
				'
' +
					'
' +
						'

{data:author_name}' +
					'
' +
				'
' +
				'' +
					'' +
				'' +
				'
' +
					'
' +
						'
' +
							'{data:title}' +
						'
' +
						'
{data:description}
' +
					'
' +
				'
' +
			'
' +
			'

' +
		'
' +
	'
';

card.templates.video =
	'
' +
		'
' +
			'
' +
				'
' +
					'

{data:author_name}' +
				'
' +
				'
' +
					'

' +
					'' +
				'
' +
				'
{data:title}
' +
				'
{data:description}
' +
				'

' +
			'
' +
		'
' +
	'
';

card.templates.link =
	'
' +
		'
' +
			'
' +
				'
' +
					'' +
				'
' +
				'
' +
					'
' +
						'{data:title}' +
					'
' +
					'
' +
						'
{data:description}
' +
					'
' +
				'
' +
				'

' +
				'

' +
			'
' +
		'
' +
	'
';

card.templates.main = function() {
	var data = this.get("data");
	var handlers = {
		"link": function(data) {
			return (data.thumbnail_width >= this.config.get("minArticleImageWidth"))
				? this.templates["photo"]
				: this.templates["link"];
		}
	};
	return handlers[data.type]
		? handlers[data.type].call(this, data)
		: this.templates[data.type];
};

card.init = function() {
	this.render();
	this.ready();
};

card.config = {
	"minArticleImageWidth": 250
};

card.renderers.sourceIcon = function(element) {
	var proviredURL = element.data("url");

	if (!proviredURL) return;

	var icon;
	var sourceIcons = [{
		"pattern": /http:\/\/instagram\.com/i,
		"url": "http://cdn.echoenabled.com/images/favicons/instagram.png"
	}];

	$.map(sourceIcons, function(item) {
		if (item.pattern.test(proviredURL)) {
			icon = item.url;
			return false;
		}
	});

	icon = icon || proviredURL +
		(proviredURL.substr(-1) === "/" ? "" : "/") + "favicon.ico";

	Echo.Utils.loadImage({
		"image": icon,
		"onerror": $.noop,
		"onload": function() {
			$(this).attr("title", element.data("name")).appendTo(element);
		}
	});
};

card.renderers.avatar = function(element) {
	// we have to do it because filter must work in IE8 only
	// in other cases we will have square avatar in IE 9
	var isIE8 = document.all && document.querySelector && !document.addEventListener;
	if (isIE8) {
		element.children()[0].style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.config.get("defaultAvatar") + "', sizingMethod='scale')";
	}
	return this.get("data.author_name") ? element : element.hide();
};

card.renderers.title = function(element) {
	return this.get("data.title") ? element : element.hide();
};

card.renderers.description = function(element) {
	return this.get("data.description") ? element : element.hide();
};

/**
 * Video
 */
card.renderers.playButton = function(element) {
	var self = this;
	var oembed = this.get("data");
	element.on("click", function() {
		self.view.get("videoPlaceholder").empty().append($(oembed.html));
	});
	return element;
};

card.renderers.videoPlaceholder = function(element) {
	var oembed = this.get("data");

	if (!oembed.thumbnail_url) {
		element.empty().append($(oembed.html));
	}

	return element.css({
		"width": oembed.width,
		"padding-bottom": oembed.height / oembed.width * 100 + "%"
	});
};

/**
 *  Photo
 */
card.renderers.photoThumbnail = function(element) {
	if (this.get("data.type") === "link") {
		element.attr("src", this.get("data.thumbnail_url"));
	} else {
		element.attr("src", this.get("data.url"));
	}
	return element;
};

card.renderers.photoLabelContainer = function(element) {
	return this.get("data.description") || this.get("data.title")
		? element
		: element.hide();
};

// calculate photoLabel max-height
var photoLabelHeight = 20 // photoLabelContainer padding
	+ 16 // photoTitle width
	+ 5 // photoTitle margin
	+ 3*16; // photoDescription line-height * lines count

card.css =
	'.{class:title} { font-weight: bold; margin: 5px 0; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; }' +
	'.{class:item} { font-family: "Helvetica Neue", arial, sans-serif; color: #42474A; font-size: 13px; line-height: 16px; display: inline-block; max-width: 100%; vertical-align: top; }' +
	'.{class:border} { white-space: normal; word-break: break-word; background-color: #FFFFFF; border: 1px solid #D2D2D2; border-bottom-width: 2px; }' +
	'.{class:item} .{class:sourceIcon} > img { max-width: 20px; }' +
	'.echo-sdk-ui .{class:avatar} > div { width: 28px; height: 28px; background-size:cover; display:inline-block; background-position:center; border-radius: 50%; margin-right: 6px; }' +
	'.{class:description} { overflow: hidden; }' +

	// photo
	'.{class:photoAvatarWrapper} { position: absolute; width: 100%; }' +
	'.{class:photoAvatar} { color: #FFF; white-space: nowrap; padding: 12px; text-overflow: ellipsis; overflow: hidden; }' +
	'.{class:photoAvatar} > div { background-image: url("{config:defaultAvatar}"); vertical-align: middle; }' +
	'.{class:photo} { position: relative; }' +
	'.{class:photo} + .{class:sourceIcon} > img { padding: 10px; }' +
	'.{class:photoLabel} { position: absolute; bottom: 0; color: #FFF; width: 100%; background-color: rgb(0, 0, 0); background-color: rgba(0, 0, 0, 0.5); }' +
	'.{class:photo} > a { display: block; max-height: 350px; overflow: hidden; }' +

	'.echo-sdk-ui .{class:photoLabel} a:link, .echo-sdk-ui .{class:photoLabel} a:visited, .echo-sdk-ui .{class:photoLabel} a:hover, .echo-sdk-ui .{class:photoLabel} a:active { color: #fff; }' +
	'.{class:photoLabelContainer} { padding: 10px; }' +
	'.{class:photoTitle} { margin: 0 0 5px 0; }' +

	'.{class:photoLabel} { overflow: hidden; max-height: ' + photoLabelHeight + 'px; }' +
	'.{class:photo}:hover .{class:photoLabel} { max-height: 100%; }' +
	$.map(["transition", "-o-transition", "-ms-transition", "-moz-transition", "-webkit-transition"], function(propertyName) {
		return '.{class:photoLabel} { ' + propertyName +': max-height ease 300ms}';
	}).join("") +

	// play button
	'.{class:playButton} { cursor: pointer; position: absolute; top: 0; left: 0; bottom: 0; right: 0; z-index: 10; }' +
	'.{class:playButton}:after { content: ""; position: absolute; top: 10px; left: 20px; border-left: 30px solid #FFF; border-top: 20px solid transparent; border-bottom: 20px solid transparent; }' +
	'.{class:playButton} { box-shadow: 0px 0px 40px #000; margin: auto; width: 60px; height: 60px; border-radius: 50%; background-color: rgb(0, 0, 0); background-color: rgba(0, 0, 0, 0.7); }' +
	'.{class:playButton}:hover { background-color: #3498DB; }' +

	// video
	'.{class:video} { padding: 10px; }' +
	'.{class:video} .{class:sourceIcon} > img { padding: 10px 0 0 0; }' +
	'.{class:videoAvatar} { margin-bottom: 8px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; }' +
	'.{class:videoTitle} { margin: 10px 0 0 0; }' +
	'.{class:videoAvatar} > div { background-image: url("{config:defaultAvatar}"); vertical-align: middle; }' +
	'.{class:videoDescription} { margin: 5px 0 0 0; }' +

	'.{class:videoPlaceholder} img { position: absolute; top: 0; left: 0; right: 0; bottom: 0; margin: auto; }' +
	'.{class:videoPlaceholder} { max-width: 100%; position: relative; padding-bottom: 75%; height: 0; float: none; margin: 0px; background: #000000; overflow: hidden; }' +
	'.{class:videoPlaceholder} > iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }' +
	'.{class:videoPlaceholder} > video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }' +
	'.{class:videoPlaceholder} > object { position: absolute; top: 0; left: 0; width: 100%;100 height: 100%; }' +

	// article
	'.{class:article} { padding: 10px; min-width: 200px; }' +
	'.{class:article} .{class:sourceIcon} > img { padding: 10px 0 0 0; }' +
	'.{class:article} .{class:articleTitle} > a { color: #42474A; font-weight: bold; }' +
	'.{class:article} .{class:articleTitle} > a:hover { color: #42474A; }' +
	'.{class:articleTitle} { padding: 0 0 5px 0; margin-left: 10px; }' +
	'.{class:articleDescription} { margin-left: 10px; font-size: 13px; line-height: 16px; }' +
	'.{class:articleThumbnail} { width: 30%; float: left; max-width: 120px; max-height: 120px; text-align:center; overflow:hidden; }' +
	'.{class:articleThumbnail} img { width: auto; height: auto; max-height:120px; max-width:120px; }' +
	'.{class:articleTemplate} { width: 70%; float: left; }';

Echo.App.create(card);

})(Echo.jQuery);
<|endoftext|>


<commit_before>/**
 * Copyright 2017 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const os = require('os');
const https = require('https');
const fs = require('fs');
const path = require('path');
const extract = require('extract-zip');
const util = require('util');
const URL = require('url');
const removeRecursive = require('rimraf');
// @ts-ignore
const ProxyAgent = require('https-proxy-agent');
// @ts-ignore
const getProxyForUrl = require('proxy-from-env').getProxyForUrl;

const DOWNLOADS_FOLDER = path.join(__dirname, '..', '.local-chromium');
const DEFAULT_DOWNLOAD_HOST = 'https://storage.googleapis.com';

const downloadURLs = {
  linux: '%s/chromium-browser-snapshots/Linux_x64/%d/chrome-linux.zip',
  mac: '%s/chromium-browser-snapshots/Mac/%d/chrome-mac.zip',
  win32: '%s/chromium-browser-snapshots/Win/%d/chrome-win32.zip',
  win64: '%s/chromium-browser-snapshots/Win_x64/%d/chrome-win32.zip',
};

module.exports = {
  /**
   * @return {!Array<string>}
   */
  supportedPlatforms: function() {
    return Object.keys(downloadURLs);
  },

  /**
   * @return {string}
   */
  currentPlatform: function() {
    const platform = os.platform();
    if (platform === 'darwin')
      return 'mac';
    if (platform === 'linux')
      return 'linux';
    if (platform === 'win32')
      return os.arch() === 'x64' ? 'win64' : 'win32';
    return '';
  },

  /**
   * @param {string} platform
   * @param {string} revision
   * @return {!Promise<boolean>}
   */
  canDownloadRevision: function(platform, revision) {
    console.assert(downloadURLs[platform], 'Unknown platform: ' + platform);

    const options = requestOptions(util.format(downloadURLs[platform], DEFAULT_DOWNLOAD_HOST, revision), 'HEAD');

    let resolve;
    const promise = new Promise(x => resolve = x);
    const request = https.request(options, response => {
      resolve(response.statusCode === 200);
    });
    request.on('error', error => {
      console.error(error);
      resolve(false);
    });
    request.end();
    return promise;
  },

  /**
   * @param {string} platform
   * @param {string} revision
   * @param {string} [downloadHost=DEFAULT_DOWNLOAD_HOST]
   * @param {?function(number, number)} progressCallback
   * @return {!Promise}
   */
  downloadRevision: function(platform, revision, downloadHost = DEFAULT_DOWNLOAD_HOST, progressCallback) {
    let url = downloadURLs[platform];
    console.assert(url, `Unsupported platform: ${platform}`);
    url = util.format(url, downloadHost, revision);
    const zipPath = path.join(DOWNLOADS_FOLDER, `download-${platform}-${revision}.zip`);
    const folderPath = getFolderPath(platform, revision);
    if (fs.existsSync(folderPath))
      return;
    if (!fs.existsSync(DOWNLOADS_FOLDER))
      fs.mkdirSync(DOWNLOADS_FOLDER);
    return downloadFile(url, zipPath, progressCallback)
        .then(() => extractZip(zipPath, folderPath))
        .catch(err => err)
        .then(err => {
          if (fs.existsSync(zipPath))
            fs.unlinkSync(zipPath);
          if (err)
            throw err;
        });
  },

  /**
   * @return {!Array<!{platform:string, revision: string}>}
   */
  downloadedRevisions: function() {
    if (!fs.existsSync(DOWNLOADS_FOLDER))
      return [];
    const fileNames = fs.readdirSync(DOWNLOADS_FOLDER);
    return fileNames.map(fileName => parseFolderPath(fileName)).filter(revision => !!revision);
  },

  /**
   * @param {string} platform
   * @param {string} revision
   * @return {!Promise}
   */
  removeRevision: function(platform, revision) {
    console.assert(downloadURLs[platform], `Unsupported platform: ${platform}`);
    const folderPath = getFolderPath(platform, revision);
    console.assert(fs.existsSync(folderPath));
    return new Promise(fulfill => removeRecursive(folderPath, fulfill));
  },

  /**
   * @param {string} platform
   * @param {string} revision
   * @return {!{folderPath: string, executablePath: string, downloaded: boolean}}
   */
  revisionInfo: function(platform, revision) {
    console.assert(downloadURLs[platform], `Unsupported platform: ${platform}`);
    const folderPath = getFolderPath(platform, revision);
    let executablePath = '';
    if (platform === 'mac')
      executablePath = path.join(folderPath, 'chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium');
    else if (platform === 'linux')
      executablePath = path.join(folderPath, 'chrome-linux', 'chrome');
    else if (platform === 'win32' || platform === 'win64')
      executablePath = path.join(folderPath, 'chrome-win32', 'chrome.exe');
    else
      throw 'Unsupported platform: ' + platform;
    return {
      executablePath,
      folderPath,
      downloaded: fs.existsSync(folderPath)
    };
  },
};

/**
 * @param {string} platform
 * @param {string} revision
 * @return {string}
 */
function getFolderPath(platform, revision) {
  return path.join(DOWNLOADS_FOLDER, platform + '-' + revision);
}

/**
 * @param {string} folderPath
 * @return {?{platform: string, revision: string}}
 */
function parseFolderPath(folderPath) {
  const name = path.basename(folderPath);
  const splits = name.split('-');
  if (splits.length !== 2)
    return null;
  const [platform, revision] = splits;
  if (!downloadURLs[platform])
    return null;
  return {platform, revision};
}

/**
 * @param {string} url
 * @param {string} destinationPath
 * @param {?function(number, number)} progressCallback
 * @return {!Promise}
 */
function downloadFile(url, destinationPath, progressCallback) {
  let fulfill, reject;

  const promise = new Promise((x, y) => { fulfill = x; reject = y; });

  const options = requestOptions(url);
  const request = https.get(options, response => {
    if (response.statusCode !== 200) {
      const error = new Error(`Download failed: server returned code ${response.statusCode}. URL: ${url}`);
      // consume response data to free up memory
      response.resume();
      reject(error);
      return;
    }
    const file = fs.createWriteStream(destinationPath);
    file.on('finish', () => fulfill());
    file.on('error', error => reject(error));
    response.pipe(file);
    const totalBytes = parseInt(/** @type {string} */ (response.headers['content-length']), 10);
    if (progressCallback)
      response.on('data', onData.bind(null, totalBytes));
  });
  request.on('error', error => reject(error));
  return promise;

  function onData(totalBytes, chunk) {
    progressCallback(totalBytes, chunk.length);
  }
}

/**
 * @param {string} zipPath
 * @param {string} folderPath
 * @return {!Promise<?Error>}
 */
function extractZip(zipPath, folderPath) {
  return new Promise(fulfill => extract(zipPath, {dir: folderPath}, fulfill));
}

function requestOptions(url, method = 'GET') {
  /** @type {Object} */
  const result = URL.parse(url);
  result.method = method;

  const proxyURL = getProxyForUrl(url);
  if (proxyURL) {
    /** @type {Object} */
    const parsedProxyURL = URL.parse(proxyURL);
    parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:';

    result.agent = new ProxyAgent(parsedProxyURL);
  }

  return result;
}
<commit_msg>fix(Downloader): better handling for HTTPS proxy (#1508)<commit_after>/**
 * Copyright 2017 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const os = require('os');
const https = require('https');
const fs = require('fs');
const path = require('path');
const extract = require('extract-zip');
const util = require('util');
const URL = require('url');
const removeRecursive = require('rimraf');
// @ts-ignore
const ProxyAgent = require('https-proxy-agent');
// @ts-ignore
const getProxyForUrl = require('proxy-from-env').getProxyForUrl;

const DOWNLOADS_FOLDER = path.join(__dirname, '..', '.local-chromium');
const DEFAULT_DOWNLOAD_HOST = 'https://storage.googleapis.com';

const downloadURLs = {
  linux: '%s/chromium-browser-snapshots/Linux_x64/%d/chrome-linux.zip',
  mac: '%s/chromium-browser-snapshots/Mac/%d/chrome-mac.zip',
  win32: '%s/chromium-browser-snapshots/Win/%d/chrome-win32.zip',
  win64: '%s/chromium-browser-snapshots/Win_x64/%d/chrome-win32.zip',
};

module.exports = {
  /**
   * @return {!Array<string>}
   */
  supportedPlatforms: function() {
    return Object.keys(downloadURLs);
  },

  /**
   * @return {string}
   */
  currentPlatform: function() {
    const platform = os.platform();
    if (platform === 'darwin')
      return 'mac';
    if (platform === 'linux')
      return 'linux';
    if (platform === 'win32')
      return os.arch() === 'x64' ? 'win64' : 'win32';
    return '';
  },

  /**
   * @param {string} platform
   * @param {string} revision
   * @return {!Promise<boolean>}
   */
  canDownloadRevision: function(platform, revision) {
    console.assert(downloadURLs[platform], 'Unknown platform: ' + platform);

    const options = requestOptions(util.format(downloadURLs[platform], DEFAULT_DOWNLOAD_HOST, revision), 'HEAD');

    let resolve;
    const promise = new Promise(x => resolve = x);
    const request = https.request(options, response => {
      resolve(response.statusCode === 200);
    });
    request.on('error', error => {
      console.error(error);
      resolve(false);
    });
    request.end();
    return promise;
  },

  /**
   * @param {string} platform
   * @param {string} revision
   * @param {string} [downloadHost=DEFAULT_DOWNLOAD_HOST]
   * @param {?function(number, number)} progressCallback
   * @return {!Promise}
   */
  downloadRevision: function(platform, revision, downloadHost = DEFAULT_DOWNLOAD_HOST, progressCallback) {
    let url = downloadURLs[platform];
    console.assert(url, `Unsupported platform: ${platform}`);
    url = util.format(url, downloadHost, revision);
    const zipPath = path.join(DOWNLOADS_FOLDER, `download-${platform}-${revision}.zip`);
    const folderPath = getFolderPath(platform, revision);
    if (fs.existsSync(folderPath))
      return;
    if (!fs.existsSync(DOWNLOADS_FOLDER))
      fs.mkdirSync(DOWNLOADS_FOLDER);
    return downloadFile(url, zipPath, progressCallback)
        .then(() => extractZip(zipPath, folderPath))
        .catch(err => err)
        .then(err => {
          if (fs.existsSync(zipPath))
            fs.unlinkSync(zipPath);
          if (err)
            throw err;
        });
  },

  /**
   * @return {!Array<!{platform:string, revision: string}>}
   */
  downloadedRevisions: function() {
    if (!fs.existsSync(DOWNLOADS_FOLDER))
      return [];
    const fileNames = fs.readdirSync(DOWNLOADS_FOLDER);
    return fileNames.map(fileName => parseFolderPath(fileName)).filter(revision => !!revision);
  },

  /**
   * @param {string} platform
   * @param {string} revision
   * @return {!Promise}
   */
  removeRevision: function(platform, revision) {
    console.assert(downloadURLs[platform], `Unsupported platform: ${platform}`);
    const folderPath = getFolderPath(platform, revision);
    console.assert(fs.existsSync(folderPath));
    return new Promise(fulfill => removeRecursive(folderPath, fulfill));
  },

  /**
   * @param {string} platform
   * @param {string} revision
   * @return {!{folderPath: string, executablePath: string, downloaded: boolean}}
   */
  revisionInfo: function(platform, revision) {
    console.assert(downloadURLs[platform], `Unsupported platform: ${platform}`);
    const folderPath = getFolderPath(platform, revision);
    let executablePath = '';
    if (platform === 'mac')
      executablePath = path.join(folderPath, 'chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium');
    else if (platform === 'linux')
      executablePath = path.join(folderPath, 'chrome-linux', 'chrome');
    else if (platform === 'win32' || platform === 'win64')
      executablePath = path.join(folderPath, 'chrome-win32', 'chrome.exe');
    else
      throw 'Unsupported platform: ' + platform;
    return {
      executablePath,
      folderPath,
      downloaded: fs.existsSync(folderPath)
    };
  },
};

/**
 * @param {string} platform
 * @param {string} revision
 * @return {string}
 */
function getFolderPath(platform, revision) {
  return path.join(DOWNLOADS_FOLDER, platform + '-' + revision);
}

/**
 * @param {string} folderPath
 * @return {?{platform: string, revision: string}}
 */
function parseFolderPath(folderPath) {
  const name = path.basename(folderPath);
  const splits = name.split('-');
  if (splits.length !== 2)
    return null;
  const [platform, revision] = splits;
  if (!downloadURLs[platform])
    return null;
  return {platform, revision};
}

/**
 * @param {string} url
 * @param {string} destinationPath
 * @param {?function(number, number)} progressCallback
 * @return {!Promise}
 */
function downloadFile(url, destinationPath, progressCallback) {
  let fulfill, reject;

  const promise = new Promise((x, y) => { fulfill = x; reject = y; });

  const options = requestOptions(url);
  const request = https.get(options, response => {
    if (response.statusCode !== 200) {
      const error = new Error(`Download failed: server returned code ${response.statusCode}. URL: ${url}`);
      // consume response data to free up memory
      response.resume();
      reject(error);
      return;
    }
    const file = fs.createWriteStream(destinationPath);
    file.on('finish', () => fulfill());
    file.on('error', error => reject(error));
    response.pipe(file);
    const totalBytes = parseInt(/** @type {string} */ (response.headers['content-length']), 10);
    if (progressCallback)
      response.on('data', onData.bind(null, totalBytes));
  });
  request.on('error', error => reject(error));
  return promise;

  function onData(totalBytes, chunk) {
    progressCallback(totalBytes, chunk.length);
  }
}

/**
 * @param {string} zipPath
 * @param {string} folderPath
 * @return {!Promise<?Error>}
 */
function extractZip(zipPath, folderPath) {
  return new Promise(fulfill => extract(zipPath, {dir: folderPath}, fulfill));
}

function requestOptions(url, method = 'GET') {
  /** @type {Object} */
  const result = URL.parse(url);
  result.method = method;

  const proxyURL = getProxyForUrl(url);
  if (proxyURL) {
    /** @type {Object} */
    const parsedProxyURL = URL.parse(proxyURL);
    parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:';
    result.agent = new ProxyAgent(parsedProxyURL);
    result.rejectUnauthorized = false;
  }

  return result;
}
<|endoftext|>


<commit_before>const path = require('path');
const fs = require('fs');
const webpack = require('webpack');

module.exports = {
    mode: "production", // development or production
    entry: './lib/index.js',
    output: {
      path: path.resolve(__dirname, 'bin'),
      filename: 'RS_ScreenManager.js'
    },
    target: "node-webkit",
    node: {
      global: true,
    },
    plugins: [
    ]
  };<commit_msg>added sourceMap<commit_after>const path = require('path');
const fs = require('fs');
const webpack = require('webpack');

module.exports = {
    mode: "production", // development or production
    entry: './lib/index.js',
    output: {
      path: path.resolve(__dirname, 'bin'),
      filename: 'RS_ScreenManager.js'
    },
    target: "node-webkit",
    node: {
      global: true,
    },
    devtool: 'inline-source-map',
    plugins: [
      new webpack.EvalSourceMapDevToolPlugin({
        filename: '[name].js.map',
      })
    ]
  };<|endoftext|>


<commit_before>/*

    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      This file is part of the Smart Developer Hub Project:
        http://www.smartdeveloperhub.org/
      Center for Open Middleware
            http://www.centeropenmiddleware.com/
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      Copyright (C) 2015 Center for Open Middleware.
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
                http://www.apache.org/licenses/LICENSE-2.0
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
     limitations under the License.
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
*/

'use strict';

exports.metricList = function(callback) {

    callback(metrics);
};

exports.getMetric = function(mid, rid, uid, from, to, accumulated, max, aggr, callback) {
    var acum = 0;

    // Normalice parameters
    if (uid && !(uid in usersById)) {
        console.log("UID not found");
        return;
    }

    if (rid && !(rid in usersById)) {
        console.log("RID not found");
        return;
    }

    if (!(mid in metricsById)) {
        console.log("MID not found");
        return;
    }

    if (typeof from == 'undefined') {
        // default date
        from = new Date("Thu Apr 1 2015");
        console.log("default from")
    }
    if (typeof to == 'undefined') {
        to = new Date("Thu Apr 25 2015");
        // default date
        console.log("default to")
    }
    from = from.getTime();
    to = to.getTime();
    /* Unnecessary. Swagger auto-validation
    if (moment(from).isValid()) {
        console.log("valid from")
        from = from.getTime();
    } else {
        // default from date
        console.log("'from' date is not valid. default date: " + from);
        from = new Date("Thu Apr 1 2015").getTime();
    }
    if (moment(to).isValid()) {
        console.log("valid to")
        to = to.getTime();
    } else {
        // default to date
        console.log("'to' date is not valid. default date: " + to);
        to = new Date("Thu Apr 25 2015").getTime();
    }
    */
    if (!accumulated) {
        accumulated = false;
    }

    if (!aggr) {
        aggr = "sum";
    }

    if (!max || max == 0) {
        // default long
        max = 24;
    }

    var localcallback = function(themetric) {
        var result = {
            "values" : themetric.data,
            "interval" : {
                "from" : from,
                "to" : to
            },
            "step" : parseInt((parseInt(to) - parseInt(from))/ max),
            "metricinfo" : metricsById[mid].path,
            "timestamp" : themetric.timestamp
        };
        callback(result);
    };

    sdhWrapper.getMetricValue(mid, rid, uid, from, to, accumulated, max, aggr, localcallback);
};
<commit_msg>Clean getMetric<commit_after>/*

    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      This file is part of the Smart Developer Hub Project:
        http://www.smartdeveloperhub.org/
      Center for Open Middleware
            http://www.centeropenmiddleware.com/
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      Copyright (C) 2015 Center for Open Middleware.
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
                http://www.apache.org/licenses/LICENSE-2.0
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
     limitations under the License.
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
*/

'use strict';

exports.metricList = function(callback) {

    callback(metrics);
};

exports.getMetric = function(mid, rid, uid, from, to, accumulated, max, aggr, callback) {
    var acum = 0;

    // Normalice parameters
    if (uid && !(uid in usersById)) {
        console.log("UID not found");
        return;
    }

    if (rid && !(rid in usersById)) {
        console.log("RID not found");
        return;
    }

    if (!(mid in metricsById)) {
        console.log("MID not found");
        return;
    }

    if (typeof from == 'undefined') {
        // default date
        from = new Date("Thu Apr 1 2015");
    }
    if (typeof to == 'undefined') {
        // default date
        to = new Date("Thu Apr 25 2015");
    }
    from = from.getTime();
    to = to.getTime();
    /* Unnecessary. Swagger auto-validation
    if (moment(from).isValid()) {
        console.log("valid from")
        from = from.getTime();
    } else {
        // default from date
        console.log("'from' date is not valid. default date: " + from);
        from = new Date("Thu Apr 1 2015").getTime();
    }
    if (moment(to).isValid()) {
        console.log("valid to")
        to = to.getTime();
    } else {
        // default to date
        console.log("'to' date is not valid. default date: " + to);
        to = new Date("Thu Apr 25 2015").getTime();
    }
    */
    if (!accumulated) {
        accumulated = false;
    }

    if (!aggr) {
        aggr = "sum";
    }

    if (!max || max == 0) {
        // default long
        max = 24;
    }

    var localcallback = function(themetric) {
        var result = {
            "values" : themetric.data,
            "interval" : {
                "from" : from,
                "to" : to
            },
            "step" : parseInt((parseInt(to) - parseInt(from))/ max),
            "metricinfo" : metricsById[mid].path,
            "timestamp" : themetric.timestamp
        };
        callback(result);
    };

    sdhWrapper.getMetricValue(mid, rid, uid, from, to, accumulated, max, aggr, localcallback);
};
<|endoftext|>


<commit_before>Yennoo.register.controller("movies.FilterCtrl"
, ["$scope", "$routeParams", "$translate", "MovieFactory"
, function($scope, $routeParams, $translate, MovieFactory){
    $scope.timer     = new Kodi.util.Timer(true);
    $scope.translate = "PROPERTY."+ $routeParams.filter.toUpperCase();
    $scope.route     = {movies: Yennoo.route.moviesIndex[0]};

    $translate($scope.translate).then(function (translation){
        if ($scope.translate === translation) return false;
        $scope.$root.breadcrumb[1].title = translation;
    });

    MovieFactory.GetMovies(function(data, $async)
    {
        var movies = [];
        var filter = $routeParams.filter;
        var values = $routeParams.value;

        for(var index in data){
            var regex = new RegExp(values, "i");
            if (Kodi.util.isType(data[index][filter], "undefined") === false){
                if (!Kodi.util.isType(data[index][filter], "object")
                && (data[index][filter] == values ||data[index][filter] !== null)
                && (regex.test(data[index][filter].toString()))) {
                    movies.push(data[index]);
                }
            }
        }

        $scope.limit  = movies.length;
        $scope.movies = movies;
        $scope.timer.stop();
        $async.apply($scope);
    });

    /**
     * Sets the breadcrumb trail for the current page
     */
    $scope.$root.breadcrumb = [
        {title: "MOVIES", href: Yennoo.route.moviesIndex[0]},
        {title: $routeParams.filter},
        {title: $routeParams.value}
    ];
}]);<commit_msg>Updated movie filter statement<commit_after>Yennoo.register.controller("movies.FilterCtrl"
, ["$scope", "$routeParams", "$translate", "MovieFactory"
, function($scope, $routeParams, $translate, MovieFactory){
    $scope.timer     = new Kodi.util.Timer(true);
    $scope.translate = "PROPERTY."+ $routeParams.filter.toUpperCase();
    $scope.route     = {movies: Yennoo.route.moviesIndex[0]};

    $translate($scope.translate).then(function (translation){
        if ($scope.translate === translation) return false;
        $scope.$root.breadcrumb[1].title = translation;
    });

    /**
     * Retrieve all movies
     */
    MovieFactory.GetMovies(function(data, $async)
    {
        var result = [];
        var filter = $routeParams.filter;
        var values = $routeParams.value;

        for(var index in data){
            var regex = new RegExp(values, "i");

            /**
             * Default
             */
            if (Kodi.util.isDefined(data[index][filter]) === true){
                if (data[index][filter] == values || data[index][filter] !== null
                && (regex.test(data[index][filter].toString()))){
                    result.push(data[index]);
                }
            }
        }

        $scope.limit  = result.length;
        $scope.movies = result;
        $scope.timer.stop();
        $async.apply($scope);
    });

    /**
     * Sets the breadcrumb trail for the current page
     */
    $scope.$root.breadcrumb = [
        {title: "MOVIES", href: Yennoo.route.moviesIndex[0]},
        {title: $routeParams.filter},
        {title: $routeParams.value}
    ];
}]);<|endoftext|>


<commit_before>MyComponents.Hour = React.createClass({
  render: function() {
    console.log(this.props.hour.BEG)
    return (

           From {this.props.hour.FROM} to {this.props.hour.TO}
          Beggining: {this.props.hour.BEG}
          End: {this.props.hour.END}
          From {this.props.hour.FROM} to {this.props.hour.TO}

    );
  }
});

//TODO: This is a component to display an item in the hours array
   //       Raw props data is {JSON.stringify(this.props)}
MyComponents.GarageHours = React.createClass({
  render: function() {

    var hours = this.props.hours.map(function(h,i){
      return <MyComponents.Hour hour={h} key={i}/>
    })

    return (

          TODO: This is a component to display the hours of this garage.
          Raw props data is {JSON.stringify(this.props)}

          { hours }

    );
  }
});
<commit_msg>Pretty much finished with this part<commit_after>MyComponents.Hour = React.createClass({
  render: function() {
    return(

           {this.props.hour.FROM}- {this.props.hour.TO}

           Beggining: {this.props.hour.BEG}

           End: {this.props.hour.END}

    );
  }
});

//TODO: This is a component to display an item in the hours array
   //       Raw props data is {JSON.stringify(this.props)}
MyComponents.GarageHours = React.createClass({
  render: function() {

    var hours = this.props.hours.map(function(h,i){
      return <MyComponents.Hour hour={h} key={i}/>
    })

    return (

 Hours

          {hours}

    );
  }
});
<|endoftext|>


<commit_before>const fs = require('fs');
const {promisify} = require('util');

const stat = promisify(fs.stat);

const checkCacheExpiry = (path, ttl) =>
    stat(path).then(stats => {

        if (new Date(stats.mtime).getTime() + ttl < Date.now()) {

            throw new Error('Cache has expired.');

        }

        return stats;

    });

module.exports = checkCacheExpiry;
<commit_msg>Throw error when cache is missing.<commit_after>const fs = require('fs');
const {promisify} = require('util');

const stat = promisify(fs.stat);

const checkCacheExpiry = (path, ttl) =>
    stat(path).then(stats => {

        if (new Date(stats.mtime).getTime() + ttl < Date.now()) {

            throw new Error('Cache has expired.');

        }

        return stats;

    })
        .catch(() => {

            throw new Error('Cache is missing.');

        });

module.exports = checkCacheExpiry;
<|endoftext|>


<commit_before>var ohm = require('ohm-js'),
    jam = require('./lib/ohm/jamscript/jam'),
    fs = require('fs'),
    JSZip = require('jszip'),
    child_process = require('child_process'),
    crypto = require('crypto'),
    path = require('path');

var cc;
var outputName;
var preprocessDecls;

// Flags
var debug = false,
    noCompile = false,
    parseOnly = false,
    preprocessOnly = false,
    translateOnly = false,
    verbose = false;

// Process arguments
var args = process.argv.slice(2);
var jamlibPath = args[0];
var tmpDir = "/tmp/jam-" + randomValueHex(20);
var cPath = undefined;
var jsPath = undefined;

for (var i = 1; i < args.length; i++) {
  if(args[i].charAt(0) == "-") {
    if(args[i] == "-A") { // Parser only
      parseOnly = true;
    } else if(args[i] == "-D") { // Debug mode
      debug = true;
    } else if(args[i] == "-help") { // help
      printHelp();
    } else if(args[i] == "-N") { // Don't compile
      noCompile = true;
    } else if(args[i] == "-P") { // Preprocessor only
      preprocessOnly = true;
    } else if(args[i] == "-V") { // Verbose
      verbose = true;
    } else if(args[i] == "-T") { // Translator only
      translateOnly = true;
    }
  } else {
    var inputPath = args[i];
    var extension = path.extname(inputPath);
    if(extension == '.js') {
      jsPath = inputPath;
    } else if(extension == '.c') {
      cPath = inputPath;
    }
  }
}

if(cPath === undefined) {
  console.error("Error: C input file not specified");
}
if(jsPath === undefined) {
  console.error("Error: JavaScript input file not specified");
}
if(cPath === undefined || jsPath === undefined) {
  // inputArgsError();
  process.exit(1);
}

// if(inputPath === undefined) {
//   inputArgsError();
//   process.exit(1);
// }

try {
  fs.mkdirSync(tmpDir);
  var preprocessed = preprocess(cPath);
  if(preprocessOnly) {
    printAndExit(preprocessed);
  }
  if(verbose) {
    console.log(preprocessed);
  }

  console.log("Parsing C Files...");
  var jsTree = jam.jamJSGrammar.match(fs.readFileSync(jsPath).toString(), 'Program');
  if(jsTree.failed()) {
    throw jsTree.message;
  }

  console.log("Parsing JavaScript Files...");
  var cTree = jam.jamCGrammar.match(preprocessed, 'Source');
  if(cTree.failed()) {
    throw cTree.message;
  }

  if(parseOnly) {
    printAndExit(cTree + jsTree);
  }
  if(verbose) {
    console.log(cTree);
    console.log(jsTree);
  }

  console.log("Generating JavaScript Code...");
	var jsOutput = jam.jsSemantics(jsTree).jamJSTranslator;
  console.log("Generating C code...");
	var cOutput = jam.cSemantics(cTree).jamCTranslator;

  // if(translateOnly) {
  //   printAndExit(output);
  // }
  // if(verbose) {
  //   console.log(output);
  // }

  // fs.writeFileSync("/usr/local/share/jam/lib/jamlib/c_core/jamlib.c", output.C);
  // child_process.execSync("make -C /usr/local/share/jam/lib/jamlib/c_core");
  // fs.createReadStream('/usr/local/share/jam/lib/jamlib/c_core/testjam').pipe(fs.createWriteStream('jamout'));
  // fs.createReadStream('/usr/local/share/jam/lib/jamlib/c_core/jamconf.dat').pipe(fs.createWriteStream('jamconf.dat'));
  var requires = '';
  requires += "var jlib = require('/usr/local/share/jam/lib/jserver/jamlib');\n";
  requires += "var jnode = require('/usr/local/share/jam/lib/jserver/jnode');\n";
  requires += "var async = require('asyncawait/async');\n";
  requires += "var await = require('asyncawait/await');\n";

  requires += "var http = require('http');\n";
  requires += "var cbor = require('cbor');\n";
  requires += "var qs = require('querystring');\n";
  requires += "var path = require('path');\n";
  requires += "var mime = require('mime');\n";
  requires += "var fs = require('fs');\n";

  fs.writeFileSync("jamout.js", requires + jsOutput.JS + cOutput.JS);

  if(!noCompile) {
    console.log("Compiling C code...");
    // Set platform options
    var options = "";
    if(process.platform != "darwin") {
      options = "-lm -lbsd";
    }

    // flowCheck(output.annotated_JS)
    var includes = '#include "jam.h"\n'
    includes = '#include <unistd.h>\n' + includes;

    fs.writeFileSync("jamout.c", includes + preprocessDecls.join("\n") + "\n" + cOutput.C + jsOutput.C);
    fs.writeFileSync(`${tmpDir}/jamout.c`, includes + preprocessDecls.join("\n") + "\n" + cOutput.C + jsOutput.C);
    try {
      child_process.execSync(`clang -g ${tmpDir}/jamout.c -I/usr/local/share/jam/lib/ ${options} -pthread -lcbor -lnanomsg /usr/local/lib/libjam.a -ltask -levent -lhiredis -L/usr/local/lib -lpaho-mqtt3c`, {stdio: [0,1,2]}) ;
    } catch(e) {
    }
    // child_process.execSync(`gcc -Wno-incompatible-library-redeclaration -shared -o ${tmpDir}/libjamout.so -fPIC ${tmpDir}/jamout.c ${jamlibPath} -lpthread`);
    // createZip(createTOML(), output.JS, tmpDir, outputName);

    // if(!debug) {
    //   deleteFolderRecursive(tmpDir);
    // }
  }
} catch(e) {
    console.log("ERROR:");
    console.log(e);
}

function printAndExit(output) {
  console.log(output);
  process.exit();
}

function preprocess(file) {
  console.log("Preprocessing...");

  var contents = fs.readFileSync(file).toString();
  preprocessDecls = contents.match(/^[#;].*/gm);
  if(preprocessDecls == null) {
    preprocessDecls = [];
  }
  var includes = '#include "jam.h"\n'
  includes = '#include "jam.h"\n' + includes;

  contents = includes + "int main();\n" + contents;

  fs.writeFileSync(`${tmpDir}/pre.c`, contents);
  return child_process.execSync(`clang -E -P -I/usr/local/share/jam/deps/fake_libc_include -I/usr/local/share/jam/lib ${tmpDir}/pre.c`).toString();
  // return child_process.execSync(`${cc} -E -P -std=iso9899:199409 ${file}`).toString();

}

function flowCheck(input) {
  // Returns empty buffer if flow installed
  var hasFlow = child_process.execSync("flow version >/dev/null 2>&1 || { echo 'not installed';}");

  if(hasFlow.length == 0) {
    const child = child_process.exec('flow check-contents --color always', (error, stdout, stderr) => {
        if (error !== null) {
          console.log("JavaScript Type Checking Error:");
          console.log(stdout.substring(stdout.indexOf("\n") + 1));
        }
    });
    child.stdin.write(input);
    child.stdin.end();
  }
}

function createZip(toml, jsout, tmpDir, outputName) {
  var zip = new JSZip();
  zip.file("MANIFEST.tml", toml);
  zip.file("jamout.js", fs.readFileSync('/usr/local/share/jam/lib/jserver/jserver-clean.js') + jsout);
  zip.file("libjamout.so", fs.readFileSync(`${tmpDir}/libjamout.so`));
  fs.writeFileSync(`${outputName}.jxe`, zip.generate({type:"nodebuffer"}));
}

function createTOML() {
  var toml = "";
  toml += "# Description of the JXE structure\n";
  toml += "title = \"JAMScript Executable Description\"\n";

  toml += "# global identification and requirements are specified next\n";
  toml += "[jxe]\n";
  toml += "version = 1.0\n";
  toml += "checksum = \"XXXDFDFDFDFDF\"\n";
  toml += "requirements = \"none\"\n";

  toml += "# javascript portion is in one file for now\n";
  toml += "[jsfile]\n";
  toml += "# any or a particular version can be specified for nodeversion\n";
  toml += "nodeversion = 0\n";
  toml += "# list of modules that should be pre-loaded into Node\n";
  toml += "requires = []\n";
  toml += "# file name for the javascript code\n";
  toml += "file = \"jamout.js\"\n";

  toml += "# c portion could be in multiple files (in shared lib format)\n";
  toml += "[cfile]\n";
  toml += "portions = 1\n";
  toml += "# definition of a C portion\n";
  toml += "[cfile.1]\n";
  toml += "# architecture for which the shared library is genereated\n";
  toml += "arch = \"x86\"\n";
  toml += "# requirements of the shared library; these are tags that indicate the requirements\n";
  toml += "requires = []\n";
  toml += "# filename of the shared library\n";
  toml += "file = \"libjamout.so\"\n";
  return toml;
}

function inputArgsError() {
  console.error("No input file specified");
  console.error("Input format:");
  console.error("\tjamc [options] <input file> <output name>");
}

function randomValueHex(len) {
    return crypto.randomBytes(Math.ceil(len/2))
        .toString('hex') // convert to hexadecimal format
        .slice(0,len);   // return required number of characters
}

function deleteFolderRecursive(path) {
  if( fs.existsSync(path) ) {
    fs.readdirSync(path).forEach(function(file,index){
      var curPath = path + "/" + file;
      if(fs.lstatSync(curPath).isDirectory()) { // recurse
        deleteFolderRecursive(curPath);
      } else { // delete file
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
  }
}

function printHelp() {
  console.log("USAGE: jamc [options] <inputs> <output name>");
  console.log("\nOptions:");
  console.log("\t-A \t\t\t Parser only");
  console.log("\t-D \t\t\t Debug mode");
  console.log("\t-help \t\t\t Display available options");
  console.log("\t-N \t\t\t Skip compilation");
  console.log("\t-P \t\t\t Preprocessor only");
  console.log("\t-V \t\t\t Verbose mode");
  console.log("\t-T \t\t\t Translator only");
  process.exit();
}
<commit_msg>Fix preprocessor include error<commit_after>var ohm = require('ohm-js'),
    jam = require('./lib/ohm/jamscript/jam'),
    fs = require('fs'),
    JSZip = require('jszip'),
    child_process = require('child_process'),
    crypto = require('crypto'),
    path = require('path');

var cc;
var outputName;
var preprocessDecls;

// Flags
var debug = false,
    noCompile = false,
    parseOnly = false,
    preprocessOnly = false,
    translateOnly = false,
    verbose = false;

// Process arguments
var args = process.argv.slice(2);
var jamlibPath = args[0];
var tmpDir = "/tmp/jam-" + randomValueHex(20);
var cPath = undefined;
var jsPath = undefined;

for (var i = 1; i < args.length; i++) {
  if(args[i].charAt(0) == "-") {
    if(args[i] == "-A") { // Parser only
      parseOnly = true;
    } else if(args[i] == "-D") { // Debug mode
      debug = true;
    } else if(args[i] == "-help") { // help
      printHelp();
    } else if(args[i] == "-N") { // Don't compile
      noCompile = true;
    } else if(args[i] == "-P") { // Preprocessor only
      preprocessOnly = true;
    } else if(args[i] == "-V") { // Verbose
      verbose = true;
    } else if(args[i] == "-T") { // Translator only
      translateOnly = true;
    }
  } else {
    var inputPath = args[i];
    var extension = path.extname(inputPath);
    if(extension == '.js') {
      jsPath = inputPath;
    } else if(extension == '.c') {
      cPath = inputPath;
    }
  }
}

if(cPath === undefined) {
  console.error("Error: C input file not specified");
}
if(jsPath === undefined) {
  console.error("Error: JavaScript input file not specified");
}
if(cPath === undefined || jsPath === undefined) {
  // inputArgsError();
  process.exit(1);
}

// if(inputPath === undefined) {
//   inputArgsError();
//   process.exit(1);
// }

try {
  fs.mkdirSync(tmpDir);
  try {
    var preprocessed = preprocess(cPath);
  } catch(e) {
    console.log("Exiting with preprocessor error");
    process.exit();
  }
  if(preprocessOnly) {
    printAndExit(preprocessed);
  }
  if(verbose) {
    console.log(preprocessed);
  }

  console.log("Parsing C Files...");
  var jsTree = jam.jamJSGrammar.match(fs.readFileSync(jsPath).toString(), 'Program');
  if(jsTree.failed()) {
    throw jsTree.message;
  }

  console.log("Parsing JavaScript Files...");
  var cTree = jam.jamCGrammar.match(preprocessed, 'Source');
  if(cTree.failed()) {
    throw cTree.message;
  }

  if(parseOnly) {
    printAndExit(cTree + jsTree);
  }
  if(verbose) {
    console.log(cTree);
    console.log(jsTree);
  }

  console.log("Generating JavaScript Code...");
	var jsOutput = jam.jsSemantics(jsTree).jamJSTranslator;
  console.log("Generating C code...");
	var cOutput = jam.cSemantics(cTree).jamCTranslator;

  // if(translateOnly) {
  //   printAndExit(output);
  // }
  // if(verbose) {
  //   console.log(output);
  // }

  // fs.writeFileSync("/usr/local/share/jam/lib/jamlib/c_core/jamlib.c", output.C);
  // child_process.execSync("make -C /usr/local/share/jam/lib/jamlib/c_core");
  // fs.createReadStream('/usr/local/share/jam/lib/jamlib/c_core/testjam').pipe(fs.createWriteStream('jamout'));
  // fs.createReadStream('/usr/local/share/jam/lib/jamlib/c_core/jamconf.dat').pipe(fs.createWriteStream('jamconf.dat'));
  var requires = '';
  requires += "var jlib = require('/usr/local/share/jam/lib/jserver/jamlib');\n";
  requires += "var jnode = require('/usr/local/share/jam/lib/jserver/jnode');\n";
  requires += "var async = require('asyncawait/async');\n";
  requires += "var await = require('asyncawait/await');\n";

  requires += "var http = require('http');\n";
  requires += "var cbor = require('cbor');\n";
  requires += "var qs = require('querystring');\n";
  requires += "var path = require('path');\n";
  requires += "var mime = require('mime');\n";
  requires += "var fs = require('fs');\n";

  fs.writeFileSync("jamout.js", requires + jsOutput.JS + cOutput.JS);

  if(!noCompile) {
    console.log("Compiling C code...");
    // Set platform options
    var options = "";
    if(process.platform != "darwin") {
      options = "-lm -lbsd";
    }

    // flowCheck(output.annotated_JS)
    var includes = '#include "jam.h"\n'
    includes = '#include "jdata.h"\n' + includes;
    includes = '#include <unistd.h>\n' + includes;

    fs.writeFileSync("jamout.c", includes + preprocessDecls.join("\n") + "\n" + cOutput.C + jsOutput.C);
    fs.writeFileSync(`${tmpDir}/jamout.c`, includes + preprocessDecls.join("\n") + "\n" + cOutput.C + jsOutput.C);
    try {
      child_process.execSync(`clang -g ${tmpDir}/jamout.c -I/usr/local/share/jam/lib/ ${options} -pthread -lcbor -lnanomsg /usr/local/lib/libjam.a -ltask -levent -lhiredis -L/usr/local/lib -lpaho-mqtt3c`, {stdio: [0,1,2]}) ;
    } catch(e) {
    }
    // child_process.execSync(`gcc -Wno-incompatible-library-redeclaration -shared -o ${tmpDir}/libjamout.so -fPIC ${tmpDir}/jamout.c ${jamlibPath} -lpthread`);
    // createZip(createTOML(), output.JS, tmpDir, outputName);

    // if(!debug) {
    //   deleteFolderRecursive(tmpDir);
    // }
  }
} catch(e) {
    console.log("ERROR:");
    console.log(e);
}

function printAndExit(output) {
  console.log(output);
  process.exit();
}

function preprocess(file) {
  console.log("Preprocessing...");

  var contents = fs.readFileSync(file).toString();
  preprocessDecls = contents.match(/^[#;].*/gm);
  if(preprocessDecls == null) {
    preprocessDecls = [];
  }
  var includes = '#include "jam.h"\n'
  includes = '#include "jam.h"\n' + includes;

  contents = includes + "int main();\n" + contents;

  fs.writeFileSync(`${tmpDir}/pre.c`, contents);
  return result = child_process.execSync(`clang -E -P -I/usr/local/share/jam/deps/fake_libc_include -I/usr/local/share/jam/lib ${tmpDir}/pre.c`).toString();

  // return child_process.execSync(`${cc} -E -P -std=iso9899:199409 ${file}`).toString();

}

function flowCheck(input) {
  // Returns empty buffer if flow installed
  var hasFlow = child_process.execSync("flow version >/dev/null 2>&1 || { echo 'not installed';}");

  if(hasFlow.length == 0) {
    const child = child_process.exec('flow check-contents --color always', (error, stdout, stderr) => {
        if (error !== null) {
          console.log("JavaScript Type Checking Error:");
          console.log(stdout.substring(stdout.indexOf("\n") + 1));
        }
    });
    child.stdin.write(input);
    child.stdin.end();
  }
}

function createZip(toml, jsout, tmpDir, outputName) {
  var zip = new JSZip();
  zip.file("MANIFEST.tml", toml);
  zip.file("jamout.js", fs.readFileSync('/usr/local/share/jam/lib/jserver/jserver-clean.js') + jsout);
  zip.file("libjamout.so", fs.readFileSync(`${tmpDir}/libjamout.so`));
  fs.writeFileSync(`${outputName}.jxe`, zip.generate({type:"nodebuffer"}));
}

function createTOML() {
  var toml = "";
  toml += "# Description of the JXE structure\n";
  toml += "title = \"JAMScript Executable Description\"\n";

  toml += "# global identification and requirements are specified next\n";
  toml += "[jxe]\n";
  toml += "version = 1.0\n";
  toml += "checksum = \"XXXDFDFDFDFDF\"\n";
  toml += "requirements = \"none\"\n";

  toml += "# javascript portion is in one file for now\n";
  toml += "[jsfile]\n";
  toml += "# any or a particular version can be specified for nodeversion\n";
  toml += "nodeversion = 0\n";
  toml += "# list of modules that should be pre-loaded into Node\n";
  toml += "requires = []\n";
  toml += "# file name for the javascript code\n";
  toml += "file = \"jamout.js\"\n";

  toml += "# c portion could be in multiple files (in shared lib format)\n";
  toml += "[cfile]\n";
  toml += "portions = 1\n";
  toml += "# definition of a C portion\n";
  toml += "[cfile.1]\n";
  toml += "# architecture for which the shared library is genereated\n";
  toml += "arch = \"x86\"\n";
  toml += "# requirements of the shared library; these are tags that indicate the requirements\n";
  toml += "requires = []\n";
  toml += "# filename of the shared library\n";
  toml += "file = \"libjamout.so\"\n";
  return toml;
}

function inputArgsError() {
  console.error("No input file specified");
  console.error("Input format:");
  console.error("\tjamc [options] <input file> <output name>");
}

function randomValueHex(len) {
    return crypto.randomBytes(Math.ceil(len/2))
        .toString('hex') // convert to hexadecimal format
        .slice(0,len);   // return required number of characters
}

function deleteFolderRecursive(path) {
  if( fs.existsSync(path) ) {
    fs.readdirSync(path).forEach(function(file,index){
      var curPath = path + "/" + file;
      if(fs.lstatSync(curPath).isDirectory()) { // recurse
        deleteFolderRecursive(curPath);
      } else { // delete file
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
  }
}

function printHelp() {
  console.log("USAGE: jamc [options] <inputs> <output name>");
  console.log("\nOptions:");
  console.log("\t-A \t\t\t Parser only");
  console.log("\t-D \t\t\t Debug mode");
  console.log("\t-help \t\t\t Display available options");
  console.log("\t-N \t\t\t Skip compilation");
  console.log("\t-P \t\t\t Preprocessor only");
  console.log("\t-V \t\t\t Verbose mode");
  console.log("\t-T \t\t\t Translator only");
  process.exit();
}
<|endoftext|>


<commit_before><commit_msg>Scroll to top on actions<commit_after><|endoftext|>


<commit_before><commit_msg>Tweak the remove-year button's title<commit_after><|endoftext|>


<commit_before><commit_msg>updated 一帧的时候轮播不滚动<commit_after><|endoftext|>


<commit_before>function VectorRenderer (leaflet, layers, styles)
{
    // this.tile_base_url = 'http://tile.openstreetmap.us/vectiles-all/';
    // this.tile_base_url = 'http://api-vector-test.mapzen.com/vector/all/';
    this.tile_base_url = 'http://api-vector-dev.mapzen.com/vector/all/';
    // this.tile_base_url = 'http://localhost:8080/all/';

    this.leaflet = leaflet;
    this.layers = layers;
    this.styles = styles;
    this.tiles = {};
}

VectorRenderer.prototype.loadTile = function (coords, div)
{
    var tile_url = this.tile_base_url + coords.z + '/' + coords.x + '/' + coords.y + '.json';
    var key = [coords.x, coords.y, coords.z].join('/');
    var req = new XMLHttpRequest();
    var renderer = this;

    this.removeTile(key);

    var tile = this.tiles[key] = this.tiles[key] || {};
    tile.key = key;
    tile.coords = coords;
    tile.xhr = req;
    tile.timers = {};
    tile.timers.network_start = +new Date();
    tile.loading = true;
    tile.loaded = false;

    req.onload = function () {
        var tile = renderer.tiles[key]; // = {};
        if (tile == null) {
            return;
        }

        tile.layers = JSON.parse(req.response);
        tile.timers.network = +new Date() - tile.timers.network_start; // network/JSON parsing

        div.setAttribute('data-tile-key', tile.key); // tile info for debugging
        div.style.width = '256px';
        div.style.height = '256px';

        // var debug_overlay = document.createElement('div');
        // debug_overlay.textContent = tile.key;
        // debug_overlay.style.position = 'absolute';
        // debug_overlay.style.left = 0;
        // debug_overlay.style.top = 0;
        // debug_overlay.style.color = 'white';
        // div.appendChild(debug_overlay);

        // Extract desired layers from full GeoJSON response
        var layers = {};
        for (var t=0; t < renderer.layers.length; t++) {
            renderer.layers[t].number = t;
            layers[renderer.layers[t].name] = renderer.layers[t].data(tile.layers) || { type: 'FeatureCollection', features: [] };
        }
        tile.layers = layers;

        // Mercator projection for geometry and bounds
        timer = +new Date();
        for (var t in tile.layers) {
            var num_features = tile.layers[t].features.length;
            for (var f=0; f < num_features; f++) {
                var feature = tile.layers[t].features[f];
                feature.geometry.coordinates = Geo.transformGeometry(feature.geometry, function (coordinates) {
                    var m = Geo.latLngToMeters(Point(coordinates[0], coordinates[1]));
                    return [m.x, m.y];
                });
            };
        }
        tile.min = Geo.metersForTile(tile.coords);
        tile.max = Geo.metersForTile({ x: tile.coords.x + 1, y: tile.coords.y + 1, z: tile.coords.z });
        tile.timers.projection = +new Date() - timer; // mercator projection

        tile.loading = false;
        tile.loaded = true;

        // Render
        timer = +new Date();
        renderer.addTile(tile, div);

        tile.timers.rendering = +new Date() - timer; // rendering/geometry prep
        console.log("timers for tile " + tile.key +
            ": network: " + (tile.timers.network) +
            ", projection: " + (tile.timers.projection) +
            ", rendering: " + (tile.timers.rendering)
        );

        renderer.leaflet.layer.tileDrawn(div);
    };
    req.open('GET', tile_url, true /* async flag */);
    req.send();
};

VectorRenderer.prototype.removeTile = function (key)
{
    console.log("tile unload for " + key);
    var tile = renderer.tiles[key];
    if (tile != null && tile.loading == true) {
        console.log("cancel tile load for " + key);
        tile.loaded = false;
        tile.xhr.abort();
        tile.xhr = null;
        tile.loading = false;
    }

    delete this.tiles[key];
};
<commit_msg>extract some tile processing to separate functions and generalize timers<commit_after>function VectorRenderer (leaflet, layers, styles)
{
    // this.tile_base_url = 'http://tile.openstreetmap.us/vectiles-all/';
    // this.tile_base_url = 'http://api-vector-test.mapzen.com/vector/all/';
    this.tile_base_url = 'http://api-vector-dev.mapzen.com/vector/all/';
    // this.tile_base_url = 'http://localhost:8080/all/';

    this.leaflet = leaflet;
    this.layers = layers;
    this.styles = styles;
    this.tiles = {};
}

VectorRenderer.prototype.loadTile = function (coords, div)
{
    var tile_url = this.tile_base_url + coords.z + '/' + coords.x + '/' + coords.y + '.json';
    var key = [coords.x, coords.y, coords.z].join('/');
    var req = new XMLHttpRequest();
    var renderer = this;

    this.removeTile(key);

    var tile = this.tiles[key] = this.tiles[key] || {};
    tile.key = key;
    tile.coords = coords;
    tile.xhr = req;
    tile.timers = {};
    tile.timers.network = +new Date();
    tile.loading = true;
    tile.loaded = false;

    req.onload = function () {
        var tile = renderer.tiles[key]; // = {};
        if (tile == null) {
            return;
        }

        tile.layers = JSON.parse(req.response);
        tile.timers.network = +new Date() - tile.timers.network; // network/JSON parsing

        div.setAttribute('data-tile-key', tile.key); // tile info for debugging
        div.style.width = '256px';
        div.style.height = '256px';

        // var debug_overlay = document.createElement('div');
        // debug_overlay.textContent = tile.key;
        // debug_overlay.style.position = 'absolute';
        // debug_overlay.style.left = 0;
        // debug_overlay.style.top = 0;
        // debug_overlay.style.color = 'white';
        // div.appendChild(debug_overlay);

        // Extract desired layers from full GeoJSON response
        renderer.processLayersForTile(tile);

        // Mercator projection for geometry and bounds
        tile.min = Geo.metersForTile(tile.coords);
        tile.max = Geo.metersForTile({ x: tile.coords.x + 1, y: tile.coords.y + 1, z: tile.coords.z });
        renderer.projectTile(tile);

        tile.loading = false;
        tile.loaded = true;

        // Render
        var timer = +new Date();
        renderer.addTile(tile, div);
        tile.timers.rendering = +new Date() - timer; // rendering/geometry prep

        // Processing time
        console.log(
            "timers for " + tile.key + ': [ ' +
            Object.keys(tile.timers).map(function (t) { return t + ': ' + tile.timers[t]; }).join(', ') + ' ]'
        );

        renderer.leaflet.layer.tileDrawn(div);
    };
    req.open('GET', tile_url, true /* async flag */);
    req.send();
};

VectorRenderer.prototype.removeTile = function (key)
{
    console.log("tile unload for " + key);
    var tile = renderer.tiles[key];
    if (tile != null && tile.loading == true) {
        console.log("cancel tile load for " + key);
        tile.loaded = false;
        tile.xhr.abort();
        tile.xhr = null;
        tile.loading = false;
    }

    delete this.tiles[key];
};

// Processes the tile response to create layers as defined by this renderer
// Can include post-processing to partially filter or re-arrange data, e.g. only including POIs that have names
VectorRenderer.prototype.processLayersForTile = function (tile)
{
    var layers = {};
    for (var t=0; t < renderer.layers.length; t++) {
        renderer.layers[t].number = t;
        layers[renderer.layers[t].name] = renderer.layers[t].data(tile.layers) || { type: 'FeatureCollection', features: [] };
    }
    tile.layers = layers;
    return tile;
};

VectorRenderer.prototype.projectTile = function (tile)
{
    var timer = +new Date();
    for (var t in tile.layers) {
        var num_features = tile.layers[t].features.length;
        for (var f=0; f < num_features; f++) {
            var feature = tile.layers[t].features[f];
            feature.geometry.coordinates = Geo.transformGeometry(feature.geometry, function (coordinates) {
                var m = Geo.latLngToMeters(Point(coordinates[0], coordinates[1]));
                return [m.x, m.y];
            });
        };
    }
    tile.timers.projection = +new Date() - timer;
    return tile;
};
<|endoftext|>


<commit_before>function updateImage(loadImage) {

	var d = new Date();
	var h = d.getHours().toString();
	var m = d.getMinutes().toString();
		if (m < 10) { m = '0' + m};

	var domain = 'http://labs.brunoamaral.eu/coffeeclock/'
	image = domain + 'public/assets/images/clock/' + h + '00.JPG';
	var element = document.getElementById('coffeetable');

	var xhr = new XMLHttpRequest();

	xhr.open("GET", image, true);
	xhr.responseType = "blob";
	xhr.onload = function(e){
		var urlCreator = window.URL || window.webkitURL;
		var imageUrl = urlCreator.createObjectURL(this.response);
	}
	xhr.send();
	// $.get(image)
	// 	.done(function(){
	// 		element.src = image;
	// 	})
	// 	.fail(function(){
	// 		element.src = 'http://placekitten.com/g/600/600';
	// });

	var loadingImage = loadImage(blob, function (img){
			element.appendChild(img);
		},
		{orientation: blob.exif.get('Orientation')}
		);
};

$(document).ready(function(){
	updateImage() // call the first time
	setInterval(updateImage, 15 * 1000) // update each 5 seconds
});<commit_msg>blob gets lost<commit_after>function updateImage(loadImage) {

	var d = new Date();
	var h = d.getHours().toString();
	var m = d.getMinutes().toString();
		if (m < 10) { m = '0' + m};

	var domain = 'http://labs.brunoamaral.eu/coffeeclock/'
	var image = domain + 'public/assets/images/clock/' + h + '00.JPG';
	var element = document.getElementById('coffeetable');

	var xhr = new XMLHttpRequest();

	xhr.open("GET", image, true);
	xhr.responseType = "arraybuffer";
	xhr.onload = function(e){
		var blob = new Blob([this.response], {type: "image/jpeg"});
console.log(blob);
	        var loadingImage = loadImage(blob, function(img){
                        document.getElementById('coffeetable').appendChild(img);
                console.log(blob); console.log(img)},
                {orientation: blob.exif.get('Orientation')}
                );
	}
	xhr.send();
	// $.get(image)
	// 	.done(function(){
	// 		element.src = image;
	// 	})
	// 	.fail(function(){
	// 		element.src = 'http://placekitten.com/g/600/600';
	// });

};

$(document).ready(function(){
	updateImage() // call the first time
	setInterval(updateImage, 15 * 1000) // update each 5 seconds
});
<|endoftext|>