<commit_before>var superagent = require('superagent')
var crypto = require('crypto')
var debug = require('debug')('mcash')
var format = require('util').format
var CONTENT_TYPE = 'application/vnd.mcash.api.merchant.v1+json'
var lodash = require('lodash')
var parseUrl = require('url').parse

superagent.parse[CONTENT_TYPE] = superagent.parse['application/json']

var Mcash = module.exports = exports = function(opts) {
    this.opts = opts
}

exports.ENDPOINTS = {
    production: 'https://api.mca.sh/merchant/v1/',
    test: 'https://mcashtestbed.appspot.com/merchant/v1/'
}

function mcashTimestamp() {
    return new Date().toISOString().replace(/T/, ' ').substr(0, 19)
}

Mcash.prototype.request = function(type, url, opts) {
    var fn = superagent[type.toLowerCase()]

    opts = lodash.extend({
        payload: null
    }, opts)

   var request = fn(exports.ENDPOINTS[this.opts.environment] + url)
    .buffer(true)
    .parse(superagent.parse.json)
    .set('Accept', 'application/vnd.mcash.api.merchant.v1+json')
    .set('X-Mcash-Merchant', this.opts.merchantId)
    .set('X-Mcash-User', this.opts.user)

    if (this.opts.environment == 'test') {
        request = request.set('X-Testbed-Token', this.opts.testbedToken)
    }

    if (this.opts.secret) {
        request = request
        .set('Authorization', 'SECRET ' + this.opts.secret)
    } else if (this.opts.privateKey) {
        var payload = opts.payload ? JSON.stringify(opts.payload) : ''
        debug('payload (post data) is:\n%s', payload)
        var digest = crypto.createHash('sha256').update(payload).digest('base64')

        request = request
        .set('X-Mcash-Timestamp', mcashTimestamp())
        .set('X-Mcash-Content-Digest', 'SHA256=' + digest)

        var parsedUrl = parseUrl(request.url)

        var concat = format('%s|%s|%s',
            request.req.method,
            request.url,
            Object.keys(request.req._headers).filter(function(key) {
                return !!key.match(/^x-mcash-/)
            }).sort().reduce(function(p, key) {
                return format('%s%s%s=%s',
                    p,
                    p.length ? '&' : '',
                    key.toUpperCase(),
                    request.req._headers[key])
            }, ''))

        var sign = crypto.createSign('RSA-SHA256')
        .update(concat)
        .sign(this.opts.privateKey, 'base64')

        debug('will sign with private key:\n%s', concat)

        request = request
        .set('Authorization', 'RSA-SHA256 ' + sign)
    }

    if (opts.payload) {
        request = request.send(opts.payload)
    }

    return request
}

exports.handler = require('./handler')
<commit_msg>Add more debugging<commit_after>var superagent = require('superagent')
var crypto = require('crypto')
var debug = require('debug')('mcash')
var format = require('util').format
var CONTENT_TYPE = 'application/vnd.mcash.api.merchant.v1+json'
var lodash = require('lodash')
var parseUrl = require('url').parse

superagent.parse[CONTENT_TYPE] = superagent.parse['application/json']

var Mcash = module.exports = exports = function(opts) {
    this.opts = opts
}

exports.ENDPOINTS = {
    production: 'https://api.mca.sh/merchant/v1/',
    test: 'https://mcashtestbed.appspot.com/merchant/v1/'
}

function mcashTimestamp() {
    return new Date().toISOString().replace(/T/, ' ').substr(0, 19)
}

Mcash.prototype.request = function(type, url, opts) {
    var fn = superagent[type.toLowerCase()]

    opts = lodash.extend({
        payload: null
    }, opts)

   var request = fn(exports.ENDPOINTS[this.opts.environment] + url)
    .buffer(true)
    .parse(superagent.parse.json)
    .set('Accept', 'application/vnd.mcash.api.merchant.v1+json')
    .set('X-Mcash-Merchant', this.opts.merchantId)
    .set('X-Mcash-User', this.opts.user)

    if (this.opts.environment == 'test') {
        request = request.set('X-Testbed-Token', this.opts.testbedToken)
    }

    if (this.opts.secret) {
        request = request
        .set('Authorization', 'SECRET ' + this.opts.secret)
    } else if (this.opts.privateKey) {
        var payload = opts.payload ? JSON.stringify(opts.payload) : ''
        debug('payload (post data) is:\n%s', payload)
        var digest = crypto.createHash('sha256').update(payload).digest('base64')

        request = request
        .set('X-Mcash-Timestamp', mcashTimestamp())
        .set('X-Mcash-Content-Digest', 'SHA256=' + digest)

        var parsedUrl = parseUrl(request.url)

        var concat = format('%s|%s|%s',
            request.req.method,
            request.url,
            Object.keys(request.req._headers).filter(function(key) {
                return !!key.match(/^x-mcash-/)
            }).sort().reduce(function(p, key) {
                return format('%s%s%s=%s',
                    p,
                    p.length ? '&' : '',
                    key.toUpperCase(),
                    request.req._headers[key])
            }, ''))

        var sign = crypto.createSign('RSA-SHA256')
        .update(concat)
        .sign(this.opts.privateKey, 'base64')

        debug('will sign with private key:\n%s', concat)

        debug('signature:\n%s', sign)

        request = request
        .set('Authorization', 'RSA-SHA256 ' + sign)
    }

    if (opts.payload) {
        request = request.send(opts.payload)
    }

    debug('all headers, for debugging:\n%s', Object.keys(request.req._headers).map(function(key) {
        return '\t' \ key + ': ' + request.req._headers[key]
    }).join('\n'))

    return request
}

exports.handler = require('./handler')
<|endoftext|>


<commit_before>var CandyShop = (function(self) { return self; }(CandyShop || {}));

CandyShop.Colors = (function(self, Candy, $) {

	var _numColors,
		_currentColor = 0;

	self.init = function(numColors) {
		_numColors = numColors ? numColors : 8;

		self.applyTranslations();

		Candy.View.Event.Message.beforeSend = function(message) {
			if(_currentColor > 0 && $.trim(message) !== '') {
				return '|c:'+ _currentColor +'|' + message;
			}
			return message;
		};

		Candy.View.Event.Message.beforeShow = function(message) {
			message = message.replace(/^\|c:([0-9]{1,2})\|(.*)/gm, '$2');
			return message;
		};

		if(Candy.Util.cookieExists('candyshop-colors-current')) {
			var color = parseInt(Candy.Util.getCookie('candyshop-colors-current'), 10);
			if(color > 0 && color < _numColors) {
				_currentColor = color;
			}
		}
		var html = '

';
		$('#emoticons-icon').after(html);
		$('#colors-control').click(function(event) {
			CandyShop.Colors.showPicker(this);
		});
	};

	self.showPicker = function(elem) {
		elem = $(elem);
		var pos = elem.offset(),
			menu = $('#context-menu'),
			content = $('ul', menu),
			colors = '',
			i;

		$('#tooltip').hide();

		for(i = _numColors-1; i >= 0; i--) {
			colors = '' + colors;
		}
		content.html('
' + colors + '
');
		content.find('span').click(function() {
			_currentColor = $(this).attr('data-color');
			$('#colors-control-indicator').attr('class', 'color-' + _currentColor);
			Candy.Util.setCookie('candyshop-colors-current', _currentColor, 365);
			Candy.View.Pane.Room.setFocusToForm(Candy.View.getCurrent().roomJid);
			menu.hide();
		});

		var posLeft = Candy.Util.getPosLeftAccordingToWindowBounds(menu, pos.left),
			posTop  = Candy.Util.getPosTopAccordingToWindowBounds(menu, pos.top);

		menu.css({'left': posLeft.px, 'top': posTop.px, backgroundPosition: posLeft.backgroundPositionAlignment + ' ' + posTop.backgroundPositionAlignment});
		menu.fadeIn('fast');

		return true;
	};

	self.applyTranslations = function() {
		Candy.View.Translation.en.candyshopColorsMessagecolor = 'Message color';
		Candy.View.Translation.de.candyshopColorsMessagecolor = 'Farbe für Nachrichten';
		Candy.View.Translation.fr.candyshopColorsMessagecolor = 'Couleur des messages';
		Candy.View.Translation.nl.candyshopColorsMessagecolor = 'Berichtkleur';
	};

	return self;
}(CandyShop.Colors || {}, Candy, jQuery));<commit_msg>Added spanish translation. Thanks to Juan Daniel Cebrian<commit_after>var CandyShop = (function(self) { return self; }(CandyShop || {}));

CandyShop.Colors = (function(self, Candy, $) {

	var _numColors,
		_currentColor = 0;

	self.init = function(numColors) {
		_numColors = numColors ? numColors : 8;

		self.applyTranslations();

		Candy.View.Event.Message.beforeSend = function(message) {
			if(_currentColor > 0 && $.trim(message) !== '') {
				return '|c:'+ _currentColor +'|' + message;
			}
			return message;
		};

		Candy.View.Event.Message.beforeShow = function(message) {
			message = message.replace(/^\|c:([0-9]{1,2})\|(.*)/gm, '$2');
			return message;
		};

		if(Candy.Util.cookieExists('candyshop-colors-current')) {
			var color = parseInt(Candy.Util.getCookie('candyshop-colors-current'), 10);
			if(color > 0 && color < _numColors) {
				_currentColor = color;
			}
		}
		var html = '

';
		$('#emoticons-icon').after(html);
		$('#colors-control').click(function(event) {
			CandyShop.Colors.showPicker(this);
		});
	};

	self.showPicker = function(elem) {
		elem = $(elem);
		var pos = elem.offset(),
			menu = $('#context-menu'),
			content = $('ul', menu),
			colors = '',
			i;

		$('#tooltip').hide();

		for(i = _numColors-1; i >= 0; i--) {
			colors = '' + colors;
		}
		content.html('
' + colors + '
');
		content.find('span').click(function() {
			_currentColor = $(this).attr('data-color');
			$('#colors-control-indicator').attr('class', 'color-' + _currentColor);
			Candy.Util.setCookie('candyshop-colors-current', _currentColor, 365);
			Candy.View.Pane.Room.setFocusToForm(Candy.View.getCurrent().roomJid);
			menu.hide();
		});

		var posLeft = Candy.Util.getPosLeftAccordingToWindowBounds(menu, pos.left),
			posTop  = Candy.Util.getPosTopAccordingToWindowBounds(menu, pos.top);

		menu.css({'left': posLeft.px, 'top': posTop.px, backgroundPosition: posLeft.backgroundPositionAlignment + ' ' + posTop.backgroundPositionAlignment});
		menu.fadeIn('fast');

		return true;
	};

	self.applyTranslations = function() {
		Candy.View.Translation.en.candyshopColorsMessagecolor = 'Message color';
		Candy.View.Translation.de.candyshopColorsMessagecolor = 'Farbe für Nachrichten';
		Candy.View.Translation.fr.candyshopColorsMessagecolor = 'Couleur des messages';
		Candy.View.Translation.nl.candyshopColorsMessagecolor = 'Berichtkleur';
		Candy.View.Translation.es.candyshopColorsMessagecolor = 'Color de los mensajes';
	};

	return self;
}(CandyShop.Colors || {}, Candy, jQuery));<|endoftext|>


<commit_before>/*
**  ComponentJS -- Component System for JavaScript <http://componentjs.com>
**  Copyright (c) 2009-2013 Ralf S. Engelschall <http://engelschall.com>
**
**  This Source Code Form is subject to the terms of the Mozilla Public
**  License, v. 2.0. If a copy of the MPL was not distributed with this
**  file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

/*  API function: select an arbitrary value via a path specification
    and either get the current value or set the new value  */
$cs.select = function (obj, spec, value) {
    /*  compile path specification (or use pre-compiled path)  */
    var path = (typeof spec === "string" ? _cs.select_parse(spec) : spec);

    /*  subset the object graph  */
    return (
          arguments.length === 2
        ? _cs.select_path(obj, path)
        : _cs.select_path(obj, path, value)
    );
};

/*  the internal compile cache  */
_cs.select_cache = {};

/*  compile a path specification into array of dereferencing steps  */
_cs.select_parse = function (spec) {
    var path = _cs.select_cache[spec];
    if (typeof path === "undefined") {
        path = [];
        var pos = 0;
        var txt = spec;
        var m;
        while (txt !== "") {
            if ((m = txt.match(/^\s*(?:\.)?\s*([a-zA-Z$_][a-zA-Z$0-9_:-]*|\*{1,2})/)) !== null)
                path.push(m[1]);
            else if ((m = txt.match(/^\s*\[\s*(\d+|\*{1,2})\s*\]/)) !== null)
                path.push(m[1]);
            else if ((m = txt.match(/^\s*\[\s*"((?:\\"|.)*?)"\s*\]/)) !== null)
                path.push(m[1].replace(/\\"/g, "\""));
            else if ((m = txt.match(/^\s*\[\s*'((?:\\'|.)*?)'\s*\]/)) !== null)
                path.push(m[1].replace(/\\'/g, "'"));
            else if ((m = txt.match(/^\s+$/)) !== null)
                break;
            else
                throw _cs.exception("select", "parse error: invalid character at: " +
                    spec.substr(0, pos) + "<" + txt.substr(0, 1) + ">" + txt.substr(1));
            pos += m[0].length;
            txt = txt.substr(m[0].length);
        }
        _cs.select_cache[spec] = path;
    }
    return path;
};

/*  subset an object graph  */
_cs.select_path = function (obj, path) {
    /*  handle special case of empty path */
    if (path.length === 0) {
        if (arguments.length === 3)
            throw _cs.exception("select", "cannot set value on empty path");
        else
            return obj;
    }

    /*  step into object graph according to path prefix  */
    var i = 0;
    while (i < path.length - 1) {
        if (typeof obj !== "object")
            throw _cs.exception("select", "cannot further dereference: no more intermediate objects in path");
        obj = obj[path[i++]];
    }

    /*  get the old value  */
    if (typeof obj !== "object")
        throw _cs.exception("select", "cannot further dereference: no object at end of path");
    var value_old = obj[path[i]];

    /*  optionally set new value  */
    if (arguments.length === 3) {
        var value_new = arguments[2];
        if (value_new === undefined) {
            /*  delete value from collection  */
            if (obj instanceof Array)
                obj.splice(parseInt(path[i]), 1);
            else
                delete obj[path[i]];
        }
        else
            /*  set value into collection  */
            obj[path[i]] = value_new;
    }

    return value_old;
};
<commit_msg>we cannot match against wildcard path segments as it makes no sense in practical scenarios<commit_after>/*
**  ComponentJS -- Component System for JavaScript <http://componentjs.com>
**  Copyright (c) 2009-2013 Ralf S. Engelschall <http://engelschall.com>
**
**  This Source Code Form is subject to the terms of the Mozilla Public
**  License, v. 2.0. If a copy of the MPL was not distributed with this
**  file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

/*  API function: select an arbitrary value via a path specification
    and either get the current value or set the new value  */
$cs.select = function (obj, spec, value) {
    /*  compile path specification (or use pre-compiled path)  */
    var path = (typeof spec === "string" ? _cs.select_parse(spec) : spec);

    /*  subset the object graph  */
    return (
          arguments.length === 2
        ? _cs.select_path(obj, path)
        : _cs.select_path(obj, path, value)
    );
};

/*  the internal compile cache  */
_cs.select_cache = {};

/*  compile a path specification into array of dereferencing steps  */
_cs.select_parse = function (spec) {
    var path = _cs.select_cache[spec];
    if (typeof path === "undefined") {
        path = [];
        var pos = 0;
        var txt = spec;
        var m;
        while (txt !== "") {
            if ((m = txt.match(/^\s*(?:\.)?\s*([a-zA-Z$_][a-zA-Z$0-9_:-]*)/)) !== null)
                path.push(m[1]);
            else if ((m = txt.match(/^\s*\[\s*(\d+|\*{1,2})\s*\]/)) !== null)
                path.push(m[1]);
            else if ((m = txt.match(/^\s*\[\s*"((?:\\"|.)*?)"\s*\]/)) !== null)
                path.push(m[1].replace(/\\"/g, "\""));
            else if ((m = txt.match(/^\s*\[\s*'((?:\\'|.)*?)'\s*\]/)) !== null)
                path.push(m[1].replace(/\\'/g, "'"));
            else if ((m = txt.match(/^\s+$/)) !== null)
                break;
            else
                throw _cs.exception("select", "parse error: invalid character at: " +
                    spec.substr(0, pos) + "<" + txt.substr(0, 1) + ">" + txt.substr(1));
            pos += m[0].length;
            txt = txt.substr(m[0].length);
        }
        _cs.select_cache[spec] = path;
    }
    return path;
};

/*  subset an object graph  */
_cs.select_path = function (obj, path) {
    /*  handle special case of empty path */
    if (path.length === 0) {
        if (arguments.length === 3)
            throw _cs.exception("select", "cannot set value on empty path");
        else
            return obj;
    }

    /*  step into object graph according to path prefix  */
    var i = 0;
    while (i < path.length - 1) {
        if (typeof obj !== "object")
            throw _cs.exception("select", "cannot further dereference: no more intermediate objects in path");
        obj = obj[path[i++]];
    }

    /*  get the old value  */
    if (typeof obj !== "object")
        throw _cs.exception("select", "cannot further dereference: no object at end of path");
    var value_old = obj[path[i]];

    /*  optionally set new value  */
    if (arguments.length === 3) {
        var value_new = arguments[2];
        if (value_new === undefined) {
            /*  delete value from collection  */
            if (obj instanceof Array)
                obj.splice(parseInt(path[i]), 1);
            else
                delete obj[path[i]];
        }
        else
            /*  set value into collection  */
            obj[path[i]] = value_new;
    }

    return value_old;
};
<|endoftext|>


<commit_before>var _ = require('lodash');
var async = require('async');
var fs = require('fs');
var path = require('path');
var http = require('http');
var url = require('url');
var requestLib = require('request');
var RunListHelper = require('../src/RunListHelper');
var CmdHelper = require('../src/CmdHelper');

module.exports = {
  name: 'cdn',
  usage: '[-r <repoPattern>] [-w <repoPattern>] [<minify>]',
  description: 'Aggregates all the static assets across all microservices and serves them via a pseudo local CDN url',
  requiresNvm: true,
  options: [{
    name: 'tag',
    alias: 't',
    type: 'string',
    desc: 'Filter by a tag defined within bosco-service.json'
  },
  {
    name: 'watch',
    alias: 'w',
    type: 'string',
    desc: 'Filter by a regex of services to watch (similar to -r in run)'
  },
  {
    name: 'local-vendor',
    alias: 'lv',
    type: 'boolean',
    desc: 'Force vendor library files to come from local cdn instead of remote cdn'
  }]
};

function cmd(bosco, args) {
  var minify = _.includes(args, 'minify');
  var port = bosco.config.get('cdn:port') || 7334;
  var repoPattern = bosco.options.repo;
  var repoRegex = new RegExp(repoPattern);
  var watchPattern = bosco.options.watch || '$a';
  var watchRegex = new RegExp(watchPattern);
  var repoTag = bosco.options.tag;
  var repos;

  bosco.log('Starting pseudo CDN on port: ' + (port + '').blue);

  if (bosco.options.list) {
    repos = bosco.options.list.split(',');
  } else {
    if (CmdHelper.checkInService(bosco)) {
      bosco.options.watch = bosco.options.watch || new RegExp(bosco.getRepoName());
      watchRegex = new RegExp(bosco.options.watch);
    }

    repos = bosco.getRepos();
  }

  if (!repos) return bosco.error('You are repo-less :( You need to initialise bosco first, try \'bosco clone\'.');

  function getRunList(next) {
    RunListHelper.getRunList(bosco, repos, repoRegex, watchRegex, repoTag, false, next);
  }

  function startServer(staticAssets, staticRepos, serverPort) {
    var isWatchedFile = function (asset) {
      var hasSourceFiles = asset.sourceFiles && asset.sourceFiles.length > 0;
      var assetPath = hasSourceFiles ? asset.sourceFiles[0] : asset.path;
      var watched;
      try {
        watched = assetPath && !fs.lstatSync(assetPath).isDirectory() && assetPath.match(watchRegex);
      } catch (ex) {
        watched = false;
      }
      return watched;
    };

    function getAsset(assetUrl) {
      var key = assetUrl.replace('/', '');
      return _.find(staticAssets, { assetKey: key });
    }

    var corsHeaders = {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'POST, GET, PUT, DELETE, OPTIONS',
      'Access-Control-Allow-Credentials': true,
      'Access-Control-Max-Age': '86400', // 24 hours
      'Access-Control-Allow-Headers': 'X-Requested-With, Access-Control-Allow-Origin, X-HTTP-Method-Override, Content-Type, Authorization, Accept'
    };

    var server = http.createServer(function (request, response) {
      if (request.method === 'OPTIONS') {
        response.writeHead(200, corsHeaders);
        return response.end();
      }

      var headers = {
        'Cache-Control': 'no-cache, must-revalidate',
        Pragma: 'no-cache',
        Expires: 'Sat, 21 May 1952 00:00:00 GMT',
        'Access-Control-Allow-Origin': '*'
      };

      var pathname = url.parse(request.url).pathname;
      if (pathname === '/repos') {
        headers['Content-Type'] = 'text/html';
        response.writeHead(200, headers);
        return response.end(staticRepos.formattedRepos);
      }

      var isLibraryAsset = pathname.indexOf('/vendor/library/') >= 0;
      // Path matches something that is service-name/build e.g. /app-home/720/css/logged-in.css
      var isRemoteAsset = pathname.match(/^\/(.*)\/(\d+)\//);
      var serveRemoteAsset = isRemoteAsset || (isLibraryAsset && !bosco.options.localVendor);
      if (serveRemoteAsset) {
        var baseCdn = bosco.config.get('cdn:remoteUrl') || 'https://duqxiy1o2cbw6.cloudfront.net/tes';
        var cdnUrl = baseCdn + pathname;
        var localCacheFolder = path.join(bosco.findConfigFolder(), 'cache');
        var cachePrefix = 'v1-';
        var localCacheFile = path.join(localCacheFolder, cachePrefix + pathname.replace(/\//g, '_') + '.json');

        // Ensure local cache folder exists
        if (!fs.existsSync(localCacheFolder)) {
          fs.mkdirSync(localCacheFolder);
        }

        var useLocalCacheFile = !bosco.options.nocache && fs.existsSync(localCacheFile);

        var responseContent;
        if (useLocalCacheFile) {
          var cacheContent = require(localCacheFile);
          response.writeHead(200, cacheContent.headers);
          responseContent = cacheContent.isBinary ? Buffer.from(cacheContent.body, 'base64') : cacheContent.body;
          response.end(responseContent);
        } else {
          var baseBoscoCdnUrl = bosco.getBaseCdnUrl();
          requestLib.get({
            uri: cdnUrl, gzip: true, timeout: 5000, encoding: null
          }, function (err, cdnResponse, body) { // body is a buffer
            if (err) {
              bosco.error('Error proxying asset for: ' + cdnUrl + ', Error: ' + err.message);
              response.writeHead(500);
              return response.end();
            }
            var contentType = cdnResponse.headers['content-type'];
            responseContent = body;
            var responseHeaders;
            if (contentType === 'text/css' || contentType === 'application/javascript') {
              responseContent = body.toString();
              // We want to convert all of the in content urls to local bosco ones to take advantage of offline caching
              // For the js / css files contained within the html fragments for remote services
              responseContent = responseContent.replace(new RegExp(baseCdn, 'g'), baseBoscoCdnUrl);
            }

            responseHeaders = _.defaults({
              'content-type': contentType,
              'content-length': responseContent.length
            }, corsHeaders);

            response.writeHead(200, responseHeaders);
            response.end(responseContent);

            var cacheContentToSave = {
              headers: responseHeaders,
              body: typeof responseContent === 'string' ? responseContent : responseContent.toString('base64'),
              isBinary: typeof responseContent !== 'string'
            };
            fs.writeSync(fs.openSync(localCacheFile, 'w'), JSON.stringify(cacheContentToSave, null, 2));
          });
        }
        return 'served-remote';
      }

      var asset = getAsset(pathname);
      if (!asset) {
        headers['Content-Type'] = 'text/html';
        response.writeHead(404, headers);
        return staticAssets ? response.end(staticAssets.formattedAssets) : response.end();
      }

      headers['content-Type'] = asset.mimeType;
      response.writeHead(200, headers);

      var hasSourceFiles = asset.sourceFiles && asset.sourceFiles.length > 0;

      if (isWatchedFile(asset)) {
        if (hasSourceFiles && !minify) {
          async.reduce(asset.sourceFiles, '', function (memo, item, callback) {
            fs.readFile(item, function (err, content) {
              callback(null, memo + content);
            });
          }, function (err, content) {
            response.end(content);
          });
        } else {
          fs.readFile(asset.path, function (err, content) {
            response.end(content);
          });
        }
      } else {
        response.end(asset.data || asset.content);
      }
    });

    server.listen(serverPort);

    bosco.log('Server is listening on ' + serverPort);
  }

  function watchCallback(err, service) {
    if (err) { return bosco.error(err); }
    bosco.log('Local CDN ready after build for service: ' + service.name.green);
  }

  if (minify) bosco.log('Running per service builds for front end assets, this can take some time ...');

  getRunList(function (err, repoList) {
    var repoNames = _.map(repoList, 'name');
    var options = {
      repos: repoNames,
      buildNumber: 'local',
      minify: minify,
      tagFilter: null,
      watchBuilds: true,
      reloadOnly: false,
      ignoreFailure: true,
      watchRegex: watchRegex,
      repoRegex: repoRegex,
      repoTag: repoTag,
      watchCallback: watchCallback,
      isCdn: true
    };

    var executeAsync = {
      staticAssets: bosco.staticUtils.getStaticAssets.bind(null, options),
      staticRepos: bosco.staticUtils.getStaticRepos.bind(null, options)
    };

    async.parallel(executeAsync, function (err, results) {
      startServer(results.staticAssets, results.staticRepos, port);
    });
  });
}

module.exports.cmd = cmd;
<commit_msg>Make cdn command more flexible on what it considers a remote asset<commit_after>var _ = require('lodash');
var async = require('async');
var fs = require('fs');
var path = require('path');
var http = require('http');
var url = require('url');
var requestLib = require('request');
var RunListHelper = require('../src/RunListHelper');
var CmdHelper = require('../src/CmdHelper');

module.exports = {
  name: 'cdn',
  usage: '[-r <repoPattern>] [-w <repoPattern>] [<minify>]',
  description: 'Aggregates all the static assets across all microservices and serves them via a pseudo local CDN url',
  requiresNvm: true,
  options: [{
    name: 'tag',
    alias: 't',
    type: 'string',
    desc: 'Filter by a tag defined within bosco-service.json'
  },
  {
    name: 'watch',
    alias: 'w',
    type: 'string',
    desc: 'Filter by a regex of services to watch (similar to -r in run)'
  },
  {
    name: 'local-vendor',
    alias: 'lv',
    type: 'boolean',
    desc: 'Force vendor library files to come from local cdn instead of remote cdn'
  }]
};

function cmd(bosco, args) {
  var minify = _.includes(args, 'minify');
  var port = bosco.config.get('cdn:port') || 7334;
  var repoPattern = bosco.options.repo;
  var repoRegex = new RegExp(repoPattern);
  var watchPattern = bosco.options.watch || '$a';
  var watchRegex = new RegExp(watchPattern);
  var repoTag = bosco.options.tag;
  var repos;

  bosco.log('Starting pseudo CDN on port: ' + (port + '').blue);

  if (bosco.options.list) {
    repos = bosco.options.list.split(',');
  } else {
    if (CmdHelper.checkInService(bosco)) {
      bosco.options.watch = bosco.options.watch || new RegExp(bosco.getRepoName());
      watchRegex = new RegExp(bosco.options.watch);
    }

    repos = bosco.getRepos();
  }

  if (!repos) return bosco.error('You are repo-less :( You need to initialise bosco first, try \'bosco clone\'.');

  function getRunList(next) {
    RunListHelper.getRunList(bosco, repos, repoRegex, watchRegex, repoTag, false, next);
  }

  function startServer(staticAssets, staticRepos, serverPort) {
    var isWatchedFile = function (asset) {
      var hasSourceFiles = asset.sourceFiles && asset.sourceFiles.length > 0;
      var assetPath = hasSourceFiles ? asset.sourceFiles[0] : asset.path;
      var watched;
      try {
        watched = assetPath && !fs.lstatSync(assetPath).isDirectory() && assetPath.match(watchRegex);
      } catch (ex) {
        watched = false;
      }
      return watched;
    };

    function getAsset(assetUrl) {
      var key = assetUrl.replace('/', '');
      return _.find(staticAssets, { assetKey: key });
    }

    var corsHeaders = {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'POST, GET, PUT, DELETE, OPTIONS',
      'Access-Control-Allow-Credentials': true,
      'Access-Control-Max-Age': '86400', // 24 hours
      'Access-Control-Allow-Headers': 'X-Requested-With, Access-Control-Allow-Origin, X-HTTP-Method-Override, Content-Type, Authorization, Accept'
    };

    var server = http.createServer(function (request, response) {
      if (request.method === 'OPTIONS') {
        response.writeHead(200, corsHeaders);
        return response.end();
      }

      var headers = {
        'Cache-Control': 'no-cache, must-revalidate',
        Pragma: 'no-cache',
        Expires: 'Sat, 21 May 1952 00:00:00 GMT',
        'Access-Control-Allow-Origin': '*'
      };

      var pathname = url.parse(request.url).pathname;
      if (pathname === '/repos') {
        headers['Content-Type'] = 'text/html';
        response.writeHead(200, headers);
        return response.end(staticRepos.formattedRepos);
      }

      var isLibraryAsset = pathname.indexOf('/vendor/library/') >= 0;
      /*
        Path matches something that is service-name/build e.g:
        - /app-home/720/css/logged-in.css
        - /app-home/ec701e5/css/logged-in.css

        but not what bundle-version gives us locally:
        - /app-home/local/css/logged-in.css
      */
      var isRemoteAsset = pathname.match(/^\/([^\/]+)\/(?!local)([^\/]+)\//);
      var serveRemoteAsset = isRemoteAsset || (isLibraryAsset && !bosco.options.localVendor);
      if (serveRemoteAsset) {
        var baseCdn = bosco.config.get('cdn:remoteUrl') || 'https://duqxiy1o2cbw6.cloudfront.net/tes';
        var cdnUrl = baseCdn + pathname;
        var localCacheFolder = path.join(bosco.findConfigFolder(), 'cache');
        var cachePrefix = 'v1-';
        var localCacheFile = path.join(localCacheFolder, cachePrefix + pathname.replace(/\//g, '_') + '.json');

        // Ensure local cache folder exists
        if (!fs.existsSync(localCacheFolder)) {
          fs.mkdirSync(localCacheFolder);
        }

        var useLocalCacheFile = !bosco.options.nocache && fs.existsSync(localCacheFile);

        var responseContent;
        if (useLocalCacheFile) {
          var cacheContent = require(localCacheFile);
          response.writeHead(200, cacheContent.headers);
          responseContent = cacheContent.isBinary ? Buffer.from(cacheContent.body, 'base64') : cacheContent.body;
          response.end(responseContent);
        } else {
          var baseBoscoCdnUrl = bosco.getBaseCdnUrl();
          requestLib.get({
            uri: cdnUrl, gzip: true, timeout: 5000, encoding: null
          }, function (err, cdnResponse, body) { // body is a buffer
            if (err) {
              bosco.error('Error proxying asset for: ' + cdnUrl + ', Error: ' + err.message);
              response.writeHead(500);
              return response.end();
            }
            var contentType = cdnResponse.headers['content-type'];
            responseContent = body;
            var responseHeaders;
            if (contentType === 'text/css' || contentType === 'application/javascript') {
              responseContent = body.toString();
              // We want to convert all of the in content urls to local bosco ones to take advantage of offline caching
              // For the js / css files contained within the html fragments for remote services
              responseContent = responseContent.replace(new RegExp(baseCdn, 'g'), baseBoscoCdnUrl);
            }

            responseHeaders = _.defaults({
              'content-type': contentType,
              'content-length': responseContent.length
            }, corsHeaders);

            response.writeHead(200, responseHeaders);
            response.end(responseContent);

            var cacheContentToSave = {
              headers: responseHeaders,
              body: typeof responseContent === 'string' ? responseContent : responseContent.toString('base64'),
              isBinary: typeof responseContent !== 'string'
            };
            fs.writeSync(fs.openSync(localCacheFile, 'w'), JSON.stringify(cacheContentToSave, null, 2));
          });
        }
        return 'served-remote';
      }

      var asset = getAsset(pathname);
      if (!asset) {
        headers['Content-Type'] = 'text/html';
        response.writeHead(404, headers);
        return staticAssets ? response.end(staticAssets.formattedAssets) : response.end();
      }

      headers['content-Type'] = asset.mimeType;
      response.writeHead(200, headers);

      var hasSourceFiles = asset.sourceFiles && asset.sourceFiles.length > 0;

      if (isWatchedFile(asset)) {
        if (hasSourceFiles && !minify) {
          async.reduce(asset.sourceFiles, '', function (memo, item, callback) {
            fs.readFile(item, function (err, content) {
              callback(null, memo + content);
            });
          }, function (err, content) {
            response.end(content);
          });
        } else {
          fs.readFile(asset.path, function (err, content) {
            response.end(content);
          });
        }
      } else {
        response.end(asset.data || asset.content);
      }
    });

    server.listen(serverPort);

    bosco.log('Server is listening on ' + serverPort);
  }

  function watchCallback(err, service) {
    if (err) { return bosco.error(err); }
    bosco.log('Local CDN ready after build for service: ' + service.name.green);
  }

  if (minify) bosco.log('Running per service builds for front end assets, this can take some time ...');

  getRunList(function (err, repoList) {
    var repoNames = _.map(repoList, 'name');
    var options = {
      repos: repoNames,
      buildNumber: 'local',
      minify: minify,
      tagFilter: null,
      watchBuilds: true,
      reloadOnly: false,
      ignoreFailure: true,
      watchRegex: watchRegex,
      repoRegex: repoRegex,
      repoTag: repoTag,
      watchCallback: watchCallback,
      isCdn: true
    };

    var executeAsync = {
      staticAssets: bosco.staticUtils.getStaticAssets.bind(null, options),
      staticRepos: bosco.staticUtils.getStaticRepos.bind(null, options)
    };

    async.parallel(executeAsync, function (err, results) {
      startServer(results.staticAssets, results.staticRepos, port);
    });
  });
}

module.exports.cmd = cmd;
<|endoftext|>


<commit_before>"use strict";

angular.module('arethusa.core').service('state', function(configurator, navigator, $rootScope) {
  var self = this;

  this.tokens = {};

  var conf = configurator.configurationFor('main');
  var tokenRetrievers = configurator.getRetrievers(conf.retrievers);

  // Loading a state

  var saveTokens = function(container, tokens) {
    angular.forEach(tokens, function(token, id) {
      var updatedToken;
      var savedToken = container[id];
      if (savedToken) {
        updatedToken = angular.extend(savedToken, token);
      } else {
        updatedToken = token;
      }
      container[id] = token;
    });
  };

  this.retrieveTokens = function() {
    var container = {};
    //navigator.reset();
    angular.forEach(tokenRetrievers, function(retriever, name) {
      retriever.getData(function(data) {
        //arethusaUtil.pushAll(navigator.sentences, data);
        //navigator.updateId();
        //saveTokens(container, navigator.currentSentence());
        saveTokens(container, data[0].tokens);
        declareLoaded(retriever);
      });
    });
    this.tokens = container;
  };

  this.checkLoadStatus = function() {
    var loaded = true;
    angular.forEach(tokenRetrievers, function(el, name) {
      loaded = loaded && el.loaded;
    });

    if (loaded) {
      this.broadcastReload();
    }
  };

  var declareLoaded = function(retriever, that) {
    retriever.loaded = true;
    self.checkLoadStatus();
  };

  // Delegators

  this.asString = function(id) {
    return this.tokens[id].string;
  };

  this.getToken = function(id) {
    return self.tokens[id] || {};
  };

  // Selections

  this.selectedTokens = {}; // ids will be inserted here

  this.isSelected = function(id) {
    return id in this.selectedTokens;
  };

  // type should be either 'click' or 'hover'
  this.selectToken = function(id, type) {
    if (this.isSelectable(this.selectionType(id), type)) {
      this.selectedTokens[id] = type;
    }
  };

  this.selectionType = function(id) {
    return this.selectedTokens[id];
  };

  this.isSelectable = function(oldVal, newVal) {
    // if an element was hovered, we only select it when another
    // selection type is present (such as 'click'), if there was
    // no selection at all (oldVal === undefined), we select too
    return (oldVal === 'hover' && newVal !== 'hover') || (! oldVal);
  };

  this.deselectToken = function(id, type) {
    // only deselect when the old selection type is the same as
    // the argument, i.e. a hover selection can only deselect a
    // hover selection, but not a click selection
    if (this.selectionType(id) === type) {
      delete this.selectedTokens[id];
    }
  };

  this.toggleSelection = function(id, type) {
    // only deselect when the selectionType is the same.
    // a hovered selection can still be selected by click.
    if (this.isSelected(id) && this.selectionType(id) == type) {
      this.deselectToken(id, type);
    } else {
      this.selectToken(id, type);
    }
  };

  this.deselectAll = function() {
    for (var el in this.selectedTokens) delete this.selectedTokens[el];
  };

  this.selectSurroundingToken = function(direction) {
    // take the first current selection
    var firstId = Object.keys(this.selectedTokens)[0];
    var allIds  = Object.keys(this.tokens);
    var index = allIds.indexOf(firstId);

    // select newId - make a roundtrip if we reached the bounds of the array
    var newId;
    switch(direction) {
      case "next":
        newId = allIds[index + 1] || allIds[0]; break;
      case "prev":
        newId = allIds[index - 1] || allIds[allIds.length - 1]; break;
    }

    // deselect all previously selected tokens
    this.deselectAll();
    // and select the new one
    this.selectToken(newId, 'click');
  };

  this.selectNextToken = function() { this.selectSurroundingToken('next'); };
  this.selectPrevToken = function() { this.selectSurroundingToken('prev'); };

  // Events

  // Listeners can be internal (angular-implementation) or external (everything
  // else). The future might bring a further distinction between different
  // of events listeners listen to - we'll see.
  this.listeners = [];
  this.externalListeners= [];

  this.registerListener = function(listener) {
    if (listener.external) {
      this.externalListeners.push(listener);
    } else {
      this.listeners.push(listener);
    }
  };

  this.fireEvent = function(target, property, oldVal, newVal) {
    var event = { target: target, property: property, oldVal: oldVal, newVal: newVal };
    event.time = new Date();
    this.notifyListeners(event);
  };

  this.notifyListeners = function(event) {
    this.notifyAngularListeners(event);
    this.notifyExternalListeners(event);
  };

  this.notifyAngularListeners = function(event) {
    angular.forEach(this.listeners, function(obj, i) {
      obj.catchEvent(event);
    });
  };

  this.notifyExternalListeners = function(event) {
    angular.forEach(this.externalListeners, function(obj, i) {
      obj.catchArethusaEvent(event);
    });
  };

  this.setState = function(id, category, val) {
    var token = this.tokens[id];
    var oldVal = token[category];
    this.fireEvent(token, category, oldVal, val);
    token[category] = val;
  };

  this.unsetState = function(id, category) {
    var token = this.tokens[id];
    var oldVal = token[category];
    this.fireEvent(token, category, oldVal,  null);
    delete token[category];
  };

  this.replaceState = function(tokens) {
    // We have to wrap this as there might be watchers on allLoaded,
    // such as the MainCtrl which has to reinit all plugins when the
    // state tokens are replaced
    this.tokens = tokens;
    this.broadcastReload();
  };

  this.setStyle = function(id, style) {
    self.getToken(id).style = style;
  };

  this.unsetStyle = function(id) {
    delete self.getToken(id).style;
  };

  this.broadcastReload = function() {
    $rootScope.$broadcast('stateLoaded');
  };

  this.addStatusObjects = function() {
    angular.forEach(self.tokens, function(token, id) {
      token.status = {};
    });
  };

  this.postInit = function() {
    self.addStatusObjects();
  };

  this.init = function() {
    this.retrieveTokens();
  };
});
<commit_msg>Better state reloading<commit_after>"use strict";

angular.module('arethusa.core').service('state', function(configurator, navigator, $rootScope) {
  var self = this;

  var conf = configurator.configurationFor('main');
  var tokenRetrievers = configurator.getRetrievers(conf.retrievers);

  // We hold tokens locally during retrieval phase.
  // Once we are done, they will be exposed through
  // this.replaceState, which also triggers
  // the stateLoaded event.
  var tokens = {};

  // Loading a state

  var saveTokens = function(container, tokens) {
    angular.forEach(tokens, function(token, id) {
      var updatedToken;
      var savedToken = container[id];
      if (savedToken) {
        updatedToken = angular.extend(savedToken, token);
      } else {
        updatedToken = token;
      }
      container[id] = token;
    });
  };

  this.retrieveTokens = function() {
    var container = {};
    //navigator.reset();
    angular.forEach(tokenRetrievers, function(retriever, name) {
      retriever.getData(function(data) {
        //arethusaUtil.pushAll(navigator.sentences, data);
        //navigator.updateId();
        //saveTokens(container, navigator.currentSentence());
        saveTokens(container, data[0].tokens);
        declareLoaded(retriever);
      });
    });
    tokens = container;
  };

  this.checkLoadStatus = function() {
    var loaded = true;
    angular.forEach(tokenRetrievers, function(el, name) {
      loaded = loaded && el.loaded;
    });

    if (loaded) {
      this.replaceState(tokens);
    }
  };

  var declareLoaded = function(retriever, that) {
    retriever.loaded = true;
    self.checkLoadStatus();
  };

  // Delegators

  this.asString = function(id) {
    return this.tokens[id].string;
  };

  this.getToken = function(id) {
    return self.tokens[id] || {};
  };

  // Selections

  this.selectedTokens = {}; // ids will be inserted here

  this.isSelected = function(id) {
    return id in this.selectedTokens;
  };

  // type should be either 'click' or 'hover'
  this.selectToken = function(id, type) {
    if (this.isSelectable(this.selectionType(id), type)) {
      this.selectedTokens[id] = type;
    }
  };

  this.selectionType = function(id) {
    return this.selectedTokens[id];
  };

  this.isSelectable = function(oldVal, newVal) {
    // if an element was hovered, we only select it when another
    // selection type is present (such as 'click'), if there was
    // no selection at all (oldVal === undefined), we select too
    return (oldVal === 'hover' && newVal !== 'hover') || (! oldVal);
  };

  this.deselectToken = function(id, type) {
    // only deselect when the old selection type is the same as
    // the argument, i.e. a hover selection can only deselect a
    // hover selection, but not a click selection
    if (this.selectionType(id) === type) {
      delete this.selectedTokens[id];
    }
  };

  this.toggleSelection = function(id, type) {
    // only deselect when the selectionType is the same.
    // a hovered selection can still be selected by click.
    if (this.isSelected(id) && this.selectionType(id) == type) {
      this.deselectToken(id, type);
    } else {
      this.selectToken(id, type);
    }
  };

  this.deselectAll = function() {
    for (var el in this.selectedTokens) delete this.selectedTokens[el];
  };

  this.selectSurroundingToken = function(direction) {
    // take the first current selection
    var firstId = Object.keys(this.selectedTokens)[0];
    var allIds  = Object.keys(this.tokens);
    var index = allIds.indexOf(firstId);

    // select newId - make a roundtrip if we reached the bounds of the array
    var newId;
    switch(direction) {
      case "next":
        newId = allIds[index + 1] || allIds[0]; break;
      case "prev":
        newId = allIds[index - 1] || allIds[allIds.length - 1]; break;
    }

    // deselect all previously selected tokens
    this.deselectAll();
    // and select the new one
    this.selectToken(newId, 'click');
  };

  this.selectNextToken = function() { this.selectSurroundingToken('next'); };
  this.selectPrevToken = function() { this.selectSurroundingToken('prev'); };

  // Events

  // Listeners can be internal (angular-implementation) or external (everything
  // else). The future might bring a further distinction between different
  // of events listeners listen to - we'll see.
  this.listeners = [];
  this.externalListeners= [];

  this.registerListener = function(listener) {
    if (listener.external) {
      this.externalListeners.push(listener);
    } else {
      this.listeners.push(listener);
    }
  };

  this.fireEvent = function(target, property, oldVal, newVal) {
    var event = { target: target, property: property, oldVal: oldVal, newVal: newVal };
    event.time = new Date();
    this.notifyListeners(event);
  };

  this.notifyListeners = function(event) {
    this.notifyAngularListeners(event);
    this.notifyExternalListeners(event);
  };

  this.notifyAngularListeners = function(event) {
    angular.forEach(this.listeners, function(obj, i) {
      obj.catchEvent(event);
    });
  };

  this.notifyExternalListeners = function(event) {
    angular.forEach(this.externalListeners, function(obj, i) {
      obj.catchArethusaEvent(event);
    });
  };

  this.setState = function(id, category, val) {
    var token = this.tokens[id];
    var oldVal = token[category];
    this.fireEvent(token, category, oldVal, val);
    token[category] = val;
  };

  this.unsetState = function(id, category) {
    var token = this.tokens[id];
    var oldVal = token[category];
    this.fireEvent(token, category, oldVal,  null);
    delete token[category];
  };

  this.replaceState = function(tokens) {
    // We have to wrap this as there might be watchers on allLoaded,
    // such as the MainCtrl which has to reinit all plugins when the
    // state tokens are replaced
    this.tokens = tokens;
    this.broadcastReload();
  };

  this.setStyle = function(id, style) {
    self.getToken(id).style = style;
  };

  this.unsetStyle = function(id) {
    delete self.getToken(id).style;
  };

  this.broadcastReload = function() {
    $rootScope.$broadcast('stateLoaded');
  };

  this.addStatusObjects = function() {
    angular.forEach(self.tokens, function(token, id) {
      token.status = {};
    });
  };

  this.postInit = function() {
    self.addStatusObjects();
  };

  this.init = function() {
    this.retrieveTokens();
  };
});
<|endoftext|>


<commit_before>'use strict';
/* A newable factory to handle xml files using the Perseus Treebank Schema
 *
 * The constructor functions takes a configuration object (that typically
 * contains a resource object for this service).
 *
 */
angular.module('arethusa').factory('TreebankRetriever', [
  'configurator',
  'documentStore',
  'retrieverHelper',
  'idHandler',
  function (configurator, documentStore, retrieverHelper, idHandler) {
    function xmlTokenToState(docId, token, sentenceId, artificials) {
      // One could formalize this to real rules that are configurable...
      //
      // Remember that attributes of the converted xml are prefixed with underscore
      var obj = aC.token(token._form, sentenceId);

      obj.morphology = {
        lemma: token._lemma,
        postag: token._postag
      };

      obj.relation = {};

      var relation = token._relation;
      obj.relation.label = (relation && relation !== 'nil') ? relation : '';

      var gloss = token._gloss;
      if (gloss) {
        obj.morphology.gloss = gloss;
      }

      var sg = token._sg;
      if (sg && !sg.match(/^\s*$/)) {
        obj.sg = { ancestors: sg.split(' ') };
      }

      if (token._artificial) {
        obj.artificial = true;
        obj.type = token._artificial;
      }

      if (aU.isTerminatingPunctuation(obj.string)) {
        obj.terminator = true;
      }

      var intId = xmlTokenId(token, sentenceId);
      retrieverHelper.generateId(obj, intId, token._id, docId);
      createHead(obj, token, artificials);

      return obj;
    }

    function createHead(stateToken, xmlToken, artificials) {
      var head = xmlToken._head;
      if (angular.isDefined(head) && head !== "") {
        var newHead = {};
        var artHead = artificials[head];
        newHead.id = artHead ? artHead : idHandler.getId(head, stateToken.sentenceId);
        stateToken.head = newHead;
      }
    }

    function xmlTokenId(token, sentenceId) {
      if (token._artificial) {
        return padWithSentenceId(token._insertion_id, sentenceId);
      } else {
        return idHandler.getId(token._id, sentenceId);
      }
    }

    // This is for backwards compatibility - we still might encounter documents, which
    // stored the insertion id without the sentence id. This is a little hacky but a
    // must have.
    function padWithSentenceId(id, sentenceId) {
      return (id.match(/-/)) ? id : idHandler.padIdWithSId(id, sentenceId);
    }

    function extractArtificial(memo, token, sentenceId) {
      if (token._artificial) {
        memo[token._id] = padWithSentenceId(token._insertion_id, sentenceId);
      }
    }

    function xmlSentenceToState(docId, words, id, cite) {
      var tokens = {};
      var artificials = arethusaUtil.inject({}, words, function(memo, token, i) {
        extractArtificial(memo, token, id);
      });
      angular.forEach(words, function (xmlToken, i) {
        var token = xmlTokenToState(docId, xmlToken, id, artificials);
        tokens[token.id] = token;
      });

      return aC.sentence(id, tokens, cite);
    }

    function parseDocument(json, docId) {
      var sentences = arethusaUtil.toAry(json.treebank.sentence);
      return arethusaUtil.inject([], sentences, function (memo, sentence, k) {
        var cite = extractCiteInfo(sentence);
        var words = arethusaUtil.toAry(sentence.word);
        memo.push(xmlSentenceToState(docId, words, sentence._id, cite));
      });
    }

    // Try to support the new as well as the old schema for now
    function extractCiteInfo(sentence) {
      var cite = sentence._cite;
      if (cite) {
        return cite;
      } else {

        var docId = sentence._document_id;
        var subdoc = sentence._subdoc;
        if (subdoc) {
          return docId + ':' + subdoc;
        } else {
          return docId;
        }
      }
    }

    function findAdditionalConfInfo(json) {
      var linkInfo = json.treebank.link;
      var links =  linkInfo ? arethusaUtil.toAry(linkInfo) : [];
      var confs = arethusaUtil.inject({}, links, function(memo, link) {
        memo[link._title] = link._href;
      });
      var format = json.treebank._format;
      if (format) {
        // For backwards compatibility to older days
        if (format == 'aldt') {
          format = 'aldt2' + json.treebank['_xml:lang'];
        }
        confs.fullFile = format;
      }
      return confs;
    }

    return function (conf) {
      var self = this;
      var resource = configurator.provideResource(conf.resource);
      var docId = conf.docIdentifier;

      this.preselections = retrieverHelper.getPreselections(conf);

      this.get = function (callback) {
        resource.get().then(function (res) {
          var xml = res.data;
          var json = arethusaUtil.xml2json(res.data);
          var moreConf = findAdditionalConfInfo(json);

          documentStore.addDocument(docId, new aC.doc(xml, json, moreConf));
          callback(parseDocument(json, docId));
        });
      };
    };
  }
]);
<commit_msg>Extract public parse function in TreebankRetriever<commit_after>'use strict';
/* A newable factory to handle xml files using the Perseus Treebank Schema
 *
 * The constructor functions takes a configuration object (that typically
 * contains a resource object for this service).
 *
 */
angular.module('arethusa').factory('TreebankRetriever', [
  'configurator',
  'documentStore',
  'retrieverHelper',
  'idHandler',
  function (configurator, documentStore, retrieverHelper, idHandler) {
    function xmlTokenToState(docId, token, sentenceId, artificials) {
      // One could formalize this to real rules that are configurable...
      //
      // Remember that attributes of the converted xml are prefixed with underscore
      var obj = aC.token(token._form, sentenceId);

      obj.morphology = {
        lemma: token._lemma,
        postag: token._postag
      };

      obj.relation = {};

      var relation = token._relation;
      obj.relation.label = (relation && relation !== 'nil') ? relation : '';

      var gloss = token._gloss;
      if (gloss) {
        obj.morphology.gloss = gloss;
      }

      var sg = token._sg;
      if (sg && !sg.match(/^\s*$/)) {
        obj.sg = { ancestors: sg.split(' ') };
      }

      if (token._artificial) {
        obj.artificial = true;
        obj.type = token._artificial;
      }

      if (aU.isTerminatingPunctuation(obj.string)) {
        obj.terminator = true;
      }

      var intId = xmlTokenId(token, sentenceId);
      retrieverHelper.generateId(obj, intId, token._id, docId);
      createHead(obj, token, artificials);

      return obj;
    }

    function createHead(stateToken, xmlToken, artificials) {
      var head = xmlToken._head;
      if (angular.isDefined(head) && head !== "") {
        var newHead = {};
        var artHead = artificials[head];
        newHead.id = artHead ? artHead : idHandler.getId(head, stateToken.sentenceId);
        stateToken.head = newHead;
      }
    }

    function xmlTokenId(token, sentenceId) {
      if (token._artificial) {
        return padWithSentenceId(token._insertion_id, sentenceId);
      } else {
        return idHandler.getId(token._id, sentenceId);
      }
    }

    // This is for backwards compatibility - we still might encounter documents, which
    // stored the insertion id without the sentence id. This is a little hacky but a
    // must have.
    function padWithSentenceId(id, sentenceId) {
      return (id.match(/-/)) ? id : idHandler.padIdWithSId(id, sentenceId);
    }

    function extractArtificial(memo, token, sentenceId) {
      if (token._artificial) {
        memo[token._id] = padWithSentenceId(token._insertion_id, sentenceId);
      }
    }

    function xmlSentenceToState(docId, words, id, cite) {
      var tokens = {};
      var artificials = arethusaUtil.inject({}, words, function(memo, token, i) {
        extractArtificial(memo, token, id);
      });
      angular.forEach(words, function (xmlToken, i) {
        var token = xmlTokenToState(docId, xmlToken, id, artificials);
        tokens[token.id] = token;
      });

      return aC.sentence(id, tokens, cite);
    }

    function parseDocument(json, docId) {
      var sentences = arethusaUtil.toAry(json.treebank.sentence);
      return arethusaUtil.inject([], sentences, function (memo, sentence, k) {
        var cite = extractCiteInfo(sentence);
        var words = arethusaUtil.toAry(sentence.word);
        memo.push(xmlSentenceToState(docId, words, sentence._id, cite));
      });
    }

    // Try to support the new as well as the old schema for now
    function extractCiteInfo(sentence) {
      var cite = sentence._cite;
      if (cite) {
        return cite;
      } else {

        var docId = sentence._document_id;
        var subdoc = sentence._subdoc;
        if (subdoc) {
          return docId + ':' + subdoc;
        } else {
          return docId;
        }
      }
    }

    function findAdditionalConfInfo(json) {
      var linkInfo = json.treebank.link;
      var links =  linkInfo ? arethusaUtil.toAry(linkInfo) : [];
      var confs = arethusaUtil.inject({}, links, function(memo, link) {
        memo[link._title] = link._href;
      });
      var format = json.treebank._format;
      if (format) {
        // For backwards compatibility to older days
        if (format == 'aldt') {
          format = 'aldt2' + json.treebank['_xml:lang'];
        }
        confs.fullFile = format;
      }
      return confs;
    }

    return function (conf) {
      var self = this;
      var resource = configurator.provideResource(conf.resource);
      var docId = conf.docIdentifier;

      this.preselections = retrieverHelper.getPreselections(conf);

      this.parse = function(xml, callback) {
        var json = arethusaUtil.xml2json(xml);
        var moreConf = findAdditionalConfInfo(json);

        documentStore.addDocument(docId, new aC.doc(xml, json, moreConf));
        callback(parseDocument(json, docId));
      };

      this.get = function (callback) {
        resource.get().then(function (res) {
          self.parse(res.data, callback);
        });
      };
    };
  }
]);
<|endoftext|>


<commit_before>module.exports = message => {
    let owo = ["<:blank:279251926409936896>",
        "<:blank:279251926409936896> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:blank:279251926409936896> <:yiff21:356202238064066561> <:blank:279251926409936896> <:yiff21:356202238064066561> <:blank:279251926409936896> <:yiff21:356202238064066561> <:blank:279251926409936896> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:blank:279251926409936896>",
        "<:yiff21:356202238064066561> <:blank:279251926409936896> <:blank:279251926409936896> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:blank:279251926409936896> <:yiff21:356202238064066561> <:blank:279251926409936896> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:blank:279251926409936896> <:blank:279251926409936896> <:yiff21:356202238064066561>",
        "<:yiff21:356202238064066561> <:blank:279251926409936896> <:blank:279251926409936896> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:blank:279251926409936896> <:yiff21:356202238064066561> <:blank:279251926409936896> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:blank:279251926409936896> <:blank:279251926409936896> <:yiff21:356202238064066561>",
        "<:yiff21:356202238064066561> <:blank:279251926409936896> <:blank:279251926409936896> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:blank:279251926409936896> <:yiff21:356202238064066561> <:blank:279251926409936896> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:blank:279251926409936896> <:blank:279251926409936896> <:yiff21:356202238064066561>",
        "<:blank:279251926409936896> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:blank:279251926409936896> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:blank:279251926409936896> <:yiff21:356202238064066561> <:yiff21:356202238064066561> <:blank:279251926409936896>"
    ];

    message.channel.createMessage(owo.join("\n"));
};
<commit_msg>aaaaa<commit_after>module.exports = message => {
    let owo = ["<:blank:279251926409936896>",
        "<:blank:279251926409936896> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:blank:279251926409936896> <:yiff21:356202124972916737> <:blank:279251926409936896> <:yiff21:356202124972916737> <:blank:279251926409936896> <:yiff21:356202124972916737> <:blank:279251926409936896> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:blank:279251926409936896>",
        "<:yiff21:356202124972916737> <:blank:279251926409936896> <:blank:279251926409936896> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:blank:279251926409936896> <:yiff21:356202124972916737> <:blank:279251926409936896> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:blank:279251926409936896> <:blank:279251926409936896> <:yiff21:356202124972916737>",
        "<:yiff21:356202124972916737> <:blank:279251926409936896> <:blank:279251926409936896> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:blank:279251926409936896> <:yiff21:356202124972916737> <:blank:279251926409936896> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:blank:279251926409936896> <:blank:279251926409936896> <:yiff21:356202124972916737>",
        "<:yiff21:356202124972916737> <:blank:279251926409936896> <:blank:279251926409936896> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:blank:279251926409936896> <:yiff21:356202124972916737> <:blank:279251926409936896> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:blank:279251926409936896> <:blank:279251926409936896> <:yiff21:356202124972916737>",
        "<:blank:279251926409936896> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:blank:279251926409936896> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:blank:279251926409936896> <:yiff21:356202124972916737> <:yiff21:356202124972916737> <:blank:279251926409936896>"
    ];

    message.channel.createMessage(owo.join("\n"));
};
<|endoftext|>


<commit_before>'use strict';

// syntax: put [item] in [container] or put [item] [container]
//TODO: Change get to auto-put or auto-hold...

// When finding item to put in container:
// - Look at held items first.
// - Then look in the room at large.

// When finding container:
// - Look at worn containers first (inventory)
// - Then nested containers
// - Finally, look in room

const util        = require('util');
const _           = require('../src/helpers');
const CommandUtil = require('../src/command_util').CommandUtil;
const Broadcast   = require('../src/broadcast').Broadcast;

exports.command = (rooms, items, players, npcs, Commands) =>
  (args, player) => {
    args = args.trim();

    if (!args) {
      return player.warn('Put which item into which container?');
    }

    if (player.isInCombat()) {
      return player.warn('You cannot do that while fighting!');
    }

    const room   = rooms.getAt(player.getLocation());
    const toRoom = Broadcast.toRoom(room, player, null, players);

    const [ itemTarget, containerTarget ] = _.getTargets(args);

    const item      = findItem(itemTarget);
    const container = findContainer(containerTarget);

    if (!item)      { return player.warn(`Could not find ${itemTarget}.`); }
    if (!container) { return player.warn(`Could not find ${containerTarget} that would fit ${item.getShortDesc()} in it.`); }

    putInContainer(item, container);

    // -- helpers -- //TODO: Put in CommandUtil/ItemUtil?

    function findItem(itemTarget) {
      return CommandUtil.findItemInRoom(items, itemTarget, room, player, true) || CommandUtil.findItemInInventory(itemTarget, player, true);
    }

    function findContainer(containerTarget) {
      if (!containerTarget || containerTarget === 'away') {
        return player.getContainerWithCapacity(items, item.getAttribute('size'));
      }
      const possibleContainersInInventory = player.getContainersWithCapacity(items, item.getAttribute('size'))
        .filter(item => item.hasKeyword(containerTarget));
      return possibleContainersInInventory[0] || CommandUtil.findItemInRoom(items, containerTarget, room, player, true);
    }

    function putInContainer(item, container) {
      container.addItem(item);

      if (item.isEquipped()) {
        item.setEquipped(false);
        const isDropping = true; //TODO: Come up with better param name...
        player.unequip(item, items, players, isDropping);
      }

      const holder = container.getHolder() || null;
      item.setHolder(holder);

      if (!holder || holder !== player.getName()) { player.removeItem(item); }

      item.setRoom(null);
      if (room) { room.removeItem(item); }

      const containerDesc = container.getShortDesc();
      const itemName = item.getShortDesc();
      toRoom({
        firstPartyMessage: 'You place the ' + itemName + ' into the ' + containerDesc + '.',
        thirdPartyMessage: player.getName() + ' places the ' + itemName + ' into the ' + containerDesc + '.'
      });

      player.emit('action', 1, items);

    }

  };
<commit_msg>Trying to fix the put command now. It should fail early if the item is not found.<commit_after>'use strict';

// syntax: put [item] in [container] or put [item] [container]
//TODO: Change get to auto-put or auto-hold...

// When finding item to put in container:
// - Look at held items first.
// - Then look in the room at large.

// When finding container:
// - Look at worn containers first (inventory)
// - Then nested containers
// - Finally, look in room

const util        = require('util');
const _           = require('../src/helpers');
const CommandUtil = require('../src/command_util').CommandUtil;
const Broadcast   = require('../src/broadcast').Broadcast;

exports.command = (rooms, items, players, npcs, Commands) =>
  (args, player) => {
    args = args.trim();

    if (!args) {
      return player.warn('Put which item into which container?');
    }

    if (player.isInCombat()) {
      return player.warn('You cannot do that while fighting!');
    }

    const room   = rooms.getAt(player.getLocation());
    const toRoom = Broadcast.toRoom(room, player, null, players);

    const [ itemTarget, containerTarget ] = _.getTargets(args);

    const item = findItem(itemTarget);
    if (!item) { return player.warn(`Could not find ${itemTarget}.`); }

    const container = findContainer(containerTarget);
    if (!container) { return player.warn(`Could not find ${containerTarget} that would fit ${item.getShortDesc()} in it.`); }

    putInContainer(item, container);

    // -- helpers -- //TODO: Put in CommandUtil/ItemUtil?

    function findItem(itemTarget) {
      return CommandUtil.findItemInRoom(items, itemTarget, room, player, true) || CommandUtil.findItemInInventory(itemTarget, player, true);
    }

    function findContainer(containerTarget) {
      if (!containerTarget || containerTarget === 'away') {
        return player.getContainerWithCapacity(items, item.getAttribute('size'));
      }
      const possibleContainersInInventory = player.getContainersWithCapacity(items, item.getAttribute('size'))
        .filter(item => item.hasKeyword(containerTarget));
      return possibleContainersInInventory[0] || CommandUtil.findItemInRoom(items, containerTarget, room, player, true);
    }

    // Main operation of putting an item into a container.

    function putInContainer(item, container) {
      container.addItem(item);

      if (item.isEquipped()) {
        item.setEquipped(false);
        const isDropping = true;
        player.unequip(item, items, players, isDropping);
      }

      const holder = container.getHolder() || null;
      item.setHolder(holder);

      if (!holder || holder !== player.getName()) { player.removeItem(item); }

      item.setRoom(null);
      if (room) { room.removeItem(item); }

      const containerDesc = container.getShortDesc();
      const itemName = item.getShortDesc();
      toRoom({
        firstPartyMessage: 'You place the ' + itemName + ' into the ' + containerDesc + '.',
        thirdPartyMessage: player.getName() + ' places the ' + itemName + ' into the ' + containerDesc + '.'
      });

      player.emit('action', 1, items);

    }

  };
<|endoftext|>


<commit_before>const table = r.table('tags');
exports.run = async (client, msg, args) => {
  let exists = await table.filter({userID : msg.author.id}).run();

  const action  = args[0];
  const name    = args[0] ? args[1] : undefined;
  const content = name ? msg.content.split(' ').slice(3).join(' ') : undefined;

  if (!action) {
    return;
  }
   if (action === 'register') {
     if (!name) return msg.reply('You must specify the name.');
     if (!content) return msg.reply('You must specify tag\'s content.')
      if (!exists[0]) {
        await table.insert({
          userID  : msg.author.id,
          tags    : [{
            name    : name,
            content : content
          }]
        }).run()
      } else {

        if (exists[0].tags.length >= 5) {
          return msg.reply('You cannot store more than 5 tags.')
        }

        for (var i = 0; i < exists[0].tags.length; i++) {
          if (exists[0].tags[i]['name'] === name) {
            return msg.reply('You already have a tag with this name.')
          }
        }

        let appendToArray = (table, uArray, doc) => r.table(table)
        .filter({userID : msg.author.id})
        .update(object => ({ [uArray]: object(uArray)
        .default([]).append(doc) }))
        .run();
        appendToArray('tags', 'tags', {name : name, content : content})

      }
      msg.channel.send(`Added the tag = ${name} = , do -tag list, so you can view the list of your tags`, {code : "asciidoc"})
   } else if (action !== 'register' && action !== 'list'){

     let tagName = action
     try {
       let tagValue = exists[0]['tags'].filter(o => o.name === tagName)[0]['content']
       msg.channel.send(tagValue)
     } catch (e) {
       return msg.reply('This tag does not exists!')
     }

   } else if (action === 'list') {
     let textArray = [`= 🔖Available tags for ${msg.author.username}🔖 =`];

     if (exists[0].tags.length < 1 || !exists[0]) {
       return msg.reply('You do not have any tags available')
     }
     for (var i = 0; i < exists[0].tags.length; i++) {
       textArray.push(`${i + 1}). ${exists[0].tags[i].name}`);
     }
     msg.channel.send(textArray.join('\n'), {code : 'asciidoc'})
   } else if (action === 'delete') {
     let toDelete = name;
     if (exists[0].tags.length < 1 || !exists[0]) {
       return msg.reply('You do not have any tags available')
     }

   }

};

exports.help = {
    category: 'fun',
    usage: 'register [name][content] : -tag [name] : -tag list',
    description: 'register and use tags for saying things',
    detail: 'By using tag you will able to make custom tags that will say things',
    botPerm: ['SEND_MESSAGES'],
    authorPerm: [],
    alias: [
        'ta'
    ],
    example: 'register tagName This message will apear when doing -tag tagName'
};
<commit_msg>removed `,`<commit_after>const table = r.table('tags');
exports.run = async (client, msg, args) => {
  let exists = await table.filter({userID : msg.author.id}).run();

  const action  = args[0];
  const name    = args[0] ? args[1] : undefined;
  const content = name ? msg.content.split(' ').slice(3).join(' ') : undefined;

  if (!action) {
    return;
  }
   if (action === 'register') {
     if (!name) return msg.reply('You must specify the name.');
     if (!content) return msg.reply('You must specify tag\'s content.')
      if (!exists[0]) {
        await table.insert({
          userID  : msg.author.id,
          tags    : [{
            name    : name,
            content : content
          }]
        }).run()
      } else {

        if (exists[0].tags.length >= 5) {
          return msg.reply('You cannot store more than 5 tags.')
        }

        for (var i = 0; i < exists[0].tags.length; i++) {
          if (exists[0].tags[i]['name'] === name) {
            return msg.reply('You already have a tag with this name.')
          }
        }

        let appendToArray = (table, uArray, doc) => r.table(table)
        .filter({userID : msg.author.id})
        .update(object => ({ [uArray]: object(uArray)
        .default([]).append(doc) }))
        .run();
        appendToArray('tags', 'tags', {name : name, content : content})

      }
      msg.channel.send(`Added the tag = ${name} =  do -tag list, so you can view the list of your tags`, {code : "asciidoc"})
   } else if (action !== 'register' && action !== 'list'){

     let tagName = action
     try {
       let tagValue = exists[0]['tags'].filter(o => o.name === tagName)[0]['content']
       msg.channel.send(tagValue)
     } catch (e) {
       return msg.reply('This tag does not exists!')
     }

   } else if (action === 'list') {
     let textArray = [`= 🔖Available tags for ${msg.author.username}🔖 =`];

     if (exists[0].tags.length < 1 || !exists[0]) {
       return msg.reply('You do not have any tags available')
     }
     for (var i = 0; i < exists[0].tags.length; i++) {
       textArray.push(`${i + 1}). ${exists[0].tags[i].name}`);
     }
     msg.channel.send(textArray.join('\n'), {code : 'asciidoc'})
   } else if (action === 'delete') {
     let toDelete = name;
     if (exists[0].tags.length < 1 || !exists[0]) {
       return msg.reply('You do not have any tags available')
     }

   }

};

exports.help = {
    category: 'fun',
    usage: 'register [name][content] : -tag [name] : -tag list',
    description: 'register and use tags for saying things',
    detail: 'By using tag you will able to make custom tags that will say things',
    botPerm: ['SEND_MESSAGES'],
    authorPerm: [],
    alias: [
        'ta'
    ],
    example: 'register tagName This message will apear when doing -tag tagName'
};
<|endoftext|>


<commit_before>/*
 * Visual Spotlighter Extension.
 * /extensions/visual-spotlighter.js
 *
 * An extension for visually spotlighting a given node.
 */

WA.Extensions.VisualSpotlighter = function() {
  /**
   * Spotlight the supplied node.
   * @param node Node to be spotlighted.  node=null unspotlights.
   */
  this.spotlight = function(node) {
    var self = this;

    if(this._nodeRecords != null && this._nodeRecords.length > 0) {
      // Unspotlight the last node, then store this node.
      this.unspotlight();
    }

    if(node == null) return;

    if(node.nodeType != 1 || node.nodeName == "OPTION") {
      node = node.parentNode;
    }

    this._nodeRecords = new Array();

    if(node.nodeName == "A") {
	    WA.Nodes.depthFirstVisitor(
	      // First node to visit.
	      node,
	      // Visitor function called for each node.
	      function(node) {
	      	self._processNode(node);
	      },
	      // isLeaf function.
		    function(node) {
		    	return (!node || node.nodeType != 1);
		    }
	    )
    } else {
    	this._processNode(node);
    }

    // Label any nodes associated with this one, specifically nodes
    // that serve as this node's label.
    if(WA.Nodes.hasAttribute(node, 'assoc_id')) {
      var assocNode = node.ownerDocument.getElementById(node.getAttribute('assoc_id'));
      this._processNode(assocNode);
    }
  };

  /**
   * Highlight the specified node and store its original style in a
   * constructed NodeRecord.
   * @param node Node to style and store.
   */
  this._processNode = function(node) {
    this._nodeRecords.push(new this.NodeRecord(node));

    if((node.className + "").length > 0) {
      node.className = "wahighlight " + node.className;
    } else {
    	node.className = "wahighlight";
    }
  },

  /**
   * Remove spotlighting from supplied node.
   */
  this.unspotlight = function() {
    var nodes = this._nodeRecords;
  	for(var i=0; i<nodes.length; i++) {
    	nodes[i].restore();
  	}
  };

  /**
   * Reset the spotlight.
   */
  this.reset = function() {
    // Jeff: commented out because IE complains if node is no longer loaded.
    /*if(this._nodeRecords) {
    	this.unspotlight();
    }*/
  	this._nodeRecords = new Array();
  };

  /**
   * A class representing the current style of a node.
   * @param node The node for which the current style will be stored.
   */
  this.NodeRecord = function(node) {
    this._node = node;

    // Store the node's current class in order to restore it later.
    if((node.className + "").length > 0) {
      this._className = node.className;
    }

    /**
     * Restore the original style of the node.
     */
    this.restore = function() {
    	if(this._node) {
      	  try {
            this._node.className = this._className;
          }
          catch(err) {
            // do nothing?
          }
    	}
    }
  };

  /**
   * Adds the CSS class used for highlighting.
   * @param doc Document to have the CSS style tag added to it.
   * @param docs Array of documents to have the CSS style tag added to each of them.
   */
  //this.oncePerDocument = function(doc) {
  this.oncePerDocument = function(docs) {

    // Avoid highlighting nodes no longer in existence.
    this._nodeRecords = null;

  	/* var styleNode = doc.createElement('div');
    // Funky way of adding style required to make this work with IE.
    styleNode.innerHTML =
      "

" +
      "";
    doc.body.appendChild(styleNode); */

    // Add the style to each document. If no iframes, then should only add
    // this to the base document.
    for(var i=0; i<nDocuments.length; i++) {
      var styleNode = docs[i].createElement('div');
      // Funky way of adding style required to make this work with IE.
      styleNode.innerHTML =
          "

" +
          "";
      docs[i].body.appendChild(styleNode);
     }
   }

  //};
};

// Initialize the visual spotlighter and add it to the extensions
// that will be executed.  Run from anonymous function to avoid polluting
// the namespace.
(function() {
  var newVS = new WA.Extensions.VisualSpotlighter();

  // Add this extension to the node spotlighter extensions.
  WA.Extensions.nodeSpotlighters.push(newVS);

  // Add the function to add the style tag to each document to the list of
  // functions called for each document.
  WA.Extensions.oncePerDocument.push(newVS);

  // Add this extension to the general list of extensions.
  WA.Extensions.extensionList.push(newVS);
})();<commit_msg>deleted that last change. tried to use svn revert but did not have an affect.<commit_after>/*
 * Visual Spotlighter Extension.
 * /extensions/visual-spotlighter.js
 *
 * An extension for visually spotlighting a given node.
 */

WA.Extensions.VisualSpotlighter = function() {
  /**
   * Spotlight the supplied node.
   * @param node Node to be spotlighted.  node=null unspotlights.
   */
  this.spotlight = function(node) {
    var self = this;

    if(this._nodeRecords != null && this._nodeRecords.length > 0) {
      // Unspotlight the last node, then store this node.
      this.unspotlight();
    }

    if(node == null) return;

    if(node.nodeType != 1 || node.nodeName == "OPTION") {
      node = node.parentNode;
    }

    this._nodeRecords = new Array();

    if(node.nodeName == "A") {
	    WA.Nodes.depthFirstVisitor(
	      // First node to visit.
	      node,
	      // Visitor function called for each node.
	      function(node) {
	      	self._processNode(node);
	      },
	      // isLeaf function.
		    function(node) {
		    	return (!node || node.nodeType != 1);
		    }
	    )
    } else {
    	this._processNode(node);
    }

    // Label any nodes associated with this one, specifically nodes
    // that serve as this node's label.
    if(WA.Nodes.hasAttribute(node, 'assoc_id')) {
      var assocNode = node.ownerDocument.getElementById(node.getAttribute('assoc_id'));
      this._processNode(assocNode);
    }
  };

  /**
   * Highlight the specified node and store its original style in a
   * constructed NodeRecord.
   * @param node Node to style and store.
   */
  this._processNode = function(node) {
    this._nodeRecords.push(new this.NodeRecord(node));

    if((node.className + "").length > 0) {
      node.className = "wahighlight " + node.className;
    } else {
    	node.className = "wahighlight";
    }
  },

  /**
   * Remove spotlighting from supplied node.
   */
  this.unspotlight = function() {
    var nodes = this._nodeRecords;
  	for(var i=0; i<nodes.length; i++) {
    	nodes[i].restore();
  	}
  };

  /**
   * Reset the spotlight.
   */
  this.reset = function() {
    // Jeff: commented out because IE complains if node is no longer loaded.
    /*if(this._nodeRecords) {
    	this.unspotlight();
    }*/
  	this._nodeRecords = new Array();
  };

  /**
   * A class representing the current style of a node.
   * @param node The node for which the current style will be stored.
   */
  this.NodeRecord = function(node) {
    this._node = node;

    // Store the node's current class in order to restore it later.
    if((node.className + "").length > 0) {
      this._className = node.className;
    }

    /**
     * Restore the original style of the node.
     */
    this.restore = function() {
    	if(this._node) {
            this._node.className = this._className;
    	}
    }
  };

  /**
   * Adds the CSS class used for highlighting.
   * @param doc Document to have the CSS style tag added to it.
   * @param docs Array of documents to have the CSS style tag added to each of them.
   */
  //this.oncePerDocument = function(doc) {
  this.oncePerDocument = function(docs) {

    // Avoid highlighting nodes no longer in existence.
    this._nodeRecords = null;

  	/* var styleNode = doc.createElement('div');
    // Funky way of adding style required to make this work with IE.
    styleNode.innerHTML =
      "

" +
      "";
    doc.body.appendChild(styleNode); */

    // Add the style to each document. If no iframes, then should only add
    // this to the base document.
    for(var i=0; i<nDocuments.length; i++) {
      var styleNode = docs[i].createElement('div');
      // Funky way of adding style required to make this work with IE.
      styleNode.innerHTML =
          "

" +
          "";
      docs[i].body.appendChild(styleNode);
     }
   }

  //};
};

// Initialize the visual spotlighter and add it to the extensions
// that will be executed.  Run from anonymous function to avoid polluting
// the namespace.
(function() {
  var newVS = new WA.Extensions.VisualSpotlighter();

  // Add this extension to the node spotlighter extensions.
  WA.Extensions.nodeSpotlighters.push(newVS);

  // Add the function to add the style tag to each document to the list of
  // functions called for each document.
  WA.Extensions.oncePerDocument.push(newVS);

  // Add this extension to the general list of extensions.
  WA.Extensions.extensionList.push(newVS);
})();<|endoftext|>


<commit_before><commit_msg>donjon import now also attempts to retrieve the map title<commit_after><|endoftext|>


<commit_before><commit_msg>api: update-party: store req info<commit_after><|endoftext|>


<commit_before>// Create our number formatter.
export const formatterZero = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  minimumFractionDigits: 0,
  maximumFractionDigits: 0
})

export const formatterTwo = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  minimumFractionDigits: 2
})

export const formatBTC = (num) => num.toFixed(8)
export const formatBTCLarge = (num) => {
  let formatStyle
  if (Number(num) > 1000) {
    formatStyle = new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 })
  } else {
    formatStyle = new Intl.NumberFormat('en-US', { maximumFractionDigits: 2 })
  }
  return formatStyle.format(num)
}

export function getClass (type) {
  if (type === 'ContractTransaction') {
    return 'neo-transaction'
  }
  if (type === 'ClaimTransaction') {
    return 'gas-transaction'
  }
  if (type === 'MinerTransaction') {
    return 'miner-transaction'
  }
  if (type === 'RegisterTransaction') {
    return 'register-transaction'
  }
  if (type === 'IssueTransaction') {
    return 'issue-transaction'
  }
  if (type === 'PublishTransaction') {
    return 'publish-transaction'
  }
  if (type === 'InvocationTransaction') {
    return 'invocation-transaction'
  }
  if (type === 'EnrollmentTransaction') {
    return 'invocation-transaction'
  }
}

export function getName (type) {
  if (type === 'ContractTransaction') {
    return 'Contract'
  }
  if (type === 'ClaimTransaction') {
    return 'GAS Claim'
  }
  if (type === 'MinerTransaction') {
    return 'Miner'
  }
  if (type === 'RegisterTransaction') {
    return 'Register'
  }
  if (type === 'IssueTransaction') {
    return 'Issue'
  }
  if (type === 'PublishTransaction') {
    return 'Publish'
  }
  if (type === 'InvocationTransaction') {
    return 'Invocation'
  }
  if (type === 'EnrollmentTransaction') {
    return 'Enrollment'
  }
}

export function getIcon (type) {
  if (type === 'ContractTransaction') {
    return 'fa-cube'
  }
  if (type === 'ClaimTransaction') {
    return 'fa-cubes'
  }
  if (type === 'MinerTransaction') {
    return 'fa-user-circle-o'
  }
  if (type === 'RegisterTransaction') {
    return 'fa-list-alt'
  }
  if (type === 'IssueTransaction') {
    return 'fa-handshake-o'
  }
  if (type === 'PublishTransaction') {
    return 'fa-cube'
  }
  if (type === 'InvocationTransaction') {
    return 'fa-paper-plane'
  }
  if (type === 'EnrollmentTransaction') {
    return 'fa-paper-plane'
  }
}
<commit_msg>state transactions js<commit_after>// Create our number formatter.
export const formatterZero = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  minimumFractionDigits: 0,
  maximumFractionDigits: 0
})

export const formatterTwo = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  minimumFractionDigits: 2
})

export const formatBTC = (num) => num.toFixed(8)
export const formatBTCLarge = (num) => {
  let formatStyle
  if (Number(num) > 1000) {
    formatStyle = new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 })
  } else {
    formatStyle = new Intl.NumberFormat('en-US', { maximumFractionDigits: 2 })
  }
  return formatStyle.format(num)
}

export function getClass (type) {
  if (type === 'ContractTransaction') {
    return 'neo-transaction'
  }
  if (type === 'ClaimTransaction') {
    return 'gas-transaction'
  }
  if (type === 'MinerTransaction') {
    return 'miner-transaction'
  }
  if (type === 'RegisterTransaction') {
    return 'register-transaction'
  }
  if (type === 'IssueTransaction') {
    return 'issue-transaction'
  }
  if (type === 'PublishTransaction') {
    return 'publish-transaction'
  }
  if (type === 'InvocationTransaction') {
    return 'invocation-transaction'
  }
  if (type === 'EnrollmentTransaction') {
    return 'invocation-transaction'
  }
  if (type === 'StateTransaction') {
    return 'invocation-transaction'
  }
}

export function getName (type) {
  if (type === 'ContractTransaction') {
    return 'Contract'
  }
  if (type === 'ClaimTransaction') {
    return 'GAS Claim'
  }
  if (type === 'MinerTransaction') {
    return 'Miner'
  }
  if (type === 'RegisterTransaction') {
    return 'Register'
  }
  if (type === 'IssueTransaction') {
    return 'Issue'
  }
  if (type === 'PublishTransaction') {
    return 'Publish'
  }
  if (type === 'InvocationTransaction') {
    return 'Invocation'
  }
  if (type === 'EnrollmentTransaction') {
    return 'Enrollment'
  }
  if (type === 'StateTransaction') {
    return 'Enrollment'
  }
}

export function getIcon (type) {
  if (type === 'ContractTransaction') {
    return 'fa-cube'
  }
  if (type === 'ClaimTransaction') {
    return 'fa-cubes'
  }
  if (type === 'MinerTransaction') {
    return 'fa-user-circle-o'
  }
  if (type === 'RegisterTransaction') {
    return 'fa-list-alt'
  }
  if (type === 'IssueTransaction') {
    return 'fa-handshake-o'
  }
  if (type === 'PublishTransaction') {
    return 'fa-cube'
  }
  if (type === 'InvocationTransaction') {
    return 'fa-paper-plane'
  }
  if (type === 'EnrollmentTransaction') {
    return 'fa-paper-plane'
  }
  if (type === 'StateTransaction') {
    return 'fa-paper-plane'
  }
}
<|endoftext|>


<commit_before>/**
 * Draw a rectangular outline as the user is drawing on
 * top of the canvas
 */
define(function( require ) {

  var asOutlineShape = require("./asOutlineShape");

  function RectOutline(canvas, cfg){
    this.initialize(canvas, cfg);
  }

  RectOutline.prototype.getOutlinePoints = function(pointDistance){
    if (pointDistance < 0) {
      return this.outline;
    }

    var points = [],
        xLength = this.outline.x + this.outline.width,
        yHeight = this.outline.y + this.outline.height,
        x = this.outline.x,
        y = this.outline.y;
    // top
    for (var i = x + pointDistance; i < xLength; i+= pointDistance){
      points.push({x: i, y: y});
    }

    // get left
    for (i = y; i < yHeight; i += pointDistance){
      points.push({x: x, y: i});
    }

    // get bottom
    for (i = x; i < xLength; i += pointDistance){
      points.push({x: i, y: yHeight});
    }

    // get right
    for (i = yHeight; i >= y; i -= pointDistance){
      points.push({x: xLength, y: i});
    }

    return points;
  };

  RectOutline.prototype.onMouseDown = function(e) {
    this.canvas.selection = false;
    var point = this.canvas.getPointer(e.e);

    this.outline = {
      x: point.x,
      y: point.y,
      width: 1,
      height: 1
    };

    this.isDrawing = true;
    this.startPoint = this.outerPoint = point;

    return this;
  };

  RectOutline.prototype.onMouseMove = function(e) {
    if (this.isDrawing) {
      var point = this.canvas.getPointer(e.e);

      this.updateOutline(point);
    }

    return this;
  };

  RectOutline.prototype.updateOutline = function( point ) {
    this.outline.height = point.y - this.outline.y;
    this.outline.width = point.x - this.outline.x;

    this.outerPoint = point;

    this.renderOutline();

    return this;
  };

  RectOutline.prototype.normalizeOutlinePosition = function() {
    if (this.outline.width < 0){
      this.outline.x = this.outline.x + this.outline.width;
      this.outline.width *= -1;
    }

    if (this.outline.height < 0) {
      this.outline.y = this.outline.y + this.outline.height;
      this.outline.height *= -1;
    }
  };

  RectOutline.prototype.renderOutline = function() {
    var ctx = this.canvas.contextTop;

    this.canvas.clearContext(ctx);
    ctx.save();

    ctx.lineWidth = 1;
    ctx.strokeStyle = this.cfg.strokeColor;
    ctx.strokeRect(this.outline.x, this.outline.y, this.outline.width, this.outline.height);

    ctx.restore();

    return this;
  };

  asOutlineShape.call(RectOutline.prototype);

  return RectOutline;

});<commit_msg>split up function for rect outline<commit_after>/**
 * Draw a rectangular outline as the user is drawing on
 * top of the canvas
 */
define(function( require ) {

  var asOutlineShape = require("./asOutlineShape");

  function getBoundaryPoint( point, xLength, yHeight, distance ) {
    var x = point.x,
        y = point.y,
        points = [];
    // top
    for (var iter = x + distance; iter < xLength; iter+= distance){
      points.push({x: iter, y: y});
    }

    // get left
    for (iter = y; iter < yHeight; iter += distance){
      points.push({x: x, y: iter});
    }

    // get bottom
    for (iter = x; iter < xLength; iter += distance){
      points.push({x: iter, y: yHeight});
    }

    // get right
    for (iter = yHeight; iter >= y; iter -= distance){
      points.push({x: xLength, y: iter});
    }

    return points;
  }

  function RectOutline(canvas, cfg){
    this.initialize(canvas, cfg);
  }

  RectOutline.prototype.getOutlinePoints = function(pointDistance){
    if (pointDistance < 0) {
      return this.outline;
    }

    var xLength = this.outline.x + this.outline.width,
        yHeight = this.outline.y + this.outline.height,
        x = this.outline.x,
        y = this.outline.y;

    return getBoundaryPoint({x: x, y: y}, xLength, yHeight, pointDistance);
  };

  RectOutline.prototype.onMouseDown = function(e) {
    this.canvas.selection = false;
    var point = this.canvas.getPointer(e.e);

    this.outline = {
      x: point.x,
      y: point.y,
      width: 1,
      height: 1
    };

    this.isDrawing = true;
    this.startPoint = this.outerPoint = point;

    return this;
  };

  RectOutline.prototype.onMouseMove = function(e) {
    if (this.isDrawing) {
      var point = this.canvas.getPointer(e.e);

      this.updateOutline(point);
    }

    return this;
  };

  RectOutline.prototype.updateOutline = function( point ) {
    this.outline.height = point.y - this.outline.y;
    this.outline.width = point.x - this.outline.x;

    this.outerPoint = point;

    this.renderOutline();

    return this;
  };

  RectOutline.prototype.normalizeOutlinePosition = function() {
    if (this.outline.width < 0){
      this.outline.x = this.outline.x + this.outline.width;
      this.outline.width *= -1;
    }

    if (this.outline.height < 0) {
      this.outline.y = this.outline.y + this.outline.height;
      this.outline.height *= -1;
    }
  };

  RectOutline.prototype.renderOutline = function() {
    var ctx = this.canvas.contextTop;

    this.canvas.clearContext(ctx);
    ctx.save();

    ctx.lineWidth = 1;
    ctx.strokeStyle = this.cfg.strokeColor;
    ctx.strokeRect(this.outline.x, this.outline.y, this.outline.width, this.outline.height);

    ctx.restore();

    return this;
  };

  asOutlineShape.call(RectOutline.prototype);

  return RectOutline;

});<|endoftext|>