<commit_before>/**
 * multi process enabled for this
 */

var cpus = require('os').cpus(),
    child_process = require('child_process');

function Workers(options) {
    this.count = options.count || 6;
    this.args = options.args || [];
    this.target = options.target;
    if (!this.target) {
        throw new Error('Invalid target file');
    }
    this.queue = []; // store pid
    this.map = {};   // store work instance

    if (this.count > cpus.length) {
        this.count = cpus.length;
    }
    this.currentIndex = 0;
    this.init();
}

/**
 * @private
 * init
 */
Workers.prototype.init = function() {
    for (var i = 0;i <  this.count; i++) {
        this.create(i);
    }
};

/**
 * @private
 * create one child process entity
 */
Workers.prototype.create = function(i) {
    var worker = child_process.fork(this.target, [i].concat(this.args));
    worker.on('exit', function() {
        console.log('[' + Date.now() + ']  Worker ' + worker.pid + ' exit.');
        delete this.map[worker.pid];
        this.create(i);
    }.bind(this));
    this.map[worker.pid] = worker;
    this.queue[i] = worker.pid;
};

/**
 * @public
 * send message to subprocess
 */
Workers.prototype.send = function() {
    var worker = null;
    while(true) {
        worker = this.map[this.queue[this.currentIndex ++]];
        this.currentIndex = this.currentIndex % this.count;
        if (!worker.connected) {
            worker.kill('SIGTERM');
        }
        else {
            break;
        }
    }
    try {
        worker.send.apply(worker, Array.prototype.slice.call(arguments, 0));
    }
    catch(e) {
        console.log('send error: ', e);
    }
};

/**
 * @public
 * close all process
 */
Workers.prototype.exit = function() {
    for (var i = 0; i < this.queue.length; i ++) {
        try {
            if (this.queue[i]) {
                var worker = this.map[this.queue[i]];
                worker.kill('SIGTERM');
                delete this.map[this.queue[i]];
                this.queue[i] = null;
            }
        }
        catch(e) {
            console.log('exit error: ', e);
        }
    }
};

module.exports = Workers;
<commit_msg>add broadcast api, use event emitter emit errors<commit_after>/**
 * multi process enabled for this
 */

var cpus = require('os').cpus();
var events = require('events');
var util = require('util');
var child_process = require('child_process');

function Workers(options) {
    if (false === (this instanceof Workers)) {
        return new Workers(options);
    }
    this.count = options.count || 8;
    this.args = options.args || [];
    this.target = options.target;
    if (!this.target) {
        throw new Error('Invalid target file');
    }
    this.queue = []; // store pid
    this.map = {};   // store work instance

    events.EventEmitter.call(this);

    if (this.count > cpus.length) {
        this.count = cpus.length;
    }
    this.currentIndex = 0;
    this._init();
}
util.inherits(Workers, events.EventEmitter);

/**
 * @private
 * init
 */
Workers.prototype._init = function() {
    for (var i = 0;i < this.count; i++) {
        this.create(i);
    }
};

/**
 * @private
 * create one child process entity
 */
Workers.prototype.create = function(i) {
    var worker = child_process.fork(this.target, [i].concat(this.args));
    worker.on('exit', function(code) {
        this.emit('uncaughtException', new Error(worker.pid));
        delete this.map[worker.pid];
        this.create(i);
    }.bind(this));
    this.map[worker.pid] = worker;
    this.queue[i] = worker.pid;
};

/**
 * @public
 * send message to subprocess
 */
Workers.prototype.send = function() {
    var worker = null;
    while(true) {
        worker = this.map[this.queue[this.currentIndex ++]];
        this.currentIndex = this.currentIndex % this.count;
        if (!worker.connected) {
            worker.kill('SIGTERM');
        }
        else {
            break;
        }
    }
    try {
        worker.send.apply(worker, Array.prototype.slice.call(arguments, 0));
    }
    catch(e) {
        this.emit('error', e);
    }
};

/**
 * @public
 * broadcast
 */
Workers.prototype.broadcast = function() {
    var worker = null;
    for (var i = 0;i < this.queue.length; i ++) {
        try {
            worker = this.map[this.queue[i]];
            if (worker.connected) {
                worker.send.apply(worker, Array.prototype.slice.call(arguments, 0));
            }
        }
        catch(e) {
            this.emit('error', e);
        }
    }
};

/**
 * @public
 * close all process
 */
Workers.prototype.exit = function() {
    for (var i = 0; i < this.queue.length; i ++) {
        try {
            if (this.queue[i]) {
                var worker = this.map[this.queue[i]];
                worker.kill('SIGTERM');
                delete this.map[this.queue[i]];
                this.queue[i] = null;
            }
        }
        catch(e) {
            this.emit('error', e);
        }
    }
};

module.exports = Workers;
<|endoftext|>


<commit_before>'use strict';
/* eslint-disable no-mixed-operators */
module.exports = function (red, green, blue) {
	if ((typeof red !== 'number' || typeof green !== 'number' || typeof blue !== 'number') &&
		(red > 255 || green > 255 || blue > 255)) {
		throw new TypeError('Expected three numbers below 256');
	}

	return ((blue | green << 8 | red << 16) | 1 << 24).toString(16).slice(1);
};
<commit_msg>fix type checking<commit_after>'use strict';
/* eslint-disable no-mixed-operators */
module.exports = function (red, green, blue) {
	if (typeof red !== 'number' ||
		typeof green !== 'number' ||
		typeof blue !== 'number' ||
		red > 255 ||
		green > 255 ||
		blue > 255) {
		throw new TypeError('Expected three numbers below 256');
	}

	return ((blue | green << 8 | red << 16) | 1 << 24).toString(16).slice(1);
};
<|endoftext|>


<commit_before>'use strict';

const got = require('got');
let URL;

module.exports = function (user, game, gotOptions) {
	if (!user) {
		throw new TypeError('Please provide a user');
	}

	game = game || '730/2/';

	if (isNaN(Number(user))) {
		URL = `http://steamcommunity.com/id/${user}/inventory/json/${game}`;
	} else {
		URL = `http://steamcommunity.com/profiles/${user}/inventory/json/${game}`;
	}

	let response = [];

	return got(URL, gotOptions).then(res => {
		let items;
		let desc;

		try {
			desc = JSON.parse(res.body).rgDescriptions;
			items = JSON.parse(res.body).rgInventory;
		} catch (e) {
			items = [];
			desc = {};
		}

		if (!items) {
			return response;
		}

		Object.keys(items).forEach(key => {
			let temp = items[key];
			let item = desc[`${temp.classid}_${temp.instanceid}`];

			if (!item) {
				return response.push({error: true});
			}

			let data = {
				id: temp.id,
				amount: temp.amount,
				pos: temp.pos,
				name: item.name,
				appid: item.appid,
				classid: item.classid,
				instanceid: item.instanceid,
				tradable: item.tradable,
				marketable: item.marketable,
				marketTradableRestriction: item.market_tradable_restriction,
				link: item.actions ? item.actions[0].link : null,
				image: `http://steamcommunity-a.akamaihd.net/economy/image/${item.icon_url_large || item.icon_url}`,
				category: null,
				type: null,
				exterior: null,
				quality: null,
				raw: item,
			};

			// To match http://steamcommunity.com/market/ filters names
			item.tags.forEach(tag => {
				if (tag.category === 'Type') {
					data.type = tag.name;
				}
				if (tag.category === 'Weapon') {
					data.weapon = tag.name;
				}
				if (tag.category === 'Quality') {
					data.category = tag.name;
				}
				if (tag.category === 'Exterior') {
					data.exterior = tag.name;
				}
			});

			response.push(data);
		});

		return response;
	});
};
<commit_msg>Added market_hash_name field<commit_after>'use strict';

const got = require('got');
let URL;

module.exports = function (user, game, gotOptions) {
	if (!user) {
		throw new TypeError('Please provide a user');
	}

	game = game || '730/2/';

	if (isNaN(Number(user))) {
		URL = `http://steamcommunity.com/id/${user}/inventory/json/${game}`;
	} else {
		URL = `http://steamcommunity.com/profiles/${user}/inventory/json/${game}`;
	}

	let response = [];

	return got(URL, gotOptions).then(res => {
		let items;
		let desc;

		try {
			desc = JSON.parse(res.body).rgDescriptions;
			items = JSON.parse(res.body).rgInventory;
		} catch (e) {
			items = [];
			desc = {};
		}

		if (!items) {
			return response;
		}

		Object.keys(items).forEach(key => {
			let temp = items[key];
			let item = desc[`${temp.classid}_${temp.instanceid}`];

			if (!item) {
				return response.push({error: true});
			}

			let data = {
				id: temp.id,
				amount: temp.amount,
				pos: temp.pos,
				name: item.name,
				market_hash_name: item.market_hash_name,
				appid: item.appid,
				classid: item.classid,
				instanceid: item.instanceid,
				tradable: item.tradable,
				marketable: item.marketable,
				marketTradableRestriction: item.market_tradable_restriction,
				link: item.actions ? item.actions[0].link : null,
				image: `http://steamcommunity-a.akamaihd.net/economy/image/${item.icon_url_large || item.icon_url}`,
				category: null,
				type: null,
				exterior: null,
				quality: null,
				raw: item,
			};

			// To match http://steamcommunity.com/market/ filters names
			item.tags.forEach(tag => {
				if (tag.category === 'Type') {
					data.type = tag.name;
				}
				if (tag.category === 'Weapon') {
					data.weapon = tag.name;
				}
				if (tag.category === 'Quality') {
					data.category = tag.name;
				}
				if (tag.category === 'Exterior') {
					data.exterior = tag.name;
				}
			});

			response.push(data);
		});

		return response;
	});
};
<|endoftext|>


<commit_before>var express = require('express');
var db = require('./db');

var app = express();

app.set('port', process.env.PORT || 3000);

app.configure('development', function() {
  app.use(express.static(__dirname + '/assets'));
});

app.use(express.bodyParser());
app.use(express.static(__dirname + '/public'));

app.post('/login', function(req, res, next) {
  db.authenticate(req.body.username, req.body.password, function(code, user) {
    switch (code) {
    case db.authConst.INVALID:
      res.status(401);
      res.send({ error: 'Invalid username or password.' });
      return;
    case db.authConst.LOCKED:
      res.writeHead(466, 'User Is Banned');
      res.end(JSON.stringify({ error: 'The account is temporarily locked ' +
        'due to too many failed login attempts.' }));
      return;
    case db.authConst.BANNED:
      res.writeHead(466, 'User Is Banned');
      res.end(JSON.stringify({ error: 'You are banned by administrators.' }));
      return;
    case db.authConst.SUCCESS:
      res.status(200);
      res.send({
        id: user._id,
        username: user.username,
        token: user.token
      });
      return;
    default:
      res.writeHead(499, 'Unknown Error');
      res.end(JSON.stringify({ error: 'Unknown Error.' }));
      return;
    }
  });
});

app.use(function(req, res, next) {
  req._user_id = null;
  req._user_token = null;
  if (req.headers) {
    req._user_id = req.headers['x-user-id'];
    req._user_token = req.headers['x-user-token'];
  }
  next();
});

function serverUnavailable(res) {
  res.status(500);
  res.send({ error: 'Server unavailable.' });
}

function permissionDenied(res) {
  res.status(403);
  res.send({ error: 'Permission denied.' });
}

function authorize(callback) {
  return function(req, res, next) {
    var user = db.users.findOne({
      _id: req.headers['x-user-id'],
      token: req.headers['x-user-token']
    }).exec(function(error, user) {
      if (error || !user) return permissionDenied(res);
      req.user = user;
      callback(req, res, next);
    });
  };
}

app.get('/accounts', authorize(function(req, res, next) {
  db.accounts.find({}, function(err, account) {
    if (err) return serverUnavailable(res);
    res.status(200);
    res.send(account);
  });
}));

app.post('/accounts', authorize(function(req, res, next) {
  var name = req.body.name;
  var code = req.body.code;
  if (!name || !code) return next();
  var user = req.user;
  db.createAccount(name, code, user, function(err, account) {
    if (err) return serverUnavailable(res);
    restartTimers();
    res.status(201);
    res.send(account);
  });
}));

app.put('/accounts/:account_id', authorize(function(req, res, next) {
  var data = req.body;
  if (!data) return next();
  db.accounts.findOne({ _id: req.params.account_id }, function(err, account) {
    if (err || !account) return next();
    var set = {};
    if (data.hasOwnProperty('code')) {
      if (!data.code) return next();
      set.code = data.code;
    }
    if (data.hasOwnProperty('name')) {
      if (!data.name) return next();
      set.name = data.name;
    }
    if (Object.keys(set).length === 0) return next();
    db.accounts.update({ _id: account._id }, { $set: set }, {}, function(err) {
      if (err) return serverUnavailable(res);
      restartTimers();
      res.status(200);
      res.send({ status: 'ok' });
    });
  });
}));

app.delete('/accounts/:account_id', authorize(function(req, res, next) {
  db.accounts.remove({ _id: req.params.account_id }, {}, function(err) {
    if (err) return serverUnavailable(res);
    restartTimers();
    res.status(200);
    res.send({ status: 'ok' });
  });
}));

var server = require('http').createServer(app);

server.listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

var https = require('https');
var io = require('socket.io').listen(server);

app.configure('production', function() {
  io.disable('browser client');
});

io.configure(function() {
  io.set('authorization', function(handshakeData, callback) {
    var id = handshakeData.query.id;
    var token = handshakeData.query.token;
    if (id && token) {
      db.users.findOne({
        _id: id,
        token: token
      }).exec(function(error, user) {
        if (error) return callback('Error occurred.', false);
        if (!user) return callback(null, false);
        return callback(null, true);
      });
      return;
    }
    callback('Please provide user id and token!', false);
  });
  io.set('log level', 1);
  // 0 - error
  // 1 - warn
  // 2 - info
  // 3 - debug
});

function getData(account, wait) {
  https.get({
    hostname: 'jiaoyi.yunfan.com',
    port: 443,
    path: '/dig/miner/log/',
    headers: {
      Cookie: 'ntts_kb_session_id=' + account.code + ';'
    }
  }, function (res) {
    var data = '';
    res.on('data', function(chunk) {
      data += chunk;
    });
    res.on('end', function() {
      processData(account, data);
      timers[account._id] = setTimeout(function() {
        getData(account);
      }, wait || 5000);
    });
    res.on('error', function() {
      // error
    });
  });
}

function sendData(account, data) {
  var bundle = {};
  bundle[account._id] = data;
  db.accounts.update({ _id: account._id }, { $set: {
    data: JSON.stringify(bundle)
  } }, {}, function() {
    db.accounts.persistence.compactDatafile();
  });
  io.sockets.emit('update', bundle);
}

function processData(account, data) {
  var data = JSON.parse(data);
  if (!data.data.stats) {
    return sendData(account, { error: 'expired' });
  }
  var miners = [];
  for (var i = 0; i < data.data.stats.length; i++) {
    var miner = data.data.stats[i];
    miners.push({
      ip: miner.ip,
      speed: miner.speed,
      total: miner.total_mineral,
      today: miner.today_mineral,
      yesterday: miner.yes_mineral,
      servertime: miner.update_time,
      status: miner.status
    });
  }
  return sendData(account, {
    updated: +new Date,
    miners: miners
  });
}

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function restartTimers() {
  cancelTimers();
  db.accounts.find({}, function(err, accounts) {
    if (err) return;
    for (var i = 0; i < accounts.length; i++) {
      var account = accounts[i];
      getData(account, getRandomInt(0, 5000));
    }
  });
}

io.sockets.on('connection', function(socket) {
  db.accounts.find({}, function(err, accounts) {
    if (err) return;
    for (var i = 0; i < accounts.length; i++) {
      var data = JSON.parse(accounts[i].data);
      socket.emit('update', data);
    }
  });
});

var timers = {};

function cancelTimers() {
  for (var timer in timers) {
    clearTimeout(timers[timer]);
  }
  timers = {};
}

restartTimers();
<commit_msg>pretty date;<commit_after>var express = require('express');
var db = require('./db');

var app = express();

app.set('port', process.env.PORT || 3000);

app.configure('development', function() {
  app.use(express.static(__dirname + '/assets'));
});

app.use(express.bodyParser());
app.use(express.static(__dirname + '/public'));

app.post('/login', function(req, res, next) {
  db.authenticate(req.body.username, req.body.password, function(code, user) {
    switch (code) {
    case db.authConst.INVALID:
      res.status(401);
      res.send({ error: 'Invalid username or password.' });
      return;
    case db.authConst.LOCKED:
      res.writeHead(466, 'User Is Banned');
      res.end(JSON.stringify({ error: 'The account is temporarily locked ' +
        'due to too many failed login attempts.' }));
      return;
    case db.authConst.BANNED:
      res.writeHead(466, 'User Is Banned');
      res.end(JSON.stringify({ error: 'You are banned by administrators.' }));
      return;
    case db.authConst.SUCCESS:
      res.status(200);
      res.send({
        id: user._id,
        username: user.username,
        token: user.token
      });
      return;
    default:
      res.writeHead(499, 'Unknown Error');
      res.end(JSON.stringify({ error: 'Unknown Error.' }));
      return;
    }
  });
});

app.use(function(req, res, next) {
  req._user_id = null;
  req._user_token = null;
  if (req.headers) {
    req._user_id = req.headers['x-user-id'];
    req._user_token = req.headers['x-user-token'];
  }
  next();
});

function serverUnavailable(res) {
  res.status(500);
  res.send({ error: 'Server unavailable.' });
}

function permissionDenied(res) {
  res.status(403);
  res.send({ error: 'Permission denied.' });
}

function authorize(callback) {
  return function(req, res, next) {
    var user = db.users.findOne({
      _id: req.headers['x-user-id'],
      token: req.headers['x-user-token']
    }).exec(function(error, user) {
      if (error || !user) return permissionDenied(res);
      req.user = user;
      callback(req, res, next);
    });
  };
}

app.get('/accounts', authorize(function(req, res, next) {
  db.accounts.find({}, function(err, account) {
    if (err) return serverUnavailable(res);
    res.status(200);
    res.send(account);
  });
}));

app.post('/accounts', authorize(function(req, res, next) {
  var name = req.body.name;
  var code = req.body.code;
  if (!name || !code) return next();
  var user = req.user;
  db.createAccount(name, code, user, function(err, account) {
    if (err) return serverUnavailable(res);
    restartTimers();
    res.status(201);
    res.send(account);
  });
}));

app.put('/accounts/:account_id', authorize(function(req, res, next) {
  var data = req.body;
  if (!data) return next();
  db.accounts.findOne({ _id: req.params.account_id }, function(err, account) {
    if (err || !account) return next();
    var set = {};
    if (data.hasOwnProperty('code')) {
      if (!data.code) return next();
      set.code = data.code;
    }
    if (data.hasOwnProperty('name')) {
      if (!data.name) return next();
      set.name = data.name;
    }
    if (Object.keys(set).length === 0) return next();
    db.accounts.update({ _id: account._id }, { $set: set }, {}, function(err) {
      if (err) return serverUnavailable(res);
      restartTimers();
      res.status(200);
      res.send({ status: 'ok' });
    });
  });
}));

app.delete('/accounts/:account_id', authorize(function(req, res, next) {
  db.accounts.remove({ _id: req.params.account_id }, {}, function(err) {
    if (err) return serverUnavailable(res);
    restartTimers();
    res.status(200);
    res.send({ status: 'ok' });
  });
}));

var server = require('http').createServer(app);

server.listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

var https = require('https');
var io = require('socket.io').listen(server);

app.configure('production', function() {
  io.disable('browser client');
});

io.configure(function() {
  io.set('authorization', function(handshakeData, callback) {
    var id = handshakeData.query.id;
    var token = handshakeData.query.token;
    if (id && token) {
      db.users.findOne({
        _id: id,
        token: token
      }).exec(function(error, user) {
        if (error) return callback('Error occurred.', false);
        if (!user) return callback(null, false);
        return callback(null, true);
      });
      return;
    }
    callback('Please provide user id and token!', false);
  });
  io.set('log level', 1);
  // 0 - error
  // 1 - warn
  // 2 - info
  // 3 - debug
});

function getData(account, wait) {
  https.get({
    hostname: 'jiaoyi.yunfan.com',
    port: 443,
    path: '/dig/miner/log/',
    headers: {
      Cookie: 'ntts_kb_session_id=' + account.code + ';'
    }
  }, function (res) {
    var data = '';
    res.on('data', function(chunk) {
      data += chunk;
    });
    res.on('end', function() {
      processData(account, data);
      timers[account._id] = setTimeout(function() {
        getData(account);
      }, wait || 5000);
    });
    res.on('error', function() {
      // error
    });
  });
}

function sendData(account, data) {
  var bundle = {};
  bundle[account._id] = data;
  db.accounts.update({ _id: account._id }, { $set: {
    data: JSON.stringify(bundle)
  } }, {}, function() {
    db.accounts.persistence.compactDatafile();
  });
  io.sockets.emit('update', bundle);
}

function processData(account, data) {
  var data = JSON.parse(data);
  if (!data.data.stats) {
    return sendData(account, { error: 'expired' });
  }
  var miners = [];
  for (var i = 0; i < data.data.stats.length; i++) {
    var miner = data.data.stats[i];
    var date = (new Date(miner.update_time)).toJSON().split(/[-T:.]/);
    date = date[1] + '-' + date[2] + ' ' + date[3] + ':' + date[4];
    miners.push({
      ip: miner.ip,
      speed: miner.speed,
      total: miner.total_mineral,
      today: miner.today_mineral,
      yesterday: miner.yes_mineral,
      servertime: date,
      status: miner.status
    });
  }
  return sendData(account, {
    updated: +new Date,
    miners: miners
  });
}

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function restartTimers() {
  cancelTimers();
  db.accounts.find({}, function(err, accounts) {
    if (err) return;
    for (var i = 0; i < accounts.length; i++) {
      var account = accounts[i];
      getData(account, getRandomInt(0, 5000));
    }
  });
}

io.sockets.on('connection', function(socket) {
  db.accounts.find({}, function(err, accounts) {
    if (err) return;
    for (var i = 0; i < accounts.length; i++) {
      var data = JSON.parse(accounts[i].data);
      socket.emit('update', data);
    }
  });
});

var timers = {};

function cancelTimers() {
  for (var timer in timers) {
    clearTimeout(timers[timer]);
  }
  timers = {};
}

restartTimers();
<|endoftext|>


<commit_before>/*
 Author: Sergey Batishchev <snb2003@rambler.ru>

 Written for fontello.com project.
 */

'use strict';

var DOMParser = require('xmldom').DOMParser;
var _ = require('lodash');

//main
function svg2ttf(buf, options, callback) {
  callback(null, new Buffer(0)); //just a stub
}

module.exports = svg2ttf;
<commit_msg>TTF tables initialized.<commit_after>/*
 Author: Sergey Batishchev <snb2003@rambler.ru>

 Written for fontello.com project.
 */

'use strict';

var DOMParser = require('xmldom').DOMParser;
var _ = require('lodash');

//------------------------constants--------------------------

//offsets
var TTF_OFFSET = {
  VERSION: 0,
  NUM_TABLES: 4,
  SEARCH_RANGE: 6,
  ENTRY_SELECTOR: 8,
  RANGE_SHIFT: 10,
  TABLES: 12
};

var TABLE_OFFSET = {
  TAG: 0,
  CHECK_SUM: 4,
  OFFSET: 8,
  LENGTH: 12
};

//sizes
var SIZEOF = {
  HEADER: 12,
  TABLE: 16
};

//various constants
var CONST = {
  VERSION: 1,
  NUM_TABLES: 16
}

//--------------------Table data templates-------------------

var CMAPTEMPLATE = {
  VERSION: {name: 'version', value: 0, length: 2},
  COUNT: {name: 'count', value: 1, length: 2},
  PLATFORM: {name: 'platform', value: 3, length: 2}, //windows standard
  ENCODING: {name: 'encoding', value: 1, length: 2}, //unicode
  SUBTABLEOFFSET: {name: 'subTableOffset', value: 12, length: 4},
  //Format 4 subtable
  STFORMAT: {name: 'stFormat', value: 4, length: 2},
  STLENGTH: {name: 'stLength', value: 32, length: 2},
  STVERSION: {name: 'stVersion', value: 0, length: 2},
  STSEGCOUNTX2: {name: 'stSegCountX2', value: 4, length: 2},
  STSEARCHRANGE: {name: 'stSearchRange', value: 4, length: 2},
  STENTRYSELECTOR: {name: 'stEntrySelector', value: 1, length: 2},
  STRANGESHIFT: {name: 'stRangeShift', value: 0, length: 2},
  STENDCOUNTARRAY: {name: 'stEndCountArray', length: 2},
  STRESERVEDPAD: {name: 'reservedPad', value: 0, length: 2},
  STSTARTCOUNTARRARRAY: {name: 'stStartCountArray', length: 2},
  STIDDELTAARRAY: {name: 'stIdDeltaArray', length: 2},
  STIDRANGEOFFSETARRAY: {name: 'stIdRangeOffsetArray', length: 2},
  STGLYPHIDARRAY: {name: 'stGlyphIdArray', length: 2}
}

var GLYFTEMPLATE = {
  GLYPH: {
    name: 'glyph',
    valueTemplate: [
      {
        NUMBEROFCONTOURS: {name: 'numberOfContours', value: 0, length: 2, signed: true},
        XMIN: {name: 'xMin', value: 0, length: 2, signed: true},
        YMIN: {name: 'yMin', value: 0, length: 2, signed: true},
        XMAX: {name: 'xMax', value: 0, length: 2, signed: true},
        YMAX: {name: 'yMax', value: 0, length: 2, signed: true}
      }
    ]
  },
  GLYPHDESCRIPTION: {
    name: 'glyphDescription',
    valueTemplate: [
      {
        ENDPTSOFCONTOURSARRAY: {name: 'endPtsOfContoursArray', length: 2},
        INSTRUCTIONLENGTH: {name: 'instructionLength', value: 0, length: 2},
        INSTRUCTIONSARRAY: {name: 'instructionsArray', length: 1},
        FLAGSARRAY: {name: 'flagsArray', length: 1},
        XCOORDINATESARRAY: {name: 'xCoordinatesArray', length: 1},
        YCOORDINATESARRAY: {name: 'yCoordinatesArray', length: 1}
      }
    ]
  }
}

var HEADTEMPLATE = {
  VERSION: {name: 'version', value: 0x10000, length: 4, signed: true},
  FONTREVISION: {name: 'fontRevision', value: 0, length: 4, signed: true},
  CHECKSUMADJUSTMENT: {name: 'checkSumAdjustment', value: 0, length: 4, signed: true},
  MAGICNUMBER: {name: 'magicNumber', value: 0x5F0F3CF5, length: 4},
  FLAGS: {name: 'flags', value: 0, length: 2},
  UNITSPEREM: {name: 'unitsPerEm', value: 0x200, length: 2},
  CREATED: {name: 'created', value: 0, length: 8},
  MODIFIED: {name: 'modified', value: 0, length: 8},
  XMIN: {name: 'xMin', value: 0, length: 2},
  YMIN: {name: 'yMin', value: 0, length: 2},
  XMAX: {name: 'xMax', value: 0x100, length: 2},
  YMAX: {name: 'yMax', value: 0, length: 2},
  MACSTYLE: {name: 'macStyle', value: 0, length: 2},
  LOWESTRECPPEM: {name: 'lowestRecPPEM', value: 1, length: 2},
  FONTDIRECTIONHINT: {name: 'fontDirectionHint', value: 2, length: 2},
  INDEXTOLOCFORMAT: {name: 'indexToLocFormat', value: 1, length: 2},
  GLYPHDATAFORMAT: {name: 'glyphDataFormat', value: 0, length: 2}
}

var HHEADTEMPLATE = {
  VERSION: {name: 'version', value: 0x10000, length: 4, signed: true},
  Ascender: {name: 'Ascender', value: 0, length: 4, signed: true},
  DESCENDER: {name: 'Descender', value: 0, length: 4, signed: true},
  LINEGAP: {name: 'LineGap', value: 0x5F0F3CF5, length: 4, signed: true},
  ADVANCEWIDTHMAX: {name: 'advanceWidthMax', value: 0, length: 2},
  MINLEFTSIDEBEARING: {name: 'minLeftSideBearing', value: 0x200, length: 2, signed: true},
  MINRIGHTSIDEBEARING: {name: 'minRightSideBearing', value: 0, length: 2, signed: true},
  XMAXEXTENT: {name: 'xMaxExtent', value: 0, length: 2, signed: true},
  CARETSLOPERISE: {name: 'caretSlopeRise', value: 0, length: 2, signed: true},
  CARETSLOPERUN: {name: 'caretSlopeRun', value: 0, length: 2, signed: true},
  RESERVED: {name: 'reserved', value: 0, length: 10},
  METRICDATAFORMAT: {name: 'metricDataFormat', value: 0, length: 2, signed: true},
  NUMBEROFHMETRICS: {name: 'numberOfHMetrics', value: 1, length: 2}
}

var HMTXTEMPLATE = {
  VERSION: {name: 'hMetrics', length: 4, signed: true},
  ASCENDER: {name: 'leftSideBearing', length: 2, signed: true}
}

var LOCATEMPLATE = {
  OFFSETSARRAY: {name: 'offsetsArray', length: 4}
}

var MAXPTEMPLATE = {
  VERSION: {name: 'version', value: 0x10000, length: 4, signed: true},
  NUMGLYPHS: {name: 'numGlyphs', value: 0, length: 2},
  MAXPOINTS: {name: 'maxPoints', value: 1, length: 2},
  MAXCONTOURS: {name: 'maxContours', value: 1, length: 2},
  MAXCOMPOSITEPOINTS: {name: 'maxCompositePoints', value: 0, length: 2},
  MAXCOMPOSITECONTOURS: {name: 'maxCompositeContours', value: 0, length: 2},
  MAXZONES: {name: 'maxZones', value: 2, length: 2},
  MAXTWILIGHTPOINTS: {name: 'maxTwilightPoints', value: 0, length: 2},
  MAXSTORAGE: {name: 'maxStorage', value: 0, length: 2},
  MAXFUNCTIONDEFS: {name: 'maxFunctionDefs', value: 0, length: 2},
  MAXINSTRUCTIONDEFS: {name: 'maxInstructionDefs', value: 0, length: 2},
  MAXSTACKELEMENTS: {name: 'maxStackElements', value: 0, length: 2},
  MAXSIZEOFINSTRUCTIONS: {name: 'maxSizeOfInstructions', value: 0, length: 2},
  MAXCOMPONENTELEMENTS: {name: 'maxComponentElements', value: 0, length: 2},
  MAXCOMPONENTDEPTH: {name: 'maxComponentDepth', value: 0, length: 2}
}

var NAMETEMPLATE = {
  FORMATSELECTOR: {name: 'formatSelector', value: 0, length: 2},
  NAMERECORDSCOUNT: {name: 'nameRecordsCount', value: 0, length: 2},
  OFFSET: {name: 'offset', value: 0, length: 2},
  NAMERECORDSARRAY: {name: 'nameRecordsArray', length: 2},
  ACTUALSTRINGDATA: {name: 'actualStringData', value: 0, length: 2}
}

var POSTTEMPLATE = {
  FORMATTYPE: {name: 'formatType', value: 0x10000, length: 4, signed: true},
  ITALICANGLE: {name: 'italicAngle', length: 4, value: 0, signed: true},
  UNDERLINEPOSITION: {name: 'underlinePosition', length: 4, value: 0, signed: true},
  UNDERLINETHICKNESS: {name: 'underlineThickness', length: 4, value: 0, signed: true},
  ISFIXEDPITCH: {name: 'isFixedPitch', length: 4, value: 0},
  MINMEMTYPE42: {name: 'minMemType42', length: 4, value: 0},
  MAXMEMTYPE42: {name: 'maxMemType42', length: 4, value: 0},
  MINMEMTYPE1: {name: 'minMemType1', length: 4, value: 0},
  MAXMEMTYPE1: {name: 'maxMemType1', length: 4, value: 0}
}

var OS2TEMPLATE = {
  VERSION: {name: 'version', value: 4, length: 2},
  XAVGCHARWIDTH: {name: 'xAvgCharWidth', value: 1, length: 2, signed: true},
  USWEIGHTCLASS: {name: 'usWeightClass', value: 100, length: 2},
  USWIDTHCLASS: {name: 'usWidthClass', value: 1, length: 2},
  FSTYPE: {name: 'fsType', value: 1, length: 2, signed: true},
  YSUBSCRIPTXSIZE: {name: 'ySubscriptXSize', value: 0, length: 2, signed: true},
  YSUBSCRIPTYSIZE: {name: 'ySubscriptYSize', value: 0, length: 2, signed: true},
  YSUBSCRIPTXOFFSET: {name: 'ySubscriptXOffset', value: 0, length: 2, signed: true},
  YSUBSCRIPTYOFFSET: {name: 'ySubscriptYOffset', value: 0, length: 2, signed: true},
  YSUPERSCRIPTXSIZE: {name: 'ySuperscriptXSize', value: 0, length: 2, signed: true},
  YSUPERSCRIPTYSIZE: {name: 'ySuperscriptYSize', value: 0, length: 2, signed: true},
  YSUPERSCRIPTXOFFSET: {name: 'ySuperscriptXOffset', value: 0, length: 2, signed: true},
  YSUPERSCRIPTYOFFSET: {name: 'ySuperscriptYOffset', value: 0, length: 2, signed: true},
  YSTRIKEOUTSIZE: {name: 'yStrikeoutSize', value: 0, length: 2, signed: true},
  YSTRIKEOUTPOSITION: {name: 'yStrikeoutPosition', value: 0, length: 2, signed: true},
  SFAMILYCLASS: {name: 'sFamilyClass', value: 0, length: 2, signed: true},
  PANOSE: {name: 'panose', value: 0, length: 10},
  ULUNICODERANGE1: {name: 'ulUnicodeRange1', value: 0, length: 4},
  ULUNICODERANGE2: {name: 'ulUnicodeRange2', value: 0, length: 4},
  ULUNICODERANGE3: {name: 'ulUnicodeRange3', value: 0, length: 4},
  ULUNICODERANGE4: {name: 'ulUnicodeRange4', value: 0, length: 4},
  ACHVENDID: {name: 'achVendID', value: 0, length: 4},
  FSSELECTION: {name: 'fsSelection', value: 0, length: 2},
  USFIRSTCHARINDEX: {name: 'usFirstCharIndex', value: 0, length: 2},
  USLASTCHARINDEX: {name: 'usLastCharIndex', value: 0, length: 2},
  STYPOASCENDER: {name: 'sTypoAscender', value: 0, length: 2},
  STYPODESCENDER: {name: 'sTypoDescender', value: 0, length: 2},
  STYPOLINEGAP: {name: 'sTypoLineGap', value: 0, length: 2},
  USWINASCENT: {name: 'usWinAscent', value: 256, length: 2},
  USWINDESCENT: {name: 'usWinDescent', value: 0, length: 2},
  ULCODEPAGERANGE1: {name: 'ulCodePageRange1', value: 0, length: 4},
  ULCODEPAGERANGE2: {name: 'ulCodePageRange2', value: 0, length: 4}
}

//--------------------------TTF tables-----------------------

var TTF_TABLES = {
  CMAP: {name: 'cmap', template: CMAPTEMPLATE},
  GLYF: {name: 'glyf', template: GLYFTEMPLATE},
  HEAD: {name: 'head', template: HEADTEMPLATE},
  HHEAD: {name: 'hhea', template: HHEADTEMPLATE},
  HMTX: {name: 'hmtx', template: HMTXTEMPLATE},
  LOCA: {name: 'loca', template: LOCATEMPLATE},
  MAXP: {name: 'maxp', template: MAXPTEMPLATE},
  NAME: {name: 'name', template: NAMETEMPLATE},
  POST: {name: 'post', template: POSTTEMPLATE},
  OS2: {name: 'OS/2', template: OS2TEMPLATE}
}

//------------------table initialization---------------------

function initTableData(dataTemplate) {
  var data = [];
  for (var name in dataTemplate) {
    addValue(data, dataTemplate[name].name, dataTemplate[name].value);
  }
  return data;
}

function createTable(table, doc, offset) {
  return {
    tag: table.name,
    checkSum: 0,
    offset: 0,
    length: 0,
    data: initTableData(table.template)
  }
}

//------------------table value routines------------------------

function addValue(object, name, value) {
  object.push({name: name, value: value});
}

function setValue(object, name, value) {
  for (var elem in object) {
    if (elem.name == name) {
      elem.value = value;
      break;
    }
  }
}

function setArray(object, name, value) {
  for (var elem in object) {
    if (elem.name == name) {
      elem.array = value;
      break;
    }
  }
}

//------------------common routines--------------------------------

function stringToUInt32(value) {
  var result = 0;
  var shift = 0;
  for (var i = 0; i < value.length; ++i) {
    var char = value.charcodeAt(i);
    result += shift * char;
    shift *= 256;
  }
  return result;
}

//------------------serialization to the buffer---------------------

function serialize(tables) {
  //still in comments
  /*  var buf = new Buffer(1000000); //some magic number of bytes
   buf.writeUInt16BE(CONST.VERSION, TTF_OFFSET.VERSION);
   buf.writeUInt16BE(CONST.NUM_TABLES, TTF_OFFSET.NUM_TABLES);
   buf.writeUInt16BE(CONST.NUM_TABLES, TTF_OFFSET.SEARCH_RANGE);
   buf.writeUInt16BE(CONST.NUM_TABLES, TTF_OFFSET.ENTRY_SELECTOR);
   buf.writeUInt16BE(CONST.NUM_TABLES, TTF_OFFSET.RANGE_SHIFT);
   */

  return new Buffer(0); //just a stub
}

//------------------------SVG parsing------------------------------

function getGlyphs(doc) {

  var result = []
    , fontHorizAdvX
    , ascent
    , descent
    , glyphSize = 1000;

  var font = doc.getElementsByTagName('font')[0];
  var fontFace = font.getElementsByTagName('font-face')[0];

  var fontHorizAdvX = +font.getAttribute('horiz-adv-x');
  var ascent = +fontFace.getAttribute('ascent');
  var descent = -fontFace.getAttribute('descent');

  _.each(font.getElementsByTagName('glyph'), function (glyph) {

    // Ignore empty glyphs (with empty code or path)
    if (!glyph.hasAttribute('d')) {
      return;
    }
    if (!glyph.hasAttribute('unicode')) {
      return;
    }

    var d = glyph.getAttribute('d');

    var unicode = glyph.getAttribute('unicode');

    var name = glyph.getAttribute('glyph-name') || ('glyph' + unicode);

    //
    // Rescale & Transform from scg fomt to svg image coordinates
    // !!! Transforms go in back order !!!
    //

    var width = glyph.getAttribute('horiz-adv-x') || fontHorizAdvX;
    var height = ascent + descent;
    var scale = glyphSize / height;

    // vertical mirror
    var transform = 'translate(0 ' + (glyphSize / 2) + ') scale(1 -1) translate(0 ' + (-glyphSize / 2) + ')';

    if (scale !== 1) {
      // scale size, only when needed
      transform += ' scale(' + scale + ')';
      // recalculate width & height
      width = width * scale;
      height = height * scale;
    }
    // descent shift
    transform += ' translate(0 ' + descent + ')';

    result.push({
      d: d,
      transform: transform,
      unicode: unicode,
      name: name,
      width: width,
      height: height
    });
  });

  return result;
}

//main
function svg2ttf(buf, options, callback) {
  var doc = (new DOMParser()).parseFromString(buf, "application/xml");
  var glyphs = getGlyphs(doc);
  var tables = {};
  var offset = TTF_OFFSET.TABLES;
  for (var tableTemplate in TTF_TABLES) {
    tables[tableTemplate] = createTable(TTF_TABLES[tableTemplate]);
  }
  setGlyphs(doc, tables, glyphs);
  callback(null, serialize(tables));
}

function setGlyphs(doc, tables, glyphs) {
  var glyphTable = tables.GLYF;

}

module.exports = svg2ttf;
<|endoftext|>


<commit_before>/**
 * PixelNode_Input_MPR121
 *
 * Inputs from Adafruits MPR121 touch sensor via a python subprocess.
 *
 * --------------------------------------------------------------------------------------------------------------------
 *
 * @author Amely Kling <mail@dwi.sk>
 *
 */

/* Includes
 * ==================================================================================================================== */

var util = require("util");
var _ = require('underscore');
var MPR121 = require('mpr121');

/* Class Constructor
 * ==================================================================================================================== */

// extending Effect
PixelNode_Input = require('pixelnode-input');

// define the Student class
function PixelNode_Input_MPR121(options,pixelData) {
  var self = this;
  PixelNode_Input_MPR121.super_.call(self, options, pixelData);
  this.className = "PixelNode_Input_MPR121";
}

// class inheritance
util.inherits(PixelNode_Input_MPR121, PixelNode_Input);

// module export
module.exports = PixelNode_Input_MPR121;

/* Variables
 * ==================================================================================================================== */

PixelNode_Input_MPR121.prototype.default_options = {
	"i2c_bus": 2,
	"i2c_address": 0x5A,
	"offset": 0,
	"verbose": false,
	"timer": 100
};
PixelNode_Input_MPR121.prototype.touchsensor = null;

var lastPins = [];

/* Overridden Methods
 * ==================================================================================================================== */

// init effect – override
PixelNode_Input_MPR121.prototype.init = function() {
	var self = this;

	// start
	console.log("Init Input MPR121".grey);

	// init input values
	var init_inputs = {};
	init_inputs["touches"] = [
		false,
		false,
		false,
		false,
		false,
		false,
		false,
		false,
		false,
		false,
		false,
		false
	];

	// init pixelNode data
	global.pixelNode.data.extend(["inputs",self.options.name], init_inputs);

	// start effect
	self.start(function(result) {
		// do offset
		if (self.options.offset != 0) {
			var segment1 = result.slice(self.options.offset);
			var segment2 = result.slice(0,self.options.offset);
			pins = segment1.concat(segment2);
		} else {
			pins = result;
		}

		// check if touch-point changes
		for (var i = pins.length - 1; i >= 0; i--) {
			if (pins[i] != lastPins[i]) {
				lastPins[i] = pins[i];
				global.pixelNode.data.set(["inputs", self.options.name, "touches", i], pins[i], !self.options.verbose);
			}
		}
	});
}

/* Methods
 * ==================================================================================================================== */

// start python listener
PixelNode_Input_MPR121.prototype.start = function(callback) {
	var self = this;
	var last_result = [0,0,0,0,0,0,0,0,0,0,0,0];

 	// setup sensor device
 	self.touchsensor = new MPR121(self.options.i2c_address, self.options.i2c_bus);

 	// initialize sensor, on success start script
 	if (self.touchsensor.begin()) {
 		self.touchsensor.set_thresholds(60, 30);

 		// Interval for reading the sonsor
 		setInterval(function() {

 			// check if config is correct, otherwise send last_result
 			// probably the i2c-bus got switched
 			if (self.touchsensor.config() != 32) {
 				callback(last_result);

 			// get data
 			} else {
	 			// get touch values
	 			var t = self.touchsensor.touched();

	 			// prepare some result array
	 			var ret = [];

	 			// loop through pins
	 			for (var i = 0; i < 12; i++) {
	 				// push status into array
	 				ret.push ((t & (1 << i)) > 0);
	 				//ret.push (self.touchsensor.is_touched(i));
	 			}

	 			// return status array
				callback(ret);

				// remember last result
				last_result = ret;
			}
 		}, self.options.timer);
 	};

}
<commit_msg>Tresholds and pincount in options<commit_after>/**
 * PixelNode_Input_MPR121
 *
 * Inputs from Adafruits MPR121 touch sensor via a python subprocess.
 *
 * --------------------------------------------------------------------------------------------------------------------
 *
 * @author Amely Kling <mail@dwi.sk>
 *
 */

/* Includes
 * ==================================================================================================================== */

var util = require("util");
var _ = require('underscore');
var MPR121 = require('mpr121');

/* Class Constructor
 * ==================================================================================================================== */

// extending Effect
PixelNode_Input = require('pixelnode-input');

// define the Student class
function PixelNode_Input_MPR121(options,pixelData) {
  var self = this;
  PixelNode_Input_MPR121.super_.call(self, options, pixelData);
  this.className = "PixelNode_Input_MPR121";
}

// class inheritance
util.inherits(PixelNode_Input_MPR121, PixelNode_Input);

// module export
module.exports = PixelNode_Input_MPR121;

/* Variables
 * ==================================================================================================================== */

PixelNode_Input_MPR121.prototype.default_options = {
	"i2c_bus": 2,
	"i2c_address": 0x5A,
	"offset": 0,
	"verbose": false,
	"timer": 100,
	"treshold_touch": 12,
	"treshold_release": 6,
	"pincount": 12
};
PixelNode_Input_MPR121.prototype.touchsensor = null;

var lastPins = [];

/* Overridden Methods
 * ==================================================================================================================== */

// init effect – override
PixelNode_Input_MPR121.prototype.init = function() {
	var self = this;

	// start
	console.log("Init Input MPR121".grey);

	// init input values
	var init_inputs = {};
	init_inputs["touches"] = [];
	for (var i = 0; i < self.options.pincount; i++) {
		init_inputs["touches"][i] = false;
	};

	// init pixelNode data
	global.pixelNode.data.extend(["inputs",self.options.name], init_inputs);

	// start effect
	self.start(function(result) {
		// do offset
		if (self.options.offset != 0) {
			var segment1 = result.slice(self.options.offset);
			var segment2 = result.slice(0,self.options.offset);
			pins = segment1.concat(segment2);
		} else {
			pins = result;
		}

		// check if touch-point changes
		for (var i = pins.length - 1; i >= 0; i--) {
			if (pins[i] != lastPins[i]) {
				lastPins[i] = pins[i];
				global.pixelNode.data.set(["inputs", self.options.name, "touches", i], pins[i], !self.options.verbose);
			}
		}
	});
}

/* Methods
 * ==================================================================================================================== */

// start python listener
PixelNode_Input_MPR121.prototype.start = function(callback) {
	var self = this;
	var last_result = [];
	for (var i = 0; i < self.options.pincount; i++) {
		last_result[i] = false;
	};

 	// setup sensor device
 	self.touchsensor = new MPR121(self.options.i2c_address, self.options.i2c_bus);

 	// initialize sensor, on success start script
 	if (self.touchsensor.begin()) {
 		self.touchsensor.set_thresholds(self.options.treshold_touch, self.options.treshold_release);

 		// Interval for reading the sonsor
 		setInterval(function() {

 			// check if config is correct, otherwise send last_result
 			// probably the i2c-bus got switched
 			if (self.touchsensor.config() != 32) {
 				callback(last_result);

 			// get data
 			} else {
	 			// get touch values
	 			var t = self.touchsensor.touched();

	 			// prepare some result array
	 			var ret = [];

	 			// loop through pins
	 			for (var i = 0; i < self.options.pincount; i++) {
	 				// push status into array
	 				ret.push ((t & (1 << i)) > 0);
	 				//ret.push (self.touchsensor.is_touched(i));
	 			}

	 			// return status array
				callback(ret);

				// remember last result
				last_result = ret;
			}
 		}, self.options.timer);
 	};

}
<|endoftext|>


<commit_before>var transparent = require('opaque').transparent;

function Texture(opts) {
  var self = this;
  if (!(this instanceof Texture)) return new Texture(opts || {});
  this.THREE              = opts.THREE          || require('three');
  this.materials          = [];
  this.texturePath        = opts.texturePath    || '/textures/';
  this.materialParams     = opts.materialParams || {};
  this.materialType       = opts.materialType   || this.THREE.MeshLambertMaterial;
  this.materialIndex      = [];
  this._materialDefaults  = { ambient: 0xbbbbbb };
  this.applyTextureParams = opts.applyTextureParams || function(map) {
    map.magFilter = self.THREE.NearestFilter;
    map.minFilter = self.THREE.LinearMipMapLinearFilter;
    map.wrapT     = self.THREE.RepeatWrapping;
    map.wrapS     = self.THREE.RepeatWrapping;
  }
}
module.exports = Texture;

Texture.prototype.load = function(names, opts) {
  var self = this;
  opts = self._options(opts);
  if (!isArray(names)) names = [names];
  if (!hasSubArray(names)) names = [names];
  return [].concat.apply([], names.map(function(name) {
    name = self._expandName(name);
    self.materialIndex.push([self.materials.length, self.materials.length + name.length]);
    return name.map(function(n) {
      if (n instanceof self.THREE.Texture) {
        var map = n;
        n = n.name;
      } else if (typeof n === 'string') {
        var map = self.THREE.ImageUtils.loadTexture(self.texturePath + ext(n));
      } else {
        var map = new self.THREE.Texture(n);
        n = map.name;
      }
      self.applyTextureParams.call(self, map);
      var mat = new opts.materialType(opts.materialParams);
      mat.map = map;
      mat.name = n;
      if (opts.transparent == null) self._isTransparent(mat);
      self.materials.push(mat);
      return mat;
    });
  }));
};

Texture.prototype.get = function(index) {
  if (index == null) return this.materials;
  if (typeof index === 'number') {
    index = this.materialIndex[index];
  } else {
    for (var i = 0; i < this.materials.length; i++) {
      if (index === this.materials[i].name) {
        index = i;
        break;
      }
    }
    for (var i = 0; i < this.materialIndex.length; i++) {
      var idx = this.materialIndex[i];
      if (index >= idx[0] && index < idx[1]) {
        index = idx;
        break;
      }
    }
  }
  return this.materials.slice(index[0], index[1]);
};

Texture.prototype._expandName = function(name) {
  if (name.top) return [name.back, name.front, name.top, name.bottom, name.left, name.right];
  if (!isArray(name)) name = [name];
  // load the 0 texture to all
  if (name.length === 1) name = [name[0],name[0],name[0],name[0],name[0],name[0]];
  // 0 is top/bottom, 1 is sides
  if (name.length === 2) name = [name[1],name[1],name[0],name[0],name[1],name[1]];
  // 0 is top, 1 is bottom, 2 is sides
  if (name.length === 3) name = [name[2],name[2],name[0],name[1],name[2],name[2]];
  // 0 is top, 1 is bottom, 2 is front/back, 3 is left/right
  if (name.length === 4) name = [name[2],name[2],name[0],name[1],name[3],name[3]];
  return name;
};

Texture.prototype._options = function(opts) {
  opts = opts || {};
  opts.materialType = opts.materialType || this.materialType;
  opts.materialParams = defaults(opts.materialParams || {}, this._materialDefaults, this.materialParams);
  opts.applyTextureParams = opts.applyTextureParams || this.applyTextureParams;
  return opts;
};

Texture.prototype.paint = function(geom) {
  var self = this;
  geom.faces.forEach(function(face, i) {
    var c = face.vertexColors[0];
    var index = self.materialIndex[Math.floor(c.b*255 + c.g*255*255 + c.r*255*255*255) - 1][0];
    // BACK, FRONT, TOP, BOTTOM, LEFT, RIGHT
    if      (face.normal.z === 1)  index += 1;
    else if (face.normal.y === 1)  index += 2;
    else if (face.normal.y === -1) index += 3;
    else if (face.normal.x === -1) index += 4;
    else if (face.normal.x === 1)  index += 5;
    face.materialIndex = index;
  });
};

Texture.prototype.sprite = function(name, w, h, cb) {
  var self = this;
  if (typeof w === 'function') { cb = w; w = null; }
  if (typeof h === 'function') { cb = h; h = null; }
  w = w || 16; h = h || w;
  var img = new Image();
  img.src = self.texturePath + ext(name);
  img.onerror = cb;
  img.onload = function() {
    var textures = [];
    for (var x = 0; x < img.width; x += w) {
      for (var y = 0; y < img.height; y += h) {
        var canvas = document.createElement('canvas');
        canvas.width = w; canvas.height = h;
        var ctx = canvas.getContext('2d');
        ctx.drawImage(img, x, y, w, h, 0, 0, w, h);
        var tex = new self.THREE.Texture(canvas);
        tex.name = name + '_' + x + '_' + y;
        tex.needsUpdate = true;
        textures.push(tex);
      }
    }
    cb(null, textures);
  };
  return self;
};

Texture.prototype._isTransparent = function(material) {
  if (!material.map) return;
  if (!material.map.image) return;
  if (material.map.image.nodeName.toLowerCase() === 'img') {
    material.map.image.onload = function() {
      if (transparent(this)) {
        material.transparent = true;
        material.needsUpdate = true;
      }
    };
  } else {
    if (transparent(material.map.image)) {
      material.transparent = true;
      material.needsUpdate = true;
    }
  }
};

function ext(name) {
  return (String(name).indexOf('.') !== -1) ? name : name + '.png';
}

// copied from https://github.com/joyent/node/blob/master/lib/util.js#L433
function isArray(ar) {
  return Array.isArray(ar) || (typeof ar === 'object' && Object.prototype.toString.call(ar) === '[object Array]');
}

function hasSubArray(ar) {
  var has = false;
  ar.forEach(function(a) { if (isArray(a)) { has = true; return false; } });
  return has;
}

function defaults(obj) {
  [].slice.call(arguments, 1).forEach(function(from) {
    if (from) for (var k in from) if (obj[k] == null) obj[k] = from[k];
  });
  return obj;
}
<commit_msg>Fix for paint and force publish, whoops :)<commit_after>var transparent = require('opaque').transparent;

function Texture(opts) {
  var self = this;
  if (!(this instanceof Texture)) return new Texture(opts || {});
  this.THREE              = opts.THREE          || require('three');
  this.materials          = [];
  this.texturePath        = opts.texturePath    || '/textures/';
  this.materialParams     = opts.materialParams || {};
  this.materialType       = opts.materialType   || this.THREE.MeshLambertMaterial;
  this.materialIndex      = [];
  this._materialDefaults  = { ambient: 0xbbbbbb };
  this.applyTextureParams = opts.applyTextureParams || function(map) {
    map.magFilter = self.THREE.NearestFilter;
    map.minFilter = self.THREE.LinearMipMapLinearFilter;
    map.wrapT     = self.THREE.RepeatWrapping;
    map.wrapS     = self.THREE.RepeatWrapping;
  }
}
module.exports = Texture;

Texture.prototype.load = function(names, opts) {
  var self = this;
  opts = self._options(opts);
  if (!isArray(names)) names = [names];
  if (!hasSubArray(names)) names = [names];
  return [].concat.apply([], names.map(function(name) {
    name = self._expandName(name);
    self.materialIndex.push([self.materials.length, self.materials.length + name.length]);
    return name.map(function(n) {
      if (n instanceof self.THREE.Texture) {
        var map = n;
        n = n.name;
      } else if (typeof n === 'string') {
        var map = self.THREE.ImageUtils.loadTexture(self.texturePath + ext(n));
      } else {
        var map = new self.THREE.Texture(n);
        n = map.name;
      }
      self.applyTextureParams.call(self, map);
      var mat = new opts.materialType(opts.materialParams);
      mat.map = map;
      mat.name = n;
      if (opts.transparent == null) self._isTransparent(mat);
      self.materials.push(mat);
      return mat;
    });
  }));
};

Texture.prototype.get = function(index) {
  if (index == null) return this.materials;
  if (typeof index === 'number') {
    index = this.materialIndex[index];
  } else {
    for (var i = 0; i < this.materials.length; i++) {
      if (index === this.materials[i].name) {
        index = i;
        break;
      }
    }
    for (var i = 0; i < this.materialIndex.length; i++) {
      var idx = this.materialIndex[i];
      if (index >= idx[0] && index < idx[1]) {
        index = idx;
        break;
      }
    }
  }
  return this.materials.slice(index[0], index[1]);
};

Texture.prototype._expandName = function(name) {
  if (name.top) return [name.back, name.front, name.top, name.bottom, name.left, name.right];
  if (!isArray(name)) name = [name];
  // load the 0 texture to all
  if (name.length === 1) name = [name[0],name[0],name[0],name[0],name[0],name[0]];
  // 0 is top/bottom, 1 is sides
  if (name.length === 2) name = [name[1],name[1],name[0],name[0],name[1],name[1]];
  // 0 is top, 1 is bottom, 2 is sides
  if (name.length === 3) name = [name[2],name[2],name[0],name[1],name[2],name[2]];
  // 0 is top, 1 is bottom, 2 is front/back, 3 is left/right
  if (name.length === 4) name = [name[2],name[2],name[0],name[1],name[3],name[3]];
  return name;
};

Texture.prototype._options = function(opts) {
  opts = opts || {};
  opts.materialType = opts.materialType || this.materialType;
  opts.materialParams = defaults(opts.materialParams || {}, this._materialDefaults, this.materialParams);
  opts.applyTextureParams = opts.applyTextureParams || this.applyTextureParams;
  return opts;
};

Texture.prototype.paint = function(geom) {
  var self = this;
  geom.faces.forEach(function(face, i) {
    var c = face.vertexColors[0];
    var index = Math.floor(c.b*255 + c.g*255*255 + c.r*255*255*255);
    index = self.materialIndex[Math.floor(Math.max(0, index - 1) % self.materialIndex.length)][0];

    // BACK, FRONT, TOP, BOTTOM, LEFT, RIGHT
    if      (face.normal.z === 1)  index += 1;
    else if (face.normal.y === 1)  index += 2;
    else if (face.normal.y === -1) index += 3;
    else if (face.normal.x === -1) index += 4;
    else if (face.normal.x === 1)  index += 5;

    face.materialIndex = index;
  });
};

Texture.prototype.sprite = function(name, w, h, cb) {
  var self = this;
  if (typeof w === 'function') { cb = w; w = null; }
  if (typeof h === 'function') { cb = h; h = null; }
  w = w || 16; h = h || w;
  var img = new Image();
  img.src = self.texturePath + ext(name);
  img.onerror = cb;
  img.onload = function() {
    var textures = [];
    for (var x = 0; x < img.width; x += w) {
      for (var y = 0; y < img.height; y += h) {
        var canvas = document.createElement('canvas');
        canvas.width = w; canvas.height = h;
        var ctx = canvas.getContext('2d');
        ctx.drawImage(img, x, y, w, h, 0, 0, w, h);
        var tex = new self.THREE.Texture(canvas);
        tex.name = name + '_' + x + '_' + y;
        tex.needsUpdate = true;
        textures.push(tex);
      }
    }
    cb(null, textures);
  };
  return self;
};

Texture.prototype._isTransparent = function(material) {
  if (!material.map) return;
  if (!material.map.image) return;
  if (material.map.image.nodeName.toLowerCase() === 'img') {
    material.map.image.onload = function() {
      if (transparent(this)) {
        material.transparent = true;
        material.needsUpdate = true;
      }
    };
  } else {
    if (transparent(material.map.image)) {
      material.transparent = true;
      material.needsUpdate = true;
    }
  }
};

function ext(name) {
  return (String(name).indexOf('.') !== -1) ? name : name + '.png';
}

// copied from https://github.com/joyent/node/blob/master/lib/util.js#L433
function isArray(ar) {
  return Array.isArray(ar) || (typeof ar === 'object' && Object.prototype.toString.call(ar) === '[object Array]');
}

function hasSubArray(ar) {
  var has = false;
  ar.forEach(function(a) { if (isArray(a)) { has = true; return false; } });
  return has;
}

function defaults(obj) {
  [].slice.call(arguments, 1).forEach(function(from) {
    if (from) for (var k in from) if (obj[k] == null) obj[k] = from[k];
  });
  return obj;
}
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const utils = require('./utils');
const _getStartAndEndCommands = require('boilerplate-update/src/get-start-and-end-commands');

module.exports = function getStartAndEndCommands({
  projectName,
  projectType,
  startVersion,
  endVersion
}) {
  let options = `${projectName} -sn -sg`;

  let command;
  switch (projectType) {
    case 'app':
      command = `new ${options}`;
      break;
    case 'addon':
      command = `addon ${options}`;
      break;
    case 'glimmer':
      // command = `new ${projectName} -b @glimmer/blueprint`;
      // break;
      // ember-cli doesn't have a way to use non-latest blueprint versions
      throw 'cannot checkout older versions of glimmer blueprint';
  }

  return _getStartAndEndCommands({
    projectName,
    projectType,
    packageName: 'ember-cli',
    commandName: 'ember',
    createProjectFromCache: createProjectFromCache(command),
    createProjectFromRemote: createProjectFromRemote(command),
    startOptions: {
      packageVersion: startVersion
    },
    endOptions: {
      packageVersion: endVersion
    }
  });
};

function createProjectFromCache(command) {
  return function createProjectFromCache({
    packageRoot,
    options
  }) {
    return function createProject(cwd) {
      utils.run(`node ${path.join(packageRoot, 'bin/ember')} ${command}`, { cwd });

      return postCreateProject({
        cwd,
        options
      });
    };
  };
}

function createProjectFromRemote(command) {
  return function createProjectFromRemote({
    options
  }) {
    return function createProject(cwd) {
      return utils.npx(`-p ember-cli@${options.packageVersion} ember ${command}`, { cwd }).then(() => {
        return postCreateProject({
          cwd,
          options
        });
      });
    };
  };
}

function postCreateProject({
  cwd,
  options: {
    projectName
  }
}) {
  return Promise.resolve(path.join(cwd, projectName));
}
<commit_msg>Revert "options refactor"<commit_after>'use strict';

const path = require('path');
const utils = require('./utils');
const _getStartAndEndCommands = require('boilerplate-update/src/get-start-and-end-commands');

module.exports = function getStartAndEndCommands({
  projectName,
  projectType,
  startVersion,
  endVersion
}) {
  let options = '-sn -sg';

  let command;
  switch (projectType) {
    case 'app':
      command = `new ${projectName} ${options}`;
      break;
    case 'addon':
      command = `addon ${projectName} ${options}`;
      break;
    case 'glimmer':
      // command = `new ${projectName} -b @glimmer/blueprint`;
      // break;
      // ember-cli doesn't have a way to use non-latest blueprint versions
      throw 'cannot checkout older versions of glimmer blueprint';
  }

  return _getStartAndEndCommands({
    projectName,
    projectType,
    packageName: 'ember-cli',
    commandName: 'ember',
    createProjectFromCache: createProjectFromCache(command),
    createProjectFromRemote: createProjectFromRemote(command),
    startOptions: {
      packageVersion: startVersion
    },
    endOptions: {
      packageVersion: endVersion
    }
  });
};

function createProjectFromCache(command) {
  return function createProjectFromCache({
    packageRoot,
    options
  }) {
    return function createProject(cwd) {
      utils.run(`node ${path.join(packageRoot, 'bin/ember')} ${command}`, { cwd });

      return postCreateProject({
        cwd,
        options
      });
    };
  };
}

function createProjectFromRemote(command) {
  return function createProjectFromRemote({
    options
  }) {
    return function createProject(cwd) {
      return utils.npx(`-p ember-cli@${options.packageVersion} ember ${command}`, { cwd }).then(() => {
        return postCreateProject({
          cwd,
          options
        });
      });
    };
  };
}

function postCreateProject({
  cwd,
  options: {
    projectName
  }
}) {
  return Promise.resolve(path.join(cwd, projectName));
}
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var Base = require('mocha').reporters.Base, util = require('util'), notify = require('osx-notifier');

/**
 * Expose `OSXReporter`.
 */

exports = module.exports = OSXReporter;

/**
 * Initialize a new `OSXReporter` test reporter.
 *
 * @param {Runner} runner
 * @api public
 */
function OSXReporter (runner) {
  Base.call(this, runner);

  var self = this;

  runner.on('end', function () {
    var title, message, stats = self.stats, type = stats.failures ? 'fail' : 'pass';
    title = util.format('%d passed, %d failed, %d pending', stats.passes, stats.failures, stats.pending);
    message = util.format('Duration: %dms, Tests: %d', stats.duration, stats.passes + stats.failures + stats.pending);
    notify({ type: type, title: 'Test results', subtitle: title, message: message, group: 'mocha' });
    self.epilogue.call(self);
  });
}

OSXReporter.prototype.__proto__ = Base.prototype;

if (process.platform !== 'darwin') {
  // overwrite reporter with void function for non-OSX
  OSXReporter = function (runner) {}
}
<commit_msg>Remove epilogue call<commit_after>/**
 * Module dependencies.
 */

var Base = require('mocha').reporters.Base, util = require('util'), notify = require('osx-notifier');

/**
 * Expose `OSXReporter`.
 */

exports = module.exports = OSXReporter;

/**
 * Initialize a new `OSXReporter` test reporter.
 *
 * @param {Runner} runner
 * @api public
 */
function OSXReporter (runner) {
  Base.call(this, runner);

  var self = this;

  runner.on('end', function () {
    var title, message, stats = self.stats, type = stats.failures ? 'fail' : 'pass';
    title = util.format('%d passed, %d failed, %d pending', stats.passes, stats.failures, stats.pending);
    message = util.format('Duration: %dms, Tests: %d', stats.duration, stats.passes + stats.failures + stats.pending);
    notify({ type: type, title: 'Test results', subtitle: title, message: message, group: 'mocha' });
  });
}

OSXReporter.prototype.__proto__ = Base.prototype;

if (process.platform !== 'darwin') {
  // overwrite reporter with void function for non-OSX
  OSXReporter = function (runner) {}
}
<|endoftext|>


<commit_before>exports.render = render
exports.append = append
exports.mime = require('./lib/mime.json')

var debug = require('debug')('render-media')
var isAscii = require('is-ascii')
var MediaElementWrapper = require('mediasource')
var path = require('path')
var streamToBlobURL = require('stream-to-blob-url')
var videostream = require('videostream')

var VIDEOSTREAM_EXTS = [
  '.m4a',
  '.m4v',
  '.mp4'
]

var MEDIASOURCE_VIDEO_EXTS = [
  '.m4v',
  '.mkv',
  '.mp4',
  '.webm'
]

var MEDIASOURCE_AUDIO_EXTS = [
  '.m4a',
  '.mp3'
]

var MEDIASOURCE_EXTS = [].concat(
  MEDIASOURCE_VIDEO_EXTS,
  MEDIASOURCE_AUDIO_EXTS
)

var AUDIO_EXTS = [
  '.aac',
  '.oga',
  '.ogg',
  '.wav'
]

var IMAGE_EXTS = [
  '.bmp',
  '.gif',
  '.jpeg',
  '.jpg',
  '.png',
  '.svg'
]

var IFRAME_EXTS = [
  '.css',
  '.html',
  '.js',
  '.md',
  '.pdf',
  '.txt'
]

// Maximum file length for which the Blob URL strategy will be attempted
// See: https://github.com/feross/render-media/issues/18
var MAX_BLOB_LENGTH = 200 * 1000 * 1000 // 200 MB

var MediaSource = typeof window !== 'undefined' && window.MediaSource

function render (file, elem, opts, cb) {
  if (typeof opts === 'function') {
    cb = opts
    opts = {}
  }
  if (!opts) opts = {}
  if (!cb) cb = function () {}

  validateFile(file)
  parseOpts(opts)

  if (typeof elem === 'string') elem = document.querySelector(elem)

  renderMedia(file, function (tagName) {
    if (elem.nodeName !== tagName.toUpperCase()) {
      var extname = path.extname(file.name).toLowerCase()

      throw new Error(
        'Cannot render "' + extname + '" inside a "' +
        elem.nodeName.toLowerCase() + '" element, expected "' + tagName + '"'
      )
    }

    return elem
  }, opts, cb)
}

function append (file, rootElem, opts, cb) {
  if (typeof opts === 'function') {
    cb = opts
    opts = {}
  }
  if (!opts) opts = {}
  if (!cb) cb = function () {}

  validateFile(file)
  parseOpts(opts)

  if (typeof rootElem === 'string') rootElem = document.querySelector(rootElem)

  if (rootElem && (rootElem.nodeName === 'VIDEO' || rootElem.nodeName === 'AUDIO')) {
    throw new Error(
      'Invalid video/audio node argument. Argument must be root element that ' +
      'video/audio tag will be appended to.'
    )
  }

  renderMedia(file, getElem, opts, done)

  function getElem (tagName) {
    if (tagName === 'video' || tagName === 'audio') return createMedia(tagName)
    else return createElem(tagName)
  }

  function createMedia (tagName) {
    var elem = createElem(tagName)
    if (opts.controls) elem.controls = true
    if (opts.autoplay) elem.autoplay = true
    rootElem.appendChild(elem)
    return elem
  }

  function createElem (tagName) {
    var elem = document.createElement(tagName)
    rootElem.appendChild(elem)
    return elem
  }

  function done (err, elem) {
    if (err && elem) elem.remove()
    cb(err, elem)
  }
}

function renderMedia (file, getElem, opts, cb) {
  var extname = path.extname(file.name).toLowerCase()
  var currentTime = 0
  var elem

  if (MEDIASOURCE_EXTS.indexOf(extname) >= 0) {
    renderMediaSource()
  } else if (AUDIO_EXTS.indexOf(extname) >= 0) {
    renderAudio()
  } else if (IMAGE_EXTS.indexOf(extname) >= 0) {
    renderImage()
  } else if (IFRAME_EXTS.indexOf(extname) >= 0) {
    renderIframe()
  } else {
    tryRenderIframe()
  }

  function renderMediaSource () {
    var tagName = MEDIASOURCE_VIDEO_EXTS.indexOf(extname) >= 0 ? 'video' : 'audio'

    if (MediaSource) {
      if (VIDEOSTREAM_EXTS.indexOf(extname) >= 0) {
        useVideostream()
      } else {
        useMediaSource()
      }
    } else {
      useBlobURL()
    }

    function useVideostream () {
      debug('Use `videostream` package for ' + file.name)
      prepareElem()
      elem.addEventListener('error', fallbackToMediaSource)
      elem.addEventListener('loadstart', onLoadStart)
      elem.addEventListener('canplay', onCanPlay)
      videostream(file, elem)
    }

    function useMediaSource () {
      debug('Use MediaSource API for ' + file.name)
      prepareElem()
      elem.addEventListener('error', fallbackToBlobURL)
      elem.addEventListener('loadstart', onLoadStart)
      elem.addEventListener('canplay', onCanPlay)

      var wrapper = new MediaElementWrapper(elem)
      var writable = wrapper.createWriteStream(getCodec(file.name))
      file.createReadStream().pipe(writable)

      if (currentTime) elem.currentTime = currentTime
    }

    function useBlobURL () {
      debug('Use Blob URL for ' + file.name)
      prepareElem()
      elem.addEventListener('error', fatalError)
      elem.addEventListener('loadstart', onLoadStart)
      elem.addEventListener('canplay', onCanPlay)
      getBlobURL(file, function (err, url) {
        if (err) return fatalError(err)
        elem.src = url
        if (currentTime) elem.currentTime = currentTime
      })
    }

    function fallbackToMediaSource (err) {
      debug('videostream error: fallback to MediaSource API: %o', err.message || err)
      elem.removeEventListener('error', fallbackToMediaSource)
      elem.removeEventListener('canplay', onCanPlay)

      useMediaSource()
    }

    function fallbackToBlobURL (err) {
      debug('MediaSource API error: fallback to Blob URL: %o', err.message || err)

      if (typeof file.length === 'number' && file.length > opts.maxBlobLength) {
        debug(
          'File length too large for Blob URL approach: %d (max: %d)',
          file.length, opts.maxBlobLength
        )
        return fatalError(new Error(
          'File length too large for Blob URL approach: ' + file.length +
          ' (max: ' + opts.maxBlobLength + ')'
        ))
      }

      elem.removeEventListener('error', fallbackToBlobURL)
      elem.removeEventListener('canplay', onCanPlay)

      useBlobURL()
    }

    function prepareElem () {
      if (!elem) {
        elem = getElem(tagName)

        elem.addEventListener('progress', function () {
          currentTime = elem.currentTime
        })
      }
    }
  }

  function renderAudio () {
    elem = getElem('audio')
    getBlobURL(file, function (err, url) {
      if (err) return fatalError(err)
      elem.addEventListener('error', fatalError)
      elem.addEventListener('loadstart', onLoadStart)
      elem.addEventListener('canplay', onCanPlay)
      elem.src = url
    })
  }

  function onLoadStart () {
    elem.removeEventListener('loadstart', onLoadStart)
    if (opts.autoplay) elem.play()
  }

  function onCanPlay () {
    elem.removeEventListener('canplay', onCanPlay)
    cb(null, elem)
  }

  function renderImage () {
    elem = getElem('img')
    getBlobURL(file, function (err, url) {
      if (err) return fatalError(err)
      elem.src = url
      elem.alt = file.name
      cb(null, elem)
    })
  }

  function renderIframe () {
    elem = getElem('iframe')

    getBlobURL(file, function (err, url) {
      if (err) return fatalError(err)
      elem.src = url
      if (extname !== '.pdf') elem.sandbox = 'allow-forms allow-scripts'
      cb(null, elem)
    })
  }

  function tryRenderIframe () {
    debug('Unknown file extension "%s" - will attempt to render into iframe', extname)

    var str = ''
    file.createReadStream({ start: 0, end: 1000 })
      .setEncoding('utf8')
      .on('data', function (chunk) {
        str += chunk
      })
      .on('end', done)
      .on('error', cb)

    function done () {
      if (isAscii(str)) {
        debug('File extension "%s" appears ascii, so will render.', extname)
        renderIframe()
      } else {
        debug('File extension "%s" appears non-ascii, will not render.', extname)
        cb(new Error('Unsupported file type "' + extname + '": Cannot append to DOM'))
      }
    }
  }

  function fatalError (err) {
    err.message = 'Error rendering file "' + file.name + '": ' + err.message
    debug(err.message)
    cb(err)
  }
}

function getBlobURL (file, cb) {
  var extname = path.extname(file.name).toLowerCase()
  streamToBlobURL(file.createReadStream(), exports.mime[extname], cb)
}

function validateFile (file) {
  if (file == null) {
    throw new Error('file cannot be null or undefined')
  }
  if (typeof file.name !== 'string') {
    throw new Error('missing or invalid file.name property')
  }
  if (typeof file.createReadStream !== 'function') {
    throw new Error('missing or invalid file.createReadStream property')
  }
}

function getCodec (name) {
  var extname = path.extname(name).toLowerCase()
  return {
    '.m4a': 'audio/mp4; codecs="mp4a.40.5"',
    '.m4v': 'video/mp4; codecs="avc1.640029, mp4a.40.5"',
    '.mkv': 'video/webm; codecs="avc1.640029, mp4a.40.5"',
    '.mp3': 'audio/mpeg',
    '.mp4': 'video/mp4; codecs="avc1.640029, mp4a.40.5"',
    '.webm': 'video/webm; codecs="opus, vorbis, vp8"'
  }[extname]
}

function parseOpts (opts) {
  if (opts.autoplay == null) opts.autoplay = true
  if (opts.controls == null) opts.controls = true
  if (opts.maxBlobLength == null) opts.maxBlobLength = MAX_BLOB_LENGTH
}
<commit_msg>Revert "Fix chrome issue with opus webm videos"<commit_after>exports.render = render
exports.append = append
exports.mime = require('./lib/mime.json')

var debug = require('debug')('render-media')
var isAscii = require('is-ascii')
var MediaElementWrapper = require('mediasource')
var path = require('path')
var streamToBlobURL = require('stream-to-blob-url')
var videostream = require('videostream')

var VIDEOSTREAM_EXTS = [
  '.m4a',
  '.m4v',
  '.mp4'
]

var MEDIASOURCE_VIDEO_EXTS = [
  '.m4v',
  '.mkv',
  '.mp4',
  '.webm'
]

var MEDIASOURCE_AUDIO_EXTS = [
  '.m4a',
  '.mp3'
]

var MEDIASOURCE_EXTS = [].concat(
  MEDIASOURCE_VIDEO_EXTS,
  MEDIASOURCE_AUDIO_EXTS
)

var AUDIO_EXTS = [
  '.aac',
  '.oga',
  '.ogg',
  '.wav'
]

var IMAGE_EXTS = [
  '.bmp',
  '.gif',
  '.jpeg',
  '.jpg',
  '.png',
  '.svg'
]

var IFRAME_EXTS = [
  '.css',
  '.html',
  '.js',
  '.md',
  '.pdf',
  '.txt'
]

// Maximum file length for which the Blob URL strategy will be attempted
// See: https://github.com/feross/render-media/issues/18
var MAX_BLOB_LENGTH = 200 * 1000 * 1000 // 200 MB

var MediaSource = typeof window !== 'undefined' && window.MediaSource

function render (file, elem, opts, cb) {
  if (typeof opts === 'function') {
    cb = opts
    opts = {}
  }
  if (!opts) opts = {}
  if (!cb) cb = function () {}

  validateFile(file)
  parseOpts(opts)

  if (typeof elem === 'string') elem = document.querySelector(elem)

  renderMedia(file, function (tagName) {
    if (elem.nodeName !== tagName.toUpperCase()) {
      var extname = path.extname(file.name).toLowerCase()

      throw new Error(
        'Cannot render "' + extname + '" inside a "' +
        elem.nodeName.toLowerCase() + '" element, expected "' + tagName + '"'
      )
    }

    return elem
  }, opts, cb)
}

function append (file, rootElem, opts, cb) {
  if (typeof opts === 'function') {
    cb = opts
    opts = {}
  }
  if (!opts) opts = {}
  if (!cb) cb = function () {}

  validateFile(file)
  parseOpts(opts)

  if (typeof rootElem === 'string') rootElem = document.querySelector(rootElem)

  if (rootElem && (rootElem.nodeName === 'VIDEO' || rootElem.nodeName === 'AUDIO')) {
    throw new Error(
      'Invalid video/audio node argument. Argument must be root element that ' +
      'video/audio tag will be appended to.'
    )
  }

  renderMedia(file, getElem, opts, done)

  function getElem (tagName) {
    if (tagName === 'video' || tagName === 'audio') return createMedia(tagName)
    else return createElem(tagName)
  }

  function createMedia (tagName) {
    var elem = createElem(tagName)
    if (opts.controls) elem.controls = true
    if (opts.autoplay) elem.autoplay = true
    rootElem.appendChild(elem)
    return elem
  }

  function createElem (tagName) {
    var elem = document.createElement(tagName)
    rootElem.appendChild(elem)
    return elem
  }

  function done (err, elem) {
    if (err && elem) elem.remove()
    cb(err, elem)
  }
}

function renderMedia (file, getElem, opts, cb) {
  var extname = path.extname(file.name).toLowerCase()
  var currentTime = 0
  var elem

  if (MEDIASOURCE_EXTS.indexOf(extname) >= 0) {
    renderMediaSource()
  } else if (AUDIO_EXTS.indexOf(extname) >= 0) {
    renderAudio()
  } else if (IMAGE_EXTS.indexOf(extname) >= 0) {
    renderImage()
  } else if (IFRAME_EXTS.indexOf(extname) >= 0) {
    renderIframe()
  } else {
    tryRenderIframe()
  }

  function renderMediaSource () {
    var tagName = MEDIASOURCE_VIDEO_EXTS.indexOf(extname) >= 0 ? 'video' : 'audio'

    if (MediaSource) {
      if (VIDEOSTREAM_EXTS.indexOf(extname) >= 0) {
        useVideostream()
      } else {
        useMediaSource()
      }
    } else {
      useBlobURL()
    }

    function useVideostream () {
      debug('Use `videostream` package for ' + file.name)
      prepareElem()
      elem.addEventListener('error', fallbackToMediaSource)
      elem.addEventListener('loadstart', onLoadStart)
      elem.addEventListener('canplay', onCanPlay)
      videostream(file, elem)
    }

    function useMediaSource () {
      debug('Use MediaSource API for ' + file.name)
      prepareElem()
      elem.addEventListener('error', fallbackToBlobURL)
      elem.addEventListener('loadstart', onLoadStart)
      elem.addEventListener('canplay', onCanPlay)

      var wrapper = new MediaElementWrapper(elem)
      var writable = wrapper.createWriteStream(getCodec(file.name))
      file.createReadStream().pipe(writable)

      if (currentTime) elem.currentTime = currentTime
    }

    function useBlobURL () {
      debug('Use Blob URL for ' + file.name)
      prepareElem()
      elem.addEventListener('error', fatalError)
      elem.addEventListener('loadstart', onLoadStart)
      elem.addEventListener('canplay', onCanPlay)
      getBlobURL(file, function (err, url) {
        if (err) return fatalError(err)
        elem.src = url
        if (currentTime) elem.currentTime = currentTime
      })
    }

    function fallbackToMediaSource (err) {
      debug('videostream error: fallback to MediaSource API: %o', err.message || err)
      elem.removeEventListener('error', fallbackToMediaSource)
      elem.removeEventListener('canplay', onCanPlay)

      useMediaSource()
    }

    function fallbackToBlobURL (err) {
      debug('MediaSource API error: fallback to Blob URL: %o', err.message || err)

      if (typeof file.length === 'number' && file.length > opts.maxBlobLength) {
        debug(
          'File length too large for Blob URL approach: %d (max: %d)',
          file.length, opts.maxBlobLength
        )
        return fatalError(new Error(
          'File length too large for Blob URL approach: ' + file.length +
          ' (max: ' + opts.maxBlobLength + ')'
        ))
      }

      elem.removeEventListener('error', fallbackToBlobURL)
      elem.removeEventListener('canplay', onCanPlay)

      useBlobURL()
    }

    function prepareElem () {
      if (!elem) {
        elem = getElem(tagName)

        elem.addEventListener('progress', function () {
          currentTime = elem.currentTime
        })
      }
    }
  }

  function renderAudio () {
    elem = getElem('audio')
    getBlobURL(file, function (err, url) {
      if (err) return fatalError(err)
      elem.addEventListener('error', fatalError)
      elem.addEventListener('loadstart', onLoadStart)
      elem.addEventListener('canplay', onCanPlay)
      elem.src = url
    })
  }

  function onLoadStart () {
    elem.removeEventListener('loadstart', onLoadStart)
    if (opts.autoplay) elem.play()
  }

  function onCanPlay () {
    elem.removeEventListener('canplay', onCanPlay)
    cb(null, elem)
  }

  function renderImage () {
    elem = getElem('img')
    getBlobURL(file, function (err, url) {
      if (err) return fatalError(err)
      elem.src = url
      elem.alt = file.name
      cb(null, elem)
    })
  }

  function renderIframe () {
    elem = getElem('iframe')

    getBlobURL(file, function (err, url) {
      if (err) return fatalError(err)
      elem.src = url
      if (extname !== '.pdf') elem.sandbox = 'allow-forms allow-scripts'
      cb(null, elem)
    })
  }

  function tryRenderIframe () {
    debug('Unknown file extension "%s" - will attempt to render into iframe', extname)

    var str = ''
    file.createReadStream({ start: 0, end: 1000 })
      .setEncoding('utf8')
      .on('data', function (chunk) {
        str += chunk
      })
      .on('end', done)
      .on('error', cb)

    function done () {
      if (isAscii(str)) {
        debug('File extension "%s" appears ascii, so will render.', extname)
        renderIframe()
      } else {
        debug('File extension "%s" appears non-ascii, will not render.', extname)
        cb(new Error('Unsupported file type "' + extname + '": Cannot append to DOM'))
      }
    }
  }

  function fatalError (err) {
    err.message = 'Error rendering file "' + file.name + '": ' + err.message
    debug(err.message)
    cb(err)
  }
}

function getBlobURL (file, cb) {
  var extname = path.extname(file.name).toLowerCase()
  streamToBlobURL(file.createReadStream(), exports.mime[extname], cb)
}

function validateFile (file) {
  if (file == null) {
    throw new Error('file cannot be null or undefined')
  }
  if (typeof file.name !== 'string') {
    throw new Error('missing or invalid file.name property')
  }
  if (typeof file.createReadStream !== 'function') {
    throw new Error('missing or invalid file.createReadStream property')
  }
}

function getCodec (name) {
  var extname = path.extname(name).toLowerCase()
  return {
    '.m4a': 'audio/mp4; codecs="mp4a.40.5"',
    '.m4v': 'video/mp4; codecs="avc1.640029, mp4a.40.5"',
    '.mkv': 'video/webm; codecs="avc1.640029, mp4a.40.5"',
    '.mp3': 'audio/mpeg',
    '.mp4': 'video/mp4; codecs="avc1.640029, mp4a.40.5"',
    '.webm': 'video/webm; codecs="vorbis, vp8"'
  }[extname]
}

function parseOpts (opts) {
  if (opts.autoplay == null) opts.autoplay = true
  if (opts.controls == null) opts.controls = true
  if (opts.maxBlobLength == null) opts.maxBlobLength = MAX_BLOB_LENGTH
}
<|endoftext|>


<commit_before>'use strict';

const $ = require('jquery');
const pick = require('mout/object/pick');
const omit = require('mout/object/omit');
const Klass = require('kist-klass');

const delegateEventSplitter = /^(\S+)\s*(.*)$/;
const viewOptions = ['el', 'events', 'childrenEl'];
const eventNamespace = '.kist.view';
let instanceCount = 0;

const hasOwnProp = Object.prototype.hasOwnProperty;

const View = module.exports = Klass.extend({

	constructor: function ( options ) {

		View.prototype.$body = View.prototype.$body.length ? View.prototype.$body : $('body');

		options = typeof options === 'object' ? options : {};

		this.uid = instanceCount++;
		this.ens = `${eventNamespace}.${this.uid}`;

		$.extend(this, pick(options, viewOptions));

		this._ensureElement();
		this.initialize.apply(this, arguments);

		this.subviews = {};
		View._super.constructor.apply(this, arguments);

	},

	$html: $('html'),
	$body: $('body'),
	$doc: $(document),
	$win: $(window),

	events: {},
	childrenEl: {},

	_ensureElement: function () {
		if ( !this.el ) {
			return;
		}
		this.setElement(this.el);
	},

	/**
	 * @param {Mixed} el
	 */
	_setElement: function ( el ) {
		this.$el = $(el);
		this.el = this.$el[0];
	},

	_removeElement: function () {
		if ( !this.el ) {
			return;
		}
		this.$el.remove();
	},

	/**
	 * @param  {Mixed} selector
	 *
	 * @return {jQuery}
	 */
	$: function ( selector ) {
		return this.$el.find(selector);
	},

	initialize: function () {

	},

	/**
	 * @return {View}
	 */
	render: function () {
		return this;
	},

	remove: function () {
		this.removeSubviews();
		delete this.subviews;
		this._removeElement();
	},

	/**
	 * @param {Object} options
	 */
	setOptions: function ( options ) {
		this.options = $.extend({}, this.options, omit(options, viewOptions));
	},

	/**
	 * @param {Element} el
	 */
	setElement: function ( el ) {
		this.undelegateEvents();
		this._setElement(el);
		this.delegateEvents();
		this.cacheChildrenEl();
	},

	/**
	 * @param  {Object} childrenEl
	 */
	cacheChildrenEl: function ( childrenEl ) {

		childrenEl = childrenEl || this.childrenEl;

		Object.keys(childrenEl)
			.forEach(( key ) => {
				const selector = this.$(childrenEl[key]);
				this[`$${key}`] = selector;
			});

	},

	/**
	 * @param  {Object} events
	 */
	delegateEvents: function ( events ) {

		events = events || this.events;
		this.undelegateEvents();

		Object.keys(events)
			.forEach(( key ) => {
				let method = events[key];
				if ( typeof method !== 'function' ) {
					method = this[method];
				}
				if ( method ) {
					const match = key.match(delegateEventSplitter);
					this.delegate(match[1], match[2], method.bind(this));
				}
			});

	},

	undelegateEvents: function () {
		if ( this.$el ) {
			this.$el.off(this.ens);
		}
	},

	/**
	 * @param  {String} eventName
	 * @param  {String} selector
	 * @param  {Function} listener
	 */
	delegate: function ( eventName, selector, listener ) {
		this.$el.on(eventName + this.ens, selector, listener);
	},

	/**
	 * @param  {String} eventName
	 * @param  {String} selector
	 * @param  {Function} listener
	 */
	undelegate: function ( eventName, selector, listener ) {
		this.$el.off(eventName + this.ens, selector, listener);
	},

	/**
	 * Returns subview by supplied key
	 *
	 * @param  {String|Number} key
	 *
	 * @return {View}
	 */
	getSubview: function ( key ) {
		return this.subviews[key];
	},

	/**
	 * Adds a subview to the current view, which will
	 * ensure its removal when this view is removed,
	 * or when view.removeSubviews is called
	 *
	 * @param {View} view
	 * @param {String|Number} key
	 *
	 * @return {View}
	 */
	addSubview: function ( view, key ) {
		if ( !(view instanceof View) ) {
			throw new Error('Subview must be a View');
		}
		if ( typeof key === 'undefined' ) {
			key = view.uid;
		}
		this.subviews[key] = view;
		return view;
	},

	/**
	 * Removes any subviews associated with this view
	 * by `addSubview`, which will in-turn remove any
	 * children of those views, and so on
	 *
	 * @return {View}
	 */
	removeSubviews: function () {

		for ( let key in this.subviews ) {
			if ( hasOwnProp.call(this.subviews, key) ) {
				const subview = this.subviews[key];
				if ( typeof subview.remove === 'function' ) {
					subview.remove();
				}
				delete this.subviews[key];
			}
		}

		return this;

	},

	/**
	 * Get subview placeholder
	 *
	 * @return {String}
	 */
	getRenderPlaceholder: function () {
		return `<div data-view-uid="${this.uid}"></div>`;
	},

	/**
	 * Replace subview placeholder with its real content
	 *
	 * @param  {String|Number} key
	 */
	assignSubview: function ( key ) {
		const view = this.getSubview(key);
		this.$(`[data-view-uid="${view.uid}"]`).replaceWith(view.render().el);
	}

});
<commit_msg>Subviews hash should be defined before initialize<commit_after>'use strict';

const $ = require('jquery');
const pick = require('mout/object/pick');
const omit = require('mout/object/omit');
const Klass = require('kist-klass');

const delegateEventSplitter = /^(\S+)\s*(.*)$/;
const viewOptions = ['el', 'events', 'childrenEl'];
const eventNamespace = '.kist.view';
let instanceCount = 0;

const hasOwnProp = Object.prototype.hasOwnProperty;

const View = module.exports = Klass.extend({

	constructor: function ( options ) {

		View.prototype.$body = View.prototype.$body.length ? View.prototype.$body : $('body');

		options = typeof options === 'object' ? options : {};

		this.uid = instanceCount++;
		this.ens = `${eventNamespace}.${this.uid}`;
		this.subviews = {};

		$.extend(this, pick(options, viewOptions));

		this._ensureElement();
		this.initialize.apply(this, arguments);

		View._super.constructor.apply(this, arguments);

	},

	$html: $('html'),
	$body: $('body'),
	$doc: $(document),
	$win: $(window),

	events: {},
	childrenEl: {},

	_ensureElement: function () {
		if ( !this.el ) {
			return;
		}
		this.setElement(this.el);
	},

	/**
	 * @param {Mixed} el
	 */
	_setElement: function ( el ) {
		this.$el = $(el);
		this.el = this.$el[0];
	},

	_removeElement: function () {
		if ( !this.el ) {
			return;
		}
		this.$el.remove();
	},

	/**
	 * @param  {Mixed} selector
	 *
	 * @return {jQuery}
	 */
	$: function ( selector ) {
		return this.$el.find(selector);
	},

	initialize: function () {

	},

	/**
	 * @return {View}
	 */
	render: function () {
		return this;
	},

	remove: function () {
		this.removeSubviews();
		delete this.subviews;
		this._removeElement();
	},

	/**
	 * @param {Object} options
	 */
	setOptions: function ( options ) {
		this.options = $.extend({}, this.options, omit(options, viewOptions));
	},

	/**
	 * @param {Element} el
	 */
	setElement: function ( el ) {
		this.undelegateEvents();
		this._setElement(el);
		this.delegateEvents();
		this.cacheChildrenEl();
	},

	/**
	 * @param  {Object} childrenEl
	 */
	cacheChildrenEl: function ( childrenEl ) {

		childrenEl = childrenEl || this.childrenEl;

		Object.keys(childrenEl)
			.forEach(( key ) => {
				const selector = this.$(childrenEl[key]);
				this[`$${key}`] = selector;
			});

	},

	/**
	 * @param  {Object} events
	 */
	delegateEvents: function ( events ) {

		events = events || this.events;
		this.undelegateEvents();

		Object.keys(events)
			.forEach(( key ) => {
				let method = events[key];
				if ( typeof method !== 'function' ) {
					method = this[method];
				}
				if ( method ) {
					const match = key.match(delegateEventSplitter);
					this.delegate(match[1], match[2], method.bind(this));
				}
			});

	},

	undelegateEvents: function () {
		if ( this.$el ) {
			this.$el.off(this.ens);
		}
	},

	/**
	 * @param  {String} eventName
	 * @param  {String} selector
	 * @param  {Function} listener
	 */
	delegate: function ( eventName, selector, listener ) {
		this.$el.on(eventName + this.ens, selector, listener);
	},

	/**
	 * @param  {String} eventName
	 * @param  {String} selector
	 * @param  {Function} listener
	 */
	undelegate: function ( eventName, selector, listener ) {
		this.$el.off(eventName + this.ens, selector, listener);
	},

	/**
	 * Returns subview by supplied key
	 *
	 * @param  {String|Number} key
	 *
	 * @return {View}
	 */
	getSubview: function ( key ) {
		return this.subviews[key];
	},

	/**
	 * Adds a subview to the current view, which will
	 * ensure its removal when this view is removed,
	 * or when view.removeSubviews is called
	 *
	 * @param {View} view
	 * @param {String|Number} key
	 *
	 * @return {View}
	 */
	addSubview: function ( view, key ) {
		if ( !(view instanceof View) ) {
			throw new Error('Subview must be a View');
		}
		if ( typeof key === 'undefined' ) {
			key = view.uid;
		}
		this.subviews[key] = view;
		return view;
	},

	/**
	 * Removes any subviews associated with this view
	 * by `addSubview`, which will in-turn remove any
	 * children of those views, and so on
	 *
	 * @return {View}
	 */
	removeSubviews: function () {

		for ( let key in this.subviews ) {
			if ( hasOwnProp.call(this.subviews, key) ) {
				const subview = this.subviews[key];
				if ( typeof subview.remove === 'function' ) {
					subview.remove();
				}
				delete this.subviews[key];
			}
		}

		return this;

	},

	/**
	 * Get subview placeholder
	 *
	 * @return {String}
	 */
	getRenderPlaceholder: function () {
		return `<div data-view-uid="${this.uid}"></div>`;
	},

	/**
	 * Replace subview placeholder with its real content
	 *
	 * @param  {String|Number} key
	 */
	assignSubview: function ( key ) {
		const view = this.getSubview(key);
		this.$(`[data-view-uid="${view.uid}"]`).replaceWith(view.render().el);
	}

});
<|endoftext|>


<commit_before>// Load in the main postcss module
var postcss = require( 'postcss' );

// Wrapper
module.exports = postcss.plugin( 'postcss-table-of-contents', function () {
	return function ( css ) {

		var i = []; // Variable for match counting
		var tocPlaceholder = /\(#\)/; // Placeholder for table of contents: (#)
		var noPlaceholder = '#)'; // Placeholder for numberings: #)

		// Traverses the container’s descendant nodes
		css.walkComments( function ( comment ) {

			var String = comment.toString(); // Get comments as string

			// Check, if table of contents placholder is in string
			var isInString = tocPlaceholder.test( String );
			if ( isInString === false ) {

				// Reset old numberings with numbering placholder #)
				var StringMatchTmp = String.replace( /(\S+)\)/, noPlaceholder );

				// Replace numbering placeholders with increment number
				var StringMatch = StringMatchTmp.replace( noPlaceholder,
					function ( m, p1 ) {
						i[ p1 ] = ( i[ p1 ] || 0 ) + 1;
						return i[ p1 ].toString() + ')';
					} );

				// Replace all comments with our new string
				comment.replaceWith( StringMatch );

			} else {
				// Get array of #) comments

				// Cum back later ;-)
			}
		} );
	};
} );
<commit_msg>Supports indexing up to three levels<commit_after>// Load in the main postcss module
var postcss = require('postcss');

// Wrapper
module.exports = postcss.plugin('postcss-table-of-contents', function () {
    return function (css) {

        var i = []; // Variable for match counting
        var ii = []; // Variable for match counting
        var iii = []; // Variable for match counting
        var tocPlaceholder = /\(#\)/; // Placeholder for table of contents: (#)

        // Function for replace placeholders below
        function replacer(match, p1, p3, p5) {
            if (match === '#)') {
                i[p1] = ( i[p1] || 0 ) + 1;
                return i[p1] + ')';
            } else if (match === '##)') {
                i[p1] = i[p1] || 0;
                ii[p3] = ( ii[p3] || 0 ) + 1;
                return i[p1] + '.' + ii[p3] + ')';
            } else {
                i[p1] = i[p1] || 0;
                ii[p3] = ii[p3] || 0;
                iii[p5] = ( iii[p5] || 0 ) + 1;
                return i[p1] + '.' + ii[p3] + '.' + iii[p5] + ')';
            }
        }

        // Traverses the container’s descendant nodes
        css.walkComments(function (comment) {

            var String = comment.toString(); // Get comments as string

            // Check, if table of contents placeholder is in string
            var isInString = tocPlaceholder.test(String);

            if (isInString === false) {

                // Reset old numberings with numbering placeholder #)
                // This must be to overwork:
                // var StringMatchTmp = String.replace(/(\S)\)/, '#');

                // Replace numbering placeholders with increment number
                var StringMatch = String.replace(/(#)(\)?)(#?)(\)?)(#?\)?)/,
                    replacer);

                // Replace all comments with our new string
                comment.replaceWith(StringMatch);

            } else {
                // Get array of #) comments

                // Cum back later ;-)
            }
        });
    };
});
<|endoftext|>