<commit_before>var request = require('request');
var async = require('async');
var accounting = require('accounting');
var express = require('express');

module.exports = SteamPriceManager;

function SteamPriceManager(options) {
	options = options || {};

	this._request = request;
	this._async = async;

	this._marketBaseUrl = 'http://steamcommunity.com/';
	this._marketUri = '/market/priceoverview/';

	this._errorCodes = {
		"400": "We did a bad request. Please report this error at Github.",
		"401": "We are not authorized to do this request. Please report this error at Github.",
		"403": "Steam is refusing to respond.",
		"500": "Steam is having issues. (Potential issue: No listings for this item.)",
		"503": "Steam is having issues.",
		"429": "We are making too many requests to Steam."
	};

	this.appID = options.appID || undefined;
	this.currency = options.currency || 3; // EUR
	this.includeFloats = options.includeFloats || false;
	this.keepCurrencySymbols = options.keepCurrencySymbols || false;

	// Backpack.TF API
	this.backpacktf = options.backpacktf || undefined;
	this._backpackBaseUrl = 'http://backpack.tf/';
	this._backpackUri = '/api/IGetMarketPrices/v1/';
	this._backpackAvailableFormats = ['json', 'vdf', 'jsonp', 'pretty'];
	this._backpackData = null;
	this._backpackTimer = false;

	// Web API
	this._webApp = express();

	this.enableWebApi = options.enableWebApi || false;
	this.webApiPort = options.webApiPort || 1337;
	this.webApiSeperator = options.webApiSeperator || '!N!';

	if(this.enableWebApi) {
		this.initWebApi();
	}
}

SteamPriceManager.prototype.getItem = function(details, callback) {
	var appID = details.appID || this.appID;
	var currency = details.currency || this.currency;
	var itemName = details.name;
	var includeFloat = details.includeFloat || this.includeFloats;

	// If user did not specify the appID let's throw an error.
	if(appID === undefined) throw new Error('You did not specify any Steam Application ID. Don\'t know what to use? Here: https://developer.valvesoftware.com/wiki/Steam_Application_IDs');
	// If user did not specify any item name let's throw an error.
	if(itemName === undefined) throw new Error('Specify an Item name.');
	// We need a callback
	if(typeof callback !== "function") throw new Error('Callback is not defined or not a function');

	this._requestItem(currency, appID, itemName, function(err, item) {
		callback(err, item);
	});
}

SteamPriceManager.prototype.getItems = function(details, callback) {
	var self = this;

	var appID = details.appID || this.appID;
	var currency = details.currency || this.currency;
	var includeFloat = details.includeFloat || this.includeFloats;

	var items = details.names;

	// If user did not specify the appID let's throw an error.
	if(appID === undefined) throw new Error('You did not specify any Steam Application ID. Don\'t know what to use? Here: https://developer.valvesoftware.com/wiki/Steam_Application_IDs');
	// If user did not specify any item name let's throw an error.
	if(items === undefined || typeof items !== 'object') throw new Error('You did not specify `names` parameter or it is not an object.');
	// We need a callback
	if(typeof callback !== "function") throw new Error('Callback is not defined or not a function');

	// Tasks object for async
	var tasks = items.map(function(itemName){
	  return function(callback) {
	    self._requestItem(currency, appID, itemName, function(err, item) {
	        if( err) {
	        	// Since async stops the whole parallel from continuing on errors we will not populate err
	            callback(null, { "name": itemName, "error": err });
	            return;
	        }

	        callback(null, { "name": itemName, "data": item });
	    });
	  }
	});
	// Go through tasks, using async parallel
	this._async.parallel(tasks, function(err, results) {
		callback(results);
	});
}

SteamPriceManager.prototype.getAllItems = function(details, callback) {
	var format = details.format || 'json';
	var key = this.backpacktf;
	var appID = details.appID || this.appID;

	// If user did not specify the appID let's throw an error.
	if(key === undefined) throw new Error('To fetch all items you must get the BackpackTF API Key. More info: http://backpack.tf/api/register');
	// If user did not specify the appID let's throw an error.
	if(appID === undefined) throw new Error('You did not specify any Steam Application ID. Don\'t know what to use? Here: https://developer.valvesoftware.com/wiki/Steam_Application_IDs');
	// Check if user specified correct format
	if(this._backpackAvailableFormats.indexOf(format) === -1) throw new Error('Invalid data format for getAllItems');
	// We need a callback
	if(typeof callback !== "function") throw new Error('Callback is not defined or not a function');

	// Backpack.tf has a 300 second query rate limit
	if(this._backpackTimer === false || this._backpackTimer > ((new Date().getTime() / 1000) + 300)) {
		this._request({
			uri: this._backpackUri,
			baseUrl: this._backpackBaseUrl,
			qs: {
				format: format,
				key: key,
				appid: appID
			}
		}, function(err, res, body) {
			if( ! err && res.statusCode !== 200) {
				callback('Unsuccessful response (' + res.statusCode + ') from Backpack.tf', null);
			} else if( ! err && res.statusCode === 200) {
				if(format == 'json') {
					body = JSON.parse(body);
					if(body.response.success == 0) {
						callback(body.response.message, null);
						return;
					}
				}
				// Set the backpack body and set the timer
				this._backpackData = body;
				this._backpackTimer = new Date().getTime() / 1000;
				callback(null, body);
			} else {
				callback(err, null);
			}
		});
	} else {
		if(this._backpackData !== null) {
			callback(null, this._backpackData);
		}
	}

}

SteamPriceManager.prototype.initWebApi = function() {
	var self = this;

	this._webApp.get('/', function(req, res) {
		res.send("github.com/Netifriik/node-steam-market-manager");
	});

	this._webApp.get('/item/:name', function(req, res) {
		var name = decodeURIComponent(req.params.name);
		self.getItem({ 'name': name }, function(err, item) {
			if( err) {
				res.json({ 'error': err });
				return;
			}

			res.json({ 'item': item });
		});
	});

	this._webApp.get('/items/all', function(req, res) {
		self.getAllItems({}, function(err, data) {
			if( err) {
				res.json({ 'error': err });
				return;
			}

			res.json({ 'items': data.response.items });
		});
	});

	this._webApp.get('/items/:names', function(req, res) {
		var items = decodeURIComponent(req.params.names);
		var names = items.split(self.webApiSeperator);

		self.getItems({ 'names': names }, function(items) {
			res.json({ 'items': items });
		});

	});

	this._webApp.listen(self.webApiPort, function () {
		console.log('API listening on port ' + self.webApiPort);
	});
}

SteamPriceManager.prototype._requestItem = function(currency, appID, itemName, callback) {
	var self = this;

	this._request({
		uri: this._marketUri,
		baseUrl: this._marketBaseUrl,
		json: true,
		qs: {
			currency: currency,
			appid: appID,
			market_hash_name: itemName
		}
	}, function(err, res, body) {
		if( ! err && res.statusCode !== 200) {
			if(self._errorCodes[res.statusCode] !== undefined) {
				callback(self._errorCodes[res.statusCode], null);
			} else {
				callback('Unsuccessful response (' + res.statusCode + '). Is Steam having issues?', null);
			}
		} else if( ! err && res.statusCode === 200) {
			if( ! self.keepCurrencySymbols) {
				// Steam uses commas to seperate decimals on all currencies? Untested..
				body.lowest_price = accounting.unformat(body.lowest_price, ",");
				body.median_price = accounting.unformat(body.median_price, ",");
			}
			callback(null, body);
		} else {
			callback(err, null);
		}
	});
}<commit_msg>Added an additional check for getAllItems()<commit_after>var request = require('request');
var async = require('async');
var accounting = require('accounting');
var express = require('express');

module.exports = SteamPriceManager;

function SteamPriceManager(options) {
	options = options || {};

	this._request = request;
	this._async = async;

	this._marketBaseUrl = 'http://steamcommunity.com/';
	this._marketUri = '/market/priceoverview/';

	this._errorCodes = {
		"400": "We did a bad request. Please report this error at Github.",
		"401": "We are not authorized to do this request. Please report this error at Github.",
		"403": "Steam is refusing to respond.",
		"500": "Steam is having issues. (Potential issue: No listings for this item.)",
		"503": "Steam is having issues.",
		"429": "We are making too many requests to Steam."
	};

	this.appID = options.appID || undefined;
	this.currency = options.currency || 3; // EUR
	this.includeFloats = options.includeFloats || false;
	this.keepCurrencySymbols = options.keepCurrencySymbols || false;

	// Backpack.TF API
	this.backpacktf = options.backpacktf || undefined;
	this._backpackBaseUrl = 'http://backpack.tf/';
	this._backpackUri = '/api/IGetMarketPrices/v1/';
	this._backpackAvailableFormats = ['json', 'vdf', 'jsonp', 'pretty'];
	this._backpackData = null;
	this._backpackTimer = false;

	// Web API
	this._webApp = express();

	this.enableWebApi = options.enableWebApi || false;
	this.webApiPort = options.webApiPort || 1337;
	this.webApiSeperator = options.webApiSeperator || '!N!';

	if(this.enableWebApi) {
		this.initWebApi();
	}
}

SteamPriceManager.prototype.getItem = function(details, callback) {
	var appID = details.appID || this.appID;
	var currency = details.currency || this.currency;
	var itemName = details.name;
	var includeFloat = details.includeFloat || this.includeFloats;

	// If user did not specify the appID let's throw an error.
	if(appID === undefined) throw new Error('You did not specify any Steam Application ID. Don\'t know what to use? Here: https://developer.valvesoftware.com/wiki/Steam_Application_IDs');
	// If user did not specify any item name let's throw an error.
	if(itemName === undefined) throw new Error('Specify an Item name.');
	// We need a callback
	if(typeof callback !== "function") throw new Error('Callback is not defined or not a function');

	this._requestItem(currency, appID, itemName, function(err, item) {
		callback(err, item);
	});
}

SteamPriceManager.prototype.getItems = function(details, callback) {
	var self = this;

	var appID = details.appID || this.appID;
	var currency = details.currency || this.currency;
	var includeFloat = details.includeFloat || this.includeFloats;

	var items = details.names;

	// If user did not specify the appID let's throw an error.
	if(appID === undefined) throw new Error('You did not specify any Steam Application ID. Don\'t know what to use? Here: https://developer.valvesoftware.com/wiki/Steam_Application_IDs');
	// If user did not specify any item name let's throw an error.
	if(items === undefined || typeof items !== 'object') throw new Error('You did not specify `names` parameter or it is not an object.');
	// We need a callback
	if(typeof callback !== "function") throw new Error('Callback is not defined or not a function');

	// Tasks object for async
	var tasks = items.map(function(itemName){
	  return function(callback) {
	    self._requestItem(currency, appID, itemName, function(err, item) {
	        if( err) {
	        	// Since async stops the whole parallel from continuing on errors we will not populate err
	            callback(null, { "name": itemName, "error": err });
	            return;
	        }

	        callback(null, { "name": itemName, "data": item });
	    });
	  }
	});
	// Go through tasks, using async parallel
	this._async.parallel(tasks, function(err, results) {
		callback(results);
	});
}

SteamPriceManager.prototype.getAllItems = function(details, callback) {
	var format = details.format || 'json';
	var key = this.backpacktf;
	var appID = details.appID || this.appID;

	// If user did not specify the appID let's throw an error.
	if(key === undefined) throw new Error('To fetch all items you must get the BackpackTF API Key. More info: http://backpack.tf/api/register');
	// If user did not specify the appID let's throw an error.
	if(appID === undefined) throw new Error('You did not specify any Steam Application ID. Don\'t know what to use? Here: https://developer.valvesoftware.com/wiki/Steam_Application_IDs');
	// Check if user specified correct format
	if(this._backpackAvailableFormats.indexOf(format) === -1) throw new Error('Invalid data format for getAllItems');
	// We need a callback
	if(typeof callback !== "function") throw new Error('Callback is not defined or not a function');

	// Backpack.tf has a 300 second query rate limit
	if(this._backpackTimer === false || this._backpackTimer > ((new Date().getTime() / 1000) + 300)) {
		this._request({
			uri: this._backpackUri,
			baseUrl: this._backpackBaseUrl,
			qs: {
				format: format,
				key: key,
				appid: appID
			}
		}, function(err, res, body) {
			if( ! err && res.statusCode !== 200) {
				callback('Unsuccessful response (' + res.statusCode + ') from Backpack.tf', null);
			} else if( ! err && res.statusCode === 200) {
				if(format == 'json') {
					body = JSON.parse(body);
					if(body.response.success == 0) {
						callback(body.response.message, null);
						return;
					}
				}
				// Set the backpack body and set the timer
				this._backpackData = body;
				this._backpackTimer = new Date().getTime() / 1000;
				callback(null, body);
			} else {
				callback(err, null);
			}
		});
	} else {
		if(this._backpackData !== null) {
			callback(null, this._backpackData);
		} else {
			// Something went wrong. Let's clear the data and re-run this function.
			this._backpackTimer = false;
			this.backpackData = null;
			this.getAllItems(details, callback);
		}
	}

}

SteamPriceManager.prototype.initWebApi = function() {
	var self = this;

	this._webApp.get('/', function(req, res) {
		res.send("github.com/Netifriik/node-steam-market-manager");
	});

	this._webApp.get('/item/:name', function(req, res) {
		var name = decodeURIComponent(req.params.name);
		self.getItem({ 'name': name }, function(err, item) {
			if( err) {
				res.json({ 'error': err });
				return;
			}

			res.json({ 'item': item });
		});
	});

	this._webApp.get('/items/all', function(req, res) {
		self.getAllItems({}, function(err, data) {
			if( err) {
				res.json({ 'error': err });
				return;
			}

			res.json({ 'items': data.response.items });
		});
	});

	this._webApp.get('/items/:names', function(req, res) {
		var items = decodeURIComponent(req.params.names);
		var names = items.split(self.webApiSeperator);

		self.getItems({ 'names': names }, function(items) {
			res.json({ 'items': items });
		});

	});

	this._webApp.listen(self.webApiPort, function () {
		console.log('API listening on port ' + self.webApiPort);
	});
}

SteamPriceManager.prototype._requestItem = function(currency, appID, itemName, callback) {
	var self = this;

	this._request({
		uri: this._marketUri,
		baseUrl: this._marketBaseUrl,
		json: true,
		qs: {
			currency: currency,
			appid: appID,
			market_hash_name: itemName
		}
	}, function(err, res, body) {
		if( ! err && res.statusCode !== 200) {
			if(self._errorCodes[res.statusCode] !== undefined) {
				callback(self._errorCodes[res.statusCode], null);
			} else {
				callback('Unsuccessful response (' + res.statusCode + '). Is Steam having issues?', null);
			}
		} else if( ! err && res.statusCode === 200) {
			if( ! self.keepCurrencySymbols) {
				// Steam uses commas to seperate decimals on all currencies? Untested..
				body.lowest_price = accounting.unformat(body.lowest_price, ",");
				body.median_price = accounting.unformat(body.median_price, ",");
			}
			callback(null, body);
		} else {
			callback(err, null);
		}
	});
}<|endoftext|>


<commit_before>'use strict'

const debuglog = require('util').debuglog
const dotenv = require('dotenv')
const fs = require('fs')
const glob = require('glob')
const Lintspaces = require('lintspaces')
const minimatch = require('minimatch')
const path = require('path')
const pkg = require('pkg-config')

const debug = debuglog('echint')
const config = pkg('echint', { root: false })

const DEFAULT_PATTERN = '**/*'
const DEFAULT_IGNORE_PATTERNS = [
  'coverage/**',
  'node_modules/**',
  'bower_components/**',
  '**/*.{jpg,png,gif,ico}'
]

dotenv.config({ silent: true })
dotenv.config({ silent: true, path: '.env.' + process.env.NODE_ENV })

module.exports = function echint (files, options, cb) {
  // organize arguments
  if (typeof arguments[1] === 'function') {
    cb = arguments[1]
    options = {}
  }

  // organize arguments
  if (!Array.isArray(arguments[0]) && typeof arguments[0] === 'object') {
    options = arguments[0]
    files = undefined
  }

  // default values
  const defaults = {
    config: process.env.ECHINT_CONFIG || '.editorconfig',
    ignore: process.env.ECHINT_IGNORE ? [process.env.ECHINT_IGNORE] : DEFAULT_IGNORE_PATTERNS,
    pattern: process.env.ECHINT_PATTERN || DEFAULT_PATTERN,
    readPackage: process.env.ECHINT_READ_PACKAGE ? (process.env.ECHINT_READ_PACKAGE === 'true') : (options ? options.readPackage : true)
  }

  // initialize options
  let opts = Object.assign({}, defaults)

  // overwrite from package.json?
  if (opts.readPackage && config) {
    debug('package.json config found')

    Object.assign(opts, config)
  }

  // overwrite from local options again
  Object.assign(opts, options)

  if (opts.extends) {
    debug('extends found')

    let extendsDir = path.join(process.cwd(), 'node_modules', opts.extends.replace(/^(echint-config-)?/, 'echint-config-'))

    let extendsMain = pkg('main', { cwd: extendsDir, root: false })

    opts.config = path.join(extendsDir, extendsMain || '.editorconfig')
  }

  debug('starting with options: config=%s ignore=%j', opts.config, opts.ignore)

  // setup validator
  const lintspaces = new Lintspaces({
    editorconfig: opts.config,
    ignores: [
      'js-comments',
      'c-comments',
      'java-comments',
      'as-comments',
      'xml-comments',
      'html-comments',
      'python-comments',
      'ruby-comments',
      'applescript-comments'
    ]
  })

  // files to check
  if (!files || !files.length) {
    debug('no file list given, using match pattern instead: "%s"', opts.pattern)

    files = glob.sync(opts.pattern, {
      ignore: opts.ignore.concat(DEFAULT_IGNORE_PATTERNS),
      nodir: true
    })

    // since glob already ignored files for us, do NOT check later
    opts.ignore = []
  }

  // Run validation
  files.forEach(file => {
    if (opts.ignore.some(pattern => minimatch(file, pattern))) {
      debug('[%s] is ignored"', file)
      return
    }

    // confirm file exists
    try {
      if (!fs.statSync(file).isFile()) throw Error('is not a file')
    } catch (e) {
      return debug('✖ [%s] is not a file ', file)
    }

    // where the magic happens
    lintspaces.validate(file)

    // debugging
    if (Object.keys(lintspaces.getInvalidLines(file)).length) {
      debug('✖ [%s] is invalid', file)
    } else {
      debug('✓ [%s] is valid', file)
    }
  })

  // get full list of errors
  const errors = lintspaces.getInvalidFiles()

  // determine if test was a success
  const valid = Object.keys(errors).length === 0

  if (typeof cb === 'function') {
    cb(valid ? null : errors, valid)
  }

  return valid
}
<commit_msg>Prefer const over let<commit_after>'use strict'

const debuglog = require('util').debuglog
const dotenv = require('dotenv')
const fs = require('fs')
const glob = require('glob')
const Lintspaces = require('lintspaces')
const minimatch = require('minimatch')
const path = require('path')
const pkg = require('pkg-config')

const debug = debuglog('echint')
const config = pkg('echint', { root: false })

const DEFAULT_PATTERN = '**/*'
const DEFAULT_IGNORE_PATTERNS = [
  'coverage/**',
  'node_modules/**',
  'bower_components/**',
  '**/*.{jpg,png,gif,ico}'
]

dotenv.config({ silent: true })
dotenv.config({ silent: true, path: '.env.' + process.env.NODE_ENV })

module.exports = function echint (files, options, cb) {
  // organize arguments
  if (typeof arguments[1] === 'function') {
    cb = arguments[1]
    options = {}
  }

  // organize arguments
  if (!Array.isArray(arguments[0]) && typeof arguments[0] === 'object') {
    options = arguments[0]
    files = undefined
  }

  // default values
  const defaults = {
    config: process.env.ECHINT_CONFIG || '.editorconfig',
    ignore: process.env.ECHINT_IGNORE ? [process.env.ECHINT_IGNORE] : DEFAULT_IGNORE_PATTERNS,
    pattern: process.env.ECHINT_PATTERN || DEFAULT_PATTERN,
    readPackage: process.env.ECHINT_READ_PACKAGE ? (process.env.ECHINT_READ_PACKAGE === 'true') : (options ? options.readPackage : true)
  }

  // initialize options
  const opts = Object.assign({}, defaults)

  // overwrite from package.json?
  if (opts.readPackage && config) {
    debug('package.json config found')

    Object.assign(opts, config)
  }

  // overwrite from local options again
  Object.assign(opts, options)

  if (opts.extends) {
    debug('extends found')

    const extendsDir = path.join(process.cwd(), 'node_modules', opts.extends.replace(/^(echint-config-)?/, 'echint-config-'))

    const extendsMain = pkg('main', { cwd: extendsDir, root: false })

    opts.config = path.join(extendsDir, extendsMain || '.editorconfig')
  }

  debug('starting with options: config=%s ignore=%j', opts.config, opts.ignore)

  // setup validator
  const lintspaces = new Lintspaces({
    editorconfig: opts.config,
    ignores: [
      'js-comments',
      'c-comments',
      'java-comments',
      'as-comments',
      'xml-comments',
      'html-comments',
      'python-comments',
      'ruby-comments',
      'applescript-comments'
    ]
  })

  // files to check
  if (!files || !files.length) {
    debug('no file list given, using match pattern instead: "%s"', opts.pattern)

    files = glob.sync(opts.pattern, {
      ignore: opts.ignore.concat(DEFAULT_IGNORE_PATTERNS),
      nodir: true
    })

    // since glob already ignored files for us, do NOT check later
    opts.ignore = []
  }

  // Run validation
  files.forEach(file => {
    if (opts.ignore.some(pattern => minimatch(file, pattern))) {
      debug('[%s] is ignored"', file)
      return
    }

    // confirm file exists
    try {
      if (!fs.statSync(file).isFile()) throw Error('is not a file')
    } catch (e) {
      return debug('✖ [%s] is not a file ', file)
    }

    // where the magic happens
    lintspaces.validate(file)

    // debugging
    if (Object.keys(lintspaces.getInvalidLines(file)).length) {
      debug('✖ [%s] is invalid', file)
    } else {
      debug('✓ [%s] is valid', file)
    }
  })

  // get full list of errors
  const errors = lintspaces.getInvalidFiles()

  // determine if test was a success
  const valid = Object.keys(errors).length === 0

  if (typeof cb === 'function') {
    cb(valid ? null : errors, valid)
  }

  return valid
}
<|endoftext|>


<commit_before>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; /* scenarioo-js
                                                                                * Copyright (C) 2014, scenarioo.org Development Team
                                                                                *
                                                                                * This program is free software: you can redistribute it and/or modify
                                                                                * it under the terms of the GNU General Public License as published by
                                                                                * the Free Software Foundation, either version 3 of the License, or
                                                                                * (at your option) any later version.
                                                                                *
                                                                                * This program is distributed in the hope that it will be useful,
                                                                                * but WITHOUT ANY WARRANTY; without even the implied warranty of
                                                                                * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                                                                                * GNU General Public License for more details.
                                                                                *
                                                                                * You should have received a copy of the GNU General Public License
                                                                                * along with this program.  If not, see <http://www.gnu.org/licenses/>.
                                                                                */

var _scenariooJs = require('./scenarioo-js');

var _scenariooJs2 = _interopRequireDefault(_scenariooJs);

var _fluentDsl = require('./dsl/fluentDsl');

var fluentDsl = _interopRequireWildcard(_fluentDsl);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

// also expose the fluent dsl functions on `scenarioo` by default
// for working nicely with typescript typings
// and to be able to import it nicely from this library root.
_scenariooJs2.default.useCase = fluentDsl.useCase;
_scenariooJs2.default.scenario = fluentDsl.scenario;
_scenariooJs2.default.step = fluentDsl.step;
_scenariooJs2.default.fluentDslConfig = fluentDsl.dslConfig;

// to support both module systems
exports.default = _scenariooJs2.default;

if ((typeof module === 'undefined' ? 'undefined' : _typeof(module)) === 'object' && module.exports) {
  module.exports = _scenariooJs2.default;
}<commit_msg>fixed fluentDslConfig on scenarioo object<commit_after>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; /* scenarioo-js
                                                                                * Copyright (C) 2014, scenarioo.org Development Team
                                                                                *
                                                                                * This program is free software: you can redistribute it and/or modify
                                                                                * it under the terms of the GNU General Public License as published by
                                                                                * the Free Software Foundation, either version 3 of the License, or
                                                                                * (at your option) any later version.
                                                                                *
                                                                                * This program is distributed in the hope that it will be useful,
                                                                                * but WITHOUT ANY WARRANTY; without even the implied warranty of
                                                                                * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                                                                                * GNU General Public License for more details.
                                                                                *
                                                                                * You should have received a copy of the GNU General Public License
                                                                                * along with this program.  If not, see <http://www.gnu.org/licenses/>.
                                                                                */

var _scenariooJs = require('./scenarioo-js');

var _scenariooJs2 = _interopRequireDefault(_scenariooJs);

var _fluentDsl = require('./dsl/fluentDsl');

var fluentDsl = _interopRequireWildcard(_fluentDsl);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

// also expose the fluent dsl functions on `scenarioo` by default
// for working nicely with typescript typings
// and to be able to import it nicely from this library root.
_scenariooJs2.default.useCase = fluentDsl.useCase;
_scenariooJs2.default.scenario = fluentDsl.scenario;
_scenariooJs2.default.step = fluentDsl.step;
_scenariooJs2.default.fluentDslConfig = fluentDsl.config;

// to support both module systems
exports.default = _scenariooJs2.default;

if ((typeof module === 'undefined' ? 'undefined' : _typeof(module)) === 'object' && module.exports) {
  module.exports = _scenariooJs2.default;
}<|endoftext|>


<commit_before>goog.provide('ngeo.RotateEvent');
goog.provide('ngeo.RotateEventType');
goog.provide('ngeo.interaction.Rotate');

goog.require('goog.asserts');
goog.require('goog.events');
goog.require('ol');
goog.require('ol.Collection');
goog.require('ol.Feature');
goog.require('ol.MapBrowserPointerEvent');
goog.require('ol.events');
goog.require('ol.interaction.Modify');
goog.require('ol.interaction.ModifyEventType');
goog.require('ol.interaction.Pointer');
goog.require('ol.geom.Point');
goog.require('ol.layer.Vector');
goog.require('ol.source.Vector');

/**
 * @enum {string}
 */
ngeo.RotateEventType = {
  /**
   * Triggered upon rotate draw end
   * @event ngeo.RotateEvent#rotateend
   */
  ROTATEEND: 'rotateend'

};

/**
 * @classdesc
 * Events emitted by {@link ngeo.interaction.Rotate} instances are
 * instances of this type.
 *
 * @constructor
 * @struct
 * @extends {ol.events.Event}
 * @implements {ngeox.RotateEvent}
 * @param {ngeo.RotateEventType} type Type.
 * @param {ol.Feature} feature The feature rotated.
 */
ngeo.RotateEvent = function(type, feature) {

  ol.events.Event.call(this, type);

  /**
   * The feature being rotated.
   * @type {ol.Feature}
   * @api stable
   */
  this.feature = feature;

};
ol.inherits(ngeo.RotateEvent, ol.events.Event);

/**
 * @classdesc
 * Interaction to rotate features.
 *
 * @constructor
 * @struct
 * @extends {ol.interaction.Pointer}
 * @param {olx.interaction.ModifyOptions} options Options.
 * @fires ngeo.interaction.ModifyCircleEvent
 * @export
 * @api
 */
ngeo.interaction.Rotate = function(options) {

  goog.asserts.assert(options.features);

  /**
   * @type {Array.<ol.EventsKey>}
   * @private
   */
  this.listenerKeys_ = [];

  /**
   * @type {boolean}
   * @private
   */
  this.modified_ = false;

  /**
   * @type {?goog.events.Key}
   * @private
   */
  this.keyPressListenerKey_ = null;

  /**
   * Indicate whether the interaction is currently changing a feature's
   * coordinates.
   * @type {boolean}
   * @private
   */
  this.changingFeature_ = false;

  /**
   * @type {number}
   * @private
   */
  this.pixelTolerance_ = options.pixelTolerance !== undefined ?
    options.pixelTolerance : 10;

  /**
   * @type {!ol.Collection.<ol.Feature>}
   * @private
   */
  this.features_ = options.features;

  /**
   * The feature currently modified.
   * @type {ol.Feature}
   * @private
   */
  this.feature_ = null;

  /**
   * @type {ol.Pixel}
   * @private
   */
  this.coordinate_ = null;

  /**
   * @type {ol.Coordinate}
   * @private
   */
  this.centerCoordinate_ = null;

  const style = options.style ? options.style : ol.interaction.Modify.getDefaultStyleFunction();

  /**
   * Draw overlay where sketch features are drawn.
   * @type {ol.layer.Vector}
   * @private
   */
  this.overlay_ = new ol.layer.Vector({
    source: new ol.source.Vector({
      useSpatialIndex: false,
      wrapX: !!options.wrapX
    }),
    style,
    updateWhileAnimating: true,
    updateWhileInteracting: true
  });

  /**
   * @type {!Object.<number, ol.Feature>}
   * @private
   */
  this.centerFeatures_ = {};

  ol.interaction.Pointer.call(this, {
    handleDownEvent: this.handleDown_,
    handleDragEvent: this.handleDrag_,
    handleUpEvent: this.handleUp_
  });

};
ol.inherits(ngeo.interaction.Rotate, ol.interaction.Pointer);

/**
 * Activate or deactivate the interaction.
 * @param {boolean} active Active.
 * @override
 * @export
 */
ngeo.interaction.Rotate.prototype.setActive = function(active) {

  if (this.keyPressListenerKey_) {
    goog.events.unlistenByKey(this.keyPressListenerKey_);
    this.keyPressListenerKey_ = null;
  }

  ol.interaction.Pointer.prototype.setActive.call(this, active);

  if (active) {
    this.keyPressListenerKey_ = goog.events.listen(
      document,
      'keyup',
      this.handleKeyUp_,
      false,
      this
    );
    this.features_.forEach(this.addFeature_, this);
    this.listenerKeys_.push(ol.events.listen(this.features_,
      ol.CollectionEventType.ADD, this.handleFeatureAdd_, this));
    this.listenerKeys_.push(ol.events.listen(this.features_,
      ol.CollectionEventType.REMOVE, this.handleFeatureRemove_, this));

  } else {
    this.listenerKeys_.forEach((key) => {
      ol.events.unlistenByKey(key);
    }, this);
    this.features_.forEach(this.removeFeature_, this);
  }
};

/**
 * @param {ol.Feature} feature Feature.
 * @private
 */
ngeo.interaction.Rotate.prototype.addFeature_ = function(feature) {
  const geometry = feature.getGeometry();
  goog.asserts.assertInstanceof(geometry, ol.geom.Geometry);

  feature.set('angle', 0);

  // Add the center icon to the overlay
  const uid = ol.getUid(feature);
  const point = new ol.geom.Point(this.getCenterCoordinate_(geometry));
  const centerFeature = new ol.Feature(point);
  this.centerFeatures_[uid] = centerFeature;
  this.overlay_.getSource().addFeature(centerFeature);

};

/**
 * @param {ol.MapBrowserPointerEvent} evt Map browser event
 * @private
 */
ngeo.interaction.Rotate.prototype.willModifyFeatures_ = function(evt) {
  if (!this.modified_) {
    this.modified_ = true;
    this.dispatchEvent(new ol.interaction.Modify.Event(
      ol.interaction.ModifyEventType.MODIFYSTART, this.features_, evt));
  }
};

/**
 * @param {ol.Feature} feature Feature.
 * @private
 */
ngeo.interaction.Rotate.prototype.removeFeature_ = function(feature) {
  this.feature_ = null;
  //this.overlay_.getSource().removeFeature(feature);

  if (feature) {
    const uid = ol.getUid(feature);

    if (this.centerFeatures_[uid]) {
      this.overlay_.getSource().removeFeature(this.centerFeatures_[uid]);
      delete this.centerFeatures_[uid];
    }
  }
};

/**
 * @inheritDoc
 */
ngeo.interaction.Rotate.prototype.setMap = function(map) {
  this.overlay_.setMap(map);
  ol.interaction.Pointer.prototype.setMap.call(this, map);
};

/**
 * @param {ol.Collection.Event} evt Event.
 * @private
 */
ngeo.interaction.Rotate.prototype.handleFeatureAdd_ = function(evt) {
  const feature = evt.element;
  goog.asserts.assertInstanceof(feature, ol.Feature,
    'feature should be an ol.Feature');
  this.addFeature_(feature);
};

/**
 * @param {ol.Collection.Event} evt Event.
 * @private
 */
ngeo.interaction.Rotate.prototype.handleFeatureRemove_ = function(evt) {
  const feature = /** @type {ol.Feature} */ (evt.element);
  this.removeFeature_(feature);
};

/**
 * @param {ol.MapBrowserPointerEvent} evt Event.
 * @return {boolean} Start drag sequence?
 * @private
 */
ngeo.interaction.Rotate.prototype.handleDown_ = function(evt) {
  const map = evt.map;

  let feature = map.forEachFeatureAtPixel(evt.pixel,
    (feature, layer) => feature, undefined);

  if (feature) {
    let found = false;
    this.features_.forEach((f) => {
      if (ol.getUid(f) == ol.getUid(feature)) {
        found = true;
      }
    });
    if (!found) {
      feature = null;
    }
  }

  if (feature) {
    this.coordinate_ = evt.coordinate;
    this.feature_ = feature;
    const geometry = (this.feature_.getGeometry());
    if (geometry !== undefined) {
      this.centerCoordinate_ = this.getCenterCoordinate_(geometry);
    }

    return true;
  }

  return false;
};

/**
 * @param {ol.geom.Geometry} geometry Geometry.
 * @return {ol.Coordinate} The center coordinate of the geometry.
 * @private
 */
ngeo.interaction.Rotate.prototype.getCenterCoordinate_ = function(
  geometry) {

  let center;

  if (geometry instanceof ol.geom.LineString) {
    center = geometry.getFlatMidpoint();
  } else if (geometry instanceof ol.geom.Polygon) {
    center = geometry.getFlatInteriorPoint();
  } else {
    const extent = geometry.getExtent();
    center = ol.extent.getCenter(extent);
  }

  return center;
};

/**
 * @param {ol.MapBrowserPointerEvent} evt Event.
 * @private
 */
ngeo.interaction.Rotate.prototype.handleDrag_ = function(evt) {
  this.willModifyFeatures_(evt);

  const geometry = /** @type {ol.geom.SimpleGeometry} */
      (this.feature_.getGeometry());

  const oldX = this.coordinate_[0];
  const oldY = this.coordinate_[1];

  const centerX = this.centerCoordinate_[0];
  const centerY = this.centerCoordinate_[1];

  const dx1 = oldX - centerX;
  const dy1 = oldY - centerY;
  const dx0 = evt.coordinate[0] - centerX;
  const dy0 = evt.coordinate[1] - centerY;

  this.coordinate_[0] = evt.coordinate[0];
  this.coordinate_[1] = evt.coordinate[1];

  const a0 = Math.atan2(dy0, dx0);
  const a1 = Math.atan2(dy1, dx1);
  const angle = a1 - a0;

  geometry.rotate(-angle, [centerX, centerY]);
};

/**
 * @param {ol.MapBrowserPointerEvent} evt Event.
 * @return {boolean} Stop drag sequence?
 * @private
 */
ngeo.interaction.Rotate.prototype.handleUp_ = function(evt) {
  if (this.modified_) {
    this.dispatchEvent(new ngeo.RotateEvent(ngeo.RotateEventType.ROTATEEND,
      this.feature_));
    this.modified_ = false;
    this.setActive(false);
  }
  return false;
};

/**
 * Deactivate this interaction if the ESC key is pressed.
 * @param {goog.events.Event} evt Event.
 * @private
 */
ngeo.interaction.Rotate.prototype.handleKeyUp_ = function(evt) {
  // 27 == ESC key
  if (evt.keyCode === 27) {
    this.setActive(false);
  }
};
<commit_msg>Remove goog.events usage in ngeo.interaction.Rotate<commit_after>goog.provide('ngeo.RotateEvent');
goog.provide('ngeo.RotateEventType');
goog.provide('ngeo.interaction.Rotate');

goog.require('goog.asserts');
goog.require('ol');
goog.require('ol.Collection');
goog.require('ol.Feature');
goog.require('ol.MapBrowserPointerEvent');
goog.require('ol.events');
goog.require('ol.interaction.Modify');
goog.require('ol.interaction.ModifyEventType');
goog.require('ol.interaction.Pointer');
goog.require('ol.geom.Point');
goog.require('ol.layer.Vector');
goog.require('ol.source.Vector');

/**
 * @enum {string}
 */
ngeo.RotateEventType = {
  /**
   * Triggered upon rotate draw end
   * @event ngeo.RotateEvent#rotateend
   */
  ROTATEEND: 'rotateend'

};

/**
 * @classdesc
 * Events emitted by {@link ngeo.interaction.Rotate} instances are
 * instances of this type.
 *
 * @constructor
 * @struct
 * @extends {ol.events.Event}
 * @implements {ngeox.RotateEvent}
 * @param {ngeo.RotateEventType} type Type.
 * @param {ol.Feature} feature The feature rotated.
 */
ngeo.RotateEvent = function(type, feature) {

  ol.events.Event.call(this, type);

  /**
   * The feature being rotated.
   * @type {ol.Feature}
   * @api stable
   */
  this.feature = feature;

};
ol.inherits(ngeo.RotateEvent, ol.events.Event);

/**
 * @classdesc
 * Interaction to rotate features.
 *
 * @constructor
 * @struct
 * @extends {ol.interaction.Pointer}
 * @param {olx.interaction.ModifyOptions} options Options.
 * @fires ngeo.interaction.ModifyCircleEvent
 * @export
 * @api
 */
ngeo.interaction.Rotate = function(options) {

  goog.asserts.assert(options.features);

  /**
   * @type {Array.<ol.EventsKey>}
   * @private
   */
  this.listenerKeys_ = [];

  /**
   * @type {boolean}
   * @private
   */
  this.modified_ = false;

  /**
   * @type {?ol.EventsKey}
   * @private
   */
  this.keyPressListenerKey_ = null;

  /**
   * Indicate whether the interaction is currently changing a feature's
   * coordinates.
   * @type {boolean}
   * @private
   */
  this.changingFeature_ = false;

  /**
   * @type {number}
   * @private
   */
  this.pixelTolerance_ = options.pixelTolerance !== undefined ?
    options.pixelTolerance : 10;

  /**
   * @type {!ol.Collection.<ol.Feature>}
   * @private
   */
  this.features_ = options.features;

  /**
   * The feature currently modified.
   * @type {ol.Feature}
   * @private
   */
  this.feature_ = null;

  /**
   * @type {ol.Pixel}
   * @private
   */
  this.coordinate_ = null;

  /**
   * @type {ol.Coordinate}
   * @private
   */
  this.centerCoordinate_ = null;

  const style = options.style ? options.style : ol.interaction.Modify.getDefaultStyleFunction();

  /**
   * Draw overlay where sketch features are drawn.
   * @type {ol.layer.Vector}
   * @private
   */
  this.overlay_ = new ol.layer.Vector({
    source: new ol.source.Vector({
      useSpatialIndex: false,
      wrapX: !!options.wrapX
    }),
    style,
    updateWhileAnimating: true,
    updateWhileInteracting: true
  });

  /**
   * @type {!Object.<number, ol.Feature>}
   * @private
   */
  this.centerFeatures_ = {};

  ol.interaction.Pointer.call(this, {
    handleDownEvent: this.handleDown_,
    handleDragEvent: this.handleDrag_,
    handleUpEvent: this.handleUp_
  });

};
ol.inherits(ngeo.interaction.Rotate, ol.interaction.Pointer);

/**
 * Activate or deactivate the interaction.
 * @param {boolean} active Active.
 * @override
 * @export
 */
ngeo.interaction.Rotate.prototype.setActive = function(active) {

  if (this.keyPressListenerKey_) {
    ol.events.unlistenByKey(this.keyPressListenerKey_);
    this.keyPressListenerKey_ = null;
  }

  ol.interaction.Pointer.prototype.setActive.call(this, active);

  if (active) {
    this.keyPressListenerKey_ = ol.events.listen(
      document,
      'keyup',
      this.handleKeyUp_,
      this
    );
    this.features_.forEach(this.addFeature_, this);
    this.listenerKeys_.push(ol.events.listen(this.features_,
      ol.CollectionEventType.ADD, this.handleFeatureAdd_, this));
    this.listenerKeys_.push(ol.events.listen(this.features_,
      ol.CollectionEventType.REMOVE, this.handleFeatureRemove_, this));

  } else {
    this.listenerKeys_.forEach((key) => {
      ol.events.unlistenByKey(key);
    }, this);
    this.features_.forEach(this.removeFeature_, this);
  }
};

/**
 * @param {ol.Feature} feature Feature.
 * @private
 */
ngeo.interaction.Rotate.prototype.addFeature_ = function(feature) {
  const geometry = feature.getGeometry();
  goog.asserts.assertInstanceof(geometry, ol.geom.Geometry);

  feature.set('angle', 0);

  // Add the center icon to the overlay
  const uid = ol.getUid(feature);
  const point = new ol.geom.Point(this.getCenterCoordinate_(geometry));
  const centerFeature = new ol.Feature(point);
  this.centerFeatures_[uid] = centerFeature;
  this.overlay_.getSource().addFeature(centerFeature);

};

/**
 * @param {ol.MapBrowserPointerEvent} evt Map browser event
 * @private
 */
ngeo.interaction.Rotate.prototype.willModifyFeatures_ = function(evt) {
  if (!this.modified_) {
    this.modified_ = true;
    this.dispatchEvent(new ol.interaction.Modify.Event(
      ol.interaction.ModifyEventType.MODIFYSTART, this.features_, evt));
  }
};

/**
 * @param {ol.Feature} feature Feature.
 * @private
 */
ngeo.interaction.Rotate.prototype.removeFeature_ = function(feature) {
  this.feature_ = null;
  //this.overlay_.getSource().removeFeature(feature);

  if (feature) {
    const uid = ol.getUid(feature);

    if (this.centerFeatures_[uid]) {
      this.overlay_.getSource().removeFeature(this.centerFeatures_[uid]);
      delete this.centerFeatures_[uid];
    }
  }
};

/**
 * @inheritDoc
 */
ngeo.interaction.Rotate.prototype.setMap = function(map) {
  this.overlay_.setMap(map);
  ol.interaction.Pointer.prototype.setMap.call(this, map);
};

/**
 * @param {ol.Collection.Event} evt Event.
 * @private
 */
ngeo.interaction.Rotate.prototype.handleFeatureAdd_ = function(evt) {
  const feature = evt.element;
  goog.asserts.assertInstanceof(feature, ol.Feature,
    'feature should be an ol.Feature');
  this.addFeature_(feature);
};

/**
 * @param {ol.Collection.Event} evt Event.
 * @private
 */
ngeo.interaction.Rotate.prototype.handleFeatureRemove_ = function(evt) {
  const feature = /** @type {ol.Feature} */ (evt.element);
  this.removeFeature_(feature);
};

/**
 * @param {ol.MapBrowserPointerEvent} evt Event.
 * @return {boolean} Start drag sequence?
 * @private
 */
ngeo.interaction.Rotate.prototype.handleDown_ = function(evt) {
  const map = evt.map;

  let feature = map.forEachFeatureAtPixel(evt.pixel,
    (feature, layer) => feature, undefined);

  if (feature) {
    let found = false;
    this.features_.forEach((f) => {
      if (ol.getUid(f) == ol.getUid(feature)) {
        found = true;
      }
    });
    if (!found) {
      feature = null;
    }
  }

  if (feature) {
    this.coordinate_ = evt.coordinate;
    this.feature_ = feature;
    const geometry = (this.feature_.getGeometry());
    if (geometry !== undefined) {
      this.centerCoordinate_ = this.getCenterCoordinate_(geometry);
    }

    return true;
  }

  return false;
};

/**
 * @param {ol.geom.Geometry} geometry Geometry.
 * @return {ol.Coordinate} The center coordinate of the geometry.
 * @private
 */
ngeo.interaction.Rotate.prototype.getCenterCoordinate_ = function(
  geometry) {

  let center;

  if (geometry instanceof ol.geom.LineString) {
    center = geometry.getFlatMidpoint();
  } else if (geometry instanceof ol.geom.Polygon) {
    center = geometry.getFlatInteriorPoint();
  } else {
    const extent = geometry.getExtent();
    center = ol.extent.getCenter(extent);
  }

  return center;
};

/**
 * @param {ol.MapBrowserPointerEvent} evt Event.
 * @private
 */
ngeo.interaction.Rotate.prototype.handleDrag_ = function(evt) {
  this.willModifyFeatures_(evt);

  const geometry = /** @type {ol.geom.SimpleGeometry} */
      (this.feature_.getGeometry());

  const oldX = this.coordinate_[0];
  const oldY = this.coordinate_[1];

  const centerX = this.centerCoordinate_[0];
  const centerY = this.centerCoordinate_[1];

  const dx1 = oldX - centerX;
  const dy1 = oldY - centerY;
  const dx0 = evt.coordinate[0] - centerX;
  const dy0 = evt.coordinate[1] - centerY;

  this.coordinate_[0] = evt.coordinate[0];
  this.coordinate_[1] = evt.coordinate[1];

  const a0 = Math.atan2(dy0, dx0);
  const a1 = Math.atan2(dy1, dx1);
  const angle = a1 - a0;

  geometry.rotate(-angle, [centerX, centerY]);
};

/**
 * @param {ol.MapBrowserPointerEvent} evt Event.
 * @return {boolean} Stop drag sequence?
 * @private
 */
ngeo.interaction.Rotate.prototype.handleUp_ = function(evt) {
  if (this.modified_) {
    this.dispatchEvent(new ngeo.RotateEvent(ngeo.RotateEventType.ROTATEEND,
      this.feature_));
    this.modified_ = false;
    this.setActive(false);
  }
  return false;
};

/**
 * Deactivate this interaction if the ESC key is pressed.
 * @param {KeyboardEvent} evt Event.
 * @private
 */
ngeo.interaction.Rotate.prototype.handleKeyUp_ = function(evt) {
  // 27 == ESC key
  if (evt.keyCode === 27) {
    this.setActive(false);
  }
};
<|endoftext|>


<commit_before>(function (ng, app) {
    app.config(['$stateProvider', function ($stateProvider) {
        $stateProvider.state('it-project.edit.communication', {
            url: '/communication',
            templateUrl: 'partials/it-project/tab-communication.html',
            controller: 'project.EditCommunicationCtrl',
            resolve: {
                comms: ['$http', '$stateParams', function ($http, $stateParams) {
                    return $http.get('api/communication/' + $stateParams.id + '?project=true').then(function (result) {
                        return result.data.response;
                    });
                }],
                //returns a map with those users who have a role in this project.
                //the names of the roles is saved in user.roleNames
                usersWithRoles: ['$http', '$stateParams', function ($http, $stateParams) {

                    //get the rights of the projects
                    return $http.get("api/itprojectrights/" + $stateParams.id)
                        .then(function (rightResult) {
                            var rights = rightResult.data.response;

                            //get the role names
                            return $http.get("api/itprojectrole/")
                                .then(function (roleResult) {
                                    var roles = roleResult.data.response;

                                    //the resulting map
                                    var users = {};
                                    _.each(rights, function (right) {

                                        //use the user from the map if possible
                                        var user = users[right.userId] || right.user;

                                        var role = _.findWhere(roles, { id: right.roleId });

                                        var roleNames = user.roleNames || [];
                                        roleNames.push(role.name);
                                        user.roleNames = roleNames;

                                        users[right.userId] = user;
                                    });

                                    return users;

                                });

                        });
                }]
            }
        });
    }]);

    app.controller('project.EditCommunicationCtrl',
    ['$scope', '$http', '$timeout', '$state', '$stateParams', 'comms', 'usersWithRoles',
        function ($scope, $http, $timeout, $state, $stateParams, comms, usersWithRoles) {
            $scope.comms = comms;
            $scope.usersWithRoles = _.values(usersWithRoles);

            $scope.comm = {
                itProjectId: $stateParams.id
            };
            $scope.save = function () {
                $scope.$broadcast('show-errors-check-validity');

                if ($scope.commForm.$invalid) { return; }

                $http.post('api/communication', $scope.comm).finally(reload);
            };

            // work around for $state.reload() not updating scope
            // https://github.com/angular-ui/ui-router/issues/582
            function reload() {
                return $state.transitionTo($state.current, $stateParams, {
                    reload: true
                }).then(function () {
                    $scope.hideContent = true;
                    return $timeout(function () {
                        return $scope.hideContent = false;
                    }, 1);
                });
            };
        }]);
})(angular, app);<commit_msg>Added delete function<commit_after>(function (ng, app) {
    app.config(['$stateProvider', function ($stateProvider) {
        $stateProvider.state('it-project.edit.communication', {
            url: '/communication',
            templateUrl: 'partials/it-project/tab-communication.html',
            controller: 'project.EditCommunicationCtrl',
            resolve: {
                comms: ['$http', '$stateParams', function ($http, $stateParams) {
                    return $http.get('api/communication/' + $stateParams.id + '?project=true').then(function (result) {
                        return result.data.response;
                    });
                }],
                //returns a map with those users who have a role in this project.
                //the names of the roles is saved in user.roleNames
                usersWithRoles: ['$http', '$stateParams', function ($http, $stateParams) {

                    //get the rights of the projects
                    return $http.get("api/itprojectrights/" + $stateParams.id)
                        .then(function (rightResult) {
                            var rights = rightResult.data.response;

                            //get the role names
                            return $http.get("api/itprojectrole/")
                                .then(function (roleResult) {
                                    var roles = roleResult.data.response;

                                    //the resulting map
                                    var users = {};
                                    _.each(rights, function (right) {

                                        //use the user from the map if possible
                                        var user = users[right.userId] || right.user;

                                        var role = _.findWhere(roles, { id: right.roleId });

                                        var roleNames = user.roleNames || [];
                                        roleNames.push(role.name);
                                        user.roleNames = roleNames;

                                        users[right.userId] = user;
                                    });

                                    return users;

                                });

                        });
                }]
            }
        });
    }]);

    app.controller('project.EditCommunicationCtrl',
    ['$scope', '$http', '$timeout', '$state', '$stateParams', 'comms', 'usersWithRoles',
        function ($scope, $http, $timeout, $state, $stateParams, comms, usersWithRoles) {
            $scope.comms = comms;
            $scope.usersWithRoles = _.values(usersWithRoles);

            $scope.comm = {
                itProjectId: $stateParams.id
            };

            $scope.save = function () {
                $scope.$broadcast('show-errors-check-validity');

                if ($scope.commForm.$invalid) { return; }

                $http.post('api/communication', $scope.comm).finally(reload);
            };

            $scope.delete = function(id) {
                $http.delete('api/communication/' + id).finally(reload);
            }

            // work around for $state.reload() not updating scope
            // https://github.com/angular-ui/ui-router/issues/582
            function reload() {
                return $state.transitionTo($state.current, $stateParams, {
                    reload: true
                }).then(function () {
                    $scope.hideContent = true;
                    return $timeout(function () {
                        return $scope.hideContent = false;
                    }, 1);
                });
            };
        }]);
})(angular, app);<|endoftext|>


<commit_before>/*
 * jitsu.js: Top-level include for the jitsu module.
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

require.paths.unshift(__dirname);

var jitsu = exports;

// Failure HTTP Response codes based
// off of `/lib/broodmother/slave/service.js`
var failCodes = jitsu.failCodes = {
  400: 'Bad Request',
  403: 'Not Authorized',
  404: 'Item not found',
  409: 'Conflict',
  500: 'Internal Server Error'
};

// Success HTTP Response codes based
// off of `/lib/broodmother/slave/service.js`
var successCodes = jitsu.successCodes = {
  200: 'OK',
  201: 'Created'
};

jitsu.skipAuth          = false;
jitsu.started           = false;
jitsu.utils             = require('jitsu/utils');
jitsu.package           = require('jitsu/package');
jitsu.log               = require('cliff');
jitsu.api               = {};
jitsu.api.Client        = require('jitsu/api/client').Client;
jitsu.api.Apps          = require('jitsu/api/apps').Apps;
jitsu.api.Databases     = require('jitsu/api/databases').Databases;
jitsu.api.Logs          = require('jitsu/api/logs').Logs;
jitsu.api.Snapshots     = require('jitsu/api/snapshots').Snapshots;
jitsu.api.Users         = require('jitsu/api/users').Users;
jitsu.prompt            = require('prompt');
jitsu.prompt.properties = require('jitsu/properties').properties;
jitsu.config            = require('jitsu/config');
jitsu.commands          = require('jitsu/commands');

//
// Alias the appropriate commands for simplier CLI usage
//
jitsu.commands.alias('create', { resource: 'apps',   command: 'create' });
jitsu.commands.alias('deploy', { resource: 'apps',   command: 'deploy' });
jitsu.commands.alias('list',   { resource: 'apps',   command: 'list' });
jitsu.commands.alias('conf',   { resource: 'config', command: 'list' });
jitsu.commands.alias('logout', { resource: 'users',  command: 'logout' });

var eyes = require('eyes'),
    winston = require('winston'),
    colors = require('colors');

//
// Setup `jitsu` to use `pkginfo` to expose version
//
require('pkginfo')(module, 'version');

//
// ### function start (command, callback)
// #### @command {string} Command to execute once started
// #### @callback {function} Continuation to pass control to when complete.
// Starts the jitsu CLI and runs the specified command.
//
jitsu.start = function (argv, callback) {
  var command = argv._;

  if (argv.version || argv.v) {
    console.log('v' + jitsu.version);
    process.exit(0);
  }

  // Setup the initial prompt but don't leave it open
  jitsu.prompt.start().pause();

  //
  // Default to the `help` command.
  //
  command[0] || (command[0] = 'help');

  winston.info('Welcome to ' + 'Nodejitsu'.grey);
  winston.info('It worked if it ends with ' + 'Nodejitsu'.grey + ' ok'.green.bold);
  jitsu.utils.checkVersion(function () {
    jitsu.config.load(function (err) {
      if (err) {
        callback(err)//need it to callback in order to test error paths.
        return jitsu.showError.apply(null, [command[0]].concat([].slice.call(arguments)));
      }

      var username = jitsu.config.get('username');
      if (!username && jitsu.commands.requiresAuth(command[0])) {
        return jitsu.setupUser(function (err) {
          if (err) {
            callback(err)//need it to callback in order to test error paths.
            return jitsu.showError.apply(jitsu, [command[0]].concat([].slice.call(arguments)));
          }

          var username = jitsu.config.get('username');
          winston.info('Successfully configured user ' + username.magenta);
          return command.length > 0 ? jitsu.exec(command, callback) : callback();
        });
      }

      return jitsu.exec(command, callback)
    });
  });
};

//
// ### function exec (command, callback)
// #### @command {string} Command to execute
// #### @callback {function} Continuation to pass control to when complete.
// Runs the specified command in the jitsu CLI.
//
jitsu.exec = function (command, callback) {
  function execCommand (err) {
    if (err) {
      return callback(err);
    }

    winston.info('Executing command ' + command.join(' ').magenta);
    jitsu.commands.run(command, function (err, shallow) {
      if (err) {
        callback(err)//need it to callback in order to test error paths.
        return jitsu.showError(command.join(' '), err, shallow);
      }

      //
      // TODO (indexzero): Something here
      //
      callback();
    });
  }

  return !jitsu.started ? jitsu.setup(execCommand) : execCommand();
};

//
// ### function setup (callback)
// #### @callback {function} Continuation to pass control to when complete.
// Sets up the instances of the Resource clients for jitsu.
// there is no io here, yet this function is ASYNC.
//
jitsu.setup = function (callback) {
  if (jitsu.started === true) {
    return callback();
  }

  jitsu.users = new jitsu.api.Users(jitsu.config);
  jitsu.apps = new jitsu.api.Apps(jitsu.config);
  jitsu.snapshots = new jitsu.api.Snapshots(jitsu.config);
  jitsu.databases = new jitsu.api.Databases(jitsu.config);
  jitsu.logs = new jitsu.api.Logs(jitsu.config);
  jitsu.started = true;

  callback();
};

//
// ### function auth (callback)
// #### @callback {function} Continuation to pass control to when complete.
// Attempts to authenicate the user identified in `jitsu.config.get('username'|'password')`
//
jitsu.auth = function (callback) {
  if (jitsu.skipAuth) {
    return callback();
  }

  var username = jitsu.config.get('username');
  winston.silly('Attempting to authenticate as ' + username.magenta);
  jitsu.users.auth(function (err, success) {
    if (err || !success) {
      winston.error('Unable to Authenticate as ' + username.magenta);
      winston.error(err.message);
      return callback(err);
    }

    jitsu.skipAuth = true;
    winston.info('Authenticated as ' + username.magenta);
    return callback();
  })
}

//
// ### function setupUser (callback)
// #### @callback {function} Continuation to pass control to when complete.
// Prompts the user for their username / password combo, then sets up the jitsu CLI,
// and saves the resulting configuration to disk.
//
jitsu.setupUser = function (callback) {
  winston.warn('No user has been setup on this machine');

  //
  // Attempt to get the password three times.
  //
  var tries = 0;

  (function setupAuth () {
    jitsu.prompt.get(['username', 'password'], function (err, result) {
      if (err) {
        return callback(err);
      }

      jitsu.config.set('username', result.username);
      jitsu.config.set('password', result.password);
      jitsu.setup(function () {
        jitsu.auth(function (err) {
          //
          // Increment the auth attempts
          //
          tries += 1;

          if (err) {
            if (tries >= 3) {
              winston.error('Exiting: Three failed login attempts');
              return callback(err);
            }

            return setupAuth();
          }

          jitsu.config.save(function (err) {
            return err ? callback(err) : callback();
          });
        });
      });
    });
  })();
};

//
// ### function showError (command, err, shallow, skip)
// #### @command {string} Command which has errored.
// #### @err {Error} Error received for the command.
// #### @shallow {boolean} Value indicating if a deep stack should be displayed
// #### @skip {boolean} Value indicating if this error should be forcibly suppressed.
// Displays the `err` to the user for the `command` supplied.
//
jitsu.showError = function (command, err, shallow, skip) {
  if (err.statusCode !== '403' && !skip) {
    winston.error('Error running command ' + command.magenta);

    if (err.message) {
      winston.error(err.message);
    }

    if (err.result) {
      if (err.result.error) {
        winston.error(err.result.error);
      }

      if (err.result.result && err.result.result.error && err.result.result.error.stack) {
        winston.warn('Error returned from Haibu');
        winston.error('Message: ' + err.result.result.error.message);
        winston.error('');
        err.result.result.error.stack.split('\n').forEach(function (line) {
          winston.error(line);
        })
      }
      else if (err.result.stack) {
        winston.warn('Error returned from Nodejitsu');
        err.result.stack.split('\n').forEach(function (line) {
          winston.error(line);
        })
      }
    }
    else {
      if (err.stack && !shallow) {
        err.stack.split('\n').forEach(function (trace) {
          winston.error(trace);
        });
      }
    }
  }

  winston.info('Nodejitsu '.grey + 'not ok'.red.bold);
};
<commit_msg>[minor] Small style updates (no trailing line comments. kthxbai)<commit_after>/*
 * jitsu.js: Top-level include for the jitsu module.
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

require.paths.unshift(__dirname);

var jitsu = exports;

// Failure HTTP Response codes based
// off of `/lib/broodmother/slave/service.js`
var failCodes = jitsu.failCodes = {
  400: 'Bad Request',
  403: 'Not Authorized',
  404: 'Item not found',
  409: 'Conflict',
  500: 'Internal Server Error'
};

// Success HTTP Response codes based
// off of `/lib/broodmother/slave/service.js`
var successCodes = jitsu.successCodes = {
  200: 'OK',
  201: 'Created'
};

jitsu.skipAuth          = false;
jitsu.started           = false;
jitsu.utils             = require('jitsu/utils');
jitsu.package           = require('jitsu/package');
jitsu.log               = require('cliff');
jitsu.api               = {};
jitsu.api.Client        = require('jitsu/api/client').Client;
jitsu.api.Apps          = require('jitsu/api/apps').Apps;
jitsu.api.Databases     = require('jitsu/api/databases').Databases;
jitsu.api.Logs          = require('jitsu/api/logs').Logs;
jitsu.api.Snapshots     = require('jitsu/api/snapshots').Snapshots;
jitsu.api.Users         = require('jitsu/api/users').Users;
jitsu.prompt            = require('prompt');
jitsu.prompt.properties = require('jitsu/properties').properties;
jitsu.config            = require('jitsu/config');
jitsu.commands          = require('jitsu/commands');

//
// Alias the appropriate commands for simplier CLI usage
//
jitsu.commands.alias('create', { resource: 'apps',   command: 'create' });
jitsu.commands.alias('deploy', { resource: 'apps',   command: 'deploy' });
jitsu.commands.alias('list',   { resource: 'apps',   command: 'list' });
jitsu.commands.alias('conf',   { resource: 'config', command: 'list' });
jitsu.commands.alias('logout', { resource: 'users',  command: 'logout' });

var eyes = require('eyes'),
    winston = require('winston'),
    colors = require('colors');

//
// Setup `jitsu` to use `pkginfo` to expose version
//
require('pkginfo')(module, 'version');

//
// ### function start (command, callback)
// #### @command {string} Command to execute once started
// #### @callback {function} Continuation to pass control to when complete.
// Starts the jitsu CLI and runs the specified command.
//
jitsu.start = function (argv, callback) {
  var command = argv._;

  if (argv.version || argv.v) {
    console.log('v' + jitsu.version);
    process.exit(0);
  }

  // Setup the initial prompt but don't leave it open
  jitsu.prompt.start().pause();

  //
  // Default to the `help` command.
  //
  command[0] || (command[0] = 'help');

  winston.info('Welcome to ' + 'Nodejitsu'.grey);
  winston.info('It worked if it ends with ' + 'Nodejitsu'.grey + ' ok'.green.bold);
  jitsu.utils.checkVersion(function () {
    jitsu.config.load(function (err) {
      if (err) {
        callback(err);
        return jitsu.showError.apply(null, [command[0]].concat(arguments));
      }

      var username = jitsu.config.get('username');
      if (!username && jitsu.commands.requiresAuth(command[0])) {
        return jitsu.setupUser(function (err) {
          if (err) {
            callback(err);
            return jitsu.showError.apply(jitsu, [command[0]].concat(arguments));
          }

          var username = jitsu.config.get('username');
          winston.info('Successfully configured user ' + username.magenta);
          return command.length > 0 ? jitsu.exec(command, callback) : callback();
        });
      }

      return jitsu.exec(command, callback)
    });
  });
};

//
// ### function exec (command, callback)
// #### @command {string} Command to execute
// #### @callback {function} Continuation to pass control to when complete.
// Runs the specified command in the jitsu CLI.
//
jitsu.exec = function (command, callback) {
  function execCommand (err) {
    if (err) {
      return callback(err);
    }

    winston.info('Executing command ' + command.join(' ').magenta);
    jitsu.commands.run(command, function (err, shallow) {
      if (err) {
        callback(err);
        return jitsu.showError(command.join(' '), err, shallow);
      }

      //
      // TODO (indexzero): Something here
      //
      callback();
    });
  }

  return !jitsu.started ? jitsu.setup(execCommand) : execCommand();
};

//
// ### function setup (callback)
// #### @callback {function} Continuation to pass control to when complete.
// Sets up the instances of the Resource clients for jitsu.
// there is no io here, yet this function is ASYNC.
//
jitsu.setup = function (callback) {
  if (jitsu.started === true) {
    return callback();
  }

  jitsu.users = new jitsu.api.Users(jitsu.config);
  jitsu.apps = new jitsu.api.Apps(jitsu.config);
  jitsu.snapshots = new jitsu.api.Snapshots(jitsu.config);
  jitsu.databases = new jitsu.api.Databases(jitsu.config);
  jitsu.logs = new jitsu.api.Logs(jitsu.config);
  jitsu.started = true;

  callback();
};

//
// ### function auth (callback)
// #### @callback {function} Continuation to pass control to when complete.
// Attempts to authenicate the user identified in `jitsu.config.get('username'|'password')`
//
jitsu.auth = function (callback) {
  if (jitsu.skipAuth) {
    return callback();
  }

  var username = jitsu.config.get('username');
  winston.silly('Attempting to authenticate as ' + username.magenta);
  jitsu.users.auth(function (err, success) {
    if (err || !success) {
      winston.error('Unable to Authenticate as ' + username.magenta);
      winston.error(err.message);
      return callback(err);
    }

    jitsu.skipAuth = true;
    winston.info('Authenticated as ' + username.magenta);
    return callback();
  })
}

//
// ### function setupUser (callback)
// #### @callback {function} Continuation to pass control to when complete.
// Prompts the user for their username / password combo, then sets up the jitsu CLI,
// and saves the resulting configuration to disk.
//
jitsu.setupUser = function (callback) {
  winston.warn('No user has been setup on this machine');

  //
  // Attempt to get the password three times.
  //
  var tries = 0;

  (function setupAuth () {
    jitsu.prompt.get(['username', 'password'], function (err, result) {
      if (err) {
        return callback(err);
      }

      jitsu.config.set('username', result.username);
      jitsu.config.set('password', result.password);
      jitsu.setup(function () {
        jitsu.auth(function (err) {
          //
          // Increment the auth attempts
          //
          tries += 1;

          if (err) {
            if (tries >= 3) {
              winston.error('Exiting: Three failed login attempts');
              return callback(err);
            }

            return setupAuth();
          }

          jitsu.config.save(function (err) {
            return err ? callback(err) : callback();
          });
        });
      });
    });
  })();
};

//
// ### function showError (command, err, shallow, skip)
// #### @command {string} Command which has errored.
// #### @err {Error} Error received for the command.
// #### @shallow {boolean} Value indicating if a deep stack should be displayed
// #### @skip {boolean} Value indicating if this error should be forcibly suppressed.
// Displays the `err` to the user for the `command` supplied.
//
jitsu.showError = function (command, err, shallow, skip) {
  if (err.statusCode !== '403' && !skip) {
    winston.error('Error running command ' + command.magenta);

    if (err.message) {
      winston.error(err.message);
    }

    if (err.result) {
      if (err.result.error) {
        winston.error(err.result.error);
      }

      if (err.result.result && err.result.result.error && err.result.result.error.stack) {
        winston.warn('Error returned from Haibu');
        winston.error('Message: ' + err.result.result.error.message);
        winston.error('');
        err.result.result.error.stack.split('\n').forEach(function (line) {
          winston.error(line);
        })
      }
      else if (err.result.stack) {
        winston.warn('Error returned from Nodejitsu');
        err.result.stack.split('\n').forEach(function (line) {
          winston.error(line);
        })
      }
    }
    else {
      if (err.stack && !shallow) {
        err.stack.split('\n').forEach(function (trace) {
          winston.error(trace);
        });
      }
    }
  }

  winston.info('Nodejitsu '.grey + 'not ok'.red.bold);
};
<|endoftext|>


<commit_before>'use strict';

/*
 * API Routes for List Content
 *
 * API calls related to simple lists.
 */

angular.module('apiRoutes.lists', [])
.factory('ApiRoutesSimpleLists', ['ApiService', function (API) {

    var api = {};

    var getList = function(path) {
        return $q(function (resolve, reject) {
            API.get(path, {}).then(
                function(success) {
                    return resolve(success.list);
                }, function(error) {
                    console.log(error);
                    return resolve([]);
                });
        });
    };

    api.simpleUsersList = function() {
        return getList('/simple-list/users');
    };

    api.simpleGroupsList = function() {
        return getList('/simple-list/user-groups');
    };

    api.simpleRolesList = function() {
        return getList('/simple-list/group-roles');
    };

    api.simpleVisibilityFieldList = function() {
        return getList('/simple-list/visibility-fields');
    };

    return api;
}]);<commit_msg>Bug fix. Missing include.<commit_after>'use strict';

/*
 * API Routes for List Content
 *
 * API calls related to simple lists.
 */

angular.module('apiRoutes.lists', [])
.factory('ApiRoutesSimpleLists', ['ApiService', '$q', function (API, $q) {

    var api = {};

    var getList = function(path) {
        return $q(function (resolve, reject) {
            API.get(path, {}).then(
                function(success) {
                    return resolve(success.list);
                }, function(error) {
                    console.log(error);
                    return resolve([]);
                });
        });
    };

    api.simpleUsersList = function() {
        return getList('/simple-list/users');
    };

    api.simpleGroupsList = function() {
        return getList('/simple-list/user-groups');
    };

    api.simpleRolesList = function() {
        return getList('/simple-list/group-roles');
    };

    api.simpleVisibilityFieldList = function() {
        return getList('/simple-list/visibility-fields');
    };

    return api;
}]);<|endoftext|>


<commit_before>
/**
 * juice
 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

 "use strict";

/**
 * Module dependencies.
 */

var utils = require('./utils');
var Selector = require('./selector');
var Property = require('./property');
var packageJson = require('../package');
var fs = require('fs');
var path = require('path');
var styleSelector = new Selector('<style attribute>', [1, 0, 0, 0]);
var importantSelector = new Selector('<!important>', [2, 0, 0, 0]);

var juice = function (html,options) {
  var $ = utils.cheerio(html, { xmlMode: options && options.xmlMode});
  var doc = juiceDocument($,options);

  if (options && options.xmlMode){
    return doc.xml();
  }
  else {
    return utils.decodeEntities(doc.html());
  }
};

module.exports = juice;

/**
 * Package version
 */

juice.version = packageJson.version;

/**
 * Export Selector.
 */

juice.Selector = Selector;

/**
 * Export Property.
 */

juice.Property = Property;

/**
 * Export utils.
 */

juice.utils = require('./utils');

juice.ignoredPseudos = ['hover', 'active', 'focus', 'visited', 'link'];
juice.widthElements = ['TABLE', 'TD', 'IMG'];
juice.tableElements = ['TABLE', 'TD', 'TH', 'TR', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'THEAD', 'TBODY', 'TFOOT'];
juice.styleToAttribute = {
  'background-color': 'bgcolor',
  'background-image': 'background',
  'text-align': 'align',
  'vertical-align': 'valign'
};

juice.juiceDocument = juiceDocument;
juice.juiceResources = juiceResources;
juice.juiceFile = juiceFile;
juice.inlineDocument = inlineDocument;
juice.inlineContent = inlineContent;

function inlineDocument($, css, options) {

  var rules = utils.parseCSS(css);
  var editedElements = [];

  rules.forEach(handleRule);
  editedElements.forEach(setStyleAttrs);

  if (options && options.inlinePseudoElements) {
    editedElements.forEach(inlinePseudoElements);
  }

  if (options && options.applyWidthAttributes) {
    editedElements.forEach(setWidthAttrs);
  }

  if (options && options.applyAttributesTableElements) {
    editedElements.forEach(setAttributesOnTableElements);
  }

  function handleRule(rule) {
    var sel = rule[0];
    var style = rule[1];
    var selector = new Selector(sel);
    var parsedSelector = selector.parsed();
    var pseudoElementType = getPseudoElementType(parsedSelector);

    // skip rule if the selector has any pseudos which are ignored
    for (var i = 0; i < parsedSelector.length; ++i) {
      var subSel = parsedSelector[i];
      if (subSel.pseudos) {
        for (var j = 0; j < subSel.pseudos.length; ++j) {
          var subSelPseudo = subSel.pseudos[j];
          if (juice.ignoredPseudos.indexOf(subSelPseudo.name) >= 0) {
            return;
          }
        }
      }
    }

    if (pseudoElementType) {
      var last = parsedSelector[parsedSelector.length - 1];
      var pseudos = last.pseudos;
      last.pseudos = filterElementPseudos(last.pseudos);
      sel = parsedSelector.toString();
      last.pseudos = pseudos;
    }

    var els;
    try {
      els = $(sel);
    } catch (err) {
      // skip invalid selector
      return;
    }

    els.each(function () {
      var el = this;

      if (pseudoElementType) {
        var pseudoElPropName = "pseudo" + pseudoElementType;
        var pseudoEl = el[pseudoElPropName];
        if (!pseudoEl) {
          pseudoEl = el[pseudoElPropName] = $("<span />");
          pseudoEl.pseudoElementType = pseudoElementType;
          pseudoEl.pseudoElementParent = el;
          el[pseudoElPropName] = pseudoEl;
        }
        el = pseudoEl;
      }

      if (!el.styleProps) {
        el.styleProps = {};

        // if the element has inline styles, fake selector with topmost specificity
        if ($(el).attr('style')) {
          var cssText = '* { ' + $(el).attr('style') + ' } ';
          addProps(utils.parseCSS(cssText)[0][1], styleSelector);
        }

        // store reference to an element we need to compile style="" attr for
        editedElements.push(el);
      }

      // go through the properties
      function addProps (style, selector) {
        for (var i = 0, l = style.length; i < l; i++) {
          var name = style[i];
          var value = style[name] + (options && options.preserveImportant && style._importants[name] ? ' !important' : '');
          var sel = style._importants[name] ? importantSelector : selector;
          var prop = new Property(name, value, sel);
          var existing = el.styleProps[name];

          if (existing && existing.compare(prop) === prop || !existing) {
            el.styleProps[name] = prop;
          }
        }
      }

      addProps(style, selector);
    });
  }

  function setStyleAttrs(el) {
    var props = Object.keys(el.styleProps).map(function(key) {
      return el.styleProps[key];
    });
    // sort properties by their originating selector's specificity so that
    // props like "padding" and "padding-bottom" are resolved as expected.
    props.sort(function(a, b) {
      return a.selector.specificity().join("").localeCompare(
        b.selector.specificity().join(""));
    });
    var string = props
      .filter(function(prop) {
        // Content becomes the innerHTML of pseudo elements, not used as a
        // style property
        return prop.prop !== "content";
      })
      .map(function(prop) {
        return prop.prop + ": " + prop.value.replace(/["]/g, "'") + ";";
      })
      .join(" ");
    if (string) {
      $(el).attr('style', string);
    }
  }

  function inlinePseudoElements(el) {
    if (el.pseudoElementType && el.styleProps.content) {
      el.html(parseContent(el.styleProps.content.value));
      var parent = el.pseudoElementParent;
      if (el.pseudoElementType === "before") {
        $(parent).prepend(el);
      }
      else {
        $(parent).append(el);
      }
    }
  }

  function setWidthAttrs(el) {
    var elName = el.name.toUpperCase();
    if (juice.widthElements.indexOf(elName) > -1) {
      for (var i in el.styleProps) {
        if (el.styleProps[i].prop === 'width' && el.styleProps[i].value.match(/px/)) {
          var pxWidth = el.styleProps[i].value.replace('px', '');
          $(el).attr('width', pxWidth);
          return;
        }
      }
    }
  }

  function setAttributesOnTableElements(el) {
    var elName = el.name.toUpperCase(),
        styleProps = Object.keys(juice.styleToAttribute);

    if (juice.tableElements.indexOf(elName) > -1) {
      for (var i in el.styleProps) {
        if (styleProps.indexOf(el.styleProps[i].prop) > -1) {
          $(el).attr(juice.styleToAttribute[el.styleProps[i].prop], el.styleProps[i].value);
        }
      }
    }
  }
}

function parseContent(content) {
  if (content === "none" || content === "normal") {
    return "";
  }

  // Naive parsing, assume well-formed value
  content = content.slice(1, content.length - 1);
  // Naive unescape, assume no unicode char codes
  content = content.replace(/\\/g, "");
  return content;
}

// Return "before" or "after" if the given selector is a pseudo element (e.g.,
// a::after).
function getPseudoElementType(selector) {
  if (selector.length === 0) {
    return;
  }

  var pseudos = selector[selector.length - 1].pseudos;
  if (!pseudos) {
    return;
  }

  for (var i = 0; i < pseudos.length; i++) {
    if (isPseudoElementName(pseudos[i])) {
      return pseudos[i].name;
    }
  }
}

function isPseudoElementName(pseudo) {
  return pseudo.name === "before" || pseudo.name === "after";
}

function filterElementPseudos(pseudos) {
  return pseudos.filter(function(pseudo) {
    return !isPseudoElementName(pseudo);
  });
}

function juiceDocument($, options) {
  options = getDefaultOptions(options);
  var css = extractCssFromDocument($, options);
  css += "\n" + options.extraCss;
  inlineDocument($, css, options);
  return $;
}

function juiceResources(html, options, callback) {
  options = getDefaultOptions(options);

  var onInline = function(err, html) {
    if(err){
      return callback(err);
    }

    var $ = utils.cheerio(html, { xmlMode: options && options.xmlMode});
    juiceDocument($, options);

    if (options.xmlMode){
      return callback(null, $.xml());
    }
    else {
      return callback(null, utils.decodeEntities($.html()));
    }
  };

  options.webResources.relativeTo = options.webResources.relativeTo || options.url; //legacy support
  utils.inlineExternal(html, options.webResources, onInline);
}

function getDefaultOptions(options) {
  var result = utils.extend({
    extraCss: "",
    applyStyleTags: true,
    removeStyleTags: true,
    preserveMediaQueries: false,
    applyWidthAttributes: false,
    applyAttributesTableElements: false,
    url: ""
  }, options);

  result.webResources = result.webResources || {};

  return result;
}

function juiceFile(filePath, options, callback) {
  // set default options
  fs.readFile(filePath, 'utf8', function(err, content) {
    if (err) {
      return callback(err);
    }
    options = getDefaultOptions(options); // so we can mutate options without guilt
    if(!options.webResources.relativeTo){
      var rel = path.dirname(path.relative(process.cwd(),filePath));
      options.webResources.relativeTo = rel;
    }
    juiceResources(content, options, callback);
  });
}

function inlineContent(html, css, options) {
    var $ = utils.cheerio(html, { xmlMode: options && options.xmlMode});
    inlineDocument($, css, options);

    if (options && options.xmlMode){
      return $.xml();
    }
    else {
      return utils.decodeEntities($.html());
    }
}

function getStylesData($, options) {
  var results = [];
  var stylesList = $("style");
  var styleDataList, styleData, styleElement;
  stylesList.each(function () {
    styleElement = this;
    styleDataList = styleElement.childNodes;
    if (styleDataList.length !== 1) {
      return;
    }
    styleData = styleDataList[0].data;
    if ( options.applyStyleTags ) {
      results.push( styleData );
    }
    if ( options.removeStyleTags )
    {
      if ( options.preserveMediaQueries )
      {
        var mediaQueries = utils.getMediaQueryText( styleElement.childNodes[0].nodeValue );
        styleElement.childNodes[0].nodeValue = mediaQueries;
      }
      else
      {
        $(styleElement).remove();
      }
    }
  });
  return results;
}

function extractCssFromDocument($, options) {
  var results = getStylesData($, options);
  var css = results.join("\n");
  return css;
}
<commit_msg>Enabled percentages for tableElements when the 'applyWidthAttributes' option is sent.<commit_after>
/**
 * juice
 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

 "use strict";

/**
 * Module dependencies.
 */

var utils = require('./utils');
var Selector = require('./selector');
var Property = require('./property');
var packageJson = require('../package');
var fs = require('fs');
var path = require('path');
var styleSelector = new Selector('<style attribute>', [1, 0, 0, 0]);
var importantSelector = new Selector('<!important>', [2, 0, 0, 0]);

var juice = function (html,options) {
  var $ = utils.cheerio(html, { xmlMode: options && options.xmlMode});
  var doc = juiceDocument($,options);

  if (options && options.xmlMode){
    return doc.xml();
  }
  else {
    return utils.decodeEntities(doc.html());
  }
};

module.exports = juice;

/**
 * Package version
 */

juice.version = packageJson.version;

/**
 * Export Selector.
 */

juice.Selector = Selector;

/**
 * Export Property.
 */

juice.Property = Property;

/**
 * Export utils.
 */

juice.utils = require('./utils');

juice.ignoredPseudos = ['hover', 'active', 'focus', 'visited', 'link'];
juice.widthElements = ['TABLE', 'TD', 'IMG'];
juice.tableElements = ['TABLE', 'TD', 'TH', 'TR', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'THEAD', 'TBODY', 'TFOOT'];
juice.styleToAttribute = {
  'background-color': 'bgcolor',
  'background-image': 'background',
  'text-align': 'align',
  'vertical-align': 'valign'
};

juice.juiceDocument = juiceDocument;
juice.juiceResources = juiceResources;
juice.juiceFile = juiceFile;
juice.inlineDocument = inlineDocument;
juice.inlineContent = inlineContent;

function inlineDocument($, css, options) {

  var rules = utils.parseCSS(css);
  var editedElements = [];

  rules.forEach(handleRule);
  editedElements.forEach(setStyleAttrs);

  if (options && options.inlinePseudoElements) {
    editedElements.forEach(inlinePseudoElements);
  }

  if (options && options.applyWidthAttributes) {
    editedElements.forEach(setWidthAttrs);
  }

  if (options && options.applyAttributesTableElements) {
    editedElements.forEach(setAttributesOnTableElements);
  }

  function handleRule(rule) {
    var sel = rule[0];
    var style = rule[1];
    var selector = new Selector(sel);
    var parsedSelector = selector.parsed();
    var pseudoElementType = getPseudoElementType(parsedSelector);

    // skip rule if the selector has any pseudos which are ignored
    for (var i = 0; i < parsedSelector.length; ++i) {
      var subSel = parsedSelector[i];
      if (subSel.pseudos) {
        for (var j = 0; j < subSel.pseudos.length; ++j) {
          var subSelPseudo = subSel.pseudos[j];
          if (juice.ignoredPseudos.indexOf(subSelPseudo.name) >= 0) {
            return;
          }
        }
      }
    }

    if (pseudoElementType) {
      var last = parsedSelector[parsedSelector.length - 1];
      var pseudos = last.pseudos;
      last.pseudos = filterElementPseudos(last.pseudos);
      sel = parsedSelector.toString();
      last.pseudos = pseudos;
    }

    var els;
    try {
      els = $(sel);
    } catch (err) {
      // skip invalid selector
      return;
    }

    els.each(function () {
      var el = this;

      if (pseudoElementType) {
        var pseudoElPropName = "pseudo" + pseudoElementType;
        var pseudoEl = el[pseudoElPropName];
        if (!pseudoEl) {
          pseudoEl = el[pseudoElPropName] = $("<span />");
          pseudoEl.pseudoElementType = pseudoElementType;
          pseudoEl.pseudoElementParent = el;
          el[pseudoElPropName] = pseudoEl;
        }
        el = pseudoEl;
      }

      if (!el.styleProps) {
        el.styleProps = {};

        // if the element has inline styles, fake selector with topmost specificity
        if ($(el).attr('style')) {
          var cssText = '* { ' + $(el).attr('style') + ' } ';
          addProps(utils.parseCSS(cssText)[0][1], styleSelector);
        }

        // store reference to an element we need to compile style="" attr for
        editedElements.push(el);
      }

      // go through the properties
      function addProps (style, selector) {
        for (var i = 0, l = style.length; i < l; i++) {
          var name = style[i];
          var value = style[name] + (options && options.preserveImportant && style._importants[name] ? ' !important' : '');
          var sel = style._importants[name] ? importantSelector : selector;
          var prop = new Property(name, value, sel);
          var existing = el.styleProps[name];

          if (existing && existing.compare(prop) === prop || !existing) {
            el.styleProps[name] = prop;
          }
        }
      }

      addProps(style, selector);
    });
  }

  function setStyleAttrs(el) {
    var props = Object.keys(el.styleProps).map(function(key) {
      return el.styleProps[key];
    });
    // sort properties by their originating selector's specificity so that
    // props like "padding" and "padding-bottom" are resolved as expected.
    props.sort(function(a, b) {
      return a.selector.specificity().join("").localeCompare(
        b.selector.specificity().join(""));
    });
    var string = props
      .filter(function(prop) {
        // Content becomes the innerHTML of pseudo elements, not used as a
        // style property
        return prop.prop !== "content";
      })
      .map(function(prop) {
        return prop.prop + ": " + prop.value.replace(/["]/g, "'") + ";";
      })
      .join(" ");
    if (string) {
      $(el).attr('style', string);
    }
  }

  function inlinePseudoElements(el) {
    if (el.pseudoElementType && el.styleProps.content) {
      el.html(parseContent(el.styleProps.content.value));
      var parent = el.pseudoElementParent;
      if (el.pseudoElementType === "before") {
        $(parent).prepend(el);
      }
      else {
        $(parent).append(el);
      }
    }
  }

  function setWidthAttrs(el) {
    var elName = el.name.toUpperCase();
    if (juice.widthElements.indexOf(elName) > -1) {
      for (var i in el.styleProps) {
        if (el.styleProps[i].prop === 'width') {
          if (el.styleProps[i].value.match(/px/)) {
            var pxWidth = el.styleProps[i].value.replace('px', '');
            $(el).attr('width', pxWidth);
            return;
          }
          if (juice.tableElements.indexOf(elName) > -1 && el.styleProps[i].value.match(/\%/)) {
            $(el).attr('width', el.styleProps[i].value);
            return;
          }
        }
      }
    }
  }

  function setAttributesOnTableElements(el) {
    var elName = el.name.toUpperCase(),
        styleProps = Object.keys(juice.styleToAttribute);

    if (juice.tableElements.indexOf(elName) > -1) {
      for (var i in el.styleProps) {
        if (styleProps.indexOf(el.styleProps[i].prop) > -1) {
          $(el).attr(juice.styleToAttribute[el.styleProps[i].prop], el.styleProps[i].value);
        }
      }
    }
  }
}

function parseContent(content) {
  if (content === "none" || content === "normal") {
    return "";
  }

  // Naive parsing, assume well-formed value
  content = content.slice(1, content.length - 1);
  // Naive unescape, assume no unicode char codes
  content = content.replace(/\\/g, "");
  return content;
}

// Return "before" or "after" if the given selector is a pseudo element (e.g.,
// a::after).
function getPseudoElementType(selector) {
  if (selector.length === 0) {
    return;
  }

  var pseudos = selector[selector.length - 1].pseudos;
  if (!pseudos) {
    return;
  }

  for (var i = 0; i < pseudos.length; i++) {
    if (isPseudoElementName(pseudos[i])) {
      return pseudos[i].name;
    }
  }
}

function isPseudoElementName(pseudo) {
  return pseudo.name === "before" || pseudo.name === "after";
}

function filterElementPseudos(pseudos) {
  return pseudos.filter(function(pseudo) {
    return !isPseudoElementName(pseudo);
  });
}

function juiceDocument($, options) {
  options = getDefaultOptions(options);
  var css = extractCssFromDocument($, options);
  css += "\n" + options.extraCss;
  inlineDocument($, css, options);
  return $;
}

function juiceResources(html, options, callback) {
  options = getDefaultOptions(options);

  var onInline = function(err, html) {
    if(err){
      return callback(err);
    }

    var $ = utils.cheerio(html, { xmlMode: options && options.xmlMode});
    juiceDocument($, options);

    if (options.xmlMode){
      return callback(null, $.xml());
    }
    else {
      return callback(null, utils.decodeEntities($.html()));
    }
  };

  options.webResources.relativeTo = options.webResources.relativeTo || options.url; //legacy support
  utils.inlineExternal(html, options.webResources, onInline);
}

function getDefaultOptions(options) {
  var result = utils.extend({
    extraCss: "",
    applyStyleTags: true,
    removeStyleTags: true,
    preserveMediaQueries: false,
    applyWidthAttributes: false,
    applyAttributesTableElements: false,
    url: ""
  }, options);

  result.webResources = result.webResources || {};

  return result;
}

function juiceFile(filePath, options, callback) {
  // set default options
  fs.readFile(filePath, 'utf8', function(err, content) {
    if (err) {
      return callback(err);
    }
    options = getDefaultOptions(options); // so we can mutate options without guilt
    if(!options.webResources.relativeTo){
      var rel = path.dirname(path.relative(process.cwd(),filePath));
      options.webResources.relativeTo = rel;
    }
    juiceResources(content, options, callback);
  });
}

function inlineContent(html, css, options) {
    var $ = utils.cheerio(html, { xmlMode: options && options.xmlMode});
    inlineDocument($, css, options);

    if (options && options.xmlMode){
      return $.xml();
    }
    else {
      return utils.decodeEntities($.html());
    }
}

function getStylesData($, options) {
  var results = [];
  var stylesList = $("style");
  var styleDataList, styleData, styleElement;
  stylesList.each(function () {
    styleElement = this;
    styleDataList = styleElement.childNodes;
    if (styleDataList.length !== 1) {
      return;
    }
    styleData = styleDataList[0].data;
    if ( options.applyStyleTags ) {
      results.push( styleData );
    }
    if ( options.removeStyleTags )
    {
      if ( options.preserveMediaQueries )
      {
        var mediaQueries = utils.getMediaQueryText( styleElement.childNodes[0].nodeValue );
        styleElement.childNodes[0].nodeValue = mediaQueries;
      }
      else
      {
        $(styleElement).remove();
      }
    }
  });
  return results;
}

function extractCssFromDocument($, options) {
  var results = getStylesData($, options);
  var css = results.join("\n");
  return css;
}
<|endoftext|>