<commit_before>'use strict';

// MODULES //

var tape = require( 'tape' );
var percentEncode = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.strictEqual( typeof percentEncode, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws an error if not provided a string', function test( t ) {
	var values;
	var i;

	values = [
		5,
		NaN,
		true,
		false,
		null,
		void 0,
		[],
		{},
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			percentEncode( value );
		};
	}
});

tape( 'the function percent-encodes a string', function test( t ) {
	var expected;
	var values;
	var out;
	var i;

	// Some test values are from https://dev.twitter.com/oauth/overview/percent-encoding-parameters.
	values = [
		'Ladies + Gentlemen',
		'An encoded string!',
		'Dogs, Cats & Mice',
		'☃',
		'æ',
		'𐐷'
	];

	expected = [
		'Ladies%20%2B%20Gentlemen',
		'An%20encoded%20string%21',
		'Dogs%2C%20Cats%20%26%20Mice',
		'%E2%98%83',
		'%C3%A6',
		'%F0%90%90%B7'
	];

	for ( i = 0; i < values.length; i++ ) {
		out = percentEncode( values[ i ] );
		t.strictEqual( out, expected[ i ], 'returns expected value for '+values[i] );
	}
	t.end();
});
<commit_msg>Add test values<commit_after>'use strict';

// MODULES //

var tape = require( 'tape' );
var percentEncode = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.strictEqual( typeof percentEncode, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws an error if not provided a string', function test( t ) {
	var values;
	var i;

	values = [
		5,
		NaN,
		true,
		false,
		null,
		void 0,
		[],
		{},
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			percentEncode( value );
		};
	}
});

tape( 'the function percent-encodes a string', function test( t ) {
	var expected;
	var values;
	var out;
	var i;

	// Some test values are from https://dev.twitter.com/oauth/overview/percent-encoding-parameters.
	values = [
		'Ladies + Gentlemen',
		'An encoded string!',
		'Dogs, Cats & Mice',
		'☃',
		'æ',
		'𐐷',
		'()',
		'https://en.wikipedia.org/wiki/Mode_(statistics)'
	];

	expected = [
		'Ladies%20%2B%20Gentlemen',
		'An%20encoded%20string%21',
		'Dogs%2C%20Cats%20%26%20Mice',
		'%E2%98%83',
		'%C3%A6',
		'%F0%90%90%B7',
		'%28%29',
		'https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FMode_%28statistics%29'
	];

	for ( i = 0; i < values.length; i++ ) {
		out = percentEncode( values[ i ] );
		t.strictEqual( out, expected[ i ], 'returns expected value for '+values[i] );
	}
	t.end();
});
<|endoftext|>


<commit_before>/*
Name:           piwik
Description:    Access a Piwik API or track hits with node.js
Author:         Franklin van de Meent (https://frankl.in)
Source & docs:  https://github.com/fvdm/nodejs-piwik
Feedback:       https://github.com/fvdm/nodejs-piwik/issues
License:        Unlicense / Public Domain (see UNLICENSE file)
                (https://github.com/fvdm/nodejs-piwik/raw/develop/UNLICENSE)
*/

var urltool = require ('url');
var querystring = require ('querystring');
var http = require ('httpreq');
var app = {settings: {}};

var defaults = {
  timeout: 5000
};

// HTTP GET
function talk (props) {
  var options = {
    url: app.settings.baseURL + (props.path || ''),
    method: props.method || 'GET',
    headers: {},
    timeout: parseInt (props.timeout || app.settings.timeout || defaults.timeout, 10)
  };

  // build request
  if (props.query instanceof Object) {
    var key;
    for (key in props.query) {
      if (typeof props.query [key] === 'object') {
        props.query [key] = JSON.stringify (props.query [key]);
      }
    }
  }

  if (props.query) {
    options.parameters = props.query;
  } else if (props.body) {
    options.body = props.body;
    options.headers ['Content-Type'] = 'application/json';
    options.headers ['Content-Length'] = options.body.length;
  }

  // send request
  http.doRequest (options, function (err, res) {
    var data = res && res.body || null;
    var error = null;

    if (err) {
      error = new Error ('request failed');
      error.error = err;
    }

    try {
      data = JSON.parse (data);
      if (data.result && data.result === 'error') {
        error = new Error ('api error');
        error.text = data.message || null;
      }
    } catch (e) {
      error = new Error ('response invalid');
      error.error = e;
    }

    if (res && res.statusCode && res.statusCode >= 300) {
      error = new Error ('http error');
      error.code = res.statusCode;
      error.body = data;
    }

    props.callback && props.callback (error, !error && data);
  });
}

// SETUP basics
app.setup = function (baseURL, token, timeout) {
  app.settings.baseURL = baseURL.replace (/\/(index\.php)?([#\?].*)?$/, '/');
  var url = urltool.parse (baseURL, true);

  // token in baseURL?
  app.settings.token = url.query && url.query.token_auth || null;

  // override with custom token, and set timeout
  if (typeof token === 'number') {
    app.settings.timeout = token;
  } else if (token) {
    app.settings.token = token;
    app.settings.timeout = timeout || defaults.timeout;
  }

  return app;
};

// API call
app.api = function (vars, cb) {
  vars = typeof vars === 'object' ? vars : {};
  vars.module = 'API';
  vars.format = 'JSON';
  vars.token_auth = app.settings.token;
  talk ({ method: 'GET', query: vars, callback: cb || null });
  return app;
};

// Track
app.track = function (vars, cb) {
  var bulk = {requests: []};
  var i, k, val, keys;
  if (app.settings.token) { bulk.token_auth = app.settings.token; }

  if (vars instanceof Array && vars [0] instanceof Object) {
    // array with objects
    for (i = 0; i < vars.length; i++) {
      keys = Object.keys (vars [i]);
      for (k = 0; k < keys.length; k++) {
        val = vars [i] [keys [k]];
        vars [i] [keys [k]] = typeof val === 'object' ? JSON.stringify (val) : val;
      }
      vars [i] .rec = 1;
      vars [i] .apiv = 1;
      vars [i] = '?' + querystring.stringify (vars [i]);
      bulk.requests.push (vars [i]);
      delete vars [i];
    }
  } else if (vars instanceof Object) {
    // object
    keys = Object.keys (vars);
    for (i = 0; i < keys.length; i++) {
      val = vars [keys [i]];
      vars [keys [i]] = typeof val === 'object' ? JSON.stringify (val) : val;
    }
    vars.rec = 1;
    vars.apiv = 1;
    bulk.requests.push ('?' + querystring.stringify (vars));
  }

  talk ({
    method: 'POST',
    path: 'piwik.php',
    body: JSON.stringify (bulk),
    callback: function (err, data) {
      var error = null;

      if (err && cb) { return cb (err); }

      if (data.status === 'success') {
        cb && cb (null, data);
      } else {
        error = new Error ('track failed');
        error.data = data;
        cb && cb (error);
      }
    }
  });

  return app;
};

// Spammers
app.loadSpammers = function (cb) {
  var options = {
    timeout: parseInt (app.settings.timeout || defaults.timeout, 10)
  };

  http.get (
    'https://github.com/piwik/referrer-spam-blacklist/raw/master/spammers.txt',
    options,
    function (err, res) {
      var data = res.body.trim () .split ('\n');
      var i;
      var line;

      if (err && cb) { return cb (err); }

      for (i = 0; i < data.length; i++) {
        line = data [i] .trim ();
        if (line === '') {
          delete data [i];
        }
      }
      data = data.sort ();
      cb && cb (null, data);
    }
  );

  return app;
};

// module
module.exports = app;
<commit_msg>Rewrite baseURL setting (#14)<commit_after>/*
Name:           piwik
Description:    Access a Piwik API or track hits with node.js
Author:         Franklin van de Meent (https://frankl.in)
Source & docs:  https://github.com/fvdm/nodejs-piwik
Feedback:       https://github.com/fvdm/nodejs-piwik/issues
License:        Unlicense / Public Domain (see UNLICENSE file)
                (https://github.com/fvdm/nodejs-piwik/raw/develop/UNLICENSE)
*/

var urltool = require ('url');
var querystring = require ('querystring');
var http = require ('httpreq');
var app = {settings: {}};

var defaults = {
  timeout: 5000
};

// HTTP GET
function talk (props) {
  var options = {
    url: app.settings.baseURL + (props.path || ''),
    method: props.method || 'GET',
    headers: {},
    timeout: parseInt (props.timeout || app.settings.timeout || defaults.timeout, 10)
  };

  // build request
  if (props.query instanceof Object) {
    var key;
    for (key in props.query) {
      if (typeof props.query [key] === 'object') {
        props.query [key] = JSON.stringify (props.query [key]);
      }
    }
  }

  if (props.query) {
    options.parameters = props.query;
  } else if (props.body) {
    options.body = props.body;
    options.headers ['Content-Type'] = 'application/json';
    options.headers ['Content-Length'] = options.body.length;
  }

  // send request
  http.doRequest (options, function (err, res) {
    var data = res && res.body || null;
    var error = null;

    if (err) {
      error = new Error ('request failed');
      error.error = err;
    }

    try {
      data = JSON.parse (data);
      if (data.result && data.result === 'error') {
        error = new Error ('api error');
        error.text = data.message || null;
      }
    } catch (e) {
      error = new Error ('response invalid');
      error.error = e;
    }

    if (res && res.statusCode && res.statusCode >= 300) {
      error = new Error ('http error');
      error.code = res.statusCode;
      error.body = data;
    }

    props.callback && props.callback (error, !error && data);
  });
}

// SETUP basics
app.setup = function (baseURL, token, timeout) {
  var url = urltool.parse (baseURL, true);
  app.settings.baseURL = url.protocol + '//' + url.host + url.pathname.replace (/\/[^\/]+$/, '/');

  // token in baseURL?
  app.settings.token = url.query && url.query.token_auth || null;

  // override with custom token, and set timeout
  if (typeof token === 'number') {
    app.settings.timeout = token;
  } else if (token) {
    app.settings.token = token;
    app.settings.timeout = timeout || defaults.timeout;
  }

  return app;
};

// API call
app.api = function (vars, cb) {
  vars = typeof vars === 'object' ? vars : {};
  vars.module = 'API';
  vars.format = 'JSON';
  vars.token_auth = app.settings.token;

  talk ({
    method: 'GET',
    path: 'index.php',
    query: vars,
    callback: cb || null
  });

  return app;
};

// Track
app.track = function (vars, cb) {
  var bulk = {requests: []};
  var i, k, val, keys;
  if (app.settings.token) { bulk.token_auth = app.settings.token; }

  if (vars instanceof Array && vars [0] instanceof Object) {
    // array with objects
    for (i = 0; i < vars.length; i++) {
      keys = Object.keys (vars [i]);
      for (k = 0; k < keys.length; k++) {
        val = vars [i] [keys [k]];
        vars [i] [keys [k]] = typeof val === 'object' ? JSON.stringify (val) : val;
      }
      vars [i] .rec = 1;
      vars [i] .apiv = 1;
      vars [i] = '?' + querystring.stringify (vars [i]);
      bulk.requests.push (vars [i]);
      delete vars [i];
    }
  } else if (vars instanceof Object) {
    // object
    keys = Object.keys (vars);
    for (i = 0; i < keys.length; i++) {
      val = vars [keys [i]];
      vars [keys [i]] = typeof val === 'object' ? JSON.stringify (val) : val;
    }
    vars.rec = 1;
    vars.apiv = 1;
    bulk.requests.push ('?' + querystring.stringify (vars));
  }

  talk ({
    method: 'POST',
    path: 'piwik.php',
    body: JSON.stringify (bulk),
    callback: function (err, data) {
      var error = null;

      if (err && cb) { return cb (err); }

      if (data.status === 'success') {
        cb && cb (null, data);
      } else {
        error = new Error ('track failed');
        error.data = data;
        cb && cb (error);
      }
    }
  });

  return app;
};

// Spammers
app.loadSpammers = function (cb) {
  var options = {
    timeout: parseInt (app.settings.timeout || defaults.timeout, 10)
  };

  http.get (
    'https://github.com/piwik/referrer-spam-blacklist/raw/master/spammers.txt',
    options,
    function (err, res) {
      var data = res.body.trim () .split ('\n');
      var i;
      var line;

      if (err && cb) { return cb (err); }

      for (i = 0; i < data.length; i++) {
        line = data [i] .trim ();
        if (line === '') {
          delete data [i];
        }
      }
      data = data.sort ();
      cb && cb (null, data);
    }
  );

  return app;
};

// module
module.exports = app;
<|endoftext|>


<commit_before>//import { version } from "../package.json";
var ms = new function() {
  this._brokenPath2D = undefined;
  this._colorModes = {};
  this._dashArrays = {
    pending: "4,4",
    anticipated: "8,12",
    feintDummy: "8,8"
  };
  this._getIcons = {};
  this._getMetadata = {};
  this._hqStaffLength = 100;
  this._iconCache = {}; // A cache of icn to speed stuff up...
  this._iconParts = [];
  this._labelCache = {}; // A cache of label overrides to speed stuff up...
  this._labelOverrides = {};
  this._iconSIDC = {};
  this._iconSIDC.letter = [];
  this._iconSIDC.number = [];
  this._STD2525 = true;
  this._svgNS = "http://www.w3.org/2000/svg";
  this._symbolParts = [];

  //this._autoSVG = false;
  this._autoValidation = false;
  this.version = "2.0.0";

  if (typeof console === "object") {
    console.info(
      "milsymbol.js " +
        this.version +
        " - Copyright (c) 2018 M" +
        String.fromCharCode(229) +
        "ns Beckman  http://www.spatialillusions.com"
    );
  }
}();

import { BBox } from "./ms/bbox.js";
import { Colormode } from "./ms/colormode.js";

ms.BBox = BBox;
ms.ColorMode = Colormode;

ms.setBrokenPath2D = function(broken) {
  ms._brokenPath2D = broken;
};

ms._getIconParts = function iconparts(
  metadata,
  colors,
  _STD2525,
  monoColor,
  alternateMedal
) {
  var icn = {};

  for (var i in this._iconParts) {
    if (!this._iconParts.hasOwnProperty(i)) continue;
    this._iconParts[i].call(
      this,
      icn,
      metadata,
      colors,
      _STD2525,
      monoColor,
      alternateMedal
    );
  }

  return icn;
};

ms._scale = function(factor, instruction) {
  return {
    type: "translate",
    x: 100 - factor * 100,
    y: 100 - factor * 100,
    draw: [{ type: "scale", factor: factor, draw: [instruction] }]
  };
};
ms._translate = function(x, y, instruction) {
  return { type: "translate", x: x, y: y, draw: [instruction] };
};

ms.addIconParts = function(parts) {
  if (typeof parts === "function" && this._iconParts.indexOf(parts) == -1) {
    this._iconParts = this._iconParts.concat(parts);
  }
  return ms;
};
ms.addLabelOverrides = function(parts, type) {
  if (typeof parts === "function") {
    if (!this._labelOverrides.hasOwnProperty(type)) {
      this._labelOverrides[type] = [];
    }
    this._labelOverrides[type] = this._labelOverrides[type].concat(parts);
  }
  return ms;
};

ms.addIcons = function(obj) {
  if (Array.isArray(obj)) {
    for (var i = 0; i < obj.length; i++) {
      ms.addSIDCicons(obj[i].icons, obj[i].type);
    }
  } else {
    ms.addSIDCicons(obj.icons, obj.type);
  }
};

ms.addSIDCicons = function(parts, type) {
  if (typeof parts === "function") {
    if (this._iconSIDC[type].indexOf(parts) == -1)
      this._iconSIDC[type] = this._iconSIDC[type].concat(parts);
  }
  return ms;
};
ms.addSymbolPart = function(part) {
  if (typeof part === "function") {
    var symbolParts = ms.getSymbolParts();
    if (symbolParts.indexOf(part) == -1)
      ms.setSymbolParts(symbolParts.concat(part));
  }
  return ms;
};

ms.getColorMode = function(mode) {
  var c = this._colorModes[mode];
  // Clone the mode and return the clone
  return new ms.ColorMode(
    c.Civilian,
    c.Friend,
    c.Hostile,
    c.Neutral,
    c.Unknown
  );
};
ms.getDashArrays = function() {
  return this._dashArrays;
};
ms.getHqStaffLength = function() {
  return this._hqStaffLength;
};

ms.getSymbolParts = function() {
  return this._symbolParts.slice(0);
};
ms.getVersion = function() {
  return this.version;
};

import outline from "./ms/outline.js";

ms.outline = outline;

ms.setColorMode = function(mode, colorMode) {
  this._colorModes[mode] = {};
  this._colorModes[mode].Hostile = colorMode.Hostile;
  this._colorModes[mode].Friend = colorMode.Friend;
  this._colorModes[mode].Neutral = colorMode.Neutral;
  this._colorModes[mode].Unknown = colorMode.Unknown;
  this._colorModes[mode].Civilian = colorMode.Civilian;
  return this._colorModes[mode];
};
ms.setDashArrays = function(pending, anticipated, feintDummy) {
  this._dashArrays.pending = pending;
  this._dashArrays.anticipated = anticipated;
  this._dashArrays.feintDummy = feintDummy;
  return this._dashArrays;
};
ms.setHqStaffLength = function(len) {
  this._hqStaffLength = len;
  return this._hqStaffLength;
};
ms.setSymbolParts = function(parts) {
  this._symbolParts = parts;
  return ms;
};
ms.setStandard = function(standard) {
  if (standard == "2525") {
    this._STD2525 = true;
    return true;
  }
  if (standard == "APP6") {
    this._STD2525 = false;
    return true;
  }
  return false;
};

/* ***************************************************************************************
Add default colors
*************************************************************************************** */
import ColorModes from "./colormodes.js";
for (var name in ColorModes) {
  ms.setColorMode(name, ColorModes[name]);
}

/* ***************************************************************************************
Add base geometries
*************************************************************************************** */
import geometries from "./ms/symbolgeometries.js";

ms._symbolGeometries = geometries;

/* ***************************************************************************************
Functions that builds the symbol
*************************************************************************************** */
import basegeometry from "./symbolfunctions/basegeometry.js";

ms.addSymbolPart(basegeometry);

import icon from "./symbolfunctions/icon.js";

ms.addSymbolPart(icon);

import modifier from "./symbolfunctions/modifier.js";

ms.addSymbolPart(modifier);

import statusmodifier from "./symbolfunctions/statusmodifier.js";

ms.addSymbolPart(statusmodifier);

import engagmentbar from "./symbolfunctions/engagmentbar.js";

ms.addSymbolPart(engagmentbar);

import affliationdimension from "./symbolfunctions/affliationdimension.js";

ms.addSymbolPart(affliationdimension);

import textfields from "./symbolfunctions/textfields.js";

ms.addSymbolPart(textfields);

import directionarrow from "./symbolfunctions/directionarrow.js";

ms.addSymbolPart(directionarrow);

export { ms };
<commit_msg>Remove logging when running in node<commit_after>//import { version } from "../package.json";
var ms = new function() {
  this._brokenPath2D = undefined;
  this._colorModes = {};
  this._dashArrays = {
    pending: "4,4",
    anticipated: "8,12",
    feintDummy: "8,8"
  };
  this._getIcons = {};
  this._getMetadata = {};
  this._hqStaffLength = 100;
  this._iconCache = {}; // A cache of icn to speed stuff up...
  this._iconParts = [];
  this._labelCache = {}; // A cache of label overrides to speed stuff up...
  this._labelOverrides = {};
  this._iconSIDC = {};
  this._iconSIDC.letter = [];
  this._iconSIDC.number = [];
  this._STD2525 = true;
  this._svgNS = "http://www.w3.org/2000/svg";
  this._symbolParts = [];

  //this._autoSVG = false;
  this._autoValidation = false;
  this.version = "2.0.0";

  if (typeof console === "object" && typeof process !== "object") {
    console.info(
      "milsymbol.js " +
        this.version +
        " - Copyright (c) 2018 M" +
        String.fromCharCode(229) +
        "ns Beckman  http://www.spatialillusions.com"
    );
  }
}();

import { BBox } from "./ms/bbox.js";
import { Colormode } from "./ms/colormode.js";

ms.BBox = BBox;
ms.ColorMode = Colormode;

ms.setBrokenPath2D = function(broken) {
  ms._brokenPath2D = broken;
};

ms._getIconParts = function iconparts(
  metadata,
  colors,
  _STD2525,
  monoColor,
  alternateMedal
) {
  var icn = {};

  for (var i in this._iconParts) {
    if (!this._iconParts.hasOwnProperty(i)) continue;
    this._iconParts[i].call(
      this,
      icn,
      metadata,
      colors,
      _STD2525,
      monoColor,
      alternateMedal
    );
  }

  return icn;
};

ms._scale = function(factor, instruction) {
  return {
    type: "translate",
    x: 100 - factor * 100,
    y: 100 - factor * 100,
    draw: [{ type: "scale", factor: factor, draw: [instruction] }]
  };
};
ms._translate = function(x, y, instruction) {
  return { type: "translate", x: x, y: y, draw: [instruction] };
};

ms.addIconParts = function(parts) {
  if (typeof parts === "function" && this._iconParts.indexOf(parts) == -1) {
    this._iconParts = this._iconParts.concat(parts);
  }
  return ms;
};
ms.addLabelOverrides = function(parts, type) {
  if (typeof parts === "function") {
    if (!this._labelOverrides.hasOwnProperty(type)) {
      this._labelOverrides[type] = [];
    }
    this._labelOverrides[type] = this._labelOverrides[type].concat(parts);
  }
  return ms;
};

ms.addIcons = function(obj) {
  if (Array.isArray(obj)) {
    for (var i = 0; i < obj.length; i++) {
      ms.addSIDCicons(obj[i].icons, obj[i].type);
    }
  } else {
    ms.addSIDCicons(obj.icons, obj.type);
  }
};

ms.addSIDCicons = function(parts, type) {
  if (typeof parts === "function") {
    if (this._iconSIDC[type].indexOf(parts) == -1)
      this._iconSIDC[type] = this._iconSIDC[type].concat(parts);
  }
  return ms;
};
ms.addSymbolPart = function(part) {
  if (typeof part === "function") {
    var symbolParts = ms.getSymbolParts();
    if (symbolParts.indexOf(part) == -1)
      ms.setSymbolParts(symbolParts.concat(part));
  }
  return ms;
};

ms.getColorMode = function(mode) {
  var c = this._colorModes[mode];
  // Clone the mode and return the clone
  return new ms.ColorMode(
    c.Civilian,
    c.Friend,
    c.Hostile,
    c.Neutral,
    c.Unknown
  );
};
ms.getDashArrays = function() {
  return this._dashArrays;
};
ms.getHqStaffLength = function() {
  return this._hqStaffLength;
};

ms.getSymbolParts = function() {
  return this._symbolParts.slice(0);
};
ms.getVersion = function() {
  return this.version;
};

import outline from "./ms/outline.js";

ms.outline = outline;

ms.setColorMode = function(mode, colorMode) {
  this._colorModes[mode] = {};
  this._colorModes[mode].Hostile = colorMode.Hostile;
  this._colorModes[mode].Friend = colorMode.Friend;
  this._colorModes[mode].Neutral = colorMode.Neutral;
  this._colorModes[mode].Unknown = colorMode.Unknown;
  this._colorModes[mode].Civilian = colorMode.Civilian;
  return this._colorModes[mode];
};
ms.setDashArrays = function(pending, anticipated, feintDummy) {
  this._dashArrays.pending = pending;
  this._dashArrays.anticipated = anticipated;
  this._dashArrays.feintDummy = feintDummy;
  return this._dashArrays;
};
ms.setHqStaffLength = function(len) {
  this._hqStaffLength = len;
  return this._hqStaffLength;
};
ms.setSymbolParts = function(parts) {
  this._symbolParts = parts;
  return ms;
};
ms.setStandard = function(standard) {
  if (standard == "2525") {
    this._STD2525 = true;
    return true;
  }
  if (standard == "APP6") {
    this._STD2525 = false;
    return true;
  }
  return false;
};

/* ***************************************************************************************
Add default colors
*************************************************************************************** */
import ColorModes from "./colormodes.js";
for (var name in ColorModes) {
  ms.setColorMode(name, ColorModes[name]);
}

/* ***************************************************************************************
Add base geometries
*************************************************************************************** */
import geometries from "./ms/symbolgeometries.js";

ms._symbolGeometries = geometries;

/* ***************************************************************************************
Functions that builds the symbol
*************************************************************************************** */
import basegeometry from "./symbolfunctions/basegeometry.js";

ms.addSymbolPart(basegeometry);

import icon from "./symbolfunctions/icon.js";

ms.addSymbolPart(icon);

import modifier from "./symbolfunctions/modifier.js";

ms.addSymbolPart(modifier);

import statusmodifier from "./symbolfunctions/statusmodifier.js";

ms.addSymbolPart(statusmodifier);

import engagmentbar from "./symbolfunctions/engagmentbar.js";

ms.addSymbolPart(engagmentbar);

import affliationdimension from "./symbolfunctions/affliationdimension.js";

ms.addSymbolPart(affliationdimension);

import textfields from "./symbolfunctions/textfields.js";

ms.addSymbolPart(textfields);

import directionarrow from "./symbolfunctions/directionarrow.js";

ms.addSymbolPart(directionarrow);

export { ms };
<|endoftext|>


<commit_before>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2010-2012 Sebastian Werner
--------------------------------------------------------------------------------------------------
  Based on the work of:
  Hogan.JS by Twitter, Inc.
  https://github.com/twitter/hogan.js
  Licensed under the Apache License, Version 2.0
  http://www.apache.org/licenses/LICENSE-2.0
==================================================================================================
*/

(function ()
{
	// Setup regex	assignments
	// remove whitespace according to Mustache spec
	var rIsWhitespace = /\S/,
			rQuot = /\"/g,
			rNewline =	/\n/g,
			rCr = /\r/g,
			rSlash = /\\/g,
			tagTypes = {
				'#': 1, '^': 2, '/': 3,	 '!': 4, '>': 5,
				'<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
			};

	/**
	 * This is a compiler for the [Mustache](http://mustache.github.com/) templating language which is based on [Hogan.js](http://twitter.github.com/hogan.js/).
	 * For information on Mustache, see the [manpage](http://mustache.github.com/mustache.5.html) and the [spec](https://github.com/mustache/spec).
	 */
	core.Module("core.template.Compiler",
	{
		/**
		 * {String[]} Tokenizer for template @text {String} using the defined @delimiters {String}. Returns an array of tokens.
		 */
		scan : function scan(text, delimiters) {
			var len = text.length,
					IN_TEXT = 0,
					IN_TAG_TYPE = 1,
					IN_TAG = 2,
					state = IN_TEXT,
					tagType = null,
					tag = null,
					buf = '',
					tokens = [],
					seenTag = false,
					i = 0,
					lineStart = 0,
					otag = '{{',
					ctag = '}}';

			function addBuf() {
				if (buf.length > 0) {
					tokens.push(new String(buf));
					buf = '';
				}
			}

			function lineIsWhitespace() {
				var isAllWhitespace = true;
				for (var j = lineStart; j < tokens.length; j++) {
					isAllWhitespace =
						(tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
						(!tokens[j].tag && tokens[j].match(rIsWhitespace) === null);
					if (!isAllWhitespace) {
						return false;
					}
				}

				return isAllWhitespace;
			}

			function filterLine(haveSeenTag, noNewLine) {
				addBuf();

				if (haveSeenTag && lineIsWhitespace()) {
					for (var j = lineStart, next; j < tokens.length; j++) {
						if (!tokens[j].tag) {
							if ((next = tokens[j+1]) && next.tag == '>') {
								// set indent to token value
								next.indent = tokens[j].toString()
							}
							tokens.splice(j, 1);
						}
					}
				} else if (!noNewLine) {
					tokens.push({tag:'\n'});
				}

				seenTag = false;
				lineStart = tokens.length;
			}

			function changeDelimiters(text, index) {
				var close = '=' + ctag,
						closeIndex = text.indexOf(close, index),
						delimiters = text.substring(text.indexOf('=', index) + 1, closeIndex).trim().split(' ');

				otag = delimiters[0];
				ctag = delimiters[1];

				return closeIndex + close.length - 1;
			}

			if (delimiters) {
				delimiters = delimiters.split(' ');
				otag = delimiters[0];
				ctag = delimiters[1];
			}

			for (i = 0; i < len; i++) {
				if (state == IN_TEXT) {
					if (tagChange(otag, text, i)) {
						--i;
						addBuf();
						state = IN_TAG_TYPE;
					} else {
						if (text.charAt(i) == '\n') {
							filterLine(seenTag);
						} else {
							buf += text.charAt(i);
						}
					}
				} else if (state == IN_TAG_TYPE) {
					i += otag.length - 1;
					tag = tagTypes[text.charAt(i + 1)];
					tagType = tag ? text.charAt(i + 1) : '_v';
					if (tagType == '=') {
						i = changeDelimiters(text, i);
						state = IN_TEXT;
					} else {
						if (tag) {
							i++;
						}
						state = IN_TAG;
					}
					seenTag = i;
				} else {
					if (tagChange(ctag, text, i)) {
						tokens.push({tag: tagType, n: buf.trim(), otag: otag, ctag: ctag, i: (tagType == '/') ? seenTag - ctag.length : i + otag.length});
						buf = '';
						i += ctag.length - 1;
						state = IN_TEXT;
						if (tagType == '{') {
							if (ctag == '}}') {
								i++;
							} else {
								cleanTripleStache(tokens[tokens.length - 1]);
							}
						}
					} else {
						buf += text.charAt(i);
					}
				}
			}

			filterLine(seenTag, true);

			return tokens;
		},

		/**
		 * {core.template.Template} Translates the @code {Array} tree from {#parse} into actual JavaScript
		 * code (in form of a {core.template.Template} instance) to insert dynamic data fields. It uses
		 * the original @text {String} for template construction.
		 */
		compile : function(text) {
			var code = writeCode(this.parse(this.scan(text), text));
			return new core.template.Template(new Function('c', 'p', 'i', code), text, this);
		},

		/**
		 * {Array} Processes the @tokens {String[]} from {#scan} to create and return a tree.
		 */
		parse : function(tokens, text) {
			return buildTree(tokens, '', []);
		}

	});

	function cleanTripleStache(token) {
		if (token.n.substr(token.n.length - 1) === '}') {
			token.n = token.n.substring(0, token.n.length - 1);
		}
	}

	function tagChange(tag, text, index) {
		if (text.charAt(index) != tag.charAt(0)) {
			return false;
		}

		for (var i = 1, l = tag.length; i < l; i++) {
			if (text.charAt(index + i) != tag.charAt(i)) {
				return false;
			}
		}

		return true;
	}

	function buildTree(tokens, kind, stack) {
		var instructions = [],
				opener = null,
				token = null;

		while (tokens.length > 0) {
			token = tokens.shift();
			if (token.tag == '#' || token.tag == '^') {
				stack.push(token);
				token.nodes = buildTree(tokens, token.tag, stack);
				instructions.push(token);
			} else if (token.tag == '/') {
				if (stack.length === 0) {
					throw new Error('Closing tag without opener: /' + token.n);
				}
				opener = stack.pop();
				if (token.n != opener.n) {
					throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);
				}
				opener.end = token.i;
				return instructions;
			} else {
				instructions.push(token);
			}
		}

		if (stack.length > 0) {
			throw new Error('missing closing tag: ' + stack.pop().n);
		}

		return instructions;
	}

	function writeCode(tree) {
		return 'var _=this;_.b(i=i||"");' + walk(tree) + 'return _.fl();';
	}

	function esc(s) {
		return s.replace(rSlash, '\\\\')
						.replace(rQuot, '\\\"')
						.replace(rNewline, '\\n')
						.replace(rCr, '\\r');
	}

	function chooseMethod(s) {
		return (~s.indexOf('.')) ? 'd' : 'f';
	}

	function walk(tree) {
		var code = '';
		for (var i = 0, l = tree.length; i < l; i++) {
			var tag = tree[i].tag;
			if (tag == '#') {
				code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n), tree[i].i, tree[i].end, tree[i].otag + " " + tree[i].ctag);
			} else if (tag == '^') {
				code += invertedSection(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n));
			} else if (tag == '<' || tag == '>') {
				code += partial(tree[i]);
			} else if (tag == '{' || tag == '&') {
				code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
			} else if (tag == '\n') {
				code += text('"\\n"' + (tree.length-1 == i ? '' : ' + i'));
			} else if (tag == '_v') {
				code += variable(tree[i].n, chooseMethod(tree[i].n));
			} else if (tag === undefined) {
				code += text('"' + esc(tree[i]) + '"');
			}
		}
		return code;
	}

	function section(nodes, id, method, start, end, tags) {
		return 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),' +
					 'c,p,0,' + start + ',' + end + ',"' + tags + '")){' +
					 '_.rs(c,p,' +
					 'function(c,p,_){' +
					 walk(nodes) +
					 '});c.pop();}';
	}

	function invertedSection(nodes, id, method) {
		return 'if(!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0,"")){' +
					 walk(nodes) +
					 '};';
	}

	function partial(tok) {
		return '_.b(_.rp("' +	 esc(tok.n) + '",c,p,"' + (tok.indent || '') + '"));';
	}

	function tripleStache(id, method) {
		return '_.b(_.t(_.' + method + '("' + esc(id) + '",c,p,0)));';
	}

	function variable(id, method) {
		return '_.b(_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
	}

	function text(id) {
		return '_.b(' + id + ');';
	}

})();<commit_msg>Removed support for changing delimiters during runtime<commit_after>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2010-2012 Sebastian Werner
--------------------------------------------------------------------------------------------------
  Based on the work of:
  Hogan.JS by Twitter, Inc.
  https://github.com/twitter/hogan.js
  Licensed under the Apache License, Version 2.0
  http://www.apache.org/licenses/LICENSE-2.0
==================================================================================================
*/

(function ()
{
	// Setup regex	assignments
	// remove whitespace according to Mustache spec
	var rIsWhitespace = /\S/,
			rQuot = /\"/g,
			rNewline =	/\n/g,
			rCr = /\r/g,
			rSlash = /\\/g,
			tagTypes = {
				'#': 1, '^': 2, '/': 3,	 '!': 4, '>': 5,
				'<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
			};

	/**
	 * This is a compiler for the [Mustache](http://mustache.github.com/) templating language which is based on [Hogan.js](http://twitter.github.com/hogan.js/).
	 * For information on Mustache, see the [manpage](http://mustache.github.com/mustache.5.html) and the [spec](https://github.com/mustache/spec).
	 */
	core.Module("core.template.Compiler",
	{
		/**
		 * {String[]} Tokenizer for template @text {String}. Returns an array of tokens.
		 */
		scan : function scan(text) {
			var len = text.length,
					IN_TEXT = 0,
					IN_TAG_TYPE = 1,
					IN_TAG = 2,
					state = IN_TEXT,
					tagType = null,
					tag = null,
					buf = '',
					tokens = [],
					seenTag = false,
					i = 0,
					lineStart = 0,
					otag = '{{',
					ctag = '}}';

			function addBuf() {
				if (buf.length > 0) {
					tokens.push(new String(buf));
					buf = '';
				}
			}

			function lineIsWhitespace() {
				var isAllWhitespace = true;
				for (var j = lineStart; j < tokens.length; j++) {
					isAllWhitespace =
						(tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
						(!tokens[j].tag && tokens[j].match(rIsWhitespace) === null);
					if (!isAllWhitespace) {
						return false;
					}
				}

				return isAllWhitespace;
			}

			function filterLine(haveSeenTag, noNewLine) {
				addBuf();

				if (haveSeenTag && lineIsWhitespace()) {
					for (var j = lineStart, next; j < tokens.length; j++) {
						if (!tokens[j].tag) {
							if ((next = tokens[j+1]) && next.tag == '>') {
								// set indent to token value
								next.indent = tokens[j].toString()
							}
							tokens.splice(j, 1);
						}
					}
				} else if (!noNewLine) {
					tokens.push({tag:'\n'});
				}

				seenTag = false;
				lineStart = tokens.length;
			}

			for (i = 0; i < len; i++) {
				if (state == IN_TEXT) {
					if (tagChange(otag, text, i)) {
						--i;
						addBuf();
						state = IN_TAG_TYPE;
					} else {
						if (text.charAt(i) == '\n') {
							filterLine(seenTag);
						} else {
							buf += text.charAt(i);
						}
					}
				} else if (state == IN_TAG_TYPE) {
					i += otag.length - 1;
					tag = tagTypes[text.charAt(i + 1)];
					tagType = tag ? text.charAt(i + 1) : '_v';
					if (tag) {
						i++;
					}
					state = IN_TAG;
					seenTag = i;
				} else {
					if (tagChange(ctag, text, i)) {
						tokens.push({tag: tagType, n: buf.trim(), otag: otag, ctag: ctag, i: (tagType == '/') ? seenTag - ctag.length : i + otag.length});
						buf = '';
						i += ctag.length - 1;
						state = IN_TEXT;
						if (tagType == '{') {
							if (ctag == '}}') {
								i++;
							} else {
								cleanTripleStache(tokens[tokens.length - 1]);
							}
						}
					} else {
						buf += text.charAt(i);
					}
				}
			}

			filterLine(seenTag, true);

			return tokens;
		},

		/**
		 * {core.template.Template} Translates the @code {Array} tree from {#parse} into actual JavaScript
		 * code (in form of a {core.template.Template} instance) to insert dynamic data fields. It uses
		 * the original @text {String} for template construction.
		 */
		compile : function(text) {
			var code = writeCode(this.parse(this.scan(text), text));
			return new core.template.Template(new Function('c', 'p', 'i', code), text, this);
		},

		/**
		 * {Array} Processes the @tokens {String[]} from {#scan} to create and return a tree.
		 */
		parse : function(tokens, text) {
			return buildTree(tokens, '', []);
		}

	});

	function cleanTripleStache(token) {
		if (token.n.substr(token.n.length - 1) === '}') {
			token.n = token.n.substring(0, token.n.length - 1);
		}
	}

	function tagChange(tag, text, index) {
		if (text.charAt(index) != tag.charAt(0)) {
			return false;
		}

		for (var i = 1, l = tag.length; i < l; i++) {
			if (text.charAt(index + i) != tag.charAt(i)) {
				return false;
			}
		}

		return true;
	}

	function buildTree(tokens, kind, stack) {
		var instructions = [],
				opener = null,
				token = null;

		while (tokens.length > 0) {
			token = tokens.shift();
			if (token.tag == '#' || token.tag == '^') {
				stack.push(token);
				token.nodes = buildTree(tokens, token.tag, stack);
				instructions.push(token);
			} else if (token.tag == '/') {
				if (stack.length === 0) {
					throw new Error('Closing tag without opener: /' + token.n);
				}
				opener = stack.pop();
				if (token.n != opener.n) {
					throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);
				}
				opener.end = token.i;
				return instructions;
			} else {
				instructions.push(token);
			}
		}

		if (stack.length > 0) {
			throw new Error('missing closing tag: ' + stack.pop().n);
		}

		return instructions;
	}

	function writeCode(tree) {
		return 'var _=this;_.b(i=i||"");' + walk(tree) + 'return _.fl();';
	}

	function esc(s) {
		return s.replace(rSlash, '\\\\')
						.replace(rQuot, '\\\"')
						.replace(rNewline, '\\n')
						.replace(rCr, '\\r');
	}

	function chooseMethod(s) {
		return (~s.indexOf('.')) ? 'd' : 'f';
	}

	function walk(tree) {
		var code = '';
		for (var i = 0, l = tree.length; i < l; i++) {
			var tag = tree[i].tag;
			if (tag == '#') {
				code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n), tree[i].i, tree[i].end, tree[i].otag + " " + tree[i].ctag);
			} else if (tag == '^') {
				code += invertedSection(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n));
			} else if (tag == '<' || tag == '>') {
				code += partial(tree[i]);
			} else if (tag == '{' || tag == '&') {
				code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
			} else if (tag == '\n') {
				code += text('"\\n"' + (tree.length-1 == i ? '' : ' + i'));
			} else if (tag == '_v') {
				code += variable(tree[i].n, chooseMethod(tree[i].n));
			} else if (tag === undefined) {
				code += text('"' + esc(tree[i]) + '"');
			}
		}
		return code;
	}

	function section(nodes, id, method, start, end, tags) {
		return 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),' +
					 'c,p,0,' + start + ',' + end + ',"' + tags + '")){' +
					 '_.rs(c,p,' +
					 'function(c,p,_){' +
					 walk(nodes) +
					 '});c.pop();}';
	}

	function invertedSection(nodes, id, method) {
		return 'if(!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0,"")){' +
					 walk(nodes) +
					 '};';
	}

	function partial(tok) {
		return '_.b(_.rp("' +	 esc(tok.n) + '",c,p,"' + (tok.indent || '') + '"));';
	}

	function tripleStache(id, method) {
		return '_.b(_.t(_.' + method + '("' + esc(id) + '",c,p,0)));';
	}

	function variable(id, method) {
		return '_.b(_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
	}

	function text(id) {
		return '_.b(' + id + ');';
	}

})();<|endoftext|>


<commit_before>var fs = require('fs');

function Tumblr(credentials) {
  this.credentials = credentials;
}

var request;

module.exports = {
  Tumblr: Tumblr,
  request: function(r) {
    request = r;
  }
};

var baseURL = 'http://api.tumblr.com/v2';

Tumblr.prototype = {

  // Tagged

  tagged: function (tag, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    this._get('/tagged', options, callback);
  },

  // Blogs

  blogInfo: function (blogName, callback) {
    this._get(blogURLPath(blogName, '/info'), {api_key: this.credentials.consumer_key}, callback);
  },

  avatar: function (blogName, size, callback) {
    if (isFunction(size)) { callback = size; size = null; }

    this._get(blogURLPath(blogName, '/avatar/' + (size || 64)), {api_key: this.credentials.consumer_key}, callback);
  },

  blogLikes: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    this._get(blogURLPath(blogName, '/likes'), options, callback);
  },

  followers: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    this._get(blogURLPath(blogName, '/followers'), options, callback);
  },

  posts: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    var path = '/posts';
    if (options.type) {
      path += '/' + options.type;
    }

    this._get(blogURLPath(blogName, path), options, callback);
  },

  queue: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get(blogURLPath(blogName, '/posts/queue'), options, callback);
  },

  drafts: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get(blogURLPath(blogName, '/posts/draft'), options, callback);
  },

  submissions: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get(blogURLPath(blogName, '/posts/submission'), options, callback);
  },

  // Posts

  edit: function (blogName, options, callback) {
    this._post(blogURLPath(blogName, '/post/edit'), options, callback);
  },

  reblog: function (blogName, options, callback) {
    this._post(blogURLPath(blogName, '/post/reblog'), options, callback);
  },

  deletePost: function (blogName, id, callback) {
    this._post(blogURLPath(blogName, '/post/delete'), {id: id}, callback);
  },

  photo: function (blogName, options, callback) {
    if (options.data && options.source) {
      callback(new Error('Can\'t pass both "data" and "source" fields'));
      return;
    }

    this._createPost(blogName, 'photo', options, callback);
  },

  quote: function (blogName, options, callback) {
    if (!options.quote) {
      callback(new Error('Missing required field: "quote"'));
      return;
    }

    this._createPost(blogName, 'quote', options, callback);
  },

  text: function (blogName, options, callback) {
    if (!options.body) {
      callback(new Error('Missing required field: "body"'));
      return;
    }

    this._createPost(blogName, 'text', options, callback);
  },

  link: function (blogName, options, callback) {
    if (!options.url) {
      callback(new Error('Missing required field: "url"'));
      return;
    }

    this._createPost(blogName, 'link', options, callback);
  },

  chat: function (blogName, options, callback) {
    if (!options.conversation) {
      callback(new Error('Missing required field: "conversation"'));
      return;
    }

    this._createPost(blogName, 'chat', options, callback);
  },

  audio: function (blogName, options, callback) {
    if (!options.data && !options.external_url) {
      callback(new Error('Missing required field: "data" or "external_url"'));
      return;
    }

    if (options.data && options.external_url) {
      callback(new Error('Can\'t pass both "data" and "external_url" fields'));
      return;
    }

    this._createPost(blogName, 'audio', options, callback);
  },

  video: function (blogName, options, callback) {
    if (!options.data && !options.external_url) {
      callback(new Error('Missing required field: "data" or "embed"'));
      return;
    }

    if (options.data && options.embed) {
      callback(new Error('Can\'t pass both "data" and "embed" fields'));
      return;
    }

    this._createPost(blogName, 'video', options, callback);
  },

  // User

  userInfo: function (callback) {
    this._get('/user/info', {}, callback);
  },

  dashboard: function (options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get('/user/dashboard', options, callback);
  },

  likes: function (offset, limit, callback) {
    if (isFunction(offset)) { callback = offset; offset = null; limit = null; }
    if (isFunction(limit)) { callback = limit; limit = null; }

    this._get('/user/likes', {offset: offset || 0, limit: limit || 20}, callback);
  },

  following: function (offset, limit, callback) {
    if (isFunction(offset)) { callback = offset; offset = null; limit = null; }
    if (isFunction(limit)) { callback = limit; limit = null; }

    this._get('/user/following', {offset: offset || 0, limit: limit || 20}, callback);
  },

  follow: function (blogName, callback) {
    this._post('/user/follow', {url: blogURL(blogName)}, callback);
  },

  unfollow: function (blogName, callback) {
    this._post('/user/unfollow', {url: blogURL(blogName)}, callback);
  },

  like: function (id, reblogKey, callback) {
    this._post('/user/like', {id: id, reblog_key: reblogKey}, callback);
  },

  unlike: function (id, reblogKey, callback) {
    this._post('/user/unlike', {id: id, reblog_key: reblogKey}, callback);
  },

  // Helpers

  _createPost: function (blogName, type, options, callback) {
    options = options || {};
    options.type = type;

    if (options.data) {
      var that = this;
      fs.readFile(options.data, function (err, data) {
        if (err) throw err;
        options.data = data.toString('base64');
        that._post(blogURLPath(blogName, '/post'), options, callback);
      });
    } else {
      this._post(blogURLPath(blogName, '/post'), options, callback);
    }
  },

  _get: function (path, params, callback) {
    request.get({url: baseURL + path, qs: params, oauth: this.credentials, followRedirect: false}, requestCallback(callback));
  },

  _post: function (path, params, callback) {
    request.post({url: baseURL + path, form: params, oauth: this.credentials, followRedirect: false}, requestCallback(callback));
  }

};

function blogURL(blogName) {
  return blogName + '.tumblr.com';
}

function blogURLPath(blogName, path) {
  return '/blog/' + blogURL(blogName) + path;
}

function requestCallback(callback) {
  if (!callback) return function () {};

  return function (err, response, body) {
    if (err) return callback(err);

    var responseBody = JSON.parse(body),
      statusCode = responseBody.meta.status,
      message = responseBody.meta.msg;

    if (Math.floor(statusCode / 100) !== 2 && statusCode != 301) // Avatar requests will return 301 responses
      return callback(new Error('API error: ' + statusCode + ' ' + message));

    return callback(null, responseBody.response);
  };
}

function isFunction(value) {
  return Object.prototype.toString.call(value) == '[object Function]';
}
<commit_msg>acceptsData<commit_after>var fs = require('fs');

function Tumblr(credentials) {
  this.credentials = credentials;
}

var request;

module.exports = {
  Tumblr: Tumblr,
  request: function(r) {
    request = r;
  }
};

var baseURL = 'http://api.tumblr.com/v2';

Tumblr.prototype = {

  // Tagged

  tagged: function (tag, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    this._get('/tagged', options, callback);
  },

  // Blogs

  blogInfo: function (blogName, callback) {
    this._get(blogURLPath(blogName, '/info'), {api_key: this.credentials.consumer_key}, callback);
  },

  avatar: function (blogName, size, callback) {
    if (isFunction(size)) { callback = size; size = null; }

    this._get(blogURLPath(blogName, '/avatar/' + (size || 64)), {api_key: this.credentials.consumer_key}, callback);
  },

  blogLikes: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    this._get(blogURLPath(blogName, '/likes'), options, callback);
  },

  followers: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    this._get(blogURLPath(blogName, '/followers'), options, callback);
  },

  posts: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    var path = '/posts';
    if (options.type) {
      path += '/' + options.type;
    }

    this._get(blogURLPath(blogName, path), options, callback);
  },

  queue: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get(blogURLPath(blogName, '/posts/queue'), options, callback);
  },

  drafts: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get(blogURLPath(blogName, '/posts/draft'), options, callback);
  },

  submissions: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get(blogURLPath(blogName, '/posts/submission'), options, callback);
  },

  // Posts

  edit: function (blogName, options, callback) {
    this._post(blogURLPath(blogName, '/post/edit'), options, callback);
  },

  reblog: function (blogName, options, callback) {
    this._post(blogURLPath(blogName, '/post/reblog'), options, callback);
  },

  deletePost: function (blogName, id, callback) {
    this._post(blogURLPath(blogName, '/post/delete'), {id: id}, callback);
  },

  photo: function (blogName, options, callback) {
    if (options.data && options.source) {
      callback(new Error('Can\'t pass both "data" and "source" fields'));
      return;
    }

    this._createPost(blogName, 'photo', options, true, callback);
  },

  quote: function (blogName, options, callback) {
    if (!options.quote) {
      callback(new Error('Missing required field: "quote"'));
      return;
    }

    this._createPost(blogName, 'quote', options, false, callback);
  },

  text: function (blogName, options, callback) {
    if (!options.body) {
      callback(new Error('Missing required field: "body"'));
      return;
    }

    this._createPost(blogName, 'text', options, false, callback);
  },

  link: function (blogName, options, callback) {
    if (!options.url) {
      callback(new Error('Missing required field: "url"'));
      return;
    }

    this._createPost(blogName, 'link', options, false, callback);
  },

  chat: function (blogName, options, callback) {
    if (!options.conversation) {
      callback(new Error('Missing required field: "conversation"'));
      return;
    }

    this._createPost(blogName, 'chat', options, false, callback);
  },

  audio: function (blogName, options, callback) {
    if (!options.data && !options.external_url) {
      callback(new Error('Missing required field: "data" or "external_url"'));
      return;
    }

    if (options.data && options.external_url) {
      callback(new Error('Can\'t pass both "data" and "external_url" fields'));
      return;
    }

    this._createPost(blogName, 'audio', options, true, callback);
  },

  video: function (blogName, options, callback) {
    if (!options.data && !options.external_url) {
      callback(new Error('Missing required field: "data" or "embed"'));
      return;
    }

    if (options.data && options.embed) {
      callback(new Error('Can\'t pass both "data" and "embed" fields'));
      return;
    }

    this._createPost(blogName, 'video', options, true, callback);
  },

  // User

  userInfo: function (callback) {
    this._get('/user/info', {}, callback);
  },

  dashboard: function (options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get('/user/dashboard', options, callback);
  },

  likes: function (offset, limit, callback) {
    if (isFunction(offset)) { callback = offset; offset = null; limit = null; }
    if (isFunction(limit)) { callback = limit; limit = null; }

    this._get('/user/likes', {offset: offset || 0, limit: limit || 20}, callback);
  },

  following: function (offset, limit, callback) {
    if (isFunction(offset)) { callback = offset; offset = null; limit = null; }
    if (isFunction(limit)) { callback = limit; limit = null; }

    this._get('/user/following', {offset: offset || 0, limit: limit || 20}, callback);
  },

  follow: function (blogName, callback) {
    this._post('/user/follow', {url: blogURL(blogName)}, callback);
  },

  unfollow: function (blogName, callback) {
    this._post('/user/unfollow', {url: blogURL(blogName)}, callback);
  },

  like: function (id, reblogKey, callback) {
    this._post('/user/like', {id: id, reblog_key: reblogKey}, callback);
  },

  unlike: function (id, reblogKey, callback) {
    this._post('/user/unlike', {id: id, reblog_key: reblogKey}, callback);
  },

  // Helpers

  _createPost: function (blogName, type, options, acceptsData, callback) {
    options = options || {};
    options.type = type;

    if (acceptsData && options.data) {
      var that = this;
      fs.readFile(options.data, function (err, data) {
        if (err) throw err;
        options.data = data.toString('base64');
        that._post(blogURLPath(blogName, '/post'), options, callback);
      });
    } else {
      this._post(blogURLPath(blogName, '/post'), options, callback);
    }
  },

  _get: function (path, params, callback) {
    request.get({url: baseURL + path, qs: params, oauth: this.credentials, followRedirect: false}, requestCallback(callback));
  },

  _post: function (path, params, callback) {
    request.post({url: baseURL + path, form: params, oauth: this.credentials, followRedirect: false}, requestCallback(callback));
  }

};

function blogURL(blogName) {
  return blogName + '.tumblr.com';
}

function blogURLPath(blogName, path) {
  return '/blog/' + blogURL(blogName) + path;
}

function requestCallback(callback) {
  if (!callback) return function () {};

  return function (err, response, body) {
    if (err) return callback(err);

    var responseBody = JSON.parse(body),
      statusCode = responseBody.meta.status,
      message = responseBody.meta.msg;

    if (Math.floor(statusCode / 100) !== 2 && statusCode != 301) // Avatar requests will return 301 responses
      return callback(new Error('API error: ' + statusCode + ' ' + message));

    return callback(null, responseBody.response);
  };
}

function isFunction(value) {
  return Object.prototype.toString.call(value) == '[object Function]';
}
<|endoftext|>


<commit_before>'use strict';
/**
 * General-purpose questions that a parent-generator may want to leverage.
 */

var chalk = require('chalk');
var _ = require('lodash');

var distros = require('./distros');
var labelMaker = require('./util').labelMaker;

var prompts = [
  {
    type: 'input',
    name: 'projectName',
    message: 'Machine-name of your project?',
    // Name of the parent directory.
    default: _.last(process.cwd().split('/')),
    validate: function (input) {
      if (input.search(' ') !== -1) return 'No spaces allowed.';
      return true;
    }
  },
  {
    type: 'input',
    name: 'projectDescription',
    message: 'One-line project description?',
    validate: function(input) {
      if (input.search('"') !== -1) return 'No quotes allowed.';
      return true;
    },
    default: function(answers) {
      return labelMaker(answers['projectName']) + ' Drupal codebase.';
    }
  },

  {
    type: 'list',
    name: 'drupalDistro',
    message: 'Which ' + chalk.red('Drupal distribution') + ' would you like to use?',
    default: 'drupal',
    filter: function(answer) {
      return distros[answer];
    },
    choices: function(answers) {
      var opts = [];
      for (var i in distros) {
        opts.push(distros[i].option);
      }

      return opts;
    }
  },
  {
    type: 'list',
    name: 'drupalDistroVersion',
    message: function(answers) {
      return 'Which version of '
        + chalk.red(answers['drupalDistro'].option.name)
        + ' would you like to use?';
    },
    default: function(answers) {
      return answers['drupalDistro'].versionDefault;
    },
    choices: function(answers) {
      return answers['drupalDistro'].versions;
    }
  }
];

module.exports = prompts;
<commit_msg>Require projectName/machine name use only lower case characters. (#106)<commit_after>'use strict';
/**
 * General-purpose questions that a parent-generator may want to leverage.
 */

var chalk = require('chalk');
var _ = require('lodash');

var distros = require('./distros');
var labelMaker = require('./util').labelMaker;

var prompts = [
  {
    type: 'input',
    name: 'projectName',
    message: 'Machine-name of your project?',
    // Name of the parent directory.
    default: _.last(process.cwd().split('/')),
    validate: function (input) {
      if (input.search(' ') !== -1) return 'No spaces allowed.';
      if (/[A-Z]/.test(input)) return 'Lower-case characters only.';
      return true;
    }
  },
  {
    type: 'input',
    name: 'projectDescription',
    message: 'One-line project description?',
    validate: function(input) {
      if (input.search('"') !== -1) return 'No quotes allowed.';
      return true;
    },
    default: function(answers) {
      return labelMaker(answers['projectName']) + ' Drupal codebase.';
    }
  },

  {
    type: 'list',
    name: 'drupalDistro',
    message: 'Which ' + chalk.red('Drupal distribution') + ' would you like to use?',
    default: 'drupal',
    filter: function(answer) {
      return distros[answer];
    },
    choices: function(answers) {
      var opts = [];
      for (var i in distros) {
        opts.push(distros[i].option);
      }

      return opts;
    }
  },
  {
    type: 'list',
    name: 'drupalDistroVersion',
    message: function(answers) {
      return 'Which version of '
        + chalk.red(answers['drupalDistro'].option.name)
        + ' would you like to use?';
    },
    default: function(answers) {
      return answers['drupalDistro'].versionDefault;
    },
    choices: function(answers) {
      return answers['drupalDistro'].versions;
    }
  }
];

module.exports = prompts;
<|endoftext|>


<commit_before>function initTypeProto(a,b,c,d,e,f,g,h,i,j,k,l);//IGNORE
function initTypeProtoI(a,b,c,d,e,f,g,h,i,j,k,l);//IGNORE
function String$(x){}//IGNORE
function Boolean$(x){}//IGNORE
function Character(x){}//IGNORE
function isOfType(a,b){}//IGNORE
function Integer(x){}//IGNORE
function smallest(x,y){}//IGNORE
function largest(x,y){}//IGNORE
function Exception(){}//IGNORE
var List,Some,Cloneable,Ranged,exports,$true,$false,larger,smaller,equal,Object$,$empty,$finished,Iterator;//IGNORE
var IdentifiableObject,Category,Sized;//IGNORE

function Sequence($$sequence) {
    return $$sequence;
}
initTypeProtoI(Sequence, 'ceylon.language.Sequence', List, Some, Cloneable, Ranged);
var Sequence$proto = Sequence.$$.prototype;
Sequence$proto.getLast = function() {
    var last = this.item(this.getLastIndex());
    if (last === null) throw Exception();
    return last;
}

function ArraySequence(value) {
    var that = new ArraySequence.$$;
    that.value = value;
    return that;
}
initTypeProto(ArraySequence, 'ceylon.language.ArraySequence', IdentifiableObject, Sequence);
var ArraySequence$proto = ArraySequence.$$.prototype;
ArraySequence$proto.item = function(index) {
    var result = this.value[index.value];
    return result!==undefined ? result:null;
}
ArraySequence$proto.getSize = function() { return Integer(this.value.length) }
ArraySequence$proto.getEmpty = function() { return this.value.length > 0 ? $false : $true; }
ArraySequence$proto.getLastIndex = function() { return this.getSize().getPredecessor(); }
ArraySequence$proto.getFirst = function() { return this.item(Integer(0)); }
ArraySequence$proto.getLast = function() { return this.item(this.getLastIndex()); }
ArraySequence$proto.segment = function(from, len) {
    var seq = [];
    if (len.compare(Integer(0)) === larger) {
        var stop = from.plus(len).value;
        for (var i=from.value; i < stop; i++) {
            var x = this.item(Integer(i));
            if (x !== null) { seq.push(x); }
        }
    }
    return ArraySequence(seq);
}
ArraySequence$proto.span = function(from, to) {
    var fromIndex = largest(Integer(0),from).value;
    var toIndex = to === null || to === undefined ? this.getLastIndex().value : smallest(to, this.getLastIndex()).value;
    var seq = [];
    if (fromIndex === toIndex) {
        return Singleton(this.item(from));
    } else if (toIndex > fromIndex) {
        for (var i = fromIndex; i <= toIndex && this.defines(Integer(i)) === $true; i++) {
            seq.push(this.item(Integer(i)));
        }
    } else {
        //Negative span, reverse seq returned
        for (var i = fromIndex; i >= toIndex && this.defines(Integer(i)) === $true; i--) {
            seq.push(this.item(Integer(i)));
        }
    }
    return ArraySequence(seq);
}
ArraySequence$proto.getRest = function() {
    return this.getSize().equals(Integer(1)) === $true ? $empty : ArraySequence(this.value.slice(1));
}
ArraySequence$proto.items = function(keys) {
    var seq = [];
    for (var i = 0; i < keys.getSize().value; i++) {
        var key = keys.item(Integer(i));
        seq.push(this.item(key));
    }
    return ArraySequence(seq);
}
ArraySequence$proto.getKeys = function() { return TypeCategory(this, 'ceylon.language.Integer'); }
ArraySequence$proto.contains = function(elem) {
    for (var i=0; i<this.value.length; i++) {
        if (elem.equals(this.value[i])) {
            return $true;
        }
    }
    return $false;
}
ArraySequence$proto.getReversed = function() {
    var arr = this.value.slice(0);
    arr.reverse();
    return ArraySequence(arr);
}

function TypeCategory(seq, type) {
    var that = new TypeCategory.$$;
    that.type = type;
    that.seq = seq;
    return that;
}
initTypeProto(TypeCategory, 'ceylon.language.TypeCategory', IdentifiableObject, Category);
var TypeCategory$proto = TypeCategory.$$.prototype;
TypeCategory$proto.contains = function(k) {
    return Boolean$(isOfType(k, this.type) === $true && this.seq.defines(k) === $true);
}

function SequenceBuilder() {
    var that = new SequenceBuilder.$$;
    that.seq = [];
    return that;
}
initTypeProto(SequenceBuilder, 'ceylon.language.SequenceBuilder', IdentifiableObject, Sized);
var SequenceBuilder$proto = SequenceBuilder.$$.prototype;
SequenceBuilder$proto.getSequence = function() { return ArraySequence(this.seq); }
SequenceBuilder$proto.append = function(e) { this.seq.push(e); }
SequenceBuilder$proto.appendAll = function(arr) {
	if (arr && arr.value && arr.value.length) {
        for (var i = 0; i < arr.value.length; i++) {
            this.seq.push(arr.value[i]);
        }
    }
}
SequenceBuilder$proto.getSize = function() { return Integer(this.seq.length); }

function SequenceAppender(other) {
	var that = new SequenceAppender.$$;
	that.seq = [];
	that.appendAll(other);
	return that;
}
initTypeProto(SequenceAppender, 'ceylon.language.SequenceAppender', SequenceBuilder);

function Singleton(elem) {
    var that = new Singleton.$$;
    that.value = [elem];
    that.elem = elem;
    return that;
}
initTypeProto(Singleton, 'ceylon.language.Singleton', Object$, Sequence);
var Singleton$proto = Singleton.$$.prototype;
Singleton$proto.getString = function() { return String$("{ " + this.elem.getString().value + " }") }
Singleton$proto.item = function(index) {
    return index.value===0 ? this.value[0] : null;
}
Singleton$proto.getSize = function() { return Integer(1); }
Singleton$proto.getLastIndex = function() { return Integer(0); }
Singleton$proto.getFirst = function() { return this.elem; }
Singleton$proto.getLast = function() { return this.elem; }
Singleton$proto.getEmpty = function() { return $false; }
Singleton$proto.getRest = function() { return $empty; }
Singleton$proto.defines = function(idx) { return idx.equals(Integer(0)); }
Singleton$proto.getKeys = function() { return TypeCategory(this, 'ceylon.language.Integer'); }
Singleton$proto.span = function(from, to) {
	if (to === undefined || to === null) to = from;
    return (from.equals(Integer(0)) === $true || to.equals(Integer(0)) === $true) ? this : $empty;
}
Singleton$proto.segment = function(idx, len) {
    if (idx.equals(Integer(0)) === $true && len.compare(Integer(0)) === larger) {
        return this;
    }
    return $empty;
}
Singleton$proto.getIterator = function() { return SingletonIterator(this.elem); }
Singleton$proto.getReversed = function() { return this; }
Singleton$proto.skipping = function(skip) {
    return skip.value==0 ? this : $empty;
}
Singleton$proto.taking = function(take) {
    return take.value>0 ? this : $empty;
}
Singleton$proto.by = function(step) {
    return this;
}
function SingletonIterator(elem) {
    var that = new SingletonIterator.$$;
    that.elem = elem;
    that.done = false;
    return that;
}
initTypeProto(SingletonIterator, 'ceylon.language.SingletonIterator', IdentifiableObject, Iterator);
var $SingletonIterator$proto = SingletonIterator.$$.prototype;
$SingletonIterator$proto.next = function() {
    if (this.done) {
        return $finished;
    }
    this.done = true;
    return this.elem;
}

exports.Sequence=Sequence;
exports.SequenceBuilder=SequenceBuilder;
exports.SequenceAppender=SequenceAppender;
exports.ArraySequence=ArraySequence;
exports.Singleton=Singleton;
<commit_msg>Singleton refines Iterable methods for #93<commit_after>function initTypeProto(a,b,c,d,e,f,g,h,i,j,k,l);//IGNORE
function initTypeProtoI(a,b,c,d,e,f,g,h,i,j,k,l);//IGNORE
function String$(x){}//IGNORE
function Boolean$(x){}//IGNORE
function Character(x){}//IGNORE
function isOfType(a,b){}//IGNORE
function Integer(x){}//IGNORE
function smallest(x,y){}//IGNORE
function largest(x,y){}//IGNORE
function Exception(){}//IGNORE
var List,Some,Cloneable,Ranged,exports,$true,$false,larger,smaller,equal,Object$,$empty,$finished,Iterator;//IGNORE
var IdentifiableObject,Category,Sized;//IGNORE

function Sequence($$sequence) {
    return $$sequence;
}
initTypeProtoI(Sequence, 'ceylon.language.Sequence', Some, Cloneable, Ranged, List);
var Sequence$proto = Sequence.$$.prototype;
Sequence$proto.getLast = function() {
    var last = this.item(this.getLastIndex());
    if (last === null) throw Exception();
    return last;
}

function ArraySequence(/* js array */value) {
    var that = new ArraySequence.$$;
    that.value = value;
    return that;
}
initTypeProto(ArraySequence, 'ceylon.language.ArraySequence', IdentifiableObject, Sequence);
var ArraySequence$proto = ArraySequence.$$.prototype;
ArraySequence$proto.item = function(index) {
    var result = this.value[index.value];
    return result!==undefined ? result:null;
}
ArraySequence$proto.getSize = function() { return Integer(this.value.length) }
ArraySequence$proto.getEmpty = function() { return this.value.length > 0 ? $false : $true; }
ArraySequence$proto.getLastIndex = function() { return this.getSize().getPredecessor(); }
ArraySequence$proto.getFirst = function() { return this.item(Integer(0)); }
ArraySequence$proto.getLast = function() { return this.item(this.getLastIndex()); }
ArraySequence$proto.segment = function(from, len) {
    var seq = [];
    if (len.compare(Integer(0)) === larger) {
        var stop = from.plus(len).value;
        for (var i=from.value; i < stop; i++) {
            var x = this.item(Integer(i));
            if (x !== null) { seq.push(x); }
        }
    }
    return ArraySequence(seq);
}
ArraySequence$proto.span = function(from, to) {
    var fromIndex = largest(Integer(0),from).value;
    var toIndex = to === null || to === undefined ? this.getLastIndex().value : smallest(to, this.getLastIndex()).value;
    var seq = [];
    if (fromIndex === toIndex) {
        return Singleton(this.item(from));
    } else if (toIndex > fromIndex) {
        for (var i = fromIndex; i <= toIndex && this.defines(Integer(i)) === $true; i++) {
            seq.push(this.item(Integer(i)));
        }
    } else {
        //Negative span, reverse seq returned
        for (var i = fromIndex; i >= toIndex && this.defines(Integer(i)) === $true; i--) {
            seq.push(this.item(Integer(i)));
        }
    }
    return ArraySequence(seq);
}
ArraySequence$proto.getRest = function() {
    return this.getSize().equals(Integer(1)) === $true ? $empty : ArraySequence(this.value.slice(1));
}
ArraySequence$proto.items = function(keys) {
    var seq = [];
    for (var i = 0; i < keys.getSize().value; i++) {
        var key = keys.item(Integer(i));
        seq.push(this.item(key));
    }
    return ArraySequence(seq);
}
ArraySequence$proto.getKeys = function() { return TypeCategory(this, 'ceylon.language.Integer'); }
ArraySequence$proto.contains = function(elem) {
    for (var i=0; i<this.value.length; i++) {
        if (elem.equals(this.value[i])) {
            return $true;
        }
    }
    return $false;
}
ArraySequence$proto.getReversed = function() {
    var arr = this.value.slice(0);
    arr.reverse();
    return ArraySequence(arr);
}

function TypeCategory(seq, type) {
    var that = new TypeCategory.$$;
    that.type = type;
    that.seq = seq;
    return that;
}
initTypeProto(TypeCategory, 'ceylon.language.TypeCategory', IdentifiableObject, Category);
var TypeCategory$proto = TypeCategory.$$.prototype;
TypeCategory$proto.contains = function(k) {
    return Boolean$(isOfType(k, this.type) === $true && this.seq.defines(k) === $true);
}

function SequenceBuilder() {
    var that = new SequenceBuilder.$$;
    that.seq = [];
    return that;
}
initTypeProto(SequenceBuilder, 'ceylon.language.SequenceBuilder', IdentifiableObject, Sized);
var SequenceBuilder$proto = SequenceBuilder.$$.prototype;
SequenceBuilder$proto.getSequence = function() { return ArraySequence(this.seq); }
SequenceBuilder$proto.append = function(e) { this.seq.push(e); }
SequenceBuilder$proto.appendAll = function(arr) {
	if (arr && arr.value && arr.value.length) {
        for (var i = 0; i < arr.value.length; i++) {
            this.seq.push(arr.value[i]);
        }
    }
}
SequenceBuilder$proto.getSize = function() { return Integer(this.seq.length); }

function SequenceAppender(other) {
	var that = new SequenceAppender.$$;
	that.seq = [];
	that.appendAll(other);
	return that;
}
initTypeProto(SequenceAppender, 'ceylon.language.SequenceAppender', SequenceBuilder);

function Singleton(elem) {
    var that = new Singleton.$$;
    that.value = [elem];
    that.elem = elem;
    return that;
}
initTypeProto(Singleton, 'ceylon.language.Singleton', Object$, Sequence);
var Singleton$proto = Singleton.$$.prototype;
Singleton$proto.getString = function() { return String$("{ " + this.elem.getString().value + " }") }
Singleton$proto.item = function(index) {
    return index.value===0 ? this.value[0] : null;
}
Singleton$proto.getSize = function() { return Integer(1); }
Singleton$proto.getLastIndex = function() { return Integer(0); }
Singleton$proto.getFirst = function() { return this.elem; }
Singleton$proto.getLast = function() { return this.elem; }
Singleton$proto.getEmpty = function() { return $false; }
Singleton$proto.getRest = function() { return $empty; }
Singleton$proto.defines = function(idx) { return idx.equals(Integer(0)); }
Singleton$proto.getKeys = function() { return TypeCategory(this, 'ceylon.language.Integer'); }
Singleton$proto.span = function(from, to) {
	if (to === undefined || to === null) to = from;
    return (from.equals(Integer(0)) === $true || to.equals(Integer(0)) === $true) ? this : $empty;
}
Singleton$proto.segment = function(idx, len) {
    if (idx.equals(Integer(0)) === $true && len.compare(Integer(0)) === larger) {
        return this;
    }
    return $empty;
}
Singleton$proto.getIterator = function() { return SingletonIterator(this.elem); }
Singleton$proto.getReversed = function() { return this; }
Singleton$proto.map = function(f) { return ArraySequence([ f(this.elem) ]); }
Singleton$proto.filter = function(f) {
    return f(this.elem) === $true ? this : $empty;
}
Singleton$proto.fold = function(v,f) {
    return f(v, this.elem);
}
Singleton$proto.find = function(f) {
    return f(this.elem) === $true ? this.elem : null;
}
Singleton$proto.findLast = function(f) {
    return f(this.elem) === $true ? this.elem : null;
}
Singleton$proto.any = function(f) {
    return f(this.elem);
}
Singleton$proto.every = function(f) {
    return f(this.elem);
}
Singleton$proto.skipping = function(skip) {
    return skip.value==0 ? this : $empty;
}
Singleton$proto.taking = function(take) {
    return take.value>0 ? this : $empty;
}
Singleton$proto.by = function(step) {
    return this;
}

function SingletonIterator(elem) {
    var that = new SingletonIterator.$$;
    that.elem = elem;
    that.done = false;
    return that;
}
initTypeProto(SingletonIterator, 'ceylon.language.SingletonIterator', IdentifiableObject, Iterator);
var $SingletonIterator$proto = SingletonIterator.$$.prototype;
$SingletonIterator$proto.next = function() {
    if (this.done) {
        return $finished;
    }
    this.done = true;
    return this.elem;
}

exports.Sequence=Sequence;
exports.SequenceBuilder=SequenceBuilder;
exports.SequenceAppender=SequenceAppender;
exports.ArraySequence=ArraySequence;
exports.Singleton=Singleton;
<|endoftext|>


<commit_before>const chai = require('chai')
const _ = require('lodash')
const fs = require('fs')
const path = require('path')
const {
  modulesWithKeyword,
  checkForNewServerVersion,
  getLatestServerVersion
} = require('./modules')

const expectedModules = [
  '@signalk/freeboard-sk',
  '@signalk/instrumentpanel',
  '@signalk/maptracker',
  '@signalk/playground',
  '@signalk/sailgauge',
  '@signalk/simplegauges'
]

const testTempDir = path.join(
  require('os').tmpdir(),
  '_skservertest_modules' + Date.now()
)

const app = {
  config: {
    appPath: path.join(__dirname + '/../'),
    configPath: testTempDir
  }
}

fs.mkdirSync(testTempDir)
const tempNodeModules = path.join(testTempDir, 'node_modules/')
fs.mkdirSync(path.join(testTempDir, 'node_modules'))
fs.mkdirSync(path.join(testTempDir, 'node_modules/@signalk'))
const configMaptrackerDirectory = path.join(
  testTempDir,
  'node_modules/@signalk/maptracker'
)
fs.mkdirSync(configMaptrackerDirectory)

const maptrackerPkg = require(path.join(
  app.config.appPath,
  'node_modules/@signalk/maptracker/package.json'
))
maptrackerPkg.version = '1000.0.0'
fs.writeFileSync(
  path.join(configMaptrackerDirectory, 'package.json'),
  JSON.stringify(maptrackerPkg)
)

describe('modulesWithKeyword', () => {
  it('returns a list of modules', () => {
    const moduleList = modulesWithKeyword(app, 'signalk-webapp')
    chai.expect(_.map(moduleList, 'module')).to.eql(expectedModules)
    chai.expect(moduleList[0].location).to.not.eql(tempNodeModules)
    chai.expect(moduleList[2].location).to.eql(tempNodeModules)
  })
})

describe('checkForNewServerVersion', () => {
  it('normal version upgrade', done => {
    checkForNewServerVersion(
      '1.17.0',
      (err, newVersion) => {
        if (err) {
          done(err)
        } else {
          chai.expect(newVersion).to.equal('1.18.0')
          done()
        }
      },
      () => Promise.resolve('1.18.0')
    )
  })

  it('normal version does not upgrade to beta', done => {
    checkForNewServerVersion(
      '1.17.0',
      err => {
        done('callback should not be called')
      },
      () => Promise.resolve('1.18.0-beta.1')
    )
    done()
  })

  it('beta upgrades to same minor newer beta', done => {
    checkForNewServerVersion(
      '1.18.0-beta.1',
      (err, newVersion) => {
        if (err) {
          done(err)
        } else {
          chai.expect(newVersion).to.equal('1.18.0-beta.2')
          done()
        }
      },
      () => Promise.resolve('1.18.0-beta.2')
    )
  })

  it('beta upgrades to same normal version', done => {
    checkForNewServerVersion(
      '1.18.0-beta.2',
      (err, newVersion) => {
        if (err) {
          done(err)
        } else {
          chai.expect(newVersion).to.equal('1.18.0')
          done()
        }
      },
      () => Promise.resolve('1.18.0')
    )
  })

  it('beta upgrades to newer normal version', done => {
    checkForNewServerVersion(
      '1.18.0-beta.2',
      (err, newVersion) => {
        if (err) {
          done(err)
        } else {
          chai.expect(newVersion).to.equal('1.19.0')
          done()
        }
      },
      () => Promise.resolve('1.19.0')
    )
  })

  it('beta does not upgrade to newer minor beta', done => {
    checkForNewServerVersion(
      '1.17.0-beta.1',
      err => {
        done('callback should not be called')
      },
      () => Promise.resolve('1.18.0-beta.2')
    )
    done()
  })
})

describe('getLatestServerVersion', () => {
  it('latest for normal is normal', () => {
    return getLatestServerVersion('1.17.0', () =>
      Promise.resolve({
        json: () => ({
          latest: '1.18.3',
          beta: '1.19.0-beta.1'
        })
      })
    ).then(newVersion => {
      chai.expect(newVersion).to.equal('1.18.3')
    })
  })

  it('latest for beta is newer same series beta', done => {
    getLatestServerVersion('1.18.0-beta.2', () =>
      Promise.resolve({
        json: () => ({
          latest: '1.17.3',
          beta: '1.18.0-beta.3'
        })
      })
    ).then(newVersion => {
      chai.expect(newVersion).to.equal('1.18.0-beta.3')
      done()
    })
  })

  it('latest for beta is newer real release', () => {
    return getLatestServerVersion('1.18.0-beta.2', () =>
      Promise.resolve({
        json: () => ({
          latest: '1.18.0',
          beta: '1.18.0-beta.3'
        })
      })
    ).then(newVersion => {
      chai.expect(newVersion).to.equal('1.18.0')
    })
  })
})
<commit_msg>tests: remove playground from modules test<commit_after>const chai = require('chai')
const _ = require('lodash')
const fs = require('fs')
const path = require('path')
const {
  modulesWithKeyword,
  checkForNewServerVersion,
  getLatestServerVersion
} = require('./modules')

const expectedModules = [
  '@signalk/freeboard-sk',
  '@signalk/instrumentpanel',
  '@signalk/maptracker',
  '@signalk/sailgauge',
  '@signalk/simplegauges'
]

const testTempDir = path.join(
  require('os').tmpdir(),
  '_skservertest_modules' + Date.now()
)

const app = {
  config: {
    appPath: path.join(__dirname + '/../'),
    configPath: testTempDir
  }
}

fs.mkdirSync(testTempDir)
const tempNodeModules = path.join(testTempDir, 'node_modules/')
fs.mkdirSync(path.join(testTempDir, 'node_modules'))
fs.mkdirSync(path.join(testTempDir, 'node_modules/@signalk'))
const configMaptrackerDirectory = path.join(
  testTempDir,
  'node_modules/@signalk/maptracker'
)
fs.mkdirSync(configMaptrackerDirectory)

const maptrackerPkg = require(path.join(
  app.config.appPath,
  'node_modules/@signalk/maptracker/package.json'
))
maptrackerPkg.version = '1000.0.0'
fs.writeFileSync(
  path.join(configMaptrackerDirectory, 'package.json'),
  JSON.stringify(maptrackerPkg)
)

describe('modulesWithKeyword', () => {
  it('returns a list of modules', () => {
    const moduleList = modulesWithKeyword(app, 'signalk-webapp')
    chai.expect(_.map(moduleList, 'module')).to.eql(expectedModules)
    chai.expect(moduleList[0].location).to.not.eql(tempNodeModules)
    chai.expect(moduleList[2].location).to.eql(tempNodeModules)
  })
})

describe('checkForNewServerVersion', () => {
  it('normal version upgrade', done => {
    checkForNewServerVersion(
      '1.17.0',
      (err, newVersion) => {
        if (err) {
          done(err)
        } else {
          chai.expect(newVersion).to.equal('1.18.0')
          done()
        }
      },
      () => Promise.resolve('1.18.0')
    )
  })

  it('normal version does not upgrade to beta', done => {
    checkForNewServerVersion(
      '1.17.0',
      err => {
        done('callback should not be called')
      },
      () => Promise.resolve('1.18.0-beta.1')
    )
    done()
  })

  it('beta upgrades to same minor newer beta', done => {
    checkForNewServerVersion(
      '1.18.0-beta.1',
      (err, newVersion) => {
        if (err) {
          done(err)
        } else {
          chai.expect(newVersion).to.equal('1.18.0-beta.2')
          done()
        }
      },
      () => Promise.resolve('1.18.0-beta.2')
    )
  })

  it('beta upgrades to same normal version', done => {
    checkForNewServerVersion(
      '1.18.0-beta.2',
      (err, newVersion) => {
        if (err) {
          done(err)
        } else {
          chai.expect(newVersion).to.equal('1.18.0')
          done()
        }
      },
      () => Promise.resolve('1.18.0')
    )
  })

  it('beta upgrades to newer normal version', done => {
    checkForNewServerVersion(
      '1.18.0-beta.2',
      (err, newVersion) => {
        if (err) {
          done(err)
        } else {
          chai.expect(newVersion).to.equal('1.19.0')
          done()
        }
      },
      () => Promise.resolve('1.19.0')
    )
  })

  it('beta does not upgrade to newer minor beta', done => {
    checkForNewServerVersion(
      '1.17.0-beta.1',
      err => {
        done('callback should not be called')
      },
      () => Promise.resolve('1.18.0-beta.2')
    )
    done()
  })
})

describe('getLatestServerVersion', () => {
  it('latest for normal is normal', () => {
    return getLatestServerVersion('1.17.0', () =>
      Promise.resolve({
        json: () => ({
          latest: '1.18.3',
          beta: '1.19.0-beta.1'
        })
      })
    ).then(newVersion => {
      chai.expect(newVersion).to.equal('1.18.3')
    })
  })

  it('latest for beta is newer same series beta', done => {
    getLatestServerVersion('1.18.0-beta.2', () =>
      Promise.resolve({
        json: () => ({
          latest: '1.17.3',
          beta: '1.18.0-beta.3'
        })
      })
    ).then(newVersion => {
      chai.expect(newVersion).to.equal('1.18.0-beta.3')
      done()
    })
  })

  it('latest for beta is newer real release', () => {
    return getLatestServerVersion('1.18.0-beta.2', () =>
      Promise.resolve({
        json: () => ({
          latest: '1.18.0',
          beta: '1.18.0-beta.3'
        })
      })
    ).then(newVersion => {
      chai.expect(newVersion).to.equal('1.18.0')
    })
  })
})
<|endoftext|>


<commit_before>'use strict';

/* jasmine specs for _.main.js go here */

describe("Test _.main.js", function() {

	/**
     * Test logging function, for debugging mode
     */
	describe("test $.log() function", function() {
		it("MODULE.config.debug should be true", function() {
			expect(MODULE.config.debug).toBe(true);
		});

		it("typeof window.console should be object", function() {
			expect(typeof window.console).toBeDefined();
		})

		it("typeof window.console.log to be defined", function() {
			expect(typeof window.console.log).toBeDefined();
		})

		it("console.debug should be available", function(){
			expect(console.debug).toBeDefined();
		})
	});

	/**
     * Test $.toType() function
     */
     describe("test $.toType() function", function() {
     	it("")

     })
})<commit_msg>Added specs for toType and facebook method<commit_after>'use strict';

/* jasmine specs for _.main.js go here */

/*Matchers Reference
• toEqual checks for equality, not necessarily the same object.
• toBe checks if two objects are the same.
• toBeTruthy checks if a value is truthy (not just true).
• toBeFalsy checks if a value is falsy (not just false).
• toContain checks if a value is inside another.
• toBeDefined checks if a value is defined.
• toBeUndefined checks if a value is undefined.
• toBeNull checks if a value is null.
• toBeNaN checks if a value is NaN.
• toBeCloseTo checks decimal proximity.
• toMatch checks if a value matches a given regular expression.
• toThrow checks if a function throws an error.
• .not inverts the meaning of the following matcher.
*/

/*Reserved Words in Jasmine
• jasmine (and everything in its namespace)
• describe
• it
• expect
• beforeEach
• afterEach
• runs
• waits
• waitsFor
• spyOn
• xdescribe
• xit
*/

/*List of Falsy Values
• false
• 0
• ""
• undefined (note that the variable undefined isn’t always undefined!)
• null
• NaN
*/

describe("Test main js file", function() {

	/**
	 * Test logging function, for debugging mode
	 */
	describe("test log function", function() { // suite
		it("MODULE.config.debug should be true", function() { // specification or spec
			expect(MODULE.config.debug).toEqual(true); // matcher, if you want to make sure something is literally true or false and nothing else, use the
			//toEqual matcher
		});

		it("typeof window.console should be object", function() {
			expect(typeof window.console !== 'undefined').toEqual(true);
		})

		it("typeof window.console.log to be defined", function() {
			expect(typeof window.console.log !== 'undefined').toEqual(true);
		})

		it("console.debug should be available", function() {
			expect(console.debug).toBeDefined();
		})
	});

	/**
	 * Test $.toType() function
	 */
	describe("test toType function", function() {
		xit("test window object 'global'", function() {
			expect($.toType(window)).toEqual("global");
		})

		it("test array object", function() {
			expect($.toType([1, 2, 3])).toEqual("array");
		})

		it("test regex object", function() {
			expect($.toType(/a-z/)).toEqual("regexp");
		})

		it("test object", function() {
			expect($.toType({
				a: 4
			})).toEqual("object");
		})

		it("test error object", function() {
			expect($.toType(new ReferenceError)).toEqual("error");
		})

		it("test date object", function() {
			expect($.toType(new Date)).toEqual("date");
		})

		it("test Math object", function() {
			expect($.toType(Math)).toEqual("math");
		})

		it("test JSON object", function() {
			expect($.toType(JSON)).toEqual("json");
		})

		it("test Number object", function() {
			expect($.toType(3)).toEqual("number");
		})

		it("test String object", function() {
			expect($.toType("Arif")).toEqual("string");
		})

		it("test Boolean object", function() {
			expect($.toType(new Boolean(true))).toEqual("boolean");
		})

		xit("test null", function() {
			expect($.toType(null)).toEqual("null");
		})

		xit("test undefined", function() {
			expect($.toType(undefined)).toEqual("undefined");
		})
	})

	describe("test public method", function() {
		it("MODULE.sayHello", function() {
			expect(MODULE.sayHello()).toEqual("Hello World!");
		})
	})

	describe("Facebook", function() {
		it("is FB available (i.e. is facebook library included)", function() {
			expect(typeof FB != "undefined").not.toEqual(true);
		});

		it("do we have an application id", function() {
			expect(MODULE.config.appId != "").toEqual(true);
		});

		it("initialize the facebook library", function() {
			MODULE.subModule.fbReady();
		});

		xit("Checking for active facebook session", function() {
			FB.getLoginStatus();
			waitsFor(function() {
				return FB.getLoginStatusResponse() && FB.getLoginStatusResponse().authResponse;
			}, "response.authResponse", 7000);
		});
	});

})<|endoftext|>