<commit_before>const assert = require('assert');
const PlexRepository = require('src/plex/plexRepository');
const plexRepository = new PlexRepository();
const configuration = require('src/config/configuration').getInstance();
const Cache = require('src/tmdb/cache');
const TMDB = require('src/tmdb/tmdb');
const cache = new Cache();
const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey'));
var Promise = require('bluebird');
var rp = require('request-promise');

const establishedDatabase = require('src/database/database');

const MailTemplate = require('src/plex/mailTemplate')

var pythonShell = require('python-shell');
const nodemailer = require('nodemailer');

class RequestRepository {

	constructor(cache, database) {
		this.database = database || establishedDatabase;
		this.queries = {
			'insertRequest': "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, CURRENT_DATE, 'requested', ?, ?)",
			'fetchRequstedItems': "SELECT * FROM requests",
			'updateRequestedById': "UPDATE requests SET status = ? WHERE id is ? AND type is ?",
		}
	}

	searchRequest(text, page, type) {
		// STRIP METADATA THAT IS NOT ALLOWED

		// Do a search in the tmdb api and return the results of the object
		let getTmdbResults = function() {
			return tmdb.search(text, page, type)
				.then((tmdbSearch) => {
					return tmdbSearch.results;
				})
		}

		// Take inputs and verify them with a list. Now we are for every item in tmdb result
		// runnning through the entire plex loop. Many loops, but safe.
		let checkIfMatchesPlexObjects = function(title, year, plexarray) {
			// Iterate all elements in plexarray
			for (let plexItem of plexarray) {
				// If matches with our title and year return true
				if (plexItem.title === title && plexItem.year === year)
					return true;
			}
			// If no matches were found, return false
			return false;
		}

		return Promise.resolve()
		.catch(() => plexRepository.searchMedia(text))
		// Get the list of plexItems matching the query passed.
		.then((plexItem) => {
			let tmdbSearchResult = getTmdbResults();

			// When we get the result from tmdbSearchResult we pass it along and iterate over each
			// element, and updates the matchedInPlex status of a item.
			return tmdbSearchResult.then((tmdbResult) => {
				for (var i = 0; i < tmdbResult.length; i++) {
					let foundMatchInPlex = checkIfMatchesPlexObjects(tmdbResult[i].title, tmdbResult[i].year, plexItem);
					tmdbResult[i].matchedInPlex = foundMatchInPlex;
				}
				return { 'results': tmdbResult, 'page': 1 };
			})
			// TODO log error
			.catch((error) => {
				console.log(error);
				throw new Error('Search query did not give any results.');
			})
		})
		.catch(() => {
			let tmdbSearchResult = getTmdbResults();

			// Catch if empty, then 404
			return tmdbSearchResult.then((tmdbResult) => {
				return {'results': tmdbResult, 'page': 1 };
			})
		})
	}

	lookup(identifier, type = 'movie') {
		if (type === 'movie') { type = 'movieInfo'}
			else if (type === 'tv') { type = 'tvInfo'}
		return Promise.resolve()
		.then(() => tmdb.lookup(identifier, type))
		.then((tmdbMovie) => {
			return Promise.resolve(plexRepository.searchMedia(tmdbMovie.title))
			.then((plexMovies) => {
				for (var i = 0; i < plexMovies.length; i++) {
					if (tmdbMovie.title === plexMovies[i].title && tmdbMovie.year === plexMovies[i].year) {
						tmdbMovie.matchedInPlex = true;
						return tmdbMovie;
					}
				}
			})
			.catch((error) => {
				return error;
			});
			return tmdbMovie;
		});
	}

	/**
	* Send request for given media id.
	* @param {identifier, type} the id of the media object and type of media must be defined
	* @returns {Promise} If nothing has gone wrong.
	*/
	sendRequest(identifier, type, ip, user_agent) {
		// TODO add to DB so can have a admin page
		// TODO try a cache hit on the movie item

		tmdb.lookup(identifier, type).then(movie => {

			// Add request to database
			this.database.run(this.queries.insertRequest, [movie.id, movie.title, movie.year, movie.poster, 'NULL', ip, user_agent, movie.type])

			//

			// create reusable transporter object using the default SMTP transport
			let transporter = nodemailer.createTransport({
				service: 'gmail',
			    auth: {
			        user: configuration.get('mail', 'user_pi'),
			        pass: configuration.get('mail', 'password_pi')
			    }
			    // host: configuration.get('mail', 'host'),
			    // port: 26,
			    // ignoreTLS: true,
			    // tls :{rejectUnauthorized: false},
			    // secure: false, // secure:true for port 465, secure:false for port 587
			});

			const mailTemplate = new MailTemplate(movie)

			// setup email data with unicode symbols
			let mailOptions = {
				// TODO get the mail adr from global location (easy to add)
			    from: 'MovieRequester <pi.midboe@gmail.com>', // sender address
			    to: 'kevin.midboe@gmail.com', // list of receivers
			    subject: 'Download request', // Subject line
			    text: mailTemplate.toText(),
			    html: mailTemplate.toHTML()
			};

			// send mail with defined transport object
			transporter.sendMail(mailOptions, (error, info) => {
			    if (error) {
			        return console.log(error);
			    }
			    console.log('Message %s sent: %s', info.messageId, info.response);
			});

		})

		// TODO add better response when done.
		return Promise.resolve();

	}

	fetchRequested() {
		return this.database.all(this.queries.fetchRequstedItems);
	}

	updateRequestedById(id, type, status) {
		return this.database.run(this.queries.updateRequestedById, [status, id, type]);
	}

}

module.exports = RequestRepository;<commit_msg>Opps, start with then.<commit_after>const assert = require('assert');
const PlexRepository = require('src/plex/plexRepository');
const plexRepository = new PlexRepository();
const configuration = require('src/config/configuration').getInstance();
const Cache = require('src/tmdb/cache');
const TMDB = require('src/tmdb/tmdb');
const cache = new Cache();
const tmdb = new TMDB(cache, configuration.get('tmdb', 'apiKey'));
var Promise = require('bluebird');
var rp = require('request-promise');

const establishedDatabase = require('src/database/database');

const MailTemplate = require('src/plex/mailTemplate')

var pythonShell = require('python-shell');
const nodemailer = require('nodemailer');

class RequestRepository {

	constructor(cache, database) {
		this.database = database || establishedDatabase;
		this.queries = {
			'insertRequest': "INSERT INTO requests VALUES (?, ?, ?, ?, ?, ?, CURRENT_DATE, 'requested', ?, ?)",
			'fetchRequstedItems': "SELECT * FROM requests",
			'updateRequestedById': "UPDATE requests SET status = ? WHERE id is ? AND type is ?",
		}
	}

	searchRequest(text, page, type) {
		// STRIP METADATA THAT IS NOT ALLOWED

		// Do a search in the tmdb api and return the results of the object
		let getTmdbResults = function() {
			return tmdb.search(text, page, type)
				.then((tmdbSearch) => {
					return tmdbSearch.results;
				})
		}

		// Take inputs and verify them with a list. Now we are for every item in tmdb result
		// runnning through the entire plex loop. Many loops, but safe.
		let checkIfMatchesPlexObjects = function(title, year, plexarray) {
			// Iterate all elements in plexarray
			for (let plexItem of plexarray) {
				// If matches with our title and year return true
				if (plexItem.title === title && plexItem.year === year)
					return true;
			}
			// If no matches were found, return false
			return false;
		}

		return Promise.resolve()
		.then(() => plexRepository.searchMedia(text))
		// Get the list of plexItems matching the query passed.
		.then((plexItem) => {
			let tmdbSearchResult = getTmdbResults();

			// When we get the result from tmdbSearchResult we pass it along and iterate over each
			// element, and updates the matchedInPlex status of a item.
			return tmdbSearchResult.then((tmdbResult) => {
				for (var i = 0; i < tmdbResult.length; i++) {
					let foundMatchInPlex = checkIfMatchesPlexObjects(tmdbResult[i].title, tmdbResult[i].year, plexItem);
					tmdbResult[i].matchedInPlex = foundMatchInPlex;
				}
				return { 'results': tmdbResult, 'page': 1 };
			})
			// TODO log error
			.catch((error) => {
				console.log(error);
				throw new Error('Search query did not give any results.');
			})
		})
		.catch(() => {
			let tmdbSearchResult = getTmdbResults();

			// Catch if empty, then 404
			return tmdbSearchResult.then((tmdbResult) => {
				return {'results': tmdbResult, 'page': 1 };
			})
		})
	}

	lookup(identifier, type = 'movie') {
		if (type === 'movie') { type = 'movieInfo'}
			else if (type === 'tv') { type = 'tvInfo'}
		return Promise.resolve()
		.then(() => tmdb.lookup(identifier, type))
		.then((tmdbMovie) => {
			return Promise.resolve(plexRepository.searchMedia(tmdbMovie.title))
			.then((plexMovies) => {
				for (var i = 0; i < plexMovies.length; i++) {
					if (tmdbMovie.title === plexMovies[i].title && tmdbMovie.year === plexMovies[i].year) {
						tmdbMovie.matchedInPlex = true;
						return tmdbMovie;
					}
				}
			})
			.catch((error) => {
				return error;
			});
			return tmdbMovie;
		});
	}

	/**
	* Send request for given media id.
	* @param {identifier, type} the id of the media object and type of media must be defined
	* @returns {Promise} If nothing has gone wrong.
	*/
	sendRequest(identifier, type, ip, user_agent) {
		// TODO add to DB so can have a admin page
		// TODO try a cache hit on the movie item

		tmdb.lookup(identifier, type).then(movie => {

			// Add request to database
			this.database.run(this.queries.insertRequest, [movie.id, movie.title, movie.year, movie.poster, 'NULL', ip, user_agent, movie.type])

			//

			// create reusable transporter object using the default SMTP transport
			let transporter = nodemailer.createTransport({
				service: 'gmail',
			    auth: {
			        user: configuration.get('mail', 'user_pi'),
			        pass: configuration.get('mail', 'password_pi')
			    }
			    // host: configuration.get('mail', 'host'),
			    // port: 26,
			    // ignoreTLS: true,
			    // tls :{rejectUnauthorized: false},
			    // secure: false, // secure:true for port 465, secure:false for port 587
			});

			const mailTemplate = new MailTemplate(movie)

			// setup email data with unicode symbols
			let mailOptions = {
				// TODO get the mail adr from global location (easy to add)
			    from: 'MovieRequester <pi.midboe@gmail.com>', // sender address
			    to: 'kevin.midboe@gmail.com', // list of receivers
			    subject: 'Download request', // Subject line
			    text: mailTemplate.toText(),
			    html: mailTemplate.toHTML()
			};

			// send mail with defined transport object
			transporter.sendMail(mailOptions, (error, info) => {
			    if (error) {
			        return console.log(error);
			    }
			    console.log('Message %s sent: %s', info.messageId, info.response);
			});

		})

		// TODO add better response when done.
		return Promise.resolve();

	}

	fetchRequested() {
		return this.database.all(this.queries.fetchRequstedItems);
	}

	updateRequestedById(id, type, status) {
		return this.database.run(this.queries.updateRequestedById, [status, id, type]);
	}

}

module.exports = RequestRepository;<|endoftext|>


<commit_before>import React from 'react';
import { DropTarget } from 'react-dnd';
import * as RJD from '../../../src/main';
import { OutputNodeModel } from './nodes/models/OutputNodeModel';
import { OutputWidgetFactory } from './nodes/OutputWidgetFactory';
import { OutputNodeFactory } from './nodes/OutputInstanceFactories';

// Setup the diagram engine
const diagramEngine = new RJD.DiagramEngine();
diagramEngine.registerNodeFactory(new RJD.DefaultNodeFactory());
diagramEngine.registerLinkFactory(new RJD.DefaultLinkFactory());
diagramEngine.registerNodeFactory(new OutputWidgetFactory());
// Register instance factories
diagramEngine.registerInstanceFactory(new RJD.DefaultNodeInstanceFactory());
diagramEngine.registerInstanceFactory(new RJD.DefaultPortInstanceFactory());
diagramEngine.registerInstanceFactory(new RJD.LinkInstanceFactory());
diagramEngine.registerInstanceFactory(new OutputNodeFactory());

// Setup the diagram model
const diagramModel = new RJD.DiagramModel();

const nodesTarget = {
  drop(props, monitor, component) {
    const { x: pageX, y: pageY } = monitor.getSourceClientOffset();
    const { left = 0, top = 0 } = diagramEngine.canvas.getBoundingClientRect();
    const { offsetX, offsetY } = diagramEngine.diagramModel;
    const x = pageX - left - offsetX;
    const y = pageY - top - offsetY;

    const outputNode = new OutputNodeModel();
    outputNode.x = x;
    outputNode.y = y;
    diagramModel.addNode(outputNode);
    diagramEngine.setDiagramModel(diagramModel);
  },
};

@DropTarget('node-source', nodesTarget, (connect, monitor) => ({
  connectDropTarget: connect.dropTarget(),
  isOver: monitor.isOver(),
  canDrop: monitor.canDrop(),
}))
export class Diagram extends React.Component {
  componentDidMount() {
    const { onNodeSelected } = this.props;

    diagramModel.addListener({
      selectionChanged: node => onNodeSelected(node),
      selectionCleared: () => onNodeSelected(null)
    });
  }

  render() {
    const { connectDropTarget } = this.props;

    // Render the canvas
    return connectDropTarget (

        <RJD.DiagramWidget diagramEngine={diagramEngine} />

    );
  }
}
<commit_msg>ensure listeners are removed on unmount<commit_after>import React from 'react';
import { DropTarget } from 'react-dnd';
import * as RJD from '../../../src/main';
import { OutputNodeModel } from './nodes/models/OutputNodeModel';
import { OutputWidgetFactory } from './nodes/OutputWidgetFactory';
import { OutputNodeFactory } from './nodes/OutputInstanceFactories';

// Setup the diagram engine
const diagramEngine = new RJD.DiagramEngine();
diagramEngine.registerNodeFactory(new RJD.DefaultNodeFactory());
diagramEngine.registerLinkFactory(new RJD.DefaultLinkFactory());
diagramEngine.registerNodeFactory(new OutputWidgetFactory());
// Register instance factories
diagramEngine.registerInstanceFactory(new RJD.DefaultNodeInstanceFactory());
diagramEngine.registerInstanceFactory(new RJD.DefaultPortInstanceFactory());
diagramEngine.registerInstanceFactory(new RJD.LinkInstanceFactory());
diagramEngine.registerInstanceFactory(new OutputNodeFactory());

// Setup the diagram model
const diagramModel = new RJD.DiagramModel();

const nodesTarget = {
  drop(props, monitor, component) {
    const { x: pageX, y: pageY } = monitor.getSourceClientOffset();
    const { left = 0, top = 0 } = diagramEngine.canvas.getBoundingClientRect();
    const { offsetX, offsetY } = diagramEngine.diagramModel;
    const x = pageX - left - offsetX;
    const y = pageY - top - offsetY;

    const outputNode = new OutputNodeModel();
    outputNode.x = x;
    outputNode.y = y;
    diagramModel.addNode(outputNode);
    diagramEngine.setDiagramModel(diagramModel);
  },
};

@DropTarget('node-source', nodesTarget, (connect, monitor) => ({
  connectDropTarget: connect.dropTarget(),
  isOver: monitor.isOver(),
  canDrop: monitor.canDrop(),
}))
export class Diagram extends React.Component {
  componentDidMount() {
    const { onNodeSelected } = this.props;
    this.listeners = {
      selectionChanged: node => onNodeSelected(node),
      selectionCleared: () => onNodeSelected(null)
    };
    diagramModel.addListener(this.listeners);
  }

  componentWillUnmount() {
    diagramModel.removeListener(this.listeners);
  }

  render() {
    const { connectDropTarget } = this.props;

    // Render the canvas
    return connectDropTarget (

        <RJD.DiagramWidget diagramEngine={diagramEngine} />

    );
  }
}
<|endoftext|>


<commit_before>import React from 'react'

import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection'

const ListContentVariations = () => (
  <ExampleSection title='Content Variations'>
    <ComponentExample
      title='Vertically Aligned'
      description='An element inside a list can be vertically aligned'
      examplePath='elements/List/ContentVariations/ListExampleVerticallyAligned'
    />

    <ComponentExample
      title='Floated'
      description='An list, or an element inside a list can be floated left or right'
      examplePath='elements/List/ContentVariations/ListExampleFloated'
    />
    <ComponentExample examplePath='elements/List/ContentVariations/ListExampleFloatedHorizontal' />
  </ExampleSection>
)

export default ListContentVariations
<commit_msg>docs(List): fix typo (#2698)<commit_after>import React from 'react'

import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection'

const ListContentVariations = () => (
  <ExampleSection title='Content Variations'>
    <ComponentExample
      title='Vertically Aligned'
      description='An element inside a list can be vertically aligned'
      examplePath='elements/List/ContentVariations/ListExampleVerticallyAligned'
    />

    <ComponentExample
      title='Floated'
      description='A list, or an element inside a list can be floated left or right'
      examplePath='elements/List/ContentVariations/ListExampleFloated'
    />
    <ComponentExample examplePath='elements/List/ContentVariations/ListExampleFloatedHorizontal' />
  </ExampleSection>
)

export default ListContentVariations
<|endoftext|>


<commit_before>"use strict";

var util = require("util");
var events = require("events");
var WebSocket = require("faye-websocket");
var EJSON = require("ddp-ejson");
var request = require('request');
var pathJoin = require('path').join;
var _ = require("ddp-underscore-patched");

var DDPClient = function(opts) {
  var self = this;

  opts = opts || {};

  // backwards compatibility
  if ("use_ssl" in opts)              { opts.ssl = opts.use_ssl; }
  if ("auto_reconnect" in opts)       { opts.autoReconnect = opts.auto_reconnect; }
  if ("auto_reconnect_timer" in opts) { opts.autoReconnectTimer = opts.auto_reconnect_timer; }
  if ("maintain_collections" in opts) { opts.maintainCollections = opts.maintain_collections; }
  if ("ddp_version" in opts)          { opts.ddpVersion = opts.ddp_version; }

  // default arguments
  self.host = opts.host || "localhost";
  self.port = opts.port || 3000;
  self.path = opts.path;
  self.ssl  = opts.ssl  || self.port === 443;
  self.tlsOpts = opts.tlsOpts || {};
  self.useSockJs = opts.useSockJs || false;
  self.autoReconnect = ("autoReconnect" in opts) ? opts.autoReconnect : true;
  self.autoReconnectTimer = ("autoReconnectTimer" in opts) ? opts.autoReconnectTimer : 500;
  self.maintainCollections = ("maintainCollections" in opts) ? opts.maintainCollections : true;
  self.url  = opts.url;
  // support multiple ddp versions
  self.ddpVersion = ("ddpVersion" in opts) ? opts.ddpVersion : "1";
  self.supportedDdpVersions = ["1", "pre2", "pre1"];

  // Expose EJSON object, so client can use EJSON.addType(...)
  self.EJSON = EJSON;

  // very very simple collections (name -> [{id -> document}])
  if (self.maintainCollections) {
    self.collections = {};
  }

  // internal stuff to track callbacks
  self._isConnecting = false;
  self._isReconnecting = false;
  self._nextId = 0;
  self._callbacks = {};
  self._updatedCallbacks = {};
  self._pendingMethods = {};
  self._observers = {};
};

DDPClient.ERRORS = {
  DISCONNECTED: new Error("DDPClient: Disconnected from DDP server")
};

/**
 * Inherits from EventEmitter
 */
util.inherits(DDPClient, events.EventEmitter);

DDPClient.prototype._prepareHandlers = function() {
  var self = this;

  self.socket.on("open", function() {
    // just go ahead and open the connection on connect
    self._send({
      msg : "connect",
      version : self.ddpVersion,
      support : self.supportedDdpVersions
    });
  });

  self.socket.on("error", function(error) {
    // error received before connection was established
    if (self._isConnecting) {
      self.emit("failed", error.message);
    }

    self.emit("socket-error", error);
  });

  self.socket.on("close", function(event) {
    self.emit("socket-close", event.code, event.reason);
    self._endPendingMethodCalls();
    self._recoverNetworkError();
  });

  self.socket.on("message", function(event) {
    self._message(event.data);
    self.emit("message", event.data);
  });
};

DDPClient.prototype._clearReconnectTimeout = function() {
  var self = this;
  if (self.reconnectTimeout) {
    clearTimeout(self.reconnectTimeout);
    self.reconnectTimeout = null;
  }
};

DDPClient.prototype._recoverNetworkError = function() {
  var self = this;
  if (self.autoReconnect && ! self._connectionFailed && ! self._isClosing) {
    self._clearReconnectTimeout();
    self.reconnectTimeout = setTimeout(function() { self.connect(); }, self.autoReconnectTimer);
    self._isReconnecting = true;
  }
};

///////////////////////////////////////////////////////////////////////////
// RAW, low level functions
DDPClient.prototype._send = function(data) {
  this.socket.send(
    EJSON.stringify(data)
  );
};

// handle a message from the server
DDPClient.prototype._message = function(data) {
  var self = this;

  data = EJSON.parse(data);

  // TODO: 'addedBefore' -- not yet implemented in Meteor
  // TODO: 'movedBefore' -- not yet implemented in Meteor

  if (!data.msg) {
    return;

  } else if (data.msg === "failed") {
    if (self.supportedDdpVersions.indexOf(data.version) !== -1) {
      this.ddpVersion = data.version;
      self.connect();
    } else {
      self.autoReconnect = false;
      self.emit("failed", "Cannot negotiate DDP version");
    }

  } else if (data.msg === "connected") {
    self.session = data.session;
    self.emit("connected");

  // method result
  } else if (data.msg === "result") {
    var cb = self._callbacks[data.id];

    if (cb) {
      cb(data.error, data.result);
      delete self._callbacks[data.id];
    }

  // method updated
  } else if (data.msg === "updated") {

    _.each(data.methods, function (method) {
      var cb = self._updatedCallbacks[method];
      if (cb) {
        cb();
        delete self._updatedCallbacks[method];
      }
    });

  // missing subscription
  } else if (data.msg === "nosub") {
    var cb = self._callbacks[data.id];

    if (cb) {
      cb(data.error);
      delete self._callbacks[data.id];
    }

  // add document to collection
  } else if (data.msg === "added") {
    if (self.maintainCollections && data.collection) {
      var name = data.collection, id = data.id;

      if (! self.collections[name])     { self.collections[name] = {}; }
      if (! self.collections[name][id]) { self.collections[name][id] = {}; }

      self.collections[name][id]._id = id;

      if (data.fields) {
        _.each(data.fields, function(value, key) {
          self.collections[name][id][key] = value;
        });
      }

      if (self._observers[name]) {
        _.each(self._observers[name], function(observer) {
          observer.added(id);
        });
      }
    }

  // remove document from collection
  } else if (data.msg === "removed") {
    if (self.maintainCollections && data.collection) {
      var name = data.collection, id = data.id;

      if (! self.collections[name][id]) {
        return;
      }

      var oldValue = self.collections[name][id];

      delete self.collections[name][id];

      if (self._observers[name]) {
        _.each(self._observers[name], function(observer) {
          observer.removed(id, oldValue);
        });
      }
    }

  // change document in collection
  } else if (data.msg === "changed") {
    if (self.maintainCollections && data.collection) {
      var name = data.collection, id = data.id;

      if (! self.collections[name])     { return; }
      if (! self.collections[name][id]) { return; }

      var oldFields     = {},
          clearedFields = data.cleared || [],
          newFields = {};

      if (data.fields) {
        _.each(data.fields, function(value, key) {
            oldFields[key] = self.collections[name][id][key];
            newFields[key] = value;
            self.collections[name][id][key] = value;
        });
      }

      if (data.cleared) {
        _.each(data.cleared, function(value) {
            delete self.collections[name][id][value];
        });
      }

      if (self._observers[name]) {
        _.each(self._observers[name], function(observer) {
          observer.changed(id, oldFields, clearedFields, newFields);
        });
      }
    }

  // subscriptions ready
  } else if (data.msg === "ready") {
    _.each(data.subs, function(id) {
      var cb = self._callbacks[id];
      if (cb) {
        cb();
        delete self._callbacks[id];
      }
    });

  // minimal heartbeat response for ddp pre2
  } else if (data.msg === "ping") {
    self._send(
      _.has(data, "id") ? { msg : "pong", id : data.id } : { msg : "pong" }
    );
  }
};

DDPClient.prototype._getNextId = function() {
  return (this._nextId += 1).toString();
};

DDPClient.prototype._addObserver = function(observer) {
  if (! this._observers[observer.name]) {
    this._observers[observer.name] = {};
  }
  this._observers[observer.name][observer._id] = observer;
};

DDPClient.prototype._removeObserver = function(observer) {
  if (! this._observers[observer.name]) { return; }

  delete this._observers[observer.name][observer._id];
};

//////////////////////////////////////////////////////////////////////////
// USER functions -- use these to control the client

/* open the connection to the server
 *
 *  connected(): Called when the 'connected' message is received
 *               If autoReconnect is true (default), the callback will be
 *               called each time the connection is opened.
 */
DDPClient.prototype.connect = function(connected) {
  var self = this;
  self._isConnecting = true;
  self._connectionFailed = false;
  self._isClosing = false;

  if (connected) {
    self.addListener("connected", function() {
      self._clearReconnectTimeout();

      connected(undefined, self._isReconnecting);
      self._isConnecting = false;
      self._isReconnecting = false;
    });
    self.addListener("failed", function(error) {
      self._isConnecting = false;
      self._connectionFailed = true;
      connected(error, self._isReconnecting);
    });
  }

  if (self.useSockJs) {
    self._makeSockJSConnection();
  } else {
    var url = self._buildWsUrl();
    self._makeWebSocketConnection(url);
  }
};

DDPClient.prototype._endPendingMethodCalls = function() {
  var self = this;
  var ids = _.keys(self._pendingMethods);
  self._pendingMethods = {};

  ids.forEach(function (id) {
    if(self._callbacks[id]) {
      self._callbacks[id](DDPClient.ERRORS.DISCONNECTED);
      delete self._callbacks[id];
    }

    if(self._updatedCallbacks[id]) {
      self._updatedCallbacks[id]();
      delete self._updatedCallbacks[id];
    }
  });
};

DDPClient.prototype._makeSockJSConnection = function() {
  var self = this;

  // do the info hit
  var protocol = self.ssl ? "https://" : "http://";
  var randomValue = "" + Math.ceil(Math.random() * 9999999);
  var path = pathJoin("/", self.path || "", "sockjs/info");
  var url = protocol + self.host + ":" + self.port + path;

  var requestOpts = {'url': url, 'agentOptions': self.tlsOpts}
  request.get(requestOpts, function(err, res, body) {
    if (err) {
      self._recoverNetworkError();
    } else if (body) {
      var info = JSON.parse(body);
      if(!info.base_url) {
        // no base_url, then use pure WS handling
        var url = self._buildWsUrl();
        self._makeWebSocketConnection(url);
      } else if (info.base_url.indexOf("http") === 0) {
        // base url for a different host
        var url = info.base_url + "/websocket";
        url = url.replace(/^http/, "ws");
        self._makeWebSocketConnection(url);
      } else {
        // base url for the same host
        var path = info.base_url + "/websocket";
        var url = self._buildWsUrl(path);
        self._makeWebSocketConnection(url);
      }
    } else {
      // no body. weird. use pure WS handling
      var url = self._buildWsUrl();
      self._makeWebSocketConnection(url);
    }
  });
};

DDPClient.prototype._buildWsUrl = function(path) {
  var self = this;
  var url;
  path = path || self.path || "websocket";
  var protocol = self.ssl ? "wss://" : "ws://";
  if (self.url && !self.useSockJs) {
    url = self.url;
  } else {
    url = protocol + self.host + ":" + self.port;
    url += (path.indexOf("/") === 0)? path : "/" + path;
  }
  return url;
};

DDPClient.prototype._makeWebSocketConnection = function(url) {
  var self = this;
  self.socket = new WebSocket.Client(url, null, self.tlsOpts);
  self._prepareHandlers();
};

DDPClient.prototype.close = function() {
  var self = this;
  self._isClosing = true;
  self.socket.close();
  self.removeAllListeners("connected");
  self.removeAllListeners("failed");
};

// call a method on the server,
//
// callback = function(err, result)
DDPClient.prototype.call = function(name, params, callback, updatedCallback) {
  var self = this;
  var id = self._getNextId();

  self._callbacks[id] = function () {
    delete self._pendingMethods[id];

    if (callback) {
      callback.apply(this, arguments);
    }
  };

  self._updatedCallbacks[id] = function () {
    delete self._pendingMethods[id];

    if (updatedCallback) {
      updatedCallback.apply(this, arguments);
    }
  };

  self._pendingMethods[id] = true;

  self._send({
    msg    : "method",
    id     : id,
    method : name,
    params : params
  });
};

DDPClient.prototype.callWithRandomSeed = function(name, params, randomSeed, callback, updatedCallback) {
  var self = this;
  var id = self._getNextId();

  if (callback) {
    self._callbacks[id] = callback;
  }

  if (updatedCallback) {
    self._updatedCallbacks[id] = updatedCallback;
  }

  self._send({
    msg        : "method",
    id         : id,
    method     : name,
    randomSeed : randomSeed,
    params     : params
  });
};

// open a subscription on the server, callback should handle on ready and nosub
DDPClient.prototype.subscribe = function(name, params, callback) {
  var self = this;
  var id = self._getNextId();

  if (callback) {
    self._callbacks[id] = callback;
  }

  self._send({
    msg    : "sub",
    id     : id,
    name   : name,
    params : params
  });

  return id;
};

DDPClient.prototype.unsubscribe = function(id) {
  var self = this;

  self._send({
    msg : "unsub",
    id  : id
  });
};

/**
 * Adds an observer to a collection and returns the observer.
 * Observation can be stopped by calling the stop() method on the observer.
 * Functions for added, updated and removed can be added to the observer
 * afterward.
 */
DDPClient.prototype.observe = function(name, added, updated, removed) {
  var self = this;
  var observer = {};
  var id = self._getNextId();

  // name, _id are immutable
  Object.defineProperty(observer, "name", {
    get: function() { return name; },
    enumerable: true
  });

  Object.defineProperty(observer, "_id", { get: function() { return id; }});

  observer.added   = added   || function(){};
  observer.updated = updated || function(){};
  observer.removed = removed || function(){};

  observer.stop = function() {
    self._removeObserver(observer);
  };

  self._addObserver(observer);

  return observer;
};

module.exports = DDPClient;
<commit_msg>style<commit_after>"use strict";

var util = require("util");
var events = require("events");
var WebSocket = require("faye-websocket");
var EJSON = require("ddp-ejson");
var request = require('request');
var pathJoin = require('path').join;
var _ = require("ddp-underscore-patched");

var DDPClient = function(opts) {
  var self = this;

  opts = opts || {};

  // backwards compatibility
  if ("use_ssl" in opts)              { opts.ssl = opts.use_ssl; }
  if ("auto_reconnect" in opts)       { opts.autoReconnect = opts.auto_reconnect; }
  if ("auto_reconnect_timer" in opts) { opts.autoReconnectTimer = opts.auto_reconnect_timer; }
  if ("maintain_collections" in opts) { opts.maintainCollections = opts.maintain_collections; }
  if ("ddp_version" in opts)          { opts.ddpVersion = opts.ddp_version; }

  // default arguments
  self.host = opts.host || "localhost";
  self.port = opts.port || 3000;
  self.path = opts.path;
  self.ssl  = opts.ssl  || self.port === 443;
  self.tlsOpts = opts.tlsOpts || {};
  self.useSockJs = opts.useSockJs || false;
  self.autoReconnect = ("autoReconnect" in opts) ? opts.autoReconnect : true;
  self.autoReconnectTimer = ("autoReconnectTimer" in opts) ? opts.autoReconnectTimer : 500;
  self.maintainCollections = ("maintainCollections" in opts) ? opts.maintainCollections : true;
  self.url  = opts.url;
  // support multiple ddp versions
  self.ddpVersion = ("ddpVersion" in opts) ? opts.ddpVersion : "1";
  self.supportedDdpVersions = ["1", "pre2", "pre1"];

  // Expose EJSON object, so client can use EJSON.addType(...)
  self.EJSON = EJSON;

  // very very simple collections (name -> [{id -> document}])
  if (self.maintainCollections) {
    self.collections = {};
  }

  // internal stuff to track callbacks
  self._isConnecting = false;
  self._isReconnecting = false;
  self._nextId = 0;
  self._callbacks = {};
  self._updatedCallbacks = {};
  self._pendingMethods = {};
  self._observers = {};
};

DDPClient.ERRORS = {
  DISCONNECTED: new Error("DDPClient: Disconnected from DDP server")
};

/**
 * Inherits from EventEmitter
 */
util.inherits(DDPClient, events.EventEmitter);

DDPClient.prototype._prepareHandlers = function() {
  var self = this;

  self.socket.on("open", function() {
    // just go ahead and open the connection on connect
    self._send({
      msg : "connect",
      version : self.ddpVersion,
      support : self.supportedDdpVersions
    });
  });

  self.socket.on("error", function(error) {
    // error received before connection was established
    if (self._isConnecting) {
      self.emit("failed", error.message);
    }

    self.emit("socket-error", error);
  });

  self.socket.on("close", function(event) {
    self.emit("socket-close", event.code, event.reason);
    self._endPendingMethodCalls();
    self._recoverNetworkError();
  });

  self.socket.on("message", function(event) {
    self._message(event.data);
    self.emit("message", event.data);
  });
};

DDPClient.prototype._clearReconnectTimeout = function() {
  var self = this;
  if (self.reconnectTimeout) {
    clearTimeout(self.reconnectTimeout);
    self.reconnectTimeout = null;
  }
};

DDPClient.prototype._recoverNetworkError = function() {
  var self = this;
  if (self.autoReconnect && ! self._connectionFailed && ! self._isClosing) {
    self._clearReconnectTimeout();
    self.reconnectTimeout = setTimeout(function() { self.connect(); }, self.autoReconnectTimer);
    self._isReconnecting = true;
  }
};

///////////////////////////////////////////////////////////////////////////
// RAW, low level functions
DDPClient.prototype._send = function(data) {
  this.socket.send(
    EJSON.stringify(data)
  );
};

// handle a message from the server
DDPClient.prototype._message = function(data) {
  var self = this;

  data = EJSON.parse(data);

  // TODO: 'addedBefore' -- not yet implemented in Meteor
  // TODO: 'movedBefore' -- not yet implemented in Meteor

  if (!data.msg) {
    return;

  } else if (data.msg === "failed") {
    if (self.supportedDdpVersions.indexOf(data.version) !== -1) {
      this.ddpVersion = data.version;
      self.connect();
    } else {
      self.autoReconnect = false;
      self.emit("failed", "Cannot negotiate DDP version");
    }

  } else if (data.msg === "connected") {
    self.session = data.session;
    self.emit("connected");

  // method result
  } else if (data.msg === "result") {
    var cb = self._callbacks[data.id];

    if (cb) {
      cb(data.error, data.result);
      delete self._callbacks[data.id];
    }

  // method updated
  } else if (data.msg === "updated") {

    _.each(data.methods, function (method) {
      var cb = self._updatedCallbacks[method];
      if (cb) {
        cb();
        delete self._updatedCallbacks[method];
      }
    });

  // missing subscription
  } else if (data.msg === "nosub") {
    var cb = self._callbacks[data.id];

    if (cb) {
      cb(data.error);
      delete self._callbacks[data.id];
    }

  // add document to collection
  } else if (data.msg === "added") {
    if (self.maintainCollections && data.collection) {
      var name = data.collection, id = data.id;

      if (! self.collections[name])     { self.collections[name] = {}; }
      if (! self.collections[name][id]) { self.collections[name][id] = {}; }

      self.collections[name][id]._id = id;

      if (data.fields) {
        _.each(data.fields, function(value, key) {
          self.collections[name][id][key] = value;
        });
      }

      if (self._observers[name]) {
        _.each(self._observers[name], function(observer) {
          observer.added(id);
        });
      }
    }

  // remove document from collection
  } else if (data.msg === "removed") {
    if (self.maintainCollections && data.collection) {
      var name = data.collection, id = data.id;

      if (! self.collections[name][id]) {
        return;
      }

      var oldValue = self.collections[name][id];

      delete self.collections[name][id];

      if (self._observers[name]) {
        _.each(self._observers[name], function(observer) {
          observer.removed(id, oldValue);
        });
      }
    }

  // change document in collection
  } else if (data.msg === "changed") {
    if (self.maintainCollections && data.collection) {
      var name = data.collection, id = data.id;

      if (! self.collections[name])     { return; }
      if (! self.collections[name][id]) { return; }

      var oldFields     = {},
          clearedFields = data.cleared || [],
          newFields = {};

      if (data.fields) {
        _.each(data.fields, function(value, key) {
            oldFields[key] = self.collections[name][id][key];
            newFields[key] = value;
            self.collections[name][id][key] = value;
        });
      }

      if (data.cleared) {
        _.each(data.cleared, function(value) {
            delete self.collections[name][id][value];
        });
      }

      if (self._observers[name]) {
        _.each(self._observers[name], function(observer) {
          observer.changed(id, oldFields, clearedFields, newFields);
        });
      }
    }

  // subscriptions ready
  } else if (data.msg === "ready") {
    _.each(data.subs, function(id) {
      var cb = self._callbacks[id];
      if (cb) {
        cb();
        delete self._callbacks[id];
      }
    });

  // minimal heartbeat response for ddp pre2
  } else if (data.msg === "ping") {
    self._send(
      _.has(data, "id") ? { msg : "pong", id : data.id } : { msg : "pong" }
    );
  }
};

DDPClient.prototype._getNextId = function() {
  return (this._nextId += 1).toString();
};

DDPClient.prototype._addObserver = function(observer) {
  if (! this._observers[observer.name]) {
    this._observers[observer.name] = {};
  }
  this._observers[observer.name][observer._id] = observer;
};

DDPClient.prototype._removeObserver = function(observer) {
  if (! this._observers[observer.name]) { return; }

  delete this._observers[observer.name][observer._id];
};

//////////////////////////////////////////////////////////////////////////
// USER functions -- use these to control the client

/* open the connection to the server
 *
 *  connected(): Called when the 'connected' message is received
 *               If autoReconnect is true (default), the callback will be
 *               called each time the connection is opened.
 */
DDPClient.prototype.connect = function(connected) {
  var self = this;
  self._isConnecting = true;
  self._connectionFailed = false;
  self._isClosing = false;

  if (connected) {
    self.addListener("connected", function() {
      self._clearReconnectTimeout();

      connected(undefined, self._isReconnecting);
      self._isConnecting = false;
      self._isReconnecting = false;
    });
    self.addListener("failed", function(error) {
      self._isConnecting = false;
      self._connectionFailed = true;
      connected(error, self._isReconnecting);
    });
  }

  if (self.useSockJs) {
    self._makeSockJSConnection();
  } else {
    var url = self._buildWsUrl();
    self._makeWebSocketConnection(url);
  }
};

DDPClient.prototype._endPendingMethodCalls = function() {
  var self = this;
  var ids = _.keys(self._pendingMethods);
  self._pendingMethods = {};

  ids.forEach(function (id) {
    if (self._callbacks[id]) {
      self._callbacks[id](DDPClient.ERRORS.DISCONNECTED);
      delete self._callbacks[id];
    }

    if (self._updatedCallbacks[id]) {
      self._updatedCallbacks[id]();
      delete self._updatedCallbacks[id];
    }
  });
};

DDPClient.prototype._makeSockJSConnection = function() {
  var self = this;

  // do the info hit
  var protocol = self.ssl ? "https://" : "http://";
  var randomValue = "" + Math.ceil(Math.random() * 9999999);
  var path = pathJoin("/", self.path || "", "sockjs/info");
  var url = protocol + self.host + ":" + self.port + path;

  var requestOpts = { 'url': url, 'agentOptions': self.tlsOpts };

  request.get(requestOpts, function(err, res, body) {
    if (err) {
      self._recoverNetworkError();
    } else if (body) {
      var info = JSON.parse(body);
      if(!info.base_url) {
        // no base_url, then use pure WS handling
        var url = self._buildWsUrl();
        self._makeWebSocketConnection(url);
      } else if (info.base_url.indexOf("http") === 0) {
        // base url for a different host
        var url = info.base_url + "/websocket";
        url = url.replace(/^http/, "ws");
        self._makeWebSocketConnection(url);
      } else {
        // base url for the same host
        var path = info.base_url + "/websocket";
        var url = self._buildWsUrl(path);
        self._makeWebSocketConnection(url);
      }
    } else {
      // no body. weird. use pure WS handling
      var url = self._buildWsUrl();
      self._makeWebSocketConnection(url);
    }
  });
};

DDPClient.prototype._buildWsUrl = function(path) {
  var self = this;
  var url;
  path = path || self.path || "websocket";
  var protocol = self.ssl ? "wss://" : "ws://";
  if (self.url && !self.useSockJs) {
    url = self.url;
  } else {
    url = protocol + self.host + ":" + self.port;
    url += (path.indexOf("/") === 0)? path : "/" + path;
  }
  return url;
};

DDPClient.prototype._makeWebSocketConnection = function(url) {
  var self = this;
  self.socket = new WebSocket.Client(url, null, self.tlsOpts);
  self._prepareHandlers();
};

DDPClient.prototype.close = function() {
  var self = this;
  self._isClosing = true;
  self.socket.close();
  self.removeAllListeners("connected");
  self.removeAllListeners("failed");
};

// call a method on the server,
//
// callback = function(err, result)
DDPClient.prototype.call = function(name, params, callback, updatedCallback) {
  var self = this;
  var id = self._getNextId();

  self._callbacks[id] = function () {
    delete self._pendingMethods[id];

    if (callback) {
      callback.apply(this, arguments);
    }
  };

  self._updatedCallbacks[id] = function () {
    delete self._pendingMethods[id];

    if (updatedCallback) {
      updatedCallback.apply(this, arguments);
    }
  };

  self._pendingMethods[id] = true;

  self._send({
    msg    : "method",
    id     : id,
    method : name,
    params : params
  });
};

DDPClient.prototype.callWithRandomSeed = function(name, params, randomSeed, callback, updatedCallback) {
  var self = this;
  var id = self._getNextId();

  if (callback) {
    self._callbacks[id] = callback;
  }

  if (updatedCallback) {
    self._updatedCallbacks[id] = updatedCallback;
  }

  self._send({
    msg        : "method",
    id         : id,
    method     : name,
    randomSeed : randomSeed,
    params     : params
  });
};

// open a subscription on the server, callback should handle on ready and nosub
DDPClient.prototype.subscribe = function(name, params, callback) {
  var self = this;
  var id = self._getNextId();

  if (callback) {
    self._callbacks[id] = callback;
  }

  self._send({
    msg    : "sub",
    id     : id,
    name   : name,
    params : params
  });

  return id;
};

DDPClient.prototype.unsubscribe = function(id) {
  var self = this;

  self._send({
    msg : "unsub",
    id  : id
  });
};

/**
 * Adds an observer to a collection and returns the observer.
 * Observation can be stopped by calling the stop() method on the observer.
 * Functions for added, updated and removed can be added to the observer
 * afterward.
 */
DDPClient.prototype.observe = function(name, added, updated, removed) {
  var self = this;
  var observer = {};
  var id = self._getNextId();

  // name, _id are immutable
  Object.defineProperty(observer, "name", {
    get: function() { return name; },
    enumerable: true
  });

  Object.defineProperty(observer, "_id", { get: function() { return id; }});

  observer.added   = added   || function(){};
  observer.updated = updated || function(){};
  observer.removed = removed || function(){};

  observer.stop = function() {
    self._removeObserver(observer);
  };

  self._addObserver(observer);

  return observer;
};

module.exports = DDPClient;
<|endoftext|>


<commit_before>var utils    = require('./utils')
  , request  = require('supertest')
  , should   = require('should')
  , express  = require('express')
  , mongoose = require('mongoose');

var app = require('../app.js');
var Article  = mongoose.model('Article');

describe('Article API CURD tests', function (argument) {

  beforeEach(function (done) {

    article = new Article({
      title: 'How to build a Blog with Node.js?',
      text:  'You should use some frameworks like Express'
    });

    done();
  });

  it('should list articles', function (done) {
    var articlesCount = 10, articlesIndex = 10;
    while(articlesIndex--){
      new Article({
        title: articlesIndex + 'Another Article Title'
      }).save();
    }
    request(app)
      .get('/api/articles')
      .expect(200, function (errors, res) {
        (res.body.length).should.be.equal(articlesCount);
        done();
      });
  });

  it('should show an article successfully', function (done) {
    article.save();
    request(app)
      .get('/api/articles/' + article._id)
      .expect(200, function (errors, res) {
        res.body.title.should.match(article.title);
        done();
      });
  });

  it('should create an article successfully', function (done) {
    request(app)
      .post('/api/articles')
      .send(article)
      .expect(200, function (errors, res) {
        res.body.title.should.match(article.title);
        res.body.text.should.match(article.text);
        done();
      });
  });

  it('should not create an article if no title is provided', function (done) {
    article.title = '';
    request(app)
      .post('/api/articles')
      .send(article)
      .expect(200, function (errors, res) {
        should.exist(errors);
        (res.body.errors.title.message).should.match('Title cannot be blank.');
        done();
      });
  });

});
<commit_msg>try fix test v3.<commit_after>var utils    = require('./utils')
  , request  = require('supertest')
  , should   = require('should')
  , express  = require('express')
  , mongoose = require('mongoose');

var app = require('../app.js');
var Article  = mongoose.model('Article');

describe('Article API CURD tests', function (argument) {

  beforeEach(function (done) {

    article = new Article({
      title: 'How to build a Blog with Node.js?',
      text:  'You should use some frameworks like Express'
    });

    done();
  });

  it('should list articles', function (done) {
    var articlesCount = 10, articlesIndex = 10;
    for (; articlesIndex > 0; articlesIndex--) {
        new Article({
          title: articlesIndex + 'Another Article Title'
        }).save();
    }
    request(app)
      .get('/api/articles')
      .expect(200, function (errors, res) {
        (res.body.length).should.be.equal(articlesCount);
        done();
      });
  });

  it('should show an article successfully', function (done) {
    article.save();
    request(app)
      .get('/api/articles/' + article._id)
      .expect(200, function (errors, res) {
        res.body.title.should.match(article.title);
        done();
      });
  });

  it('should create an article successfully', function (done) {
    request(app)
      .post('/api/articles')
      .send(article)
      .expect(200, function (errors, res) {
        res.body.title.should.match(article.title);
        res.body.text.should.match(article.text);
        done();
      });
  });

  it('should not create an article if no title is provided', function (done) {
    article.title = '';
    request(app)
      .post('/api/articles')
      .send(article)
      .expect(200, function (errors, res) {
        should.exist(errors);
        (res.body.errors.title.message).should.match('Title cannot be blank.');
        done();
      });
  });

});
<|endoftext|>


<commit_before>
/*
 * Leaflet plugin to create map icons using Maki Icons from MapBox.
 *
 * References:
 *   Maki Icons: https://www.mapbox.com/maki/
 *   MapBox Marker API: https://www.mapbox.com/developers/api/#Stand-alone.markers
 *
 * Usage:
 *   var marker = L.MakiMarkers.icon({icon: "rocket", color: "#b0b", size: "m"})
 *
 * License:
 *   MIT: http://jseppi.mit-license.org/
 */
(function () {
  "use strict";
  L.MakiMarkers = {
    // Available Maki Icons
    icons: ["circle-stroked", "circle", "square-stroked", "square",
      "triangle-stroked", "triangle", "star-stroked", "star", "cross",
      "marker-stroked", "marker", "religious-jewish", "religious-christian",
      "religious-muslim", "cemetery", "rocket", "airport", "heliport", "rail",
      "rail-metro", "rail-light", "bus", "fuel", "parking", "parking-garage",
      "airfield", "roadblock", "ferry", "harbor", "bicycle", "park", "park2",
      "museum", "lodging", "monument", "zoo", "garden", "campsite", "theatre",
      "art-gallery", "pitch", "soccer", "america-football", "tennis", "basketball",
      "baseball", "golf", "swimming", "cricket", "skiing", "school", "college",
      "library", "post", "fire-station", "town-hall", "police", "prison",
      "embassy", "beer", "restaurant", "cafe", "shop", "fast-food", "bar", "bank",
      "grocery", "cinema", "pharmacy", "hospital", "danger", "industrial",
      "warehouse", "commercial", "building", "place-of-worship", "alcohol-shop",
      "logging", "oil-well", "slaughterhouse", "dam", "water", "wetland",
      "disability", "telephone", "emergency-telephone", "toilets", "waste-basket",
      "music", "land-use", "city", "town", "village", "farm", "bakery", "dog-park",
      "lighthouse", "clothing-store", "polling-place", "playground", "entrance",
      "heart", "london-underground", "minefield", "rail-underground", "rail-above",
      "camera", "laundry", "car", "suitcase"],
    defaultColor: "#0a0",
    defaultIcon: "circle-stroked",
    defaultSize: "m",
    apiUrl: "https://api.tiles.mapbox.com/v3/marker/",
    smallOptions: {
      iconSize: [20, 50],
      popupAnchor: [0,-20]
    },
    mediumOptions: {
      iconSize: [30,70],
      popupAnchor: [0,-30]
    },
    largeOptions: {
      iconSize: [36,90],
      popupAnchor: [0,-40]
    }
  };

  L.MakiMarkers.Icon = L.Icon.extend({
    options: {
      //Maki icon: any from https://www.mapbox.com/maki/ (ref: L.MakiMarkers.icons)
      icon: L.MakiMarkers.defaultIcon,
      //Marker color: short or long form hex color code
      color: L.MakiMarkers.defaultColor,
      //Marker size: "s" (small), "m" (medium), or "l" (large)
      size: L.MakiMarkers.defaultSize,
      shadowAnchor: null,
      shadowSize: null,
      shadowUrl: null,
      className: 'maki-marker'
    },

    initialize: function(options) {
      var pin;

      options = L.setOptions(this, options);

      switch (options.size) {
        case "s":
          L.extend(options, L.MakiMarkers.smallOptions);
          break;
        case "l":
          L.extend(options, L.MakiMarkers.largeOptions);
          break;
        default:
          options.size = "m";
          L.extend(options, L.MakiMarkers.mediumOptions);
          break;
      }

      if (options.color.charAt(0) === '#') {
        options.color = options.color.substr(1);
      }

      pin = "pin-" + options.size + "-" + options.icon + "+" +
        options.color + ".png";

      options.iconUrl = "" + L.MakiMarkers.apiUrl + pin;
    }
  });

  L.MakiMarkers.icon = function(options) {
    return new L.MakiMarkers.Icon(options);
  };
})();<commit_msg>change var name<commit_after>
/*
 * Leaflet plugin to create map icons using Maki Icons from MapBox.
 *
 * References:
 *   Maki Icons: https://www.mapbox.com/maki/
 *   MapBox Marker API: https://www.mapbox.com/developers/api/#Stand-alone.markers
 *
 * Usage:
 *   var icon = L.MakiMarkers.icon({icon: "rocket", color: "#b0b", size: "m"})
 *
 * License:
 *   MIT: http://jseppi.mit-license.org/
 */
(function () {
  "use strict";
  L.MakiMarkers = {
    // Available Maki Icons
    icons: ["circle-stroked", "circle", "square-stroked", "square",
      "triangle-stroked", "triangle", "star-stroked", "star", "cross",
      "marker-stroked", "marker", "religious-jewish", "religious-christian",
      "religious-muslim", "cemetery", "rocket", "airport", "heliport", "rail",
      "rail-metro", "rail-light", "bus", "fuel", "parking", "parking-garage",
      "airfield", "roadblock", "ferry", "harbor", "bicycle", "park", "park2",
      "museum", "lodging", "monument", "zoo", "garden", "campsite", "theatre",
      "art-gallery", "pitch", "soccer", "america-football", "tennis", "basketball",
      "baseball", "golf", "swimming", "cricket", "skiing", "school", "college",
      "library", "post", "fire-station", "town-hall", "police", "prison",
      "embassy", "beer", "restaurant", "cafe", "shop", "fast-food", "bar", "bank",
      "grocery", "cinema", "pharmacy", "hospital", "danger", "industrial",
      "warehouse", "commercial", "building", "place-of-worship", "alcohol-shop",
      "logging", "oil-well", "slaughterhouse", "dam", "water", "wetland",
      "disability", "telephone", "emergency-telephone", "toilets", "waste-basket",
      "music", "land-use", "city", "town", "village", "farm", "bakery", "dog-park",
      "lighthouse", "clothing-store", "polling-place", "playground", "entrance",
      "heart", "london-underground", "minefield", "rail-underground", "rail-above",
      "camera", "laundry", "car", "suitcase"],
    defaultColor: "#0a0",
    defaultIcon: "circle-stroked",
    defaultSize: "m",
    apiUrl: "https://api.tiles.mapbox.com/v3/marker/",
    smallOptions: {
      iconSize: [20, 50],
      popupAnchor: [0,-20]
    },
    mediumOptions: {
      iconSize: [30,70],
      popupAnchor: [0,-30]
    },
    largeOptions: {
      iconSize: [36,90],
      popupAnchor: [0,-40]
    }
  };

  L.MakiMarkers.Icon = L.Icon.extend({
    options: {
      //Maki icon: any from https://www.mapbox.com/maki/ (ref: L.MakiMarkers.icons)
      icon: L.MakiMarkers.defaultIcon,
      //Marker color: short or long form hex color code
      color: L.MakiMarkers.defaultColor,
      //Marker size: "s" (small), "m" (medium), or "l" (large)
      size: L.MakiMarkers.defaultSize,
      shadowAnchor: null,
      shadowSize: null,
      shadowUrl: null,
      className: 'maki-marker'
    },

    initialize: function(options) {
      var pin;

      options = L.setOptions(this, options);

      switch (options.size) {
        case "s":
          L.extend(options, L.MakiMarkers.smallOptions);
          break;
        case "l":
          L.extend(options, L.MakiMarkers.largeOptions);
          break;
        default:
          options.size = "m";
          L.extend(options, L.MakiMarkers.mediumOptions);
          break;
      }

      if (options.color.charAt(0) === '#') {
        options.color = options.color.substr(1);
      }

      pin = "pin-" + options.size + "-" + options.icon + "+" +
        options.color + ".png";

      options.iconUrl = "" + L.MakiMarkers.apiUrl + pin;
    }
  });

  L.MakiMarkers.icon = function(options) {
    return new L.MakiMarkers.Icon(options);
  };
})();<|endoftext|>


<commit_before>enyo.kind({
	name: "SimpleTabBar",
	fit: true,
	components: [
		{name:"bar",kind: "onyx.TabBar"},
		{
			style: "border: 2px solid grey; ",
			components: [
				{
					content: 'Only the content of this kind is changed',
					style: 'padding: 1em'
				},
				{name: 'stuff', content: 'empty', style: 'padding: 1em'}
			]
		}
	],

	handlers: {
		onTabChanged: "switchStuff"
	},

	rendered: function() {
		this.inherited(arguments);
		this.$.bar.addTab(
			{
				'caption': 'English',
				'tooltipMsg': 'English/Anglais',
				'data' : { 'msg': 'Hello World !' } // arbitrary user data
			}
		) ;
		this.$.bar.addTab(
			{
				'caption': 'Français',
				'tooltipMsg': 'French/Français',
				'data' : { 'msg': 'Bonjour tout le monde !' } // arbitrary user data
			}
		) ;
	},

	switchStuff: function(inSender,inEvent) {
		this.log("Tapped tab with caption "+ inEvent.caption
			+ " and message " + inEvent.data.msg );
		this.$.stuff.setContent( inEvent.data.msg);
	}
});

enyo.kind(
	{
		name: "DynamicTabBar",
		fit: true,
		components: [
			{name:"bar",kind: "onyx.TabBar", maxMenuHeight: 200},
			{
				style: "border: 2px solid grey; ",
				components: [
					{
						content: 'create many tabs and reduce the width of the browser'
					},
					{name: 'stuff', content: 'empty', style: 'padding: 1em'},
					{
						kind: 'onyx.Button',
						content: 'create tab',
						ontap: 'addATab',
						style: 'margin: 0.5em'
					},
					{
						kind: 'onyx.Button',
						content: 'kill last tab',
						ontap: 'killTab'
					}
				]
			}
		],

		handlers: {
			onTabChanged: "switchStuff"
		},

		number: 1,
		rendered: function() {
			this.inherited(arguments);
			var date = new Date();
			this.creationTime = date.getTime();
			this.addATab() ;
		},

		addATab: function(inSender,inEvent) {
			this.log("adding a tab");
			var date = new Date();
			var delta = ( date.getTime() - this.creationTime ) / 1000 ;
			this.$.bar.addTab(
				{
					'caption': 'Tab label ' + this.number ,
					data: { msg: "tab " + this.number++ + " created after " + delta + " seconds" }
				}
			) ;
		},

		switchStuff: function(inSender,inEvent) {
			this.log("Tapped tab with caption "+ inEvent.caption
				+ " and message " + inEvent.data.msg );
			this.$.stuff.setContent( inEvent.data.msg);
		},
		killTab: function(inSender,inEvent) {
			this.log("killing tab");
			this.$.bar.removeTab({index: this.number-- - 2});
		}

	}
);

enyo.kind({
	name: "onyx.sample.TabBarSample",
	classes: "onyx onyx-sample",
	components: [
		{
			classes: "onyx-sample-divider",
			content: "Simple Tab Bar"
		},
		{
			kind:"SimpleTabBar"
		},
		{
			classes: "onyx-sample-divider",
			content: "Dynamic Tab Bar",
			style: 'padding-top: 4em;'
		},
		{
			kind:"DynamicTabBar"
		}

	]
});
<commit_msg>ENYO-3802: added sample for tab bar with call-back<commit_after>/*global enyo, setTimeout */

enyo.kind({
	name: "SimpleTabBar",
	fit: true,
	components: [
		{name:"bar",kind: "onyx.TabBar"},
		{
			style: "border: 2px solid grey; ",
			components: [
				{
					content: 'Only the content of this kind is changed',
					style: 'padding: 1em'
				},
				{name: 'stuff', content: 'empty', style: 'padding: 1em'}
			]
		}
	],

	handlers: {
		onTabChanged: "switchStuff"
	},

	rendered: function() {
		this.inherited(arguments);
		this.$.bar.addTab(
			{
				'caption': 'English',
				'tooltipMsg': 'English/Anglais',
				'data' : { 'msg': 'Hello World !' } // arbitrary user data
			}
		) ;
		this.$.bar.addTab(
			{
				'caption': 'Français',
				'tooltipMsg': 'French/Français',
				'data' : { 'msg': 'Bonjour tout le monde !' } // arbitrary user data
			}
		) ;
	},

	switchStuff: function(inSender,inEvent) {
		this.log("Tapped tab with caption "+ inEvent.caption
			+ " and message " + inEvent.data.msg );
		this.$.stuff.setContent( inEvent.data.msg);
	}
});

enyo.kind(
	{
		name: "DynamicTabBar",
		fit: true,
		components: [
			{name:"bar",kind: "onyx.TabBar", maxMenuHeight: 200},
			{
				style: "border: 2px solid grey; ",
				components: [
					{
						content: 'create many tabs and reduce the width of the browser'
					},
					{name: 'stuff', content: 'empty', style: 'padding: 1em'},
					{
						kind: 'onyx.Button',
						content: 'create tab',
						ontap: 'addATab',
						style: 'margin: 0.5em'
					},
					{
						kind: 'onyx.Button',
						content: 'kill last tab',
						ontap: 'killTab'
					}
				]
			}
		],

		handlers: {
			onTabChanged: "switchStuff"
		},

		number: 1,
		rendered: function() {
			this.inherited(arguments);
			var date = new Date();
			this.creationTime = date.getTime();
			this.addATab() ;
		},

		addATab: function(inSender,inEvent) {
			this.log("adding a tab");
			var date = new Date();
			var delta = ( date.getTime() - this.creationTime ) / 1000 ;
			this.$.bar.addTab(
				{
					'caption': 'Tab label ' + this.number ,
					data: { msg: "tab " + this.number++ + " created after " + delta + " seconds" }
				}
			) ;
		},

		switchStuff: function(inSender,inEvent) {
			this.log("Tapped tab with caption "+ inEvent.caption
				+ " and message " + inEvent.data.msg );
			this.$.stuff.setContent( inEvent.data.msg);
		},
		killTab: function(inSender,inEvent) {
			this.log("killing tab");
			this.$.bar.removeTab({index: this.number-- - 2});
		}

	}
);

// This class shows how actual switch or actual close can be controlled
// from the application. In the example below, these are controlled by a
// 500ms timer.

enyo.kind({
	name: "DelayedTabBar",
	fit: true,
	components: [
		{
			name:"bar",
			kind: "onyx.TabBar",
			checkBeforeChanging: true,
			checkBeforeClosing: true
		},
		{
			style: "border: 2px solid grey; ",
			components: [
				{
					content: 'Only the content of this kind is changed',
					style: 'padding: 1em'
				},
				{name: 'stuff', content: 'empty', style: 'padding: 1em'}
			]
		},
		{
			name: "delayPopup",
			kind: "onyx.Popup",
			modal: true,
			floating: true,
			centered: true,
			content: "delayed"
		}
	],

	handlers: {
		// for convenienve, the same delay is applied to tabChange and close
		// Of course, different handlers can be used.
		onTabChangeRequested: "delayAction",
		onTabRemoveRequested: "delayAction"
	},

	rendered: function() {
		this.inherited(arguments);
		// With apologies to Morris and Goscinny
		var names = ['Joe','Jack','William','Averell'];

		var add = function (name) {
			this.$.bar.addTab({
				'caption': name,
				'data' : { 'msg': 'Hello ' + name } // arbitrary user data
			});
		};
		enyo.forEach(names, add, this);
	},

	delayAction: function(inSender, inEvent) {
		this.log("Tapped tab with caption "+ inEvent.caption
			+ " and message " + inEvent.data.msg );
		this.$.delayPopup.show();
		setTimeout(enyo.bind(this, this.resumeAction, inSender,inEvent), 500);
	},
	resumeAction: function(inSender,inEvent) {
		this.$.delayPopup.hide();
		this.$.stuff.setContent( inEvent.data.msg);
		inEvent.next(); // call inEvent.next(error) is abort is needed
	}
});

enyo.kind({
	name: "onyx.sample.TabBarSample",
	classes: "onyx onyx-sample",
	components: [
		{
			classes: "onyx-sample-divider",
			content: "Simple Tab Bar"
		},
		{
			kind:"SimpleTabBar"
		},
		{
			classes: "onyx-sample-divider",
			content: "Dynamic Tab Bar",
			style: 'padding-top: 4em;'
		},
		{
			kind:"DynamicTabBar"
		},
		{
			classes: "onyx-sample-divider",
			content: "Delayed Tab Bar",
			style: 'padding-top: 4em;'
		},
		{
			kind:"DelayedTabBar"
		}

	]
});
<|endoftext|>


<commit_before>CodeMirror.defineMode("karel-en", function(conf) {
    var ERRORCLASS = 'ka-error';

    function wordRegexp(words) {
        return new RegExp("^((" + words.join(")|(") + "))\\b");
    }

    var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
    var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
    var doubleOperators = new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
    var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
    var tripleDelimiters = new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
    var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*");

    var wordOperators = wordRegexp(['not', 'and', 'or']);
    var commonkeywords = ['go', 'left', 'right', 'put', 'get', 'repeat',
    'while', 'if', 'else', 'def'];
    var commontypes = ['home', 'north', 'empty', 'acid', 'anchor', 'bone', 'box', 'bush', 'cactus', 'corn', 'fire', 'gem', 'jellyfish', 'mark', 'mine', 'palm', 'plant', 'radiation', 'rock', 'scorpion', 'skull', 'stone', 'stump', 'tomb', 'torpedo', 'tray', 'tree', 'wall', 'water', 'wood'];
    var commonBlockKeywords = ['repeat', 'while', 'if', 'else', 'def'];
    var ka2 = {
        'types': ['basestring', 'buffer', 'file', 'long', 'unicode',
        'xrange'],
        'keywords': ['exec', 'print']
        };
    var ka3 = {
        'types': ['bytearray', 'bytes', 'filter', 'map', 'memoryview',
        'open', 'range', 'zip'],
        'keywords': ['nonlocal']
        };
    var stringPrefixes;

    if (!!conf.mode.version && parseInt(conf.mode.version, 10) === 3) {
        commonkeywords = commonkeywords.concat(ka3.keywords);
        commontypes = commontypes.concat(ka3.types);
        stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i");
    } else {
        commonkeywords = commonkeywords.concat(ka2.keywords);
        commontypes = commontypes.concat(ka2.types);
        stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
    }
    var keywords = wordRegexp(commonkeywords);
    var types = wordRegexp(commontypes);
    var blockKeywords = new RegExp("^(" + commonBlockKeywords.join("|") + ")$");

    // tokenizers
    function tokenBase(stream, state) {
        // Handle scope changes
        if (stream.sol()) {
            var scopeOffset = state.scopes[0].offset;
            if (stream.eatSpace()) {
                var lineOffset = stream.indentation();
                if (lineOffset > scopeOffset) {
                    return 'ka-indent';
                } else if (lineOffset < scopeOffset) {
                    return 'ka-dedent';
                }
                return 'whitespace';
            } else {
                if (scopeOffset > 0) {
                    dedent(stream, state);
                }
            }
        }
        if (stream.eatSpace()) {
            return 'ka-space';
        }

        var ch = stream.peek();

        // Handle Comments
        if (ch === '#') {
            stream.skipToEnd();
            return 'ka-comment';
        }

        // Handle Number Literals
        if (stream.match(/^[0-9\.]/, false)) {
            var floatLiteral = false;
            // Floats
            if (stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)) {
                floatLiteral = true;
            }
            if (stream.match(/^\d+\.\d*/)) {
                floatLiteral = true;
            }
            if (stream.match(/^\.\d+/)) {
                floatLiteral = true;
            }
            if (floatLiteral) {
                // Float literals may be "imaginary"
                stream.eat(/J/i);
                return 'ka-literal';
            }
            // Integers
            var intLiteral = false;
            // Hex
            if (stream.match(/^0x[0-9a-f]+/i)) {
                intLiteral = true;
            }
            // Binary
            if (stream.match(/^0b[01]+/i)) {
                intLiteral = true;
            }
            // Octal
            if (stream.match(/^0o[0-7]+/i)) {
                intLiteral = true;
            }
            // Decimal
            if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) {
                // Decimal literals may be "imaginary"
                stream.eat(/J/i);
                // TODO - Can you have imaginary longs?
                intLiteral = true;
            }
            // Zero by itself with no other piece of number.
            if (stream.match(/^0(?![\dx])/i)) {
                intLiteral = true;
            }
            if (intLiteral) {
                // Integer literals may be "long"
                stream.eat(/L/i);
                return 'ka-literal';
            }
        }

        // Handle Strings
        if (stream.match(stringPrefixes)) {
            state.tokenize = tokenStringFactory(stream.current());
            return state.tokenize(stream, state);
        }

        // Handle operators and Delimiters
        if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
            return 'ka-delimiter';
        }
        if (stream.match(doubleOperators)
            || stream.match(singleOperators)
            || stream.match(wordOperators)) {
            return 'ka-operator';
        }
        if (stream.match(singleDelimiters)) {
            return 'ka-delimiter';
        }

        if (stream.match(types)) {
            return 'ka-type';
        }

        if (stream.match(keywords)) {
            return 'ka-keyword';
        }

        if (stream.match(identifiers)) {
            return 'ka-identifier';
        }

        // Handle non-detected items
        stream.next();
        return ERRORCLASS;
    }

    function tokenStringFactory(delimiter) {
        while ('rub'.indexOf(delimiter[0].toLowerCase()) >= 0) {
            delimiter = delimiter.substr(1);
        }
        var delim_re = new RegExp(delimiter);
        var singleline = delimiter.length == 1;
        var OUTCLASS = 'ka-string';

        return function tokenString(stream, state) {
            while (!stream.eol()) {
                stream.eatWhile(/[^'"\\]/);
                if (stream.eat('\\')) {
                    stream.next();
                    if (singleline && stream.eol()) {
                        return OUTCLASS;
                    }
                } else if (stream.match(delim_re)) {
                    state.tokenize = tokenBase;
                    return OUTCLASS;
                } else {
                    stream.eat(/['"]/);
                }
            }
            if (singleline) {
                if (conf.mode.singleLineStringErrors) {
                    OUTCLASS = ERRORCLASS
                } else {
                    state.tokenize = tokenBase;
                }
            }
            return OUTCLASS;
        };
    }

    function indent(stream, state, type) {
        type = type || 'py';
        var indentUnit = 0;
        if (type === 'py') {
            for (var i = 0; i < state.scopes.length; ++i) {
                if (state.scopes[i].type === 'py') {
                    indentUnit = state.scopes[i].offset + conf.indentUnit;
                    break;
                }
            }
        } else {
            indentUnit = stream.column() + stream.current().length;
        }
        state.scopes.unshift({
            offset: indentUnit,
            type: type
        });
    }

    function dedent(stream, state) {
        if (state.scopes.length == 1) return;
        if (state.scopes[0].type === 'py') {
            var _indent = stream.indentation();
            var _indent_index = -1;
            for (var i = 0; i < state.scopes.length; ++i) {
                if (_indent === state.scopes[i].offset) {
                    _indent_index = i;
                    break;
                }
            }
            if (_indent_index === -1) {
                return true;
            }
            while (state.scopes[0].offset !== _indent) {
                state.scopes.shift();
            }
            return false
        } else {
            state.scopes.shift();
            return false;
        }
    }

    function tokenLexer(stream, state) {
        var style = state.tokenize(stream, state);
        var current = stream.current();

        // Handle '.' connected identifiers
        if (current === '.') {
            style = state.tokenize(stream, state);
            current = stream.current();
            if (style === 'ka-identifier') {
                return 'ka-identifier';
            } else {
                return ERRORCLASS;
            }
        }

        // Handle decorators
        if (current === '@') {
            style = state.tokenize(stream, state);
            current = stream.current();
            if (style === 'ka-identifier'
                || current === '@staticmethod'
                || current === '@classmethod') {
                return 'ka-decorator';
            } else {
                return ERRORCLASS;
            }
        }

        // Handle scope changes.
        if (current === 'pass' || current === 'return') {
            state.dedent += 1;
        }
        if ((stream.string.slice(stream.indentation(), stream.pos).match(blockKeywords)
            && !state.lambda && state.scopes[0].type == 'py')
            || style === 'ka-indent') {
            indent(stream, state);
        }
        var delimiter_index = '[({'.indexOf(current);
        if (delimiter_index !== -1) {
            indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));
        }
        if (style === 'ka-dedent') {
            if (dedent(stream, state)) {
                return ERRORCLASS;
            }
        }
        delimiter_index = '])}'.indexOf(current);
        if (delimiter_index !== -1) {
            if (dedent(stream, state)) {
                return ERRORCLASS;
            }
        }
        if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'py') {
            if (state.scopes.length > 1) state.scopes.shift();
            state.dedent -= 1;
        }

        return style;
    }

    var external = {
        startState: function(basecolumn) {
            return {
                tokenize: tokenBase,
                scopes: [{
                    offset:basecolumn || 0,
                    type:'py'
                }],
                lastToken: null,
                lambda: false,
                dedent: 0
            };
        },

        token: function(stream, state) {
            var style = tokenLexer(stream, state);

            state.lastToken = {
                style:style,
                content: stream.current()
                };

            if (stream.eol() && stream.lambda) {
                state.lambda = false;
            }

            return style;
        },

        indent: function(state, textAfter) {
            if (state.tokenize != tokenBase) {
                return 0;
            }

            return state.scopes[0].offset;
        }

    };
    return external;
});

CodeMirror.defineMIME("text/x-karel", "karel-en");
<commit_msg>new English commands<commit_after>CodeMirror.defineMode("karel-en", function(conf) {
    var ERRORCLASS = 'ka-error';

    function wordRegexp(words) {
        return new RegExp("^((" + words.join(")|(") + "))\\b");
    }

    var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
    var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
    var doubleOperators = new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
    var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
    var tripleDelimiters = new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
    var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*");

    var wordOperators = wordRegexp(['not', 'and', 'or']);
    var commonkeywords = ['go', 'left', 'right', 'put', 'get', 'repeat',
    'while', 'if', 'else', 'def'];
    var commontypes = ['home', 'north', 'empty', 'acid', 'anchor', 'bone', 'box', 'bush', 'cactus', 'corn', 'fire', 'gem', 'jellyfish', 'mark', 'mine', 'palm', 'plant', 'radiation', 'rock', 'scorpion', 'skull', 'stone', 'stump', 'tomb', 'torpedo', 'tray', 'tree', 'wall', 'water', 'wood', 'bag', 'baket', 'cart', 'chest', 'vault', 'net', 'bin', 'trash', 'toilet', 'bowl', 'nugget', 'pumpkin', 'spider', 'snake', 'rose', 'tulip', 'apple', 'cherry', 'eye', 'brain', 'candy', 'book', 'key', 'pie', 'gears', 'coin', 'gun', 'ammo', 'grenade', 'pill', 'medkit', 'radio', 'bomb', 'starfish', 'pearl', 'crab', 'shoe', 'beads', 'ribbon', 'ring', 'map', 'hat', 'pipe', 'lens', 'phone', 'watch', 'rug', 'shield', 'mask', 'ball', 'orchid', 'sword', 'chip', 'basket', 'lollipop'];
    var commonBlockKeywords = ['repeat', 'while', 'if', 'else', 'def'];
    var ka2 = {
        'types': ['basestring', 'buffer', 'file', 'long', 'unicode',
        'xrange'],
        'keywords': ['exec', 'print']
        };
    var ka3 = {
        'types': ['bytearray', 'bytes', 'filter', 'map', 'memoryview',
        'open', 'range', 'zip'],
        'keywords': ['nonlocal']
        };
    var stringPrefixes;

    if (!!conf.mode.version && parseInt(conf.mode.version, 10) === 3) {
        commonkeywords = commonkeywords.concat(ka3.keywords);
        commontypes = commontypes.concat(ka3.types);
        stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i");
    } else {
        commonkeywords = commonkeywords.concat(ka2.keywords);
        commontypes = commontypes.concat(ka2.types);
        stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
    }
    var keywords = wordRegexp(commonkeywords);
    var types = wordRegexp(commontypes);
    var blockKeywords = new RegExp("^(" + commonBlockKeywords.join("|") + ")$");

    // tokenizers
    function tokenBase(stream, state) {
        // Handle scope changes
        if (stream.sol()) {
            var scopeOffset = state.scopes[0].offset;
            if (stream.eatSpace()) {
                var lineOffset = stream.indentation();
                if (lineOffset > scopeOffset) {
                    return 'ka-indent';
                } else if (lineOffset < scopeOffset) {
                    return 'ka-dedent';
                }
                return 'whitespace';
            } else {
                if (scopeOffset > 0) {
                    dedent(stream, state);
                }
            }
        }
        if (stream.eatSpace()) {
            return 'ka-space';
        }

        var ch = stream.peek();

        // Handle Comments
        if (ch === '#') {
            stream.skipToEnd();
            return 'ka-comment';
        }

        // Handle Number Literals
        if (stream.match(/^[0-9\.]/, false)) {
            var floatLiteral = false;
            // Floats
            if (stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)) {
                floatLiteral = true;
            }
            if (stream.match(/^\d+\.\d*/)) {
                floatLiteral = true;
            }
            if (stream.match(/^\.\d+/)) {
                floatLiteral = true;
            }
            if (floatLiteral) {
                // Float literals may be "imaginary"
                stream.eat(/J/i);
                return 'ka-literal';
            }
            // Integers
            var intLiteral = false;
            // Hex
            if (stream.match(/^0x[0-9a-f]+/i)) {
                intLiteral = true;
            }
            // Binary
            if (stream.match(/^0b[01]+/i)) {
                intLiteral = true;
            }
            // Octal
            if (stream.match(/^0o[0-7]+/i)) {
                intLiteral = true;
            }
            // Decimal
            if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) {
                // Decimal literals may be "imaginary"
                stream.eat(/J/i);
                // TODO - Can you have imaginary longs?
                intLiteral = true;
            }
            // Zero by itself with no other piece of number.
            if (stream.match(/^0(?![\dx])/i)) {
                intLiteral = true;
            }
            if (intLiteral) {
                // Integer literals may be "long"
                stream.eat(/L/i);
                return 'ka-literal';
            }
        }

        // Handle Strings
        if (stream.match(stringPrefixes)) {
            state.tokenize = tokenStringFactory(stream.current());
            return state.tokenize(stream, state);
        }

        // Handle operators and Delimiters
        if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
            return 'ka-delimiter';
        }
        if (stream.match(doubleOperators)
            || stream.match(singleOperators)
            || stream.match(wordOperators)) {
            return 'ka-operator';
        }
        if (stream.match(singleDelimiters)) {
            return 'ka-delimiter';
        }

        if (stream.match(types)) {
            return 'ka-type';
        }

        if (stream.match(keywords)) {
            return 'ka-keyword';
        }

        if (stream.match(identifiers)) {
            return 'ka-identifier';
        }

        // Handle non-detected items
        stream.next();
        return ERRORCLASS;
    }

    function tokenStringFactory(delimiter) {
        while ('rub'.indexOf(delimiter[0].toLowerCase()) >= 0) {
            delimiter = delimiter.substr(1);
        }
        var delim_re = new RegExp(delimiter);
        var singleline = delimiter.length == 1;
        var OUTCLASS = 'ka-string';

        return function tokenString(stream, state) {
            while (!stream.eol()) {
                stream.eatWhile(/[^'"\\]/);
                if (stream.eat('\\')) {
                    stream.next();
                    if (singleline && stream.eol()) {
                        return OUTCLASS;
                    }
                } else if (stream.match(delim_re)) {
                    state.tokenize = tokenBase;
                    return OUTCLASS;
                } else {
                    stream.eat(/['"]/);
                }
            }
            if (singleline) {
                if (conf.mode.singleLineStringErrors) {
                    OUTCLASS = ERRORCLASS
                } else {
                    state.tokenize = tokenBase;
                }
            }
            return OUTCLASS;
        };
    }

    function indent(stream, state, type) {
        type = type || 'py';
        var indentUnit = 0;
        if (type === 'py') {
            for (var i = 0; i < state.scopes.length; ++i) {
                if (state.scopes[i].type === 'py') {
                    indentUnit = state.scopes[i].offset + conf.indentUnit;
                    break;
                }
            }
        } else {
            indentUnit = stream.column() + stream.current().length;
        }
        state.scopes.unshift({
            offset: indentUnit,
            type: type
        });
    }

    function dedent(stream, state) {
        if (state.scopes.length == 1) return;
        if (state.scopes[0].type === 'py') {
            var _indent = stream.indentation();
            var _indent_index = -1;
            for (var i = 0; i < state.scopes.length; ++i) {
                if (_indent === state.scopes[i].offset) {
                    _indent_index = i;
                    break;
                }
            }
            if (_indent_index === -1) {
                return true;
            }
            while (state.scopes[0].offset !== _indent) {
                state.scopes.shift();
            }
            return false
        } else {
            state.scopes.shift();
            return false;
        }
    }

    function tokenLexer(stream, state) {
        var style = state.tokenize(stream, state);
        var current = stream.current();

        // Handle '.' connected identifiers
        if (current === '.') {
            style = state.tokenize(stream, state);
            current = stream.current();
            if (style === 'ka-identifier') {
                return 'ka-identifier';
            } else {
                return ERRORCLASS;
            }
        }

        // Handle decorators
        if (current === '@') {
            style = state.tokenize(stream, state);
            current = stream.current();
            if (style === 'ka-identifier'
                || current === '@staticmethod'
                || current === '@classmethod') {
                return 'ka-decorator';
            } else {
                return ERRORCLASS;
            }
        }

        // Handle scope changes.
        if (current === 'pass' || current === 'return') {
            state.dedent += 1;
        }
        if ((stream.string.slice(stream.indentation(), stream.pos).match(blockKeywords)
            && !state.lambda && state.scopes[0].type == 'py')
            || style === 'ka-indent') {
            indent(stream, state);
        }
        var delimiter_index = '[({'.indexOf(current);
        if (delimiter_index !== -1) {
            indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));
        }
        if (style === 'ka-dedent') {
            if (dedent(stream, state)) {
                return ERRORCLASS;
            }
        }
        delimiter_index = '])}'.indexOf(current);
        if (delimiter_index !== -1) {
            if (dedent(stream, state)) {
                return ERRORCLASS;
            }
        }
        if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'py') {
            if (state.scopes.length > 1) state.scopes.shift();
            state.dedent -= 1;
        }

        return style;
    }

    var external = {
        startState: function(basecolumn) {
            return {
                tokenize: tokenBase,
                scopes: [{
                    offset:basecolumn || 0,
                    type:'py'
                }],
                lastToken: null,
                lambda: false,
                dedent: 0
            };
        },

        token: function(stream, state) {
            var style = tokenLexer(stream, state);

            state.lastToken = {
                style:style,
                content: stream.current()
                };

            if (stream.eol() && stream.lambda) {
                state.lambda = false;
            }

            return style;
        },

        indent: function(state, textAfter) {
            if (state.tokenize != tokenBase) {
                return 0;
            }

            return state.scopes[0].offset;
        }

    };
    return external;
});

CodeMirror.defineMIME("text/x-karel", "karel-en");
<|endoftext|>


<commit_before>Package.describe({
	name: 'nathantreid:css-modules-mss',
	version: '0.6.0',
	// Brief, one-line summary of the package.
	summary: 'CSS modules core implementation. CSS for components!',
	// URL to the Git repository containing the source code for this package.
	git: 'https://github.com/nathantreid/meteor-css-modules-mss.git',
	// By default, Meteor will default to using README.md for documentation.
	// To avoid submitting documentation, set this field to null.
	documentation: 'README.md'
});

Package.registerBuildPlugin({
	name: 'css-modules-css-build-plugin',
	use: [
		'nathantreid:css-modules-mss-compiler@0.6.1'
	],
	sources: [
		'plugin.js',
	]
});

Package.onUse(function (api) {
	api.versionsFrom('1.2.0.1');
	api.use('isobuild:compiler-plugin@1.0.0');
});
<commit_msg>version bump<commit_after>Package.describe({
	name: 'nathantreid:css-modules-mss',
	version: '0.6.1',
	// Brief, one-line summary of the package.
	summary: 'CSS modules core implementation. CSS for components!',
	// URL to the Git repository containing the source code for this package.
	git: 'https://github.com/nathantreid/meteor-css-modules-mss.git',
	// By default, Meteor will default to using README.md for documentation.
	// To avoid submitting documentation, set this field to null.
	documentation: 'README.md'
});

Package.registerBuildPlugin({
	name: 'css-modules-css-build-plugin',
	use: [
		'nathantreid:css-modules-mss-compiler@0.6.1'
	],
	sources: [
		'plugin.js',
	]
});

Package.onUse(function (api) {
	api.versionsFrom('1.2.0.1');
	api.use('isobuild:compiler-plugin@1.0.0');
});
<|endoftext|>


<commit_before>var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var webpack = require('webpack');
var cssLoaders = [
  {
    loader: 'css-loader'
  },
  {
    loader: 'sass-loader',
    options: {
      includePaths: join('/node_modules')
    }
  }
];
var imgLoaders = [
  { loader: 'file-loader' },
  { loader: 'url-loader',
    options: {
      limit: 10000,
      name: '../images/[name].[ext]'
    }
  }
];

function join(dest) { return path.resolve(__dirname, dest); }

function web(dest) { return join('web/static/' + dest); }

module.exports = {
  devtool: 'source-map',
  entry: {
    application: [
      'babel-polyfill',
      web('css/application.scss'),
      web('js/application.js')
    ]
  },
  output: {
    path: join('priv/static'),
    filename: 'js/application.js',
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    }),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compressor: {
        warnings: false
      },
      minimize: true
    }),
    new ExtractTextPlugin('css/application.css')
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: [/node_modules/],
        use: 'babel-loader'
      },
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          use: cssLoaders,
          fallback: 'style-loader'
        })
      },
      {
        test: /\.(svg|png)$/i,
        exclude: [/node_modules/],
        use: imgLoaders
      }
    ]
  }
};
<commit_msg>remove dedupe and uglifyJs plugins<commit_after>var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var webpack = require('webpack');
var cssLoaders = [
  {
    loader: 'css-loader'
  },
  {
    loader: 'sass-loader',
    options: {
      includePaths: join('/node_modules')
    }
  }
];
var imgLoaders = [
  { loader: 'file-loader' },
  { loader: 'url-loader',
    options: {
      limit: 10000,
      name: '../images/[name].[ext]'
    }
  }
];

function join(dest) { return path.resolve(__dirname, dest); }

function web(dest) { return join('web/static/' + dest); }

module.exports = {
  devtool: 'source-map',
  entry: {
    application: [
      'babel-polyfill',
      web('css/application.scss'),
      web('js/application.js')
    ]
  },
  output: {
    path: join('priv/static'),
    filename: 'js/application.js',
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    }),
    new ExtractTextPlugin('css/application.css')
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: [/node_modules/],
        use: 'babel-loader'
      },
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          use: cssLoaders,
          fallback: 'style-loader'
        })
      },
      {
        test: /\.(svg|png)$/i,
        exclude: [/node_modules/],
        use: imgLoaders
      }
    ]
  }
};
<|endoftext|>